{"id":9,"date":"2006-05-10T03:35:50","date_gmt":"2006-05-10T11:35:50","guid":{"rendered":"http:\/\/www.pagetable.com\/?p=9"},"modified":"2006-05-10T03:35:50","modified_gmt":"2006-05-10T11:35:50","slug":"asking-the-kernel-how-to-make-a-syscall","status":"publish","type":"post","link":"https:\/\/www.pagetable.com\/?p=9","title":{"rendered":"Asking the kernel how to make a syscall"},"content":{"rendered":"<p>Imagine you&#8217;re an i386 user mode application on a modern operating system, and you want to make a syscall, for example to request some memory or create a new thread. But syscalls can be made in various ways on the i386 family of CPUs (int, call gates, sysenter, syscall), and CPUs tend to support only a subset of them. But hardcoding &#8220;int&#8221; into the kernel is a waste of resources on modern CPUs, because sysenter is a lot faster.<\/p>\n<p>The Windows XP kernel for example therefore detects the CPU type and tells user mode applications what mechanism to use. It maps at a constant location in every address space a read-only page that contains a small stub that can be called from user mode like a library function, and that does nothing more than transparently make the syscall.<\/p>\n<p>do_syscall:<br \/>\n    sysenter<br \/>\n    ret<\/p>\n<p>So far so good. But what if, for compatibility reasons, your cannot just map this page at a constant location? A microkernel like L4 is, among other things (to make a long story short), designed to support running unmodified applications written for many different operating systems at the same time, so we cannot guarantee for any location in the 4 GB address space that we can safely map a page of code there without destroying compatibility with some operating system.<\/p>\n<p>So the question is, how can we ask the kernel how to make syscalls, if the kernel cannot put the info in our memory, and we obviously cannot make a syscall to ask the kernel&#8230;<\/p>\n<p>The idea is to trap into kernel mode, by doing something illegal, so the kernel can put the information in a register and return to user mode. A division by zero is such a trap &#8211; but then the kernel would not be able to distinguish between this special syscall and a real division by zero exception. Using an illegal instruction doesn&#8217;t help either, because no i386 opcode is guaranteed to be illegal in the future.<\/p>\n<p>The L4 guys came up with &#8220;lock nop&#8221;. &#8220;lock&#8221; is a prefix that makes sure that in the following instruction, the memory bus is not shared with any other CPU in an SMP configuration. But &#8220;lock&#8221; may only be used with one of 17 specific instructions &#8211; all other instructions following a &#8220;lock&#8221; will cause an &#8220;undefined opcode&#8221; exception and trap into the kernel, which can easily look up whether it was &#8220;lock nop&#8221; that caused the exception.<\/p>\n<p>(Now here is a question: I found a hint on the net that &#8220;lock nop&#8221; didn&#8217;t do anything on some early Intel i386 CPUs &#8211; does anyone have more information?)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Imagine you&#8217;re an i386 user mode application on a modern operating system, and you want to make a syscall, for example to request some memory or create a new thread. But syscalls can be made in various ways on the i386 family of CPUs (int, call gates, sysenter, syscall), and CPUs tend to support only &#8230; <a title=\"Asking the kernel how to make a syscall\" class=\"read-more\" href=\"https:\/\/www.pagetable.com\/?p=9\" aria-label=\"Read more about Asking the kernel how to make a syscall\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,33,38],"tags":[],"class_list":["post-9","post","type-post","status-publish","format-standard","hentry","category-operating-systems","category-trivia","category-x86"],"_links":{"self":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/9","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=9"}],"version-history":[{"count":0,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/9\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=9"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=9"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}