]> xenbits.xensource.com Git - xen.git/commitdiff
x86-64: fix #GP generation in assembly code
authorJan Beulich <jbeulich@suse.com>
Tue, 17 Apr 2012 13:33:53 +0000 (15:33 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 17 Apr 2012 13:33:53 +0000 (15:33 +0200)
When guest use of sysenter (64-bit PV guest) or syscall (32-bit PV
guest) gets converted into a GP fault (due to no callback having got
registered), we must
- honor the GP fault handler's request the keep enabled or mask event
  delivery
- not allow TBF_EXCEPTION to remain set past the generation of the
  (guest) exception in the vCPU's trap_bounce.flags, as that would
  otherwise allow for the next exception occurring in guest mode,
  should it happen to get handled in Xen itself, to nevertheless get
  bounced to the guest kernel.

Also, just like compat mode syscall handling already did, native mode
sysenter handling should, when converting to #GP, subtract 2 from the
RIP present in the frame so that the guest's GP fault handler would
see the fault pointing to the offending instruction instead of past it.

Finally, since those exception generating code blocks needed to be
modified anyway, convert them to make use of UNLIKELY_{START,END}().

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
xen/arch/x86/x86_64/asm-offsets.c
xen/arch/x86/x86_64/compat/entry.S
xen/arch/x86/x86_64/entry.S

index 6108ea62bee7e1c61c32467622a3b6c015f0fe89..b6d1919cc24c6ab2f68d17f526e2dd658332c5a3 100644 (file)
@@ -145,6 +145,7 @@ void __dummy__(void)
 
     OFFSET(TRAPINFO_eip, struct trap_info, address);
     OFFSET(TRAPINFO_cs, struct trap_info, cs);
+    OFFSET(TRAPINFO_flags, struct trap_info, flags);
     DEFINE(TRAPINFO_sizeof, sizeof(struct trap_info));
     BLANK();
 
index 1d952ac2d122f7ba32e84e78d4d58d2bbdfd0b27..fabdd69914cdab34f4f6f6592caea2a2c9836bc3 100644 (file)
@@ -213,6 +213,7 @@ compat_failsafe_callback:
 ENTRY(compat_post_handle_exception)
         testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx)
         jz    compat_test_all_events
+.Lcompat_bounce_exception:
         call  compat_create_bounce_frame
         movb  $0,TRAPBOUNCE_flags(%rdx)
         jmp   compat_test_all_events
@@ -225,20 +226,21 @@ ENTRY(compat_syscall)
         leaq  VCPU_trap_bounce(%rbx),%rdx
         testl $~3,%esi
         leal  (,%rcx,TBF_INTERRUPT),%ecx
-        jz    2f
-1:      movq  %rax,TRAPBOUNCE_eip(%rdx)
-        movw  %si,TRAPBOUNCE_cs(%rdx)
-        movb  %cl,TRAPBOUNCE_flags(%rdx)
-        call  compat_create_bounce_frame
-        jmp   compat_test_all_events
-2:      movq  VCPU_trap_ctxt(%rbx),%rsi
+UNLIKELY_START(z, compat_syscall_gpf)
+        movq  VCPU_trap_ctxt(%rbx),%rdi
         movl  $TRAP_gp_fault,UREGS_entry_vector(%rsp)
         subl  $2,UREGS_rip(%rsp)
-        movl  TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_eip(%rsi),%eax
-        movzwl TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_cs(%rsi),%esi
-        movb  $(TBF_EXCEPTION|TBF_EXCEPTION_ERRCODE|TBF_INTERRUPT),%cl
         movl  $0,TRAPBOUNCE_error_code(%rdx)
-        jmp   1b
+        movl  TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_eip(%rdi),%eax
+        movzwl TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_cs(%rdi),%esi
+        testb $4,TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_flags(%rdi)
+        setnz %cl
+        leal  TBF_EXCEPTION|TBF_EXCEPTION_ERRCODE(,%rcx,TBF_INTERRUPT),%ecx
+UNLIKELY_END(compat_syscall_gpf)
+        movq  %rax,TRAPBOUNCE_eip(%rdx)
+        movw  %si,TRAPBOUNCE_cs(%rdx)
+        movb  %cl,TRAPBOUNCE_flags(%rdx)
+        jmp   .Lcompat_bounce_exception
 
 ENTRY(compat_sysenter)
         movq  VCPU_trap_ctxt(%rbx),%rcx
index 943c845560da31491a9cc66559c13851fa689a0e..3c15a04e5132d569b960e1c17e8ddafeab8fcde2 100644 (file)
@@ -277,20 +277,22 @@ sysenter_eflags_saved:
         leaq  VCPU_trap_bounce(%rbx),%rdx
         testq %rax,%rax
         leal  (,%rcx,TBF_INTERRUPT),%ecx
-        jz    2f
-1:      movq  VCPU_domain(%rbx),%rdi
+UNLIKELY_START(z, sysenter_gpf)
+        movq  VCPU_trap_ctxt(%rbx),%rsi
+        movl  $TRAP_gp_fault,UREGS_entry_vector(%rsp)
+        subl  $2,UREGS_rip(%rsp)
+        movl  %eax,TRAPBOUNCE_error_code(%rdx)
+        movq  TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_eip(%rsi),%rax
+        testb $4,TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_flags(%rsi)
+        setnz %cl
+        leal  TBF_EXCEPTION|TBF_EXCEPTION_ERRCODE(,%rcx,TBF_INTERRUPT),%ecx
+UNLIKELY_END(sysenter_gpf)
+        movq  VCPU_domain(%rbx),%rdi
         movq  %rax,TRAPBOUNCE_eip(%rdx)
         movb  %cl,TRAPBOUNCE_flags(%rdx)
         testb $1,DOMAIN_is_32bit_pv(%rdi)
         jnz   compat_sysenter
-        call  create_bounce_frame
-        jmp   test_all_events
-2:      movq  VCPU_trap_ctxt(%rbx),%rcx
-        movl  %eax,TRAPBOUNCE_error_code(%rdx)
-        movq  TRAP_gp_fault * TRAPINFO_sizeof + TRAPINFO_eip(%rcx),%rax
-        movb  $(TBF_EXCEPTION|TBF_EXCEPTION_ERRCODE|TBF_INTERRUPT),%cl
-        movl  $TRAP_gp_fault,UREGS_entry_vector(%rsp)
-        jmp   1b
+        jmp   .Lbounce_exception
 
 ENTRY(int80_direct_trap)
         pushq $0
@@ -483,6 +485,7 @@ handle_exception_saved:
         jnz   compat_post_handle_exception
         testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx)
         jz    test_all_events
+.Lbounce_exception:
         call  create_bounce_frame
         movb  $0,TRAPBOUNCE_flags(%rdx)
         jmp   test_all_events