[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Allow unknown NMIs to be propagated to domain0 via new
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 931acb64fbaf762fd47f9035b411ae6f1b5cb50b # Parent b34f4169b12ea40e4f60f1cb805d6bcadb0d08fc Allow unknown NMIs to be propagated to domain0 via new VIRQ_NMI. Also simplify x86_32 NMI handling -- there's no need to greedily consume IO/parity errors in assembly code as they can be deferred without causing an interrupt storm (the NMI pin is always edge-triggered even though the sources are level-asserted). Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Tue Dec 20 11:55:19 2005 +++ b/xen/arch/x86/traps.c Tue Dec 20 16:55:20 2005 @@ -1074,29 +1074,35 @@ return 0; } -unsigned long nmi_softirq_reason; -static void nmi_softirq(void) + +/* Defer dom0 notification to softirq context (unsafe in NMI context). */ +static unsigned long nmi_dom0_softirq_reason; +#define NMI_DOM0_PARITY_ERR 0 +#define NMI_DOM0_IO_ERR 1 +#define NMI_DOM0_UNKNOWN 2 + +static void nmi_dom0_softirq(void) { if ( dom0 == NULL ) return; - if ( test_and_clear_bit(0, &nmi_softirq_reason) ) + if ( test_and_clear_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason) ) send_guest_virq(dom0->vcpu[0], VIRQ_PARITY_ERR); - if ( test_and_clear_bit(1, &nmi_softirq_reason) ) + if ( test_and_clear_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason) ) send_guest_virq(dom0->vcpu[0], VIRQ_IO_ERR); + + if ( test_and_clear_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason) ) + send_guest_virq(dom0->vcpu[0], VIRQ_NMI); } asmlinkage void mem_parity_error(struct cpu_user_regs *regs) { - /* Clear and disable the parity-error line. */ - outb((inb(0x61)&15)|4,0x61); - switch ( opt_nmi[0] ) { case 'd': /* 'dom0' */ - set_bit(0, &nmi_softirq_reason); - raise_softirq(NMI_SOFTIRQ); + set_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason); + raise_softirq(NMI_DOM0_SOFTIRQ); case 'i': /* 'ignore' */ break; default: /* 'fatal' */ @@ -1104,18 +1110,19 @@ printk("\n\nNMI - MEMORY ERROR\n"); fatal_trap(TRAP_nmi, regs); } + + outb((inb(0x61) & 0x0f) | 0x04, 0x61); /* clear-and-disable parity check */ + mdelay(1); + outb((inb(0x61) & 0x0b) | 0x00, 0x61); /* enable parity check */ } asmlinkage void io_check_error(struct cpu_user_regs *regs) { - /* Clear and disable the I/O-error line. */ - outb((inb(0x61)&15)|8,0x61); - switch ( opt_nmi[0] ) { case 'd': /* 'dom0' */ - set_bit(0, &nmi_softirq_reason); - raise_softirq(NMI_SOFTIRQ); + set_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason); + raise_softirq(NMI_DOM0_SOFTIRQ); case 'i': /* 'ignore' */ break; default: /* 'fatal' */ @@ -1123,43 +1130,59 @@ printk("\n\nNMI - I/O ERROR\n"); fatal_trap(TRAP_nmi, regs); } + + outb((inb(0x61) & 0x0f) | 0x08, 0x61); /* clear-and-disable IOCK */ + mdelay(1); + outb((inb(0x61) & 0x07) | 0x00, 0x61); /* enable IOCK */ } static void unknown_nmi_error(unsigned char reason) { - printk("Uhhuh. NMI received for unknown reason %02x.\n", reason); - printk("Dazed and confused, but trying to continue\n"); - printk("Do you have a strange power saving mode enabled?\n"); -} - -static void default_do_nmi(struct cpu_user_regs *regs, unsigned long reason) -{ - if ( nmi_watchdog ) - nmi_watchdog_tick(regs); - - if ( reason & 0x80 ) - mem_parity_error(regs); - else if ( reason & 0x40 ) - io_check_error(regs); - else if ( !nmi_watchdog ) - unknown_nmi_error((unsigned char)(reason&0xff)); + switch ( opt_nmi[0] ) + { + case 'd': /* 'dom0' */ + set_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason); + raise_softirq(NMI_DOM0_SOFTIRQ); + case 'i': /* 'ignore' */ + break; + default: /* 'fatal' */ + printk("Uhhuh. NMI received for unknown reason %02x.\n", reason); + printk("Dazed and confused, but trying to continue\n"); + printk("Do you have a strange power saving mode enabled?\n"); + } } static int dummy_nmi_callback(struct cpu_user_regs *regs, int cpu) { - return 0; + return 0; } static nmi_callback_t nmi_callback = dummy_nmi_callback; -asmlinkage void do_nmi(struct cpu_user_regs *regs, unsigned long reason) +asmlinkage void do_nmi(struct cpu_user_regs *regs) { unsigned int cpu = smp_processor_id(); + unsigned char reason; ++nmi_count(cpu); - if ( !nmi_callback(regs, cpu) ) - default_do_nmi(regs, reason); + if ( nmi_callback(regs, cpu) ) + return; + + if ( nmi_watchdog ) + nmi_watchdog_tick(regs); + + /* Only the BSP gets external NMIs from the system. */ + if ( cpu == 0 ) + { + reason = inb(0x61); + if ( reason & 0x80 ) + mem_parity_error(regs); + else if ( reason & 0x40 ) + io_check_error(regs); + else if ( !nmi_watchdog ) + unknown_nmi_error((unsigned char)(reason&0xff)); + } } void set_nmi_callback(nmi_callback_t callback) @@ -1169,7 +1192,7 @@ void unset_nmi_callback(void) { - nmi_callback = dummy_nmi_callback; + nmi_callback = dummy_nmi_callback; } asmlinkage int math_state_restore(struct cpu_user_regs *regs) @@ -1318,7 +1341,7 @@ cpu_init(); - open_softirq(NMI_SOFTIRQ, nmi_softirq); + open_softirq(NMI_DOM0_SOFTIRQ, nmi_dom0_softirq); } diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/vmx.c --- a/xen/arch/x86/vmx.c Tue Dec 20 11:55:19 2005 +++ b/xen/arch/x86/vmx.c Tue Dec 20 16:55:20 2005 @@ -335,7 +335,7 @@ extern long evtchn_send(int lport); extern long do_block(void); -void do_nmi(struct cpu_user_regs *, unsigned long); +void do_nmi(struct cpu_user_regs *); static int check_vmx_controls(ctrls, msr) { @@ -1850,7 +1850,7 @@ break; } case TRAP_nmi: - do_nmi(®s, 0); + do_nmi(®s); break; default: vmx_reflect_exception(v); diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Tue Dec 20 11:55:19 2005 +++ b/xen/arch/x86/x86_32/entry.S Tue Dec 20 16:55:20 2005 @@ -601,15 +601,7 @@ pushl %eax SAVE_ALL_NOSEGREGS(a) - # Check for hardware problems. - inb $0x61,%al - testb $0x80,%al - jne nmi_parity_err - testb $0x40,%al - jne nmi_io_err - movl %eax,%ebx - - # Okay, its almost a normal NMI tick. We can only process it if: + # We can only process the NMI if: # A. We are the outermost Xen activation (in which case we have # the selectors safely saved on our stack) # B. DS and ES contain sane Xen values. @@ -619,7 +611,7 @@ movl UREGS_eflags(%esp),%eax movb UREGS_cs(%esp),%al testl $(3|X86_EFLAGS_VM),%eax - jnz do_watchdog_tick + jnz continue_nmi movl %ds,%eax cmpw $(__HYPERVISOR_DS),%ax jne defer_nmi @@ -627,15 +619,14 @@ cmpw $(__HYPERVISOR_DS),%ax jne defer_nmi -do_watchdog_tick: +continue_nmi: movl $(__HYPERVISOR_DS),%edx movl %edx,%ds movl %edx,%es movl %esp,%edx - pushl %ebx # reason - pushl %edx # regs + pushl %edx call do_nmi - addl $8,%esp + addl $4,%esp jmp ret_from_intr defer_nmi: @@ -648,55 +639,6 @@ movl $(APIC_DM_FIXED | APIC_DEST_SELF | APIC_DEST_LOGICAL | \ TRAP_deferred_nmi),%ss:APIC_ICR(%eax) jmp restore_all_xen - -nmi_parity_err: - # Clear and disable the parity-error line - andb $0xf,%al - orb $0x4,%al - outb %al,$0x61 - cmpb $'i',%ss:opt_nmi # nmi=ignore - je nmi_out - bts $0,%ss:nmi_softirq_reason - bts $NMI_SOFTIRQ,%ss:irq_stat - cmpb $'d',%ss:opt_nmi # nmi=dom0 - je nmi_out - movl $(__HYPERVISOR_DS),%edx # nmi=fatal - movl %edx,%ds - movl %edx,%es - movl %esp,%edx - push %edx - call mem_parity_error - addl $4,%esp -nmi_out:movl %ss:UREGS_eflags(%esp),%eax - movb %ss:UREGS_cs(%esp),%al - testl $(3|X86_EFLAGS_VM),%eax - jz restore_all_xen - movl $(__HYPERVISOR_DS),%edx - movl %edx,%ds - movl %edx,%es - GET_CURRENT(%ebx) - jmp test_all_events - -nmi_io_err: - # Clear and disable the I/O-error line - andb $0xf,%al - orb $0x8,%al - outb %al,$0x61 - cmpb $'i',%ss:opt_nmi # nmi=ignore - je nmi_out - bts $1,%ss:nmi_softirq_reason - bts $NMI_SOFTIRQ,%ss:irq_stat - cmpb $'d',%ss:opt_nmi # nmi=dom0 - je nmi_out - movl $(__HYPERVISOR_DS),%edx # nmi=fatal - movl %edx,%ds - movl %edx,%es - movl %esp,%edx - push %edx - call io_check_error - addl $4,%esp - jmp nmi_out - ENTRY(setup_vm86_frame) # Copies the entire stack frame forwards by 16 bytes. diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/x86_32/traps.c --- a/xen/arch/x86/x86_32/traps.c Tue Dec 20 11:55:19 2005 +++ b/xen/arch/x86/x86_32/traps.c Tue Dec 20 16:55:20 2005 @@ -160,9 +160,9 @@ BUILD_SMP_INTERRUPT(deferred_nmi, TRAP_deferred_nmi) asmlinkage void smp_deferred_nmi(struct cpu_user_regs regs) { - asmlinkage void do_nmi(struct cpu_user_regs *, unsigned long); + asmlinkage void do_nmi(struct cpu_user_regs *); ack_APIC_irq(); - do_nmi(®s, 0); + do_nmi(®s); } void __init percpu_traps_init(void) diff -r b34f4169b12e -r 931acb64fbaf xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Tue Dec 20 11:55:19 2005 +++ b/xen/arch/x86/x86_64/entry.S Tue Dec 20 16:55:20 2005 @@ -567,9 +567,7 @@ ENTRY(nmi) pushq $0 SAVE_ALL - inb $0x61,%al - movl %eax,%esi # reason - movq %rsp,%rdi # regs + movq %rsp,%rdi call do_nmi jmp restore_all_xen diff -r b34f4169b12e -r 931acb64fbaf xen/include/public/xen.h --- a/xen/include/public/xen.h Tue Dec 20 11:55:19 2005 +++ b/xen/include/public/xen.h Tue Dec 20 16:55:20 2005 @@ -67,12 +67,13 @@ */ #define VIRQ_TIMER 0 /* Timebase update, and/or requested timeout. */ #define VIRQ_DEBUG 1 /* Request guest to dump debug info. */ -#define VIRQ_CONSOLE 2 /* (DOM0) bytes received on emergency console. */ +#define VIRQ_CONSOLE 2 /* (DOM0) Bytes received on emergency console. */ #define VIRQ_DOM_EXC 3 /* (DOM0) Exceptional event for some domain. */ -#define VIRQ_PARITY_ERR 4 /* (DOM0) NMI parity error. */ -#define VIRQ_IO_ERR 5 /* (DOM0) NMI I/O error. */ +#define VIRQ_PARITY_ERR 4 /* (DOM0) NMI parity error (port 0x61, bit 7). */ +#define VIRQ_IO_ERR 5 /* (DOM0) NMI I/O error (port 0x61, bit 6). */ #define VIRQ_DEBUGGER 6 /* (DOM0) A domain has paused for debugging. */ -#define NR_VIRQS 7 +#define VIRQ_NMI 7 /* (DOM0) Unknown NMI (not from ISA port 0x61).*/ +#define NR_VIRQS 8 /* * MMU-UPDATE REQUESTS diff -r b34f4169b12e -r 931acb64fbaf xen/include/xen/softirq.h --- a/xen/include/xen/softirq.h Tue Dec 20 11:55:19 2005 +++ b/xen/include/xen/softirq.h Tue Dec 20 16:55:20 2005 @@ -6,7 +6,7 @@ #define SCHEDULE_SOFTIRQ 1 #define NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ 2 #define KEYPRESS_SOFTIRQ 3 -#define NMI_SOFTIRQ 4 +#define NMI_DOM0_SOFTIRQ 4 #define PAGE_SCRUB_SOFTIRQ 5 #define DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ 6 #define NR_SOFTIRQS 7 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |