{"id":48,"date":"2006-08-23T21:47:00","date_gmt":"2006-08-24T02:47:00","guid":{"rendered":"http:\/\/www.nynaeve.net\/?p=48"},"modified":"2019-12-13T17:41:47","modified_gmt":"2019-12-13T22:41:47","slug":"the-system-call-dispatcher-on-x86","status":"publish","type":"post","link":"http:\/\/www.nynaeve.net\/?p=48","title":{"rendered":"The system call dispatcher on x86"},"content":{"rendered":"<p>The system call dispatcher on x86 NT has undergone several revisions over the years.<\/p>\n<p>Until recently, the primary method used to make system calls was the <em>int 2e<\/em> instruction (software interrupt, vector 0x2e).  This is a fairly quick way to enter CPL 0 (kernel mode), and it is backwards compatible with all 32-bit capable x86 processors.<\/p>\n<p>With Windows XP, the mainstream mechanism used to do system calls changed;  From this point forward, the operating system selects a more optimized kernel transition mechanism based on your processor type.  Pentium II and later processors will instead use the <em>sysenter<\/em> instruction, which is a more efficient mechanism of switching to CPL 0 (kernel mode), as it dispenses with some needless (in this case) overhead of usual interrupt dispatching.<\/p>\n<p>How is this switch accomplished?  Well, starting with Windows XP, the system service call stubs do not hardcode a particular instruction (say, <em>int 2e<\/em>) anymore.  Instead, they indirect through a field in the <em>KUSER_SHARED_DATA<\/em> block (&#8220;SystemCall&#8221;).  The meaning of this field changed in Windows XP SP2 and Windows Server 2003 SP1; in prior versions, the SystemCall field held the actual code used to make the system call (and was filled in at runtime with the proper values).  In XP SP2 and Srv03 SP1, in the interests of reducing system attack surface, the <em>KUSER_SHARED_DATA<\/em> region was marked non-executable, and SystemCall becomes a pointer to a stub residing in NTDLL (with the pointer value being adjusted at runtime based on the processor type, to refer to an appropriate system call stub).<\/p>\n<p>What this means for you today is that on modern systems, you can expect to see a sequence like so for system calls:<\/p>\n<pre>0:001> u ntdll!NtClose\r\nntdll!ZwClose:\r\n7c821138 b81b000000       mov     eax,0x1b\r\n7c82113d ba0003fe7f       mov     edx,0x7ffe0300\r\n7c821142 ff12             call    dword ptr [edx]\r\n7c821144 c20400           ret     0x4\r\n7c821147 90               nop\r\n<\/pre>\n<p>0x7ffe0300 is +0x300 bytes into <em>KUSER_SHARED_DATA<\/em>.  Looking at the structure definition, we can see that this is &#8220;SystemCall&#8221;:<\/p>\n<pre>0:001> dt ntdll!_KUSER_SHARED_DATA\r\n   +0x000 TickCountLowDeprecated : Uint4B\r\n   +0x004 TickCountMultiplier : Uint4B\r\n   +0x008 InterruptTime    : _KSYSTEM_TIME\r\n   [...]\r\n   +0x300 SystemCall       : Uint4B\r\n   +0x304 SystemCallReturn : Uint4B\r\n   +0x308 SystemCallPad    : [3] Uint8B\r\n   [...]<\/pre>\n<p>Since my system is Srv03 SP1, SystemCall is a pointer to a stub in NTDLL.<\/p>\n<pre>0:001> u poi(0x7ffe0300)\r\nntdll!KiFastSystemCall:\r\n7c82ed50 8bd4             mov     edx,esp\r\n7c82ed52 0f34             sysenter\r\nntdll!KiFastSystemCallRet:\r\n7c82ed54 c3               ret\r\n<\/pre>\n<p>On my system, the system call dispatcher is using <em>sysenter<\/em>.  You can look at the old <em>int 2e<\/em> dispatcher if you wish, as it is still supported for compatibility with older processors:<\/p>\n<pre>0:001> u ntdll!KiIntsystemCall\r\nntdll!KiIntSystemCall:\r\n7c82ed60 8d542408         lea     edx,[esp+0x8]\r\n7c82ed64 cd2e             int     2e\r\n7c82ed66 c3               ret\r\n<\/pre>\n<p>The actual calling convention used by the system call dispatcher is thus:<\/p>\n<ul>\n<li>eax contains the system call ordinal.<\/li>\n<li>edx points to either the argument array of the system call on the stack (for <em>int 2e<\/em>), or the return address plus argument array (for <em>sysenter<\/em>).<\/li>\n<\/ul>\n<p>For most of the time, though, you&#8217;ll probably not be dealing directly with the system call dispatching mechanism itself.  If you are, however, now you know how it works.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The system call dispatcher on x86 NT has undergone several revisions over the years. Until recently, the primary method used to make system calls was the int 2e instruction (software interrupt, vector 0x2e). This is a fairly quick way to enter CPL 0 (kernel mode), and it is backwards compatible with all 32-bit capable x86 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[2,4,8,5],"tags":[],"_links":{"self":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/48"}],"collection":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=48"}],"version-history":[{"count":1,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/48\/revisions"}],"predecessor-version":[{"id":686,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/48\/revisions\/686"}],"wp:attachment":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=48"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=48"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=48"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}