diff -ur src/sys/i386/i386/exception.s src-sysenter/sys/i386/i386/exception.s
--- src/sys/i386/i386/exception.s	Thu Jul 28 03:30:53 2005
+++ src-sysenter/sys/i386/i386/exception.s	Tue Aug 29 08:45:16 2006
@@ -343,3 +343,5 @@
 	movl	$0,TF_ERR(%esp)	/* XXX should be the error code */
 	movl	$T_PROTFLT,TF_TRAPNO(%esp)
 	jmp	alltraps_with_regs_pushed
+#include <i386/i386/sysenter.s>
+
diff -ur src/sys/i386/i386/genassym.c src-sysenter/sys/i386/i386/genassym.c
--- src/sys/i386/i386/genassym.c	Wed Apr 13 22:57:17 2005
+++ src-sysenter/sys/i386/i386/genassym.c	Tue Aug 29 08:50:31 2006
@@ -71,6 +71,7 @@
 #endif
 #include <machine/cpu.h>
 #include <machine/pcb.h>
+#include <machine/pcb_ext.h>
 #include <machine/sigframe.h>
 #include <machine/vm86.h>
 #include <machine/proc.h>
@@ -132,7 +133,10 @@
 ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
 ASSYM(PCB_PSL, offsetof(struct pcb, pcb_psl));
 ASSYM(PCB_DBREGS, PCB_DBREGS);
+ASSYM(PCB_FULLCTX, PCB_FULLCTX);
+ASSYM(PCB_SYSENTER, PCB_SYSENTER);
 ASSYM(PCB_EXT, offsetof(struct pcb, pcb_ext));
+ASSYM(PCB_EXT_TSS_ESP0, offsetof(struct pcb_ext, ext_tss.tss_esp0));
 
 ASSYM(PCB_FSD, offsetof(struct pcb, pcb_fsd));
 ASSYM(PCB_VM86, offsetof(struct pcb, pcb_vm86));
@@ -144,12 +148,17 @@
 
 ASSYM(PCB_SIZE, sizeof(struct pcb));
 ASSYM(PCB_VM86CALL, PCB_VM86CALL);
+ASSYM(TF_EAX, offsetof(struct trapframe, tf_eax));
+ASSYM(TF_EDX, offsetof(struct trapframe, tf_edx));
+ASSYM(TF_ECX, offsetof(struct trapframe, tf_ecx));
 
 ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno));
 ASSYM(TF_ERR, offsetof(struct trapframe, tf_err));
 ASSYM(TF_EIP, offsetof(struct trapframe, tf_eip));
 ASSYM(TF_CS, offsetof(struct trapframe, tf_cs));
 ASSYM(TF_EFLAGS, offsetof(struct trapframe, tf_eflags));
+ASSYM(TF_ESP, offsetof(struct trapframe, tf_esp));
+
 ASSYM(SIGF_HANDLER, offsetof(struct sigframe, sf_ahu.sf_handler));
 #ifdef COMPAT_43
 ASSYM(SIGF_SC, offsetof(struct osigframe, sf_siginfo.si_sc));
@@ -198,6 +207,7 @@
 ASSYM(PC_CURRENTLDT, offsetof(struct pcpu, pc_currentldt));
 ASSYM(PC_CPUID, offsetof(struct pcpu, pc_cpuid));
 ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap));
+ASSYM(PC_SYSENTER_STACKPTR, offsetof(struct pcpu, pc_sysenter_stackptr));
 
 #ifdef DEV_APIC
 ASSYM(LA_VER, offsetof(struct LAPIC, version));
@@ -212,6 +222,9 @@
 ASSYM(KCSEL, GSEL(GCODE_SEL, SEL_KPL));
 ASSYM(KDSEL, GSEL(GDATA_SEL, SEL_KPL));
 ASSYM(KPSEL, GSEL(GPRIV_SEL, SEL_KPL));
+
+ASSYM(UCSEL, GSEL(GUCODE_SEL, SEL_UPL));
+ASSYM(UDSEL, GSEL(GUDATA_SEL, SEL_UPL));
 
 ASSYM(BC32SEL, GSEL(GBIOSCODE32_SEL, SEL_KPL));
 ASSYM(GPROC0_SEL, GPROC0_SEL);
diff -ur src/sys/i386/i386/machdep.c src-sysenter/sys/i386/i386/machdep.c
--- src/sys/i386/i386/machdep.c	Tue Aug 22 16:52:41 2006
+++ src-sysenter/sys/i386/i386/machdep.c	Tue Aug 29 08:54:10 2006
@@ -167,6 +167,16 @@
 static void set_fpregs_xmm(struct save87 *, struct savexmm *);
 static void fill_fpregs_xmm(struct savexmm *, struct save87 *);
 #endif /* CPU_ENABLE_SSE */
+
+struct sysenter_pcpu {
+	char	stack[KSTACK_PAGES * PAGE_SIZE];
+};
+
+static struct sysenter_pcpu	sysenter_pcpus[MAXCPU];
+
+static void sysenter_setup(void);
+
+
 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
 
 #ifdef DDB
@@ -799,6 +809,7 @@
 	SIG_CANTMASK(td->td_sigmask);
 	signotify(td);
 	PROC_UNLOCK(p);
+	td->td_pcb->pcb_flags |= PCB_FULLCTX;
 	return (EJUSTRETURN);
 }
 #endif /* COMPAT_43 */
@@ -907,6 +918,7 @@
 	SIG_CANTMASK(td->td_sigmask);
 	signotify(td);
 	PROC_UNLOCK(p);
+	td->td_pcb->pcb_flags |= PCB_FULLCTX;
 	return (EJUSTRETURN);
 }
 #endif	/* COMPAT_FREEBSD4 */
@@ -1017,6 +1029,7 @@
 	SIG_CANTMASK(td->td_sigmask);
 	signotify(td);
 	PROC_UNLOCK(p);
+	td->td_pcb->pcb_flags |= PCB_FULLCTX;
 	return (EJUSTRETURN);
 }
 
@@ -1250,6 +1263,22 @@
 	cr0 |= CR0_MP | CR0_NE | CR0_TS | CR0_WP | CR0_AM;
 	load_cr0(cr0);
 	load_gs(_udatasel);
+	sysenter_setup();
+
+}
+
+void
+sysenter_setup(void)
+{
+	char *p;
+
+	if (cpu_feature & CPUID_SEP) {
+		p = sysenter_pcpus[PCPU_GET(cpuid)].stack +
+			 KSTACK_PAGES * PAGE_SIZE - sizeof(register_t);
+		wrmsr(MSR_SYSENTER_CS, GSEL(GCODE_SEL, SEL_KPL));
+		wrmsr(MSR_SYSENTER_EIP, (uint32_t)sysenter_syscall);
+		wrmsr(MSR_SYSENTER_ESP, (uint32_t)p);
+	}
 }
 
 static int
@@ -2319,7 +2348,7 @@
 	_udatasel = GSEL(GUDATA_SEL, SEL_UPL);
 
 	/* setup proc 0's pcb */
-	thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
+	thread0.td_pcb->pcb_flags = 0;
 #ifdef PAE
 	thread0.td_pcb->pcb_cr3 = (int)IdlePDPT;
 #else
@@ -2334,6 +2363,9 @@
 {
 
 	pcpu->pc_acpi_id = 0xffffffff;
+	pcpu->pc_sysenter_stackptr = sysenter_pcpus[cpuid].stack +
+	 	KSTACK_PAGES * PAGE_SIZE - sizeof(register_t);
+
 }
 
 void
@@ -2489,6 +2521,7 @@
 	tp->tf_esp = regs->r_esp;
 	tp->tf_ss = regs->r_ss;
 	pcb->pcb_gs = regs->r_gs;
+	pcb->pcb_fullctx = 1;
 	return (0);
 }
 
@@ -2646,6 +2679,7 @@
 		tp->tf_esp = mcp->mc_esp;
 		tp->tf_ss = mcp->mc_ss;
 		td->td_pcb->pcb_gs = mcp->mc_gs;
+		td->td_pcb->pcb_fullctx = 1;
 		ret = 0;
 	}
 	return (ret);
Only in src-sysenter/sys/i386/i386: new.s
diff -ur src/sys/i386/i386/swtch.s src-sysenter/sys/i386/i386/swtch.s
--- src/sys/i386/i386/swtch.s	Wed Apr 13 22:57:17 2005
+++ src-sysenter/sys/i386/i386/swtch.s	Tue Aug 29 08:55:14 2006
@@ -199,6 +199,9 @@
 	je	1f				/* If not, use the default */
 	btsl	%esi, private_tss		/* mark use of private tss */
 	movl	PCB_EXT(%edx), %edi		/* new tss descriptor */
