[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Pass NMIs to DOM0 via a dedicated callback, Xen x86_32 support.



# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID fe4d06b15a36efe0f7a0926f7ba761747ee43d1a
# Parent  c6f7774cae63932f327413586d58f3c7d08cb378
Pass NMIs to DOM0 via a dedicated callback, Xen x86_32 support.

Handle NMI interrupts and dispatch to dom0 on x86_32.

Renames the switch_vm86 hypercall to iret and implements full iret
semantics instead only what is required by VM86 returns.

Plumb in nmi_op hypercall to generic code.

Signed-off-by: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>

diff -r c6f7774cae63 -r fe4d06b15a36 xen/arch/x86/x86_32/asm-offsets.c
--- a/xen/arch/x86/x86_32/asm-offsets.c Wed Jan 11 15:51:56 2006
+++ b/xen/arch/x86/x86_32/asm-offsets.c Wed Jan 11 15:52:12 2006
@@ -65,6 +65,10 @@
            arch.guest_context.kernel_ss);
     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 c6f7774cae63 -r fe4d06b15a36 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Wed Jan 11 15:51:56 2006
+++ b/xen/arch/x86/x86_32/entry.S       Wed Jan 11 15:52:12 2006
@@ -326,7 +326,9 @@
         shl  $IRQSTAT_shift,%eax
         test %ecx,irq_stat(%eax,1)
         jnz  process_softirqs
-/*test_guest_events:*/
+        btr  $_VCPUF_nmi_pending,VCPU_flags(%ebx)
+        jc   process_nmi
+test_guest_events:
         movl VCPU_vcpu_info(%ebx),%eax
         testb $0xFF,VCPUINFO_upcall_mask(%eax)
         jnz  restore_all_guest
@@ -348,7 +350,24 @@
         sti       
         call do_softirq
         jmp  test_all_events
-                
+       
+       ALIGN
+process_nmi:
+        movl VCPU_nmi_addr(%ebx),%eax
+        test %eax,%eax
+        jz   test_all_events
+        bts  $_VCPUF_nmi_masked,VCPU_flags(%ebx)
+        jc   1f
+        sti
+        leal VCPU_trap_bounce(%ebx),%edx
+        movl %eax,TRAPBOUNCE_eip(%edx)
+        movw $FLAT_KERNEL_CS,TRAPBOUNCE_cs(%edx)
+        movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx)
+        call create_bounce_frame
+        jmp  test_all_events
+1:      bts  $_VCPUF_nmi_pending,VCPU_flags(%ebx)
+        jmp  test_guest_events
+
 /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK:            */
 /*   {EIP, CS, EFLAGS, [ESP, SS]}                                        */
 /* %edx == trap_bounce, %ebx == struct vcpu                       */
@@ -620,9 +639,7 @@
         jne   defer_nmi
 
 continue_nmi:
-        movl  $(__HYPERVISOR_DS),%edx
-        movl  %edx,%ds
-        movl  %edx,%es
+        SET_XEN_SEGMENTS(d)
         movl  %esp,%edx
         pushl %edx
         call  do_nmi
@@ -659,42 +676,6 @@
         GET_GUEST_REGS(%ecx)
         movl %eax,UREGS_eax(%ecx)
         jmp  do_sched_op
-
-do_switch_vm86:
-        # Reset the stack pointer
-        GET_GUEST_REGS(%ecx)
-        movl %ecx,%esp
-
-        # GS:ESI == Ring-1 stack activation
-        movl UREGS_esp(%esp),%esi
-VFLT1:  mov  UREGS_ss(%esp),%gs
-
-        # ES:EDI == Ring-0 stack activation
-        leal UREGS_eip(%esp),%edi
-
-        # Restore the hypercall-number-clobbered EAX on our stack frame
-VFLT2:  movl %gs:(%esi),%eax
-        movl %eax,UREGS_eax(%esp)
-        addl $4,%esi
-               
-       # Copy the VM86 activation from the ring-1 stack to the ring-0 stack
-        movl $(UREGS_user_sizeof-UREGS_eip)/4,%ecx
-VFLT3:  movl %gs:(%esi),%eax
-        stosl
-        addl $4,%esi
-        loop VFLT3
-
-        # Fix up EFLAGS: IOPL=0, IF=1, VM=1
-        andl $~X86_EFLAGS_IOPL,UREGS_eflags(%esp)
-        orl  $X86_EFLAGS_IF|X86_EFLAGS_VM,UREGS_eflags(%esp)
-        
-        jmp test_all_events
-
-.section __ex_table,"a"
-        .long VFLT1,domain_crash_synchronous
-        .long VFLT2,domain_crash_synchronous
-        .long VFLT3,domain_crash_synchronous
-.previous
 
 .data
 
@@ -744,11 +725,12 @@
         .long do_grant_table_op     /* 20 */
         .long do_vm_assist
         .long do_update_va_mapping_otherdomain
-        .long do_switch_vm86
+        .long do_iret
         .long do_vcpu_op
         .long do_ni_hypercall       /* 25 */
         .long do_mmuext_op
-        .long do_acm_op             /* 27 */
+        .long do_acm_op
+        .long do_nmi_op
         .rept NR_hypercalls-((.-hypercall_table)/4)
         .long do_ni_hypercall
         .endr
@@ -777,11 +759,12 @@
         .byte 3 /* do_grant_table_op    */  /* 20 */
         .byte 2 /* do_vm_assist         */
         .byte 5 /* do_update_va_mapping_otherdomain */
-        .byte 0 /* do_switch_vm86       */
+        .byte 0 /* do_iret              */
         .byte 3 /* do_vcpu_op           */
         .byte 0 /* do_ni_hypercall      */  /* 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 c6f7774cae63 -r fe4d06b15a36 xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Wed Jan 11 15:51:56 2006
+++ b/xen/arch/x86/x86_32/traps.c       Wed Jan 11 15:52:12 2006
@@ -157,6 +157,49 @@
         __asm__ __volatile__ ( "hlt" );
 }
 
+asmlinkage unsigned long do_iret(void)
+{
+    struct cpu_user_regs *regs = guest_cpu_user_regs();
+
+    /* Restore EAX (clobbered by hypercall) */
+    if (copy_from_user(&regs->eax, (void __user *)regs->esp, 4))
+        domain_crash_synchronous();
+    regs->esp += 4;
+
+    /* Restore EFLAGS, CS and EIP */
+    if (copy_from_user(&regs->eip, (void __user *)regs->esp, 12))
+        domain_crash_synchronous();
+
+    if (VM86_MODE(regs)) {
+        /* return to VM86 mode: restore ESP,SS,ES,DS,FS and GS */
+        if(copy_from_user(&regs->esp, (void __user *)(regs->esp+12), 24))
+            domain_crash_synchronous();
+    } else if (RING_0(regs)) {
+        domain_crash_synchronous();
+    } else if (RING_1(regs)) {
+        /* return to ring 1: pop EFLAGS,CS and EIP */
+        regs->esp += 12;
+    } else {
+        /* return to ring 2/3: restore ESP and SS */
+        if(copy_from_user(&regs->esp, (void __user *)(regs->esp+12), 8))
+            domain_crash_synchronous();
+    }
+
+    /* Fixup EFLAGS */
+    regs->eflags &= ~X86_EFLAGS_IOPL;
+    regs->eflags |= X86_EFLAGS_IF;
+
+    /* No longer in NMI context */
+    clear_bit(_VCPUF_nmi_masked, &current->vcpu_flags);
+
+    /* Restore upcall mask from saved value */
+    current->vcpu_info->evtchn_upcall_mask = regs->saved_upcall_mask;
+
+    /* the hypercall exit path will overwrite eax
+     * with this return value */
+    return regs->eax;
+}
+
 BUILD_SMP_INTERRUPT(deferred_nmi, TRAP_deferred_nmi)
 asmlinkage void smp_deferred_nmi(struct cpu_user_regs regs)
 {
diff -r c6f7774cae63 -r fe4d06b15a36 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Wed Jan 11 15:51:56 2006
+++ b/xen/include/public/xen.h  Wed Jan 11 15:52:12 2006
@@ -53,7 +53,8 @@
 #define __HYPERVISOR_grant_table_op       20
 #define __HYPERVISOR_vm_assist            21
 #define __HYPERVISOR_update_va_mapping_otherdomain 22
-#define __HYPERVISOR_switch_vm86          23 /* x86/32 only */
+#define __HYPERVISOR_iret                 23 /* x86/32 only */
+#define __HYPERVISOR_switch_vm86          23 /* x86/32 only (obsolete name) */
 #define __HYPERVISOR_switch_to_user       23 /* x86/64 only */
 #define __HYPERVISOR_vcpu_op              24
 #define __HYPERVISOR_set_segment_base     25 /* x86/64 only */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.