[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Pass NMIs to DOM0 via a dedicated callback, Xen/Linux x86_64 support.
# HG changeset patch # User Ian.Campbell@xxxxxxxxxxxxx # Node ID 0ffd94a0231812372c0072af7caeeb3b8ff8ac0e # Parent 278e536ade72e6b31651315e12095b47f3be8676 Pass NMIs to DOM0 via a dedicated callback, Xen/Linux x86_64 support. Register our NMI handler with Xen. Do an iret via the hypervisor whenever the return CS is > RING0. Add include/asm-xen/asm-x86_64/nmi.h as a Xen modified copy of include/asm-x86_64/nmi.h in order that we can implement get_nmi_reason() in a manner suitable for Xen. Signed-off-by: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx> diff -r 278e536ade72 -r 0ffd94a02318 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S Wed Jan 11 15:52:54 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S Wed Jan 11 15:53:59 2006 @@ -121,19 +121,19 @@ .endm /* - * Must be consistent with the definition in arch_x86_64.h: - * struct switch_to_user { + * Must be consistent with the definition in arch-x86_64.h: + * struct iret_context { * u64 rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; * }; * #define VGCF_IN_SYSCALL (1<<8) */ - .macro SWITCH_TO_USER flag + .macro HYPERVISOR_IRET flag subq $8*4,%rsp # reuse rip, cs, rflags, rsp, ss in the stack movq %rax,(%rsp) movq %r11,1*8(%rsp) movq %rcx,2*8(%rsp) # we saved %rcx upon exceptions movq $\flag,3*8(%rsp) - movq $__HYPERVISOR_switch_to_user,%rax + movq $__HYPERVISOR_iret,%rax syscall .endm @@ -225,7 +225,7 @@ jnz sysret_careful XEN_UNBLOCK_EVENTS(%rsi) RESTORE_ARGS 0,8,0 - SWITCH_TO_USER VGCF_IN_SYSCALL + HYPERVISOR_IRET VGCF_IN_SYSCALL /* Handle reschedules */ /* edx: work, edi: workmask */ @@ -478,7 +478,7 @@ orb $3,1*8(%rsp) iretq user_mode: - SWITCH_TO_USER 0 + HYPERVISOR_IRET 0 /* edi: workmask, edx: work */ retint_careful: @@ -719,6 +719,16 @@ call evtchn_do_upcall jmp error_exit +ENTRY(nmi) + zeroentry do_nmi_callback +ENTRY(do_nmi_callback) + addq $8, %rsp + call do_nmi + RESTORE_REST + XEN_BLOCK_EVENTS(%rsi) + GET_THREAD_INFO(%rcx) + jmp retint_restore_args + ALIGN restore_all_enable_events: XEN_UNBLOCK_EVENTS(%rsi) # %rsi is already set up... @@ -733,7 +743,7 @@ orb $3,1*8(%rsp) iretq crit_user_mode: - SWITCH_TO_USER 0 + HYPERVISOR_IRET 0 14: XEN_LOCKED_BLOCK_EVENTS(%rsi) XEN_PUT_VCPU_INFO(%rsi) diff -r 278e536ade72 -r 0ffd94a02318 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Wed Jan 11 15:52:54 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Wed Jan 11 15:53:59 2006 @@ -62,6 +62,7 @@ #include <asm-xen/xen-public/physdev.h> #include "setup_arch_pre.h" #include <asm/hypervisor.h> +#include <asm-xen/xen-public/nmi.h> #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) #define end_pfn_map end_pfn diff -r 278e536ade72 -r 0ffd94a02318 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c Wed Jan 11 15:52:54 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c Wed Jan 11 15:53:59 2006 @@ -559,9 +559,11 @@ printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); printk("You probably have a hardware problem with your RAM chips\n"); +#if 0 /* XEN */ /* Clear and disable the memory parity error line. */ reason = (reason & 0xf) | 4; outb(reason, 0x61); +#endif /* XEN */ } static void io_check_error(unsigned char reason, struct pt_regs * regs) @@ -569,12 +571,14 @@ printk("NMI: IOCK error (debug interrupt?)\n"); show_registers(regs); +#if 0 /* XEN */ /* Re-enable the IOCK line, wait for a few seconds */ reason = (reason & 0xf) | 8; outb(reason, 0x61); mdelay(2000); reason &= ~8; outb(reason, 0x61); +#endif /* XEN */ } static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) diff -r 278e536ade72 -r 0ffd94a02318 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Wed Jan 11 15:52:54 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Wed Jan 11 15:53:59 2006 @@ -287,9 +287,9 @@ } static inline int -HYPERVISOR_switch_to_user(void) -{ - return _hypercall0(int, switch_to_user); +HYPERVISOR_iret(void) +{ + return _hypercall0(int, iret); } static inline int @@ -305,6 +305,14 @@ { return _hypercall3(int, sched_op, SCHEDOP_shutdown, 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 -r 278e536ade72 -r 0ffd94a02318 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h Wed Jan 11 15:52:54 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h Wed Jan 11 15:53:59 2006 @@ -35,6 +35,7 @@ extern void hypervisor_callback(void); extern void failsafe_callback(void); +extern void nmi(void); static void __init machine_specific_arch_setup(void) { @@ -43,5 +44,7 @@ (unsigned long) failsafe_callback, (unsigned long) system_call); + HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi); + machine_specific_modify_cpu_capabilities(&boot_cpu_data); } diff -r 278e536ade72 -r 0ffd94a02318 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/nmi.h --- /dev/null Wed Jan 11 15:52:54 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/nmi.h Wed Jan 11 15:53:59 2006 @@ -0,0 +1,75 @@ +/* + * linux/include/asm-i386/nmi.h + */ +#ifndef ASM_NMI_H +#define ASM_NMI_H + +#include <linux/pm.h> + +#include <asm-xen/xen-public/nmi.h> + +struct pt_regs; + +typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu); + +/** + * set_nmi_callback + * + * Set a handler for an NMI. Only one handler may be + * set. Return 1 if the NMI was handled. + */ +void set_nmi_callback(nmi_callback_t callback); + +/** + * unset_nmi_callback + * + * Remove the handler previously set. + */ +void unset_nmi_callback(void); + +#ifdef CONFIG_PM + +/** Replace the PM callback routine for NMI. */ +struct pm_dev * set_nmi_pm_callback(pm_callback callback); + +/** Unset the PM callback routine back to the default. */ +void unset_nmi_pm_callback(struct pm_dev * dev); + +#else + +static inline struct pm_dev * set_nmi_pm_callback(pm_callback callback) +{ + return 0; +} + +static inline void unset_nmi_pm_callback(struct pm_dev * dev) +{ +} + +#endif /* CONFIG_PM */ + +extern void default_do_nmi(struct pt_regs *); +extern void die_nmi(char *str, struct pt_regs *regs); + +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; +} + +extern int panic_on_timeout; +extern int unknown_nmi_panic; + +extern int check_nmi_watchdog(void); + +#endif /* ASM_NMI_H */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |