diff options
author | Jan Beulich <jbeulich@suse.com> | 2012-04-17 15:33:53 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2012-04-17 15:33:53 +0200 |
commit | 63a9a8edb97a726c87b1ce80a6f9c1493410993c (patch) | |
tree | a6ac6d7152504fe41c51ba9ab3a9acc9eef6578a | |
parent | 55fb80266efe5583fe34ac62a93cee55bd30a44b (diff) | |
download | xen-63a9a8edb97a726c87b1ce80a6f9c1493410993c.tar.gz xen-63a9a8edb97a726c87b1ce80a6f9c1493410993c.tar.bz2 xen-63a9a8edb97a726c87b1ce80a6f9c1493410993c.zip |
x86-64: fix #GP generation in assembly code
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>
-rw-r--r-- | xen/arch/x86/x86_64/asm-offsets.c | 1 | ||||
-rw-r--r-- | xen/arch/x86/x86_64/compat/entry.S | 24 | ||||
-rw-r--r-- | xen/arch/x86/x86_64/entry.S | 23 |
3 files changed, 27 insertions, 21 deletions
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c index 6108ea62be..b6d1919cc2 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -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(); diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S index 1d952ac2d1..fabdd69914 100644 --- a/xen/arch/x86/x86_64/compat/entry.S +++ b/xen/arch/x86/x86_64/compat/entry.S @@ -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 diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 943c845560..3c15a04e51 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -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 |