From: Ian.Campbell@xensource.com Date: Wed, 11 Jan 2006 15:52:54 +0000 (+0000) Subject: Pass NMIs to DOM0 via a dedicated callback, Xen/Linux i386 support. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16541^2~61^2~10 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=716d68d4c2979938d4d4c36b0fe3fa34cc676621;p=xen.git Pass NMIs to DOM0 via a dedicated callback, Xen/Linux i386 support. Register our NMI handler with Xen. Use a pseudo-flag in EFLAGS in indicate that we should return from the NMI via a hypervisor iret. Signed-off-by: Ian Campbell --- diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S index 6522f7a249..9c50c32426 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S @@ -76,7 +76,9 @@ IF_MASK = 0x00000200 DF_MASK = 0x00000400 NT_MASK = 0x00004000 VM_MASK = 0x00020000 - +/* pseudo-eflags */ +NMI_MASK = 0x80000000 + /* Offsets into shared_info_t. */ #define evtchn_upcall_pending /* 0 */ #define evtchn_upcall_mask 1 @@ -305,8 +307,8 @@ restore_all: je ldt_ss # returning to user-space with LDT SS #endif /* XEN */ restore_nocheck: - testl $VM_MASK, EFLAGS(%esp) - jnz resume_vm86 + testl $(VM_MASK|NMI_MASK), EFLAGS(%esp) + jnz hypervisor_iret movb EVENT_MASK(%esp), %al notb %al # %al == ~saved_mask XEN_GET_VCPU_INFO(%esi) @@ -328,11 +330,11 @@ iret_exc: .long 1b,iret_exc .previous -resume_vm86: - XEN_UNBLOCK_EVENTS(%esi) +hypervisor_iret: + andl $~NMI_MASK, EFLAGS(%esp) RESTORE_REGS movl %eax,(%esp) - movl $__HYPERVISOR_switch_vm86,%eax + movl $__HYPERVISOR_iret,%eax int $0x82 ud2 @@ -691,6 +693,15 @@ debug_stack_correct: call do_debug jmp ret_from_exception +ENTRY(nmi) + pushl %eax + SAVE_ALL + xorl %edx,%edx # zero error code + movl %esp,%eax # pt_regs pointer + call do_nmi + orl $NMI_MASK, EFLAGS(%esp) + jmp restore_all + #if 0 /* XEN */ /* * NMI is doubly nasty. It can happen _while_ we're handling diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h index 6fc4203116..04edbd3741 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h @@ -32,6 +32,7 @@ #include #include +#include #define _hypercall0(type, name) \ ({ \ @@ -300,6 +301,14 @@ HYPERVISOR_suspend( SHUTDOWN_suspend, srec); } +static inline int +HYPERVISOR_nmi_op( + unsigned long op, + unsigned long arg) +{ + return _hypercall2(int, nmi_op, op, arg); +} + #endif /* __HYPERCALL_H__ */ /* diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/mach_traps.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/mach_traps.h new file mode 100644 index 0000000000..14c607962b --- /dev/null +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/mach_traps.h @@ -0,0 +1,33 @@ +/* + * include/asm-xen/asm-i386/mach-xen/mach_traps.h + * + * Machine specific NMI handling for Xen + */ +#ifndef _MACH_TRAPS_H +#define _MACH_TRAPS_H + +#include +#include + +static inline void clear_mem_error(unsigned char reason) {} +static inline void clear_io_check_error(unsigned char reason) {} + +static inline unsigned char get_nmi_reason(void) +{ + shared_info_t *s = HYPERVISOR_shared_info; + unsigned char reason = 0; + + /* construct a value which looks like it came from + * port 0x61. + */ + if (test_bit(_XEN_NMIREASON_io_error, &s->arch.nmi_reason)) + reason |= 0x40; + if (test_bit(_XEN_NMIREASON_parity_error, &s->arch.nmi_reason)) + reason |= 0x80; + + return reason; +} + +static inline void reassert_nmi(void) {} + +#endif /* !_MACH_TRAPS_H */ diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h index b30853d2cf..fa7d6191b1 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h @@ -29,6 +29,7 @@ void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) extern void hypervisor_callback(void); extern void failsafe_callback(void); +extern void nmi(void); static void __init machine_specific_arch_setup(void) { @@ -36,5 +37,7 @@ static void __init machine_specific_arch_setup(void) __KERNEL_CS, (unsigned long)hypervisor_callback, __KERNEL_CS, (unsigned long)failsafe_callback); + HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi); + machine_specific_modify_cpu_capabilities(&boot_cpu_data); }