[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Pass NMIs to DOM0 via a dedicated callback, Xen x86_64 support.
# HG changeset patch # User Ian.Campbell@xxxxxxxxxxxxx # Node ID 06ab200a9e23b1820197e3ae4a101e5b7590041b # Parent fe4d06b15a36efe0f7a0926f7ba761747ee43d1a Pass NMIs to DOM0 via a dedicated callback, Xen x86_64 support. Handle NMI interrupts and dispatch to dom0 on x86_64. Renames the switch_to_user hypercall to iret. Extend the semantics to include returns to guest/kernel if CS indicates ring 1. Retain the old semantics of returning to guest/user if CS indicates ring3. Plumb in nmi_op hypercall to generic code. Signed-off-by: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx> diff -r fe4d06b15a36 -r 06ab200a9e23 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Wed Jan 11 15:52:12 2006 +++ b/xen/arch/x86/domain.c Wed Jan 11 15:52:33 2006 @@ -659,35 +659,6 @@ percpu_ctxt[smp_processor_id()].dirty_segment_mask = dirty_segment_mask; } -long do_switch_to_user(void) -{ - struct cpu_user_regs *regs = guest_cpu_user_regs(); - struct switch_to_user stu; - struct vcpu *v = current; - - if ( unlikely(copy_from_user(&stu, (void *)regs->rsp, sizeof(stu))) || - unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) - return -EFAULT; - - toggle_guest_mode(v); - - regs->rip = stu.rip; - regs->cs = stu.cs | 3; /* force guest privilege */ - regs->rflags = (stu.rflags & ~(EF_IOPL|EF_VM)) | EF_IE; - regs->rsp = stu.rsp; - regs->ss = stu.ss | 3; /* force guest privilege */ - - if ( !(stu.flags & VGCF_IN_SYSCALL) ) - { - regs->entry_vector = 0; - regs->r11 = stu.r11; - regs->rcx = stu.rcx; - } - - /* Saved %rax gets written back to regs->rax in entry.S. */ - return stu.rax; -} - #define switch_kernel_stack(_n,_c) ((void)0) #elif defined(__i386__) diff -r fe4d06b15a36 -r 06ab200a9e23 xen/arch/x86/x86_64/asm-offsets.c --- a/xen/arch/x86/x86_64/asm-offsets.c Wed Jan 11 15:52:12 2006 +++ b/xen/arch/x86/x86_64/asm-offsets.c Wed Jan 11 15:52:33 2006 @@ -65,6 +65,10 @@ arch.guest_context.syscall_callback_eip); OFFSET(VCPU_kernel_sp, struct vcpu, arch.guest_context.kernel_sp); + OFFSET(VCPU_flags, struct vcpu, vcpu_flags); + OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr); + DEFINE(_VCPUF_nmi_pending, _VCPUF_nmi_pending); + DEFINE(_VCPUF_nmi_masked, _VCPUF_nmi_masked); BLANK(); OFFSET(VCPUINFO_upcall_pending, vcpu_info_t, evtchn_upcall_pending); diff -r fe4d06b15a36 -r 06ab200a9e23 xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Wed Jan 11 15:52:12 2006 +++ b/xen/arch/x86/x86_64/entry.S Wed Jan 11 15:52:33 2006 @@ -171,7 +171,9 @@ leaq irq_stat(%rip),%rcx testl $~0,(%rcx,%rax,1) jnz process_softirqs -/*test_guest_events:*/ + btr $_VCPUF_nmi_pending,VCPU_flags(%rbx) + jc process_nmi +test_guest_events: movq VCPU_vcpu_info(%rbx),%rax testb $0xFF,VCPUINFO_upcall_mask(%rax) jnz restore_all_guest @@ -322,6 +324,23 @@ call do_softirq jmp test_all_events + ALIGN +/* %rbx: struct vcpu */ +process_nmi: + movq VCPU_nmi_addr(%rbx),%rax + test %rax,%rax + jz test_all_events + bts $_VCPUF_nmi_masked,VCPU_flags(%rbx) + jc 1f + sti + leaq VCPU_trap_bounce(%rbx),%rdx + movq %rax,TRAPBOUNCE_eip(%rdx) + movw $(TBF_INTERRUPT|TBF_SLOW_IRET),TRAPBOUNCE_flags(%rdx) + call create_bounce_frame + jmp test_all_events +1: bts $_VCPUF_nmi_pending,VCPU_flags(%rbx) + jmp test_guest_events + /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK: */ /* { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */ /* %rdx: trap_bounce, %rbx: struct vcpu */ @@ -339,6 +358,9 @@ 1: /* In kernel context already: push new frame at existing %rsp. */ movq UREGS_rsp+8(%rsp),%rsi andb $0xfc,UREGS_cs+8(%rsp) # Indicate kernel context to guest. + testw $(TBF_SLOW_IRET),TRAPBOUNCE_flags(%rdx) + jz 2f + orb $0x01,UREGS_cs+8(%rsp) 2: andq $~0xf,%rsi # Stack frames are 16-byte aligned. movq $HYPERVISOR_VIRT_START,%rax cmpq %rax,%rsi @@ -569,7 +591,7 @@ SAVE_ALL movq %rsp,%rdi call do_nmi - jmp restore_all_xen + jmp ret_from_intr do_arch_sched_op: # Ensure we return success even if we return via schedule_tail() @@ -626,11 +648,12 @@ .quad do_grant_table_op /* 20 */ .quad do_vm_assist .quad do_update_va_mapping_otherdomain - .quad do_switch_to_user + .quad do_iret .quad do_vcpu_op .quad do_set_segment_base /* 25 */ .quad do_mmuext_op .quad do_acm_op + .quad do_nmi_op .rept NR_hypercalls-((.-hypercall_table)/4) .quad do_ni_hypercall .endr @@ -659,11 +682,12 @@ .byte 3 /* do_grant_table_op */ /* 20 */ .byte 2 /* do_vm_assist */ .byte 4 /* do_update_va_mapping_otherdomain */ - .byte 0 /* do_switch_to_user */ + .byte 0 /* do_iret */ .byte 3 /* do_vcpu_op */ .byte 2 /* do_set_segment_base */ /* 25 */ .byte 4 /* do_mmuext_op */ .byte 1 /* do_acm_op */ + .byte 2 /* do_nmi_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff -r fe4d06b15a36 -r 06ab200a9e23 xen/arch/x86/x86_64/traps.c --- a/xen/arch/x86/x86_64/traps.c Wed Jan 11 15:52:12 2006 +++ b/xen/arch/x86/x86_64/traps.c Wed Jan 11 15:52:33 2006 @@ -12,6 +12,7 @@ #include <asm/current.h> #include <asm/flushtlb.h> #include <asm/msr.h> +#include <asm/shadow.h> #include <asm/vmx.h> void show_registers(struct cpu_user_regs *regs) @@ -113,6 +114,42 @@ __asm__ __volatile__ ( "hlt" ); } +extern void toggle_guest_mode(struct vcpu *); + +long do_iret(void) +{ + struct cpu_user_regs *regs = guest_cpu_user_regs(); + struct iret_context iret_saved; + struct vcpu *v = current; + + if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, sizeof(iret_saved))) || + unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) + return -EFAULT; + + /* returning to user mode */ + if ((iret_saved.cs & 0x03) == 3) + toggle_guest_mode(v); + + regs->rip = iret_saved.rip; + regs->cs = iret_saved.cs | 3; /* force guest privilege */ + regs->rflags = (iret_saved.rflags & ~(EF_IOPL|EF_VM)) | EF_IE; + regs->rsp = iret_saved.rsp; + regs->ss = iret_saved.ss | 3; /* force guest privilege */ + + if ( !(iret_saved.flags & VGCF_IN_SYSCALL) ) + { + regs->entry_vector = 0; + regs->r11 = iret_saved.r11; + regs->rcx = iret_saved.rcx; + } + + /* No longer in NMI context */ + clear_bit(_VCPUF_nmi_masked, ¤t->vcpu_flags); + + /* Saved %rax gets written back to regs->rax in entry.S. */ + return iret_saved.rax; +} + asmlinkage void syscall_enter(void); void __init percpu_traps_init(void) { diff -r fe4d06b15a36 -r 06ab200a9e23 xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h Wed Jan 11 15:52:12 2006 +++ b/xen/include/asm-x86/processor.h Wed Jan 11 15:52:33 2006 @@ -123,6 +123,7 @@ #define TBF_EXCEPTION_ERRCODE 2 #define TBF_INTERRUPT 8 #define TBF_FAILSAFE 16 +#define TBF_SLOW_IRET 32 /* 'arch_vcpu' flags values */ #define _TF_kernel_mode 0 diff -r fe4d06b15a36 -r 06ab200a9e23 xen/include/public/arch-x86_64.h --- a/xen/include/public/arch-x86_64.h Wed Jan 11 15:52:12 2006 +++ b/xen/include/public/arch-x86_64.h Wed Jan 11 15:52:33 2006 @@ -88,11 +88,20 @@ #define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */ /* - * int HYPERVISOR_switch_to_user(void) + * int HYPERVISOR_iret(void) * All arguments are on the kernel stack, in the following format. * Never returns if successful. Current kernel context is lost. + * The saved CS is mapped as follows: + * RING0 -> RING3 kernel mode. + * RING1 -> RING3 kernel mode. + * RING2 -> RING3 kernel mode. + * RING3 -> RING3 user mode. + * However RING0 indicates that the guest kernel should return to iteself + * directly with + * orb $3,1*8(%rsp) + * iretq * If flags contains VGCF_IN_SYSCALL: - * Restore RAX, RIP, RFLAGS, RSP. + * Restore RAX, RIP, RFLAGS, RSP. * Discard R11, RCX, CS, SS. * Otherwise: * Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP. @@ -100,10 +109,17 @@ */ /* Guest exited in SYSCALL context? Return to guest with SYSRET? */ #define VGCF_IN_SYSCALL (1<<8) +struct iret_context { + /* Top of stack (%rsp at point of hypercall). */ + uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; + /* Bottom of iret stack frame. */ +}; +/* For compatibility with HYPERVISOR_switch_to_user which is the old + * name for HYPERVISOR_iret */ struct switch_to_user { /* Top of stack (%rsp at point of hypercall). */ uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; - /* Bottom of switch_to_user stack frame. */ + /* Bottom of iret stack frame. */ }; /* diff -r fe4d06b15a36 -r 06ab200a9e23 xen/include/public/xen.h --- a/xen/include/public/xen.h Wed Jan 11 15:52:12 2006 +++ b/xen/include/public/xen.h Wed Jan 11 15:52:33 2006 @@ -53,9 +53,9 @@ #define __HYPERVISOR_grant_table_op 20 #define __HYPERVISOR_vm_assist 21 #define __HYPERVISOR_update_va_mapping_otherdomain 22 -#define __HYPERVISOR_iret 23 /* x86/32 only */ +#define __HYPERVISOR_iret 23 /* x86 only */ #define __HYPERVISOR_switch_vm86 23 /* x86/32 only (obsolete name) */ -#define __HYPERVISOR_switch_to_user 23 /* x86/64 only */ +#define __HYPERVISOR_switch_to_user 23 /* x86/64 only (obsolete name) */ #define __HYPERVISOR_vcpu_op 24 #define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ #define __HYPERVISOR_mmuext_op 26 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |