|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 4/4] x86/pv: Implement the failsafe callback using the general path
Reintroduce TBF_FAILSAFE and update pv_create_exception_frame() to cope with
the additional data segment registers.
load_segments() now fills in trap_bounce, and lets the general return-to-guest
path inject the exception.
Bloat-o-meter reports:
add/remove: 0/0 grow/shrink: 1/1 up/down: 123/-2522 (-2399)
function old new delta
pv_create_exception_frame 1088 1211 +123
context_switch 3565 1043 -2522
which I suspect is largely due to the quantity of code hidden behind
put_user().
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
---
xen/arch/x86/domain.c | 100 +++-------------------------------------
xen/arch/x86/pv/traps.c | 31 ++++++++++---
xen/include/asm-x86/processor.h | 1 +
3 files changed, 33 insertions(+), 99 deletions(-)
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 7b301e3..c533e05 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1275,100 +1275,14 @@ static void load_segments(struct vcpu *n)
if ( unlikely(!all_segs_okay) )
{
- struct pv_vcpu *pv = &n->arch.pv_vcpu;
- struct cpu_user_regs *regs = guest_cpu_user_regs();
- unsigned long *rsp =
- (unsigned long *)(((n->arch.flags & TF_kernel_mode)
- ? regs->rsp : pv->kernel_sp) & ~0xf);
- unsigned long cs_and_mask, rflags;
-
- /* Fold upcall mask and architectural IOPL into RFLAGS.IF. */
- rflags = regs->rflags & ~(X86_EFLAGS_IF|X86_EFLAGS_IOPL);
- rflags |= !vcpu_info(n, evtchn_upcall_mask) << 9;
- if ( VM_ASSIST(n->domain, architectural_iopl) )
- rflags |= n->arch.pv_vcpu.iopl;
-
- if ( is_pv_32bit_vcpu(n) )
- {
- unsigned int *esp = ring_1(regs) ?
- (unsigned int *)regs->rsp :
- (unsigned int *)pv->kernel_sp;
- int ret = 0;
-
- /* CS longword also contains full evtchn_upcall_mask. */
- cs_and_mask = (unsigned short)regs->cs |
- ((unsigned int)vcpu_info(n, evtchn_upcall_mask) << 16);
-
- if ( !ring_1(regs) )
- {
- ret = put_user(regs->ss, esp-1);
- ret |= put_user(regs->esp, esp-2);
- esp -= 2;
- }
-
- if ( ret |
- put_user(rflags, esp-1) |
- put_user(cs_and_mask, esp-2) |
- put_user(regs->eip, esp-3) |
- put_user(uregs->gs, esp-4) |
- put_user(uregs->fs, esp-5) |
- put_user(uregs->es, esp-6) |
- put_user(uregs->ds, esp-7) )
- {
- gprintk(XENLOG_ERR,
- "error while creating compat failsafe callback
frame\n");
- domain_crash(n->domain);
- }
+ bool disable = n->arch.vgc_flags & VGCF_failsafe_disables_events;
- if ( n->arch.vgc_flags & VGCF_failsafe_disables_events )
- vcpu_info(n, evtchn_upcall_mask) = 1;
-
- regs->entry_vector |= TRAP_syscall;
- regs->eflags &= ~(X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT|
- X86_EFLAGS_IOPL|X86_EFLAGS_TF);
- regs->ss = FLAT_COMPAT_KERNEL_SS;
- regs->esp = (unsigned long)(esp-7);
- regs->cs = FLAT_COMPAT_KERNEL_CS;
- regs->eip = pv->failsafe_callback_eip;
- return;
- }
-
- if ( !(n->arch.flags & TF_kernel_mode) )
- toggle_guest_mode(n);
- else
- regs->cs &= ~3;
-
- /* CS longword also contains full evtchn_upcall_mask. */
- cs_and_mask = (unsigned long)regs->cs |
- ((unsigned long)vcpu_info(n, evtchn_upcall_mask) << 32);
-
- if ( put_user(regs->ss, rsp- 1) |
- put_user(regs->rsp, rsp- 2) |
- put_user(rflags, rsp- 3) |
- put_user(cs_and_mask, rsp- 4) |
- put_user(regs->rip, rsp- 5) |
- put_user(uregs->gs, rsp- 6) |
- put_user(uregs->fs, rsp- 7) |
- put_user(uregs->es, rsp- 8) |
- put_user(uregs->ds, rsp- 9) |
- put_user(regs->r11, rsp-10) |
- put_user(regs->rcx, rsp-11) )
- {
- gprintk(XENLOG_ERR,
- "error while creating failsafe callback frame\n");
- domain_crash(n->domain);
- }
-
- if ( n->arch.vgc_flags & VGCF_failsafe_disables_events )
- vcpu_info(n, evtchn_upcall_mask) = 1;
-
- regs->entry_vector |= TRAP_syscall;
- regs->rflags &= ~(X86_EFLAGS_AC|X86_EFLAGS_VM|X86_EFLAGS_RF|
- X86_EFLAGS_NT|X86_EFLAGS_IOPL|X86_EFLAGS_TF);
- regs->ss = FLAT_KERNEL_SS;
- regs->rsp = (unsigned long)(rsp-11);
- regs->cs = FLAT_KERNEL_CS;
- regs->rip = pv->failsafe_callback_eip;
+ n->arch.pv_vcpu.trap_bounce = (struct trap_bounce){
+ .flags = (TBF_FAILSAFE | TBF_EXCEPTION |
+ (disable ? TBF_INTERRUPT : 0)),
+ .cs = FLAT_COMPAT_KERNEL_CS, /* Ignored for 64bit guests. */
+ .eip = n->arch.pv_vcpu.failsafe_callback_eip
+ };
}
}
diff --git a/xen/arch/x86/pv/traps.c b/xen/arch/x86/pv/traps.c
index 8973b23..e372ecd 100644
--- a/xen/arch/x86/pv/traps.c
+++ b/xen/arch/x86/pv/traps.c
@@ -44,7 +44,8 @@ void pv_create_exception_frame(void)
{
struct vcpu *curr = current;
struct trap_bounce *tb = &curr->arch.pv_vcpu.trap_bounce;
- struct cpu_user_regs *regs = guest_cpu_user_regs();
+ struct cpu_user_regs *regs = guest_cpu_user_regs(),
+ *uregs = &curr->arch.user_regs;
const bool user_mode_frame = !guest_kernel_mode(curr, regs);
uint8_t *evt_mask = &vcpu_info(curr, evtchn_upcall_mask);
unsigned long rflags;
@@ -66,10 +67,18 @@ void pv_create_exception_frame(void)
if ( is_pv_32bit_vcpu(curr) )
{
- /* { [ERRCODE,] EIP, CS/MASK , EFLAGS, [ESP, SS] } */
- unsigned int frame[6], *ptr = frame, ksp =
+ /* { [DS-GS,] [ERRCODE,] EIP, CS/MASK , EFLAGS, [ESP, SS] } */
+ unsigned int frame[10], *ptr = frame, ksp =
(user_mode_frame ? curr->arch.pv_vcpu.kernel_sp : regs->esp);
+ if ( tb->flags & TBF_FAILSAFE )
+ {
+ *ptr++ = uregs->ds;
+ *ptr++ = uregs->es;
+ *ptr++ = uregs->fs;
+ *ptr++ = uregs->gs;
+ }
+
if ( tb->flags & TBF_EXCEPTION_ERRCODE )
*ptr++ = tb->error_code;
@@ -100,13 +109,15 @@ void pv_create_exception_frame(void)
regs->eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_RF |
X86_EFLAGS_NT | X86_EFLAGS_TF);
regs->rsp = ksp;
- if ( user_mode_frame )
+ if ( tb->flags & TBF_FAILSAFE )
+ regs->ss = FLAT_COMPAT_KERNEL_SS;
+ else if ( user_mode_frame )
regs->ss = curr->arch.pv_vcpu.kernel_ss;
}
else
{
- /* { RCX, R11, [ERRCODE,] RIP, CS/MASK, RFLAGS, RSP, SS } */
- unsigned long frame[7], *ptr = frame, ksp =
+ /* { RCX, R11, [DS-GS,] [ERRCODE,] RIP, CS/MASK, RFLAGS, RSP, SS } */
+ unsigned long frame[11], *ptr = frame, ksp =
(user_mode_frame ? curr->arch.pv_vcpu.kernel_sp : regs->rsp) &
~0xf;
if ( user_mode_frame )
@@ -115,6 +126,14 @@ void pv_create_exception_frame(void)
*ptr++ = regs->rcx;
*ptr++ = regs->r11;
+ if ( tb->flags & TBF_FAILSAFE )
+ {
+ *ptr++ = uregs->ds;
+ *ptr++ = uregs->es;
+ *ptr++ = uregs->fs;
+ *ptr++ = uregs->gs;
+ }
+
if ( tb->flags & TBF_EXCEPTION_ERRCODE )
*ptr++ = tb->error_code;
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index 50435e3..76414df 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -60,6 +60,7 @@
/* 'trap_bounce' flags values */
#define TBF_EXCEPTION 1
#define TBF_EXCEPTION_ERRCODE 2
+#define TBF_FAILSAFE 4
#define TBF_INTERRUPT 8
/* 'arch_vcpu' flags values */
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |