Index: kernel/arch/amd64/include/syscall.h
===================================================================
--- kernel/arch/amd64/include/syscall.h	(revision d364e94360c20325ba21bb69e6ac2542ade79708)
+++ kernel/arch/amd64/include/syscall.h	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
@@ -36,6 +36,4 @@
 #define KERN_amd64_SYSCALL_H_
 
-#include <arch/types.h>
-
 extern void syscall_setup_cpu(void);
 
Index: kernel/arch/ia32/Makefile.inc
===================================================================
--- kernel/arch/ia32/Makefile.inc	(revision d364e94360c20325ba21bb69e6ac2542ade79708)
+++ kernel/arch/ia32/Makefile.inc	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
@@ -161,3 +161,4 @@
 	arch/$(ARCH)/src/boot/memmap.c \
 	arch/$(ARCH)/src/fpu_context.c \
-	arch/$(ARCH)/src/debugger.c
+	arch/$(ARCH)/src/debugger.c \
+	arch/$(ARCH)/src/syscall.c
Index: kernel/arch/ia32/include/asm.h
===================================================================
--- kernel/arch/ia32/include/asm.h	(revision d364e94360c20325ba21bb69e6ac2542ade79708)
+++ kernel/arch/ia32/include/asm.h	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
@@ -248,4 +248,20 @@
 }
 
+/** Write to MSR */
+static inline void write_msr(uint32_t msr, uint64_t value)
+{
+	asm volatile ("wrmsr" : : "c" (msr), "a" ((uint32_t)(value)),
+	    "d" ((uint32_t)(value >> 32)));
+}
+
+static inline uint64_t read_msr(uint32_t msr)
+{
+	uint32_t ax, dx;
+
+	asm volatile ("rdmsr" : "=a"(ax), "=d"(dx) : "c" (msr));
+	return ((uint64_t)dx << 32) | ax;
+}
+
+
 /** Return base address of current stack
  *
Index: kernel/arch/ia32/include/cpu.h
===================================================================
--- kernel/arch/ia32/include/cpu.h	(revision d364e94360c20325ba21bb69e6ac2542ade79708)
+++ kernel/arch/ia32/include/cpu.h	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
@@ -36,9 +36,18 @@
 #define KERN_ia32_CPU_H_
 
+#define EFLAGS_IF       (1 << 9)
+#define EFLAGS_RF       (1 << 16)
+
+#define CR4_OSFXSR_MASK (1<<9)
+
+/* Support for SYSENTER and SYSEXIT */
+#define IA32_MSR_SYSENTER_CS	0x174
+#define IA32_MSR_SYSENTER_ESP	0x175
+#define IA32_MSR_SYSENTER_EIP	0x176
+
+#ifndef __ASM__
+
 #include <arch/pm.h>
 #include <arch/asm.h>
-
-#define EFLAGS_IF       (1 << 9)
-#define EFLAGS_RF       (1 << 16)
 
 typedef struct {
@@ -52,6 +61,5 @@
 } cpu_arch_t;
 
-
-#define CR4_OSFXSR_MASK (1<<9)
+#endif
 
 #endif
Index: kernel/arch/ia32/include/syscall.h
===================================================================
--- kernel/arch/ia32/include/syscall.h	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
+++ kernel/arch/ia32/include/syscall.h	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
@@ -0,0 +1,1 @@
+../../amd64/include/syscall.h
Index: kernel/arch/ia32/src/asm.S
===================================================================
--- kernel/arch/ia32/src/asm.S	(revision d364e94360c20325ba21bb69e6ac2542ade79708)
+++ kernel/arch/ia32/src/asm.S	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
@@ -147,4 +147,43 @@
 	popfl
 .endm	
+
+/*
+ * The SYSENTER syscall mechanism can be used for syscalls with
+ * four or fewer arguments. To pass these four arguments, we
+ * use four registers: EDX, ECX, EBX, ESI. The syscall number
+ * is passed in EAX. We use EDI to remember the return address
+ * and EBP to remember the stack. The INT-based syscall mechanism
+ * can actually handle six arguments plus the syscall number
+ * entirely in registers.
+ */
+.global sysenter_handler
+sysenter_handler:
+	pushl %ebp	# remember user stack
+	pushl %edi	# remember return user address
+
+	pushl %gs	# remember TLS
+
+	pushl %eax	# syscall number
+	subl $8, %esp	# unused sixth and fifth argument
+	pushl %esi	# fourth argument
+	pushl %ebx	# third argument
+	pushl %ecx	# second argument
+	pushl %edx	# first argument
+
+	movw $16, %ax
+	movw %ax, %ds
+	movw %ax, %es
+
+	cld
+	call syscall_handler
+	addl $28, %esp	# remove arguments from stack
+
+	pop %gs		# restore TLS
+
+	pop %edx	# prepare return EIP for SYSEXIT
+	pop %ecx	# prepare userspace ESP for SYSEXIT
+
+	sysexit		# return to userspace
+
 
 ## Declare interrupt handlers
Index: kernel/arch/ia32/src/cpu/cpu.c
===================================================================
--- kernel/arch/ia32/src/cpu/cpu.c	(revision d364e94360c20325ba21bb69e6ac2542ade79708)
+++ kernel/arch/ia32/src/cpu/cpu.c	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
@@ -43,4 +43,5 @@
 
 #include <arch/smp/apic.h>
+#include <arch/syscall.h>
 
 /*
@@ -124,4 +125,7 @@
 		);
 	}
+	
+	/* Setup fast SYSENTER/SYSEXIT syscalls */
+	syscall_setup_cpu();
 }
 
Index: kernel/arch/ia32/src/proc/scheduler.c
===================================================================
--- kernel/arch/ia32/src/proc/scheduler.c	(revision d364e94360c20325ba21bb69e6ac2542ade79708)
+++ kernel/arch/ia32/src/proc/scheduler.c	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
@@ -59,6 +59,12 @@
 void before_thread_runs_arch(void)
 {
-	CPU->arch.tss->esp0 = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
+	uintptr_t kstk = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
 	    SP_DELTA];
+
+	/* Set kernel stack for CP3 -> CPL0 switch via SYSENTER */
+	write_msr(IA32_MSR_SYSENTER_ESP, kstk);
+
+	/* Set kernel stack for CPL3 -> CPL0 switch via interrupt */
+	CPU->arch.tss->esp0 = kstk;
 	CPU->arch.tss->ss0 = selector(KDATA_DES);
 
Index: kernel/arch/ia32/src/syscall.c
===================================================================
--- kernel/arch/ia32/src/syscall.c	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
+++ kernel/arch/ia32/src/syscall.c	(revision c61d34be34099f5ca3cf83937a9935c4e09a9773)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2008 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ia32	
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/syscall.h>
+#include <arch/cpu.h>
+#include <arch/asm.h>
+#include <arch/types.h>
+#include <arch/pm.h>
+
+/** Enable & setup support for SYSENTER/SYSEXIT */
+void syscall_setup_cpu(void)
+{
+	extern void sysenter_handler(void);
+
+	/* set kernel mode CS selector */
+	write_msr(IA32_MSR_SYSENTER_CS, selector(KTEXT_DES));
+	/* set kernel mode entry point */
+	write_msr(IA32_MSR_SYSENTER_EIP, (uint32_t) sysenter_handler);
+}
+
+/** @}
+ */
