* [PATCH] x86-64: fix #GP generation in assembly code
@ 2012-04-17 12:45 Jan Beulich
2012-04-17 13:08 ` Keir Fraser
0 siblings, 1 reply; 2+ messages in thread
From: Jan Beulich @ 2012-04-17 12:45 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 5034 bytes --]
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>
--- 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();
--- 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
--- 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
[-- Attachment #2: x86_64-trap-bounce-flags.patch --]
[-- Type: text/plain, Size: 5077 bytes --]
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>
--- 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();
--- 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
--- 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
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] x86-64: fix #GP generation in assembly code
2012-04-17 12:45 [PATCH] x86-64: fix #GP generation in assembly code Jan Beulich
@ 2012-04-17 13:08 ` Keir Fraser
0 siblings, 0 replies; 2+ messages in thread
From: Keir Fraser @ 2012-04-17 13:08 UTC (permalink / raw)
To: Jan Beulich, xen-devel
On 17/04/2012 13:45, "Jan Beulich" <JBeulich@suse.com> wrote:
> 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>
> --- 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();
>
> --- 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
> --- 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
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-04-17 13:08 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-17 12:45 [PATCH] x86-64: fix #GP generation in assembly code Jan Beulich
2012-04-17 13:08 ` Keir Fraser
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).