aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/x86_64/entry.S
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2012-04-17 15:33:53 +0200
committerJan Beulich <jbeulich@suse.com>2012-04-17 15:33:53 +0200
commit63a9a8edb97a726c87b1ce80a6f9c1493410993c (patch)
treea6ac6d7152504fe41c51ba9ab3a9acc9eef6578a /xen/arch/x86/x86_64/entry.S
parent55fb80266efe5583fe34ac62a93cee55bd30a44b (diff)
downloadxen-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>
Diffstat (limited to 'xen/arch/x86/x86_64/entry.S')
-rw-r--r--xen/arch/x86/x86_64/entry.S23
1 files changed, 13 insertions, 10 deletions
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