⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nmi.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
{	if (nmi_pm_active > 0)		enable_lapic_nmi_watchdog();	return 0;}static struct sysdev_class nmi_sysclass = {	set_kset_name("lapic_nmi"),	.resume		= lapic_nmi_resume,	.suspend	= lapic_nmi_suspend,};static struct sys_device device_lapic_nmi = {	.id	= 0,	.cls	= &nmi_sysclass,};static int __init init_lapic_nmi_sysfs(void){	int error;	if (nmi_active == 0 || nmi_watchdog != NMI_LOCAL_APIC)		return 0;	error = sysdev_class_register(&nmi_sysclass);	if (!error)		error = sysdev_register(&device_lapic_nmi);	return error;}/* must come after the local APIC's device_initcall() */late_initcall(init_lapic_nmi_sysfs);#endif	/* CONFIG_PM *//* * Activate the NMI watchdog via the local APIC. * Original code written by Keith Owens. */static void clear_msr_range(unsigned int base, unsigned int n){	unsigned int i;	for(i = 0; i < n; ++i)		wrmsr(base+i, 0, 0);}static inline void write_watchdog_counter(const char *descr){	u64 count = (u64)cpu_khz * 1000;	do_div(count, nmi_hz);	if(descr)		Dprintk("setting %s to -0x%08Lx\n", descr, count);	wrmsrl(nmi_perfctr_msr, 0 - count);}static void setup_k7_watchdog(void){	unsigned int evntsel;	nmi_perfctr_msr = MSR_K7_PERFCTR0;	clear_msr_range(MSR_K7_EVNTSEL0, 4);	clear_msr_range(MSR_K7_PERFCTR0, 4);	evntsel = K7_EVNTSEL_INT		| K7_EVNTSEL_OS		| K7_EVNTSEL_USR		| K7_NMI_EVENT;	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);	write_watchdog_counter("K7_PERFCTR0");	apic_write(APIC_LVTPC, APIC_DM_NMI);	evntsel |= K7_EVNTSEL_ENABLE;	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);}static void setup_p6_watchdog(void){	unsigned int evntsel;	nmi_perfctr_msr = MSR_P6_PERFCTR0;	clear_msr_range(MSR_P6_EVNTSEL0, 2);	clear_msr_range(MSR_P6_PERFCTR0, 2);	evntsel = P6_EVNTSEL_INT		| P6_EVNTSEL_OS		| P6_EVNTSEL_USR		| P6_NMI_EVENT;	wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);	write_watchdog_counter("P6_PERFCTR0");	apic_write(APIC_LVTPC, APIC_DM_NMI);	evntsel |= P6_EVNTSEL0_ENABLE;	wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);}static int setup_p4_watchdog(void){	unsigned int misc_enable, dummy;	rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);	if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))		return 0;	nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;	nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;#ifdef CONFIG_SMP	if (smp_num_siblings == 2)		nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;#endif	if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))		clear_msr_range(0x3F1, 2);	/* MSR 0x3F0 seems to have a default value of 0xFC00, but current	   docs doesn't fully define it, so leave it alone for now. */	if (boot_cpu_data.x86_model >= 0x3) {		/* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */		clear_msr_range(0x3A0, 26);		clear_msr_range(0x3BC, 3);	} else {		clear_msr_range(0x3A0, 31);	}	clear_msr_range(0x3C0, 6);	clear_msr_range(0x3C8, 6);	clear_msr_range(0x3E0, 2);	clear_msr_range(MSR_P4_CCCR0, 18);	clear_msr_range(MSR_P4_PERFCTR0, 18);	wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);	wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);	write_watchdog_counter("P4_IQ_COUNTER0");	apic_write(APIC_LVTPC, APIC_DM_NMI);	wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);	return 1;}void setup_apic_nmi_watchdog (void){	switch (boot_cpu_data.x86_vendor) {	case X86_VENDOR_AMD:		if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15)			return;		setup_k7_watchdog();		break;	case X86_VENDOR_INTEL:		switch (boot_cpu_data.x86) {		case 6:			if (boot_cpu_data.x86_model > 0xd)				return;			setup_p6_watchdog();			break;		case 15:			if (boot_cpu_data.x86_model > 0x4)				return;			if (!setup_p4_watchdog())				return;			break;		default:			return;		}		break;	default:		return;	}	lapic_nmi_owner = LAPIC_NMI_WATCHDOG;	nmi_active = 1;}/* * the best way to detect whether a CPU has a 'hard lockup' problem * is to check it's local APIC timer IRQ counts. If they are not * changing then that CPU has some problem. * * as these watchdog NMI IRQs are generated on every CPU, we only * have to check the current processor. * * since NMIs don't listen to _any_ locks, we have to be extremely * careful not to rely on unsafe variables. The printk might lock * up though, so we have to break up any console locks first ... * [when there will be more tty-related locks, break them up *  here too!] */static unsigned int	last_irq_sums [NR_CPUS],	alert_counter [NR_CPUS];void touch_nmi_watchdog (void){	int i;	/*	 * Just reset the alert counters, (other CPUs might be	 * spinning on locks we hold):	 */	for (i = 0; i < NR_CPUS; i++)		alert_counter[i] = 0;	/*	 * Tickle the softlockup detector too:	 */	touch_softlockup_watchdog();}extern void die_nmi(struct pt_regs *, const char *msg);void nmi_watchdog_tick (struct pt_regs * regs){	/*	 * Since current_thread_info()-> is always on the stack, and we	 * always switch the stack NMI-atomically, it's safe to use	 * smp_processor_id().	 */	int sum, cpu = smp_processor_id();	sum = per_cpu(irq_stat, cpu).apic_timer_irqs;	if (last_irq_sums[cpu] == sum) {		/*		 * Ayiee, looks like this CPU is stuck ...		 * wait a few IRQs (5 seconds) before doing the oops ...		 */		alert_counter[cpu]++;		if (alert_counter[cpu] == 5*nmi_hz)			/*			 * die_nmi will return ONLY if NOTIFY_STOP happens..			 */			die_nmi(regs, "NMI Watchdog detected LOCKUP");		last_irq_sums[cpu] = sum;		alert_counter[cpu] = 0;	}	if (nmi_perfctr_msr) {		if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {			/*			 * P4 quirks:			 * - An overflown perfctr will assert its interrupt			 *   until the OVF flag in its CCCR is cleared.			 * - LVTPC is masked on interrupt and must be			 *   unmasked by the LVTPC handler.			 */			wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);			apic_write(APIC_LVTPC, APIC_DM_NMI);		}		else if (nmi_perfctr_msr == MSR_P6_PERFCTR0) {			/* Only P6 based Pentium M need to re-unmask			 * the apic vector but it doesn't hurt			 * other P6 variant */			apic_write(APIC_LVTPC, APIC_DM_NMI);		}		write_watchdog_counter(NULL);	}}#ifdef CONFIG_SYSCTLstatic int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu){	unsigned char reason = get_nmi_reason();	char buf[64];	if (!(reason & 0xc0)) {		sprintf(buf, "NMI received for unknown reason %02x\n", reason);		die_nmi(regs, buf);	}	return 0;}/* * proc handler for /proc/sys/kernel/unknown_nmi_panic */int proc_unknown_nmi_panic(ctl_table *table, int write, struct file *file,			void __user *buffer, size_t *length, loff_t *ppos){	int old_state;	old_state = unknown_nmi_panic;	proc_dointvec(table, write, file, buffer, length, ppos);	if (!!old_state == !!unknown_nmi_panic)		return 0;	if (unknown_nmi_panic) {		if (reserve_lapic_nmi() < 0) {			unknown_nmi_panic = 0;			return -EBUSY;		} else {			set_nmi_callback(unknown_nmi_panic_callback);		}	} else {		release_lapic_nmi();		unset_nmi_callback();	}	return 0;}#endifEXPORT_SYMBOL(nmi_active);EXPORT_SYMBOL(nmi_watchdog);EXPORT_SYMBOL(reserve_lapic_nmi);EXPORT_SYMBOL(release_lapic_nmi);EXPORT_SYMBOL(disable_timer_nmi_watchdog);EXPORT_SYMBOL(enable_timer_nmi_watchdog);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -