139 lines
5.5 KiB
Diff
139 lines
5.5 KiB
Diff
|
References: bnc#757970
|
||
|
|
||
|
# HG changeset patch
|
||
|
# User Jan Beulich <jbeulich@suse.com>
|
||
|
# Date 1334669633 -7200
|
||
|
# Node ID 80f4113be5007f5b8a61048272193ce134b4fc28
|
||
|
# Parent 6092641e364428e7be20c9e23497d7a1fc535112
|
||
|
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>
|
||
|
|
||
|
# HG changeset patch
|
||
|
# User Jan Beulich <jbeulich@suse.com>
|
||
|
# Date 1334675825 -7200
|
||
|
# Node ID 569d6f05e1ef3146c269bca6313e2777420d616d
|
||
|
# Parent cf129a80e47e3664eb14070600a3b5c8c2a60440
|
||
|
x86-64: fix updating of UREGS_rip when converting sysenter to #GP
|
||
|
|
||
|
(I spotted this copy-and-paste mistake only when backporting c/s
|
||
|
25200:80f4113be500 to 4.1 and 4.0.)
|
||
|
|
||
|
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||
|
Acked-by: Keir Fraser <keir@xen.org>
|
||
|
|
||
|
--- a/xen/arch/x86/x86_64/asm-offsets.c
|
||
|
+++ b/xen/arch/x86/x86_64/asm-offsets.c
|
||
|
@@ -90,6 +90,8 @@ void __dummy__(void)
|
||
|
arch.guest_context.trap_ctxt[TRAP_gp_fault].address);
|
||
|
OFFSET(VCPU_gp_fault_sel, struct vcpu,
|
||
|
arch.guest_context.trap_ctxt[TRAP_gp_fault].cs);
|
||
|
+ OFFSET(VCPU_gp_fault_flags, struct vcpu,
|
||
|
+ arch.guest_context.trap_ctxt[TRAP_gp_fault].flags);
|
||
|
OFFSET(VCPU_kernel_sp, struct vcpu, arch.guest_context.kernel_sp);
|
||
|
OFFSET(VCPU_kernel_ss, struct vcpu, arch.guest_context.kernel_ss);
|
||
|
OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags);
|
||
|
--- a/xen/arch/x86/x86_64/compat/entry.S
|
||
|
+++ b/xen/arch/x86/x86_64/compat/entry.S
|
||
|
@@ -214,6 +214,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
|
||
|
@@ -226,19 +227,20 @@ 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: movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
|
||
|
+UNLIKELY_START(z, compat_syscall_gpf)
|
||
|
+ movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
|
||
|
subl $2,UREGS_rip(%rsp)
|
||
|
- movq VCPU_gp_fault_addr(%rbx),%rax
|
||
|
- movzwl VCPU_gp_fault_sel(%rbx),%esi
|
||
|
- movb $(TBF_EXCEPTION|TBF_EXCEPTION_ERRCODE|TBF_INTERRUPT),%cl
|
||
|
movl $0,TRAPBOUNCE_error_code(%rdx)
|
||
|
- jmp 1b
|
||
|
+ movl VCPU_gp_fault_addr(%rbx),%eax
|
||
|
+ movzwl VCPU_gp_fault_sel(%rbx),%esi
|
||
|
+ testb $4,VCPU_gp_fault_flags(%rbx)
|
||
|
+ 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)
|
||
|
cmpl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
|
||
|
--- a/xen/arch/x86/x86_64/entry.S
|
||
|
+++ b/xen/arch/x86/x86_64/entry.S
|
||
|
@@ -278,19 +278,21 @@ 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)
|
||
|
+ movl $TRAP_gp_fault,UREGS_entry_vector(%rsp)
|
||
|
+ subq $2,UREGS_rip(%rsp)
|
||
|
+ movl %eax,TRAPBOUNCE_error_code(%rdx)
|
||
|
+ movq VCPU_gp_fault_addr(%rbx),%rax
|
||
|
+ testb $4,VCPU_gp_fault_flags(%rbx)
|
||
|
+ 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: movl %eax,TRAPBOUNCE_error_code(%rdx)
|
||
|
- movq VCPU_gp_fault_addr(%rbx),%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
|
||
|
@@ -482,6 +484,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
|