# 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(®s->eax, (void __user *)regs->esp, 4))
+ domain_crash_synchronous();
+ regs->esp += 4;
+
+ /* Restore EFLAGS, CS and EIP */
+ if (copy_from_user(®s->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(®s->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(®s->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, ¤t->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
|