+	movl    PCPU(SYSENTER_STACKPTR), %eax	/* sysenter stack ptr */
+	movl    PCB_EXT_TSS_ESP0(%edi), %ebx	/* ring 0 stack */
+	movl    %ebx, (%eax)
 	jmp	2f				/* Load it up */
 
 1:	/*
@@ -208,6 +211,8 @@
 	 */
 	leal	-16(%edx), %ebx			/* leave space for vm86 */
 	movl	%ebx, PCPU(COMMON_TSS) + TSS_ESP0
+	movl    PCPU(SYSENTER_STACKPTR), %eax
+	movl    %ebx, (%eax)
 
 	/*
 	 * Test this CPU's  bit in the bitmap to see if this
Only in src-sysenter/sys/i386/i386: sysenter.s
diff -ur src/sys/i386/i386/trap.c src-sysenter/sys/i386/i386/trap.c
--- src/sys/i386/i386/trap.c	Mon Nov 28 20:03:04 2005
+++ src-sysenter/sys/i386/i386/trap.c	Tue Aug 29 09:03:57 2006
@@ -507,15 +507,19 @@
 				frame.tf_eip = (int)doreti_iret_fault;
 				goto out;
 			}
-			if (frame.tf_eip == (int)doreti_popl_ds) {
+
+			if (frame.tf_eip == (int)doreti_popl_ds ||
+			    frame.tf_eip == (int)sysenter_popl_ds) {
 				frame.tf_eip = (int)doreti_popl_ds_fault;
 				goto out;
 			}
-			if (frame.tf_eip == (int)doreti_popl_es) {
+			if (frame.tf_eip == (int)doreti_popl_es ||
+			    frame.tf_eip == (int)sysenter_popl_es) {
 				frame.tf_eip = (int)doreti_popl_es_fault;
 				goto out;
 			}
-			if (frame.tf_eip == (int)doreti_popl_fs) {
+			if (frame.tf_eip == (int)doreti_popl_fs ||
+			    frame.tf_eip == (int)sysenter_popl_fs) {
 				frame.tf_eip = (int)doreti_popl_fs_fault;
 				goto out;
 			}
@@ -543,6 +547,36 @@
 			break;
 
 		case T_TRCTRAP:	 /* trace trap */
+			if (frame.tf_eip >= (int)sysenter_syscall &&
+			    frame.tf_eip < (int)sysenter_push_cs) {
+				/*
+				 * We've just entered system mode via the
+				 * syscall sysenter.  Continue single stepping
+				 * silently until the syscall handler has
+				 * saved the flags.
+				 */
+				goto out;
+			}
+
+			if (frame.tf_eip == (int)sysenter_push_cs) {
+				/*
+				 * The syscall handler has now saved the
+				 * flags.  Stop single stepping it.
+				 */
+				frame.tf_eflags &= ~PSL_T;
+				goto out;
+			}
+
+			if (frame.tf_eip == (int)sysenter_sysexit) {
+				/*
+				 * The syscall handler restored userland eflags.
+				 * Continue single stepping silently until the
+				 * syscall handler returns to userland.
+				 */
+				goto out;
+			}
+
+
 			if (frame.tf_eip == (int)IDTVEC(lcall_syscall)) {
 				/*
 				 * We've just entered system mode via the
@@ -879,6 +913,7 @@
 	struct thread *td = curthread;
 	struct proc *p = td->td_proc;
 	register_t orig_tf_eflags;
+	register_t orig_edx;
 	u_int sticks;
 	int error;
 	int narg;
@@ -909,6 +944,7 @@
 	params = (caddr_t)frame.tf_esp + sizeof(int);
 	code = frame.tf_eax;
 	orig_tf_eflags = frame.tf_eflags;
+	orig_edx = frame.tf_edx;
 
 	if (p->p_sysent->sv_prepsyscall) {
 		/*
@@ -1016,6 +1052,13 @@
 	 */
 	if ((callp->sy_narg & SYF_MPSAFE) == 0)
 		mtx_unlock(&Giant);
+
+ 	/*
+	 * If %edx was changed, we can not use sysexit, because it
+	 * needs %edx to restore userland %eip.
+	 */
+	if (orig_edx != frame.tf_edx)
+		td->td_pcb->pcb_flags |= PCB_FULLCTX;
 
 	/*
 	 * Traced syscall.
diff -ur src/sys/i386/include/md_var.h src-sysenter/sys/i386/include/md_var.h
--- src/sys/i386/include/md_var.h	Mon Jul 24 23:28:09 2006
+++ src-sysenter/sys/i386/include/md_var.h	Tue Aug 29 09:04:27 2006
@@ -90,6 +90,12 @@
 void	doreti_popl_es_fault(void) __asm(__STRING(doreti_popl_es_fault));
 void	doreti_popl_fs(void) __asm(__STRING(doreti_popl_fs));
 void	doreti_popl_fs_fault(void) __asm(__STRING(doreti_popl_fs_fault));
+void	sysenter_syscall(void) __asm(__STRING(sysenter_syscall));
+void	sysenter_push_cs(void) __asm(__STRING(sysenter_push_cs));
+void	sysenter_popl_ds(void) __asm(__STRING(sysenter_popl_ds));
+void	sysenter_popl_es(void) __asm(__STRING(sysenter_popl_es));
+void	sysenter_popl_fs(void) __asm(__STRING(sysenter_popl_fs));
+void	sysenter_sysexit(void) __asm(__STRING(sysenter_sysexit));
 void	dump_add_page(vm_paddr_t);
 void	dump_drop_page(vm_paddr_t);
 void	enable_sse(void);
diff -ur src/sys/i386/include/pcb.h src-sysenter/sys/i386/include/pcb.h
--- src/sys/i386/include/pcb.h	Thu Apr 14 04:13:27 2005
+++ src-sysenter/sys/i386/include/pcb.h	Tue Aug 29 09:04:43 2006
@@ -67,6 +67,8 @@
 #define	PCB_NPXTRAP	0x04	/* npx trap pending */
 #define	PCB_NPXINITDONE	0x08	/* fpu state is initialized */
 #define	PCB_VM86CALL	0x10	/* in vm86 call */
+#define	PCB_FULLCTX	0x40	/* sysenter syscall */
+#define	PCB_SYSENTER	0x80	/* sysenter syscall */
 
 	caddr_t	pcb_onfault;	/* copyin/out fault recovery */
 	int	pcb_gs;
diff -ur src/sys/i386/include/pcpu.h src-sysenter/sys/i386/include/pcpu.h
--- src/sys/i386/include/pcpu.h	Wed Apr 13 22:57:17 2005
+++ src-sysenter/sys/i386/include/pcpu.h	Tue Aug 29 09:05:09 2006
@@ -54,7 +54,9 @@
 	struct	segment_descriptor *pc_fsgs_gdt;			\
 	int	pc_currentldt;						\
 	u_int	pc_acpi_id;						\
-	u_int	pc_apic_id
+	u_int	pc_apic_id;						\
+	int	pc_private_tss;	/* flag indicating private tss */	\
+	void	*pc_sysenter_stackptr;
 
 #if defined(lint)
  
diff -ur src/sys/i386/include/specialreg.h src-sysenter/sys/i386/include/specialreg.h
--- src/sys/i386/include/specialreg.h	Fri Jul 21 15:12:03 2006
+++ src-sysenter/sys/i386/include/specialreg.h	Tue Aug 29 09:05:20 2006
@@ -164,9 +164,9 @@
 #define	MSR_BBL_CR_TRIG		0x11a
 #define	MSR_BBL_CR_BUSY		0x11b
 #define	MSR_BBL_CR_CTL3		0x11e
-#define	MSR_SYSENTER_CS_MSR	0x174
-#define	MSR_SYSENTER_ESP_MSR	0x175
-#define	MSR_SYSENTER_EIP_MSR	0x176
+#define	MSR_SYSENTER_CS		0x174
+#define	MSR_SYSENTER_ESP	0x175
+#define	MSR_SYSENTER_EIP	0x176
 #define MSR_MCG_CAP		0x179
 #define MSR_MCG_STATUS		0x17a
 #define MSR_MCG_CTL		0x17b
