ia64/xen-unstable

changeset 9817:42a398e1daf1

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@xensource.com>
author Ian.Campbell@xensource.com
date Fri Apr 21 17:19:31 2006 +0100 (2006-04-21)
parents 3ffb6cc6b8d2
children 9b1c9d4133f8
files linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S	Fri Apr 21 17:19:29 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S	Fri Apr 21 17:19:31 2006 +0100
     1.3 @@ -239,7 +239,7 @@ 1:	movl (%ebp),%ebp
     1.4  	jae syscall_badsys
     1.5  	call *sys_call_table(,%eax,4)
     1.6  	movl %eax,EAX(%esp)
     1.7 -	cli
     1.8 +	DISABLE_INTERRUPTS
     1.9  	movl TI_flags(%ebp), %ecx
    1.10  	testw $_TIF_ALLWORK_MASK, %cx
    1.11  	jne syscall_exit_work
    1.12 @@ -247,8 +247,23 @@ 1:	movl (%ebp),%ebp
    1.13  	movl EIP(%esp), %edx
    1.14  	movl OLDESP(%esp), %ecx
    1.15  	xorl %ebp,%ebp
    1.16 +#ifdef CONFIG_XEN
    1.17 +	__ENABLE_INTERRUPTS
    1.18 +sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/
    1.19 +	__TEST_PENDING
    1.20 +	jnz  14f			# process more events if necessary...
    1.21 +	movl ESI(%esp), %esi
    1.22 +	sysexit
    1.23 +14:	__DISABLE_INTERRUPTS
    1.24 +sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/
    1.25 +	push %esp
    1.26 +	call evtchn_do_upcall
    1.27 +	add  $4,%esp
    1.28 +	jmp  ret_from_intr
    1.29 +#else
    1.30  	sti
    1.31  	sysexit
    1.32 +#endif /* !CONFIG_XEN */
    1.33  
    1.34  
    1.35  	# system call handler stub
    1.36 @@ -530,6 +545,11 @@ error_code:
    1.37  # So, on entry to the handler we detect whether we interrupted an
    1.38  # existing activation in its critical region -- if so, we pop the current
    1.39  # activation and restart the handler using the previous one.
    1.40 +#
    1.41 +# The sysexit critical region is slightly different. sysexit
    1.42 +# atomically removes the entire stack frame. If we interrupt in the
    1.43 +# critical region we know that the entire frame is present and correct
    1.44 +# so we can simply throw away the new one.
    1.45  ENTRY(hypervisor_callback)
    1.46  	pushl %eax
    1.47  	SAVE_ALL
    1.48 @@ -538,6 +558,11 @@ ENTRY(hypervisor_callback)
    1.49  	jb   11f
    1.50  	cmpl $ecrit,%eax
    1.51  	jb   critical_region_fixup
    1.52 +	cmpl $sysexit_scrit,%eax
    1.53 +	jb   11f
    1.54 +	cmpl $sysexit_ecrit,%eax
    1.55 +	ja   11f
    1.56 +	addl $0x34,%esp			# Remove cs...ebx from stack frame.
    1.57  11:	push %esp
    1.58  	call evtchn_do_upcall
    1.59  	add  $4,%esp
     2.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c	Fri Apr 21 17:19:29 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/sysenter.c	Fri Apr 21 17:19:31 2006 +0100
     2.3 @@ -20,6 +20,10 @@
     2.4  #include <asm/pgtable.h>
     2.5  #include <asm/unistd.h>
     2.6  
     2.7 +#ifdef CONFIG_XEN
     2.8 +#include <xen/interface/callback.h>
     2.9 +#endif
    2.10 +
    2.11  extern asmlinkage void sysenter_entry(void);
    2.12  
    2.13  void enable_sep_cpu(void)
    2.14 @@ -54,6 +58,18 @@ int __init sysenter_setup(void)
    2.15  {
    2.16  	syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
    2.17  
    2.18 +#ifdef CONFIG_XEN
    2.19 +	if (boot_cpu_has(X86_FEATURE_SEP)) {
    2.20 +		struct callback_register sysenter = {
    2.21 +			.type = CALLBACKTYPE_sysenter,
    2.22 +			.address = { __KERNEL_CS, (unsigned long)sysenter_entry },
    2.23 +		};
    2.24 +
    2.25 +		if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) < 0)
    2.26 +			clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability);
    2.27 +	}
    2.28 +#endif
    2.29 +
    2.30  	if (boot_cpu_has(X86_FEATURE_SEP)) {
    2.31  		memcpy(syscall_page,
    2.32  		       &vsyscall_sysenter_start,