[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 5/5] 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> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> --- CC: Wei Liu <wei.liu2@xxxxxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> v2: * Use const uregs. --- xen/arch/x86/domain.c | 100 +++------------------------------------- xen/arch/x86/pv/traps.c | 29 ++++++++++-- xen/include/asm-x86/processor.h | 1 + 3 files changed, 32 insertions(+), 98 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 69679a6..7bce7de 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -1354,100 +1354,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 b7d7d2b..8745e44 100644 --- a/xen/arch/x86/pv/traps.c +++ b/xen/arch/x86/pv/traps.c @@ -258,6 +258,7 @@ 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(); + const struct 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 int flags, bytes, missing; @@ -279,10 +280,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; @@ -321,13 +330,15 @@ void pv_create_exception_frame(void) regs->rflags &= ~(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[8], *ptr = frame, ksp = + /* { RCX, R11, [DS-GS,] [ERRCODE,] RIP, CS/MASK, RFLAGS, RSP, SS } */ + unsigned long frame[12], *ptr = frame, ksp = (user_mode_frame ? curr->arch.pv_vcpu.kernel_sp : regs->rsp) & ~0xf; if ( user_mode_frame ) @@ -336,6 +347,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 01bc89f..4fba9a4 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -61,6 +61,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@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |