# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID 42a398e1daf1fcc823156f33f85bfe1d785662c4
# Parent 3ffb6cc6b8d2a42dd4f3c6399783a5f99458023b
Linux support for sysenter/exit on x86_32.
This support is only active when supervisor_mode_kernel is enabled
in the Xen build (and when the hardware supports sysenter).
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
diff -r 3ffb6cc6b8d2 -r 42a398e1daf1
linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S
--- a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S Fri Apr 21 17:19:29
2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S Fri Apr 21 17:19:31
2006 +0100
@@ -239,7 +239,7 @@ 1: movl (%ebp),%ebp
jae syscall_badsys
call *sys_call_table(,%eax,4)
movl %eax,EAX(%esp)
- cli
+ DISABLE_INTERRUPTS
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx
jne syscall_exit_work
@@ -247,8 +247,23 @@ 1: movl (%ebp),%ebp
movl EIP(%esp), %edx
movl OLDESP(%esp), %ecx
xorl %ebp,%ebp
+#ifdef CONFIG_XEN
+ __ENABLE_INTERRUPTS
+sysexit_scrit: /**** START OF SYSEXIT CRITICAL REGION ****/
+ __TEST_PENDING
+ jnz 14f # process more events if necessary...
+ movl ESI(%esp), %esi
+ sysexit
+14: __DISABLE_INTERRUPTS
+sysexit_ecrit: /**** END OF SYSEXIT CRITICAL REGION ****/
+ push %esp
+ call evtchn_do_upcall
+ add $4,%esp
+ jmp ret_from_intr
+#else
sti
sysexit
+#endif /* !CONFIG_XEN */
# system call handler stub
@@ -530,6 +545,11 @@ error_code:
# So, on entry to the handler we detect whether we interrupted an
# existing activation in its critical region -- if so, we pop the current
# activation and restart the handler using the previous one.
+#
+# The sysexit critical region is slightly different. sysexit
+# atomically removes the entire stack frame. If we interrupt in the
+# critical region we know that the entire frame is present and correct
+# so we can simply throw away the new one.
ENTRY(hypervisor_callback)
pushl %eax
SAVE_ALL
@@ -538,6 +558,11 @@ ENTRY(hypervisor_callback)
jb 11f
cmpl $ecrit,%eax
jb critical_region_fixup
+ cmpl $sysexit_scrit,%eax
+ jb 11f
+ cmpl $sysexit_ecrit,%eax
+ ja 11f
+ addl $0x34,%esp # Remove cs...ebx from stack frame.
11: push %esp
call evtchn_do_upcall
add $4,%esp
diff -r 3ffb6cc6b8d2 -r 42a398e1daf1
linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c Fri Apr 21 17:19:29
2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c Fri Apr 21 17:19:31
2006 +0100
@@ -19,6 +19,10 @@
#include <asm/msr.h>
#include <asm/pgtable.h>
#include <asm/unistd.h>
+
+#ifdef CONFIG_XEN
+#include <xen/interface/callback.h>
+#endif
extern asmlinkage void sysenter_entry(void);
@@ -53,6 +57,18 @@ int __init sysenter_setup(void)
int __init sysenter_setup(void)
{
syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+
+#ifdef CONFIG_XEN
+ if (boot_cpu_has(X86_FEATURE_SEP)) {
+ struct callback_register sysenter = {
+ .type = CALLBACKTYPE_sysenter,
+ .address = { __KERNEL_CS, (unsigned long)sysenter_entry
},
+ };
+
+ if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) < 0)
+ clear_bit(X86_FEATURE_SEP,
boot_cpu_data.x86_capability);
+ }
+#endif
if (boot_cpu_has(X86_FEATURE_SEP)) {
memcpy(syscall_page,
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|