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

📄 apic.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * document number 292116).  So here it goes...	 */	init_apic_ldr();	/*	 * Set Task Priority to 'accept all'. We never change this	 * later on.	 */	value = apic_read(APIC_TASKPRI);	value &= ~APIC_TPRI_MASK;	apic_write_around(APIC_TASKPRI, value);	/*	 * Now that we are all set up, enable the APIC	 */	value = apic_read(APIC_SPIV);	value &= ~APIC_VECTOR_MASK;	/*	 * Enable APIC	 */	value |= APIC_SPIV_APIC_ENABLED;	/*	 * Some unknown Intel IO/APIC (or APIC) errata is biting us with	 * certain networking cards. If high frequency interrupts are	 * happening on a particular IOAPIC pin, plus the IOAPIC routing	 * entry is masked/unmasked at a high rate as well then sooner or	 * later IOAPIC line gets 'stuck', no more interrupts are received	 * from the device. If focus CPU is disabled then the hang goes	 * away, oh well :-(	 *	 * [ This bug can be reproduced easily with a level-triggered	 *   PCI Ne2000 networking cards and PII/PIII processors, dual	 *   BX chipset. ]	 */	/*	 * Actually disabling the focus CPU check just makes the hang less	 * frequent as it makes the interrupt distributon model be more	 * like LRU than MRU (the short-term load is more even across CPUs).	 * See also the comment in end_level_ioapic_irq().  --macro	 */#if 1	/* Enable focus processor (bit==0) */	value &= ~APIC_SPIV_FOCUS_DISABLED;#else	/* Disable focus processor (bit==1) */	value |= APIC_SPIV_FOCUS_DISABLED;#endif	/*	 * Set spurious IRQ vector	 */	value |= SPURIOUS_APIC_VECTOR;	apic_write_around(APIC_SPIV, value);	/*	 * Set up LVT0, LVT1:	 *	 * set up through-local-APIC on the BP's LINT0. This is not	 * strictly necessery in pure symmetric-IO mode, but sometimes	 * we delegate interrupts to the 8259A.	 */	/*	 * TODO: set up through-local-APIC from through-I/O-APIC? --macro	 */	value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;	if (!smp_processor_id() && (pic_mode || !value)) {		value = APIC_DM_EXTINT;		apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",				smp_processor_id());	} else {		value = APIC_DM_EXTINT | APIC_LVT_MASKED;		apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",				smp_processor_id());	}	apic_write_around(APIC_LVT0, value);	/*	 * only the BP should see the LINT1 NMI signal, obviously.	 */	if (!smp_processor_id())		value = APIC_DM_NMI;	else		value = APIC_DM_NMI | APIC_LVT_MASKED;	if (!APIC_INTEGRATED(ver))		/* 82489DX */		value |= APIC_LVT_LEVEL_TRIGGER;	apic_write_around(APIC_LVT1, value);	if (APIC_INTEGRATED(ver) && !esr_disable) {		/* !82489DX */		maxlvt = get_maxlvt();		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */			apic_write(APIC_ESR, 0);		oldvalue = apic_read(APIC_ESR);		value = ERROR_APIC_VECTOR;      // enables sending errors		apic_write_around(APIC_LVTERR, value);		/*		 * spec says clear errors after enabling vector.		 */		if (maxlvt > 3)			apic_write(APIC_ESR, 0);		value = apic_read(APIC_ESR);		if (value != oldvalue)			apic_printk(APIC_VERBOSE, "ESR value before enabling "				"vector: 0x%08lx  after: 0x%08lx\n",				oldvalue, value);	} else {		if (esr_disable)				/* 			 * Something untraceble is creating bad interrupts on 			 * secondary quads ... for the moment, just leave the			 * ESR disabled - we can't do anything useful with the			 * errors anyway - mbligh			 */			printk("Leaving ESR disabled.\n");		else 			printk("No ESR for 82489DX.\n");	}	if (nmi_watchdog == NMI_LOCAL_APIC)		setup_apic_nmi_watchdog();	apic_pm_activate();}/* * If Linux enabled the LAPIC against the BIOS default * disable it down before re-entering the BIOS on shutdown. * Otherwise the BIOS may get confused and not power-off. * Additionally clear all LVT entries before disable_local_APIC * for the case where Linux didn't enable the LAPIC. */void lapic_shutdown(void){	if (!cpu_has_apic)		return;	local_irq_disable();	clear_local_APIC();	if (enabled_via_apicbase)		disable_local_APIC();	local_irq_enable();}#ifdef CONFIG_PMstatic struct {	int active;	/* r/w apic fields */	unsigned int apic_id;	unsigned int apic_taskpri;	unsigned int apic_ldr;	unsigned int apic_dfr;	unsigned int apic_spiv;	unsigned int apic_lvtt;	unsigned int apic_lvtpc;	unsigned int apic_lvt0;	unsigned int apic_lvt1;	unsigned int apic_lvterr;	unsigned int apic_tmict;	unsigned int apic_tdcr;	unsigned int apic_thmr;} apic_pm_state;static int lapic_suspend(struct sys_device *dev, pm_message_t state){	unsigned long flags;	if (!apic_pm_state.active)		return 0;	apic_pm_state.apic_id = apic_read(APIC_ID);	apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);	apic_pm_state.apic_ldr = apic_read(APIC_LDR);	apic_pm_state.apic_dfr = apic_read(APIC_DFR);	apic_pm_state.apic_spiv = apic_read(APIC_SPIV);	apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);	apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);	apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);	apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);	apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);	apic_pm_state.apic_tmict = apic_read(APIC_TMICT);	apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);	apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);		local_irq_save(flags);	disable_local_APIC();	local_irq_restore(flags);	return 0;}static int lapic_resume(struct sys_device *dev){	unsigned int l, h;	unsigned long flags;	if (!apic_pm_state.active)		return 0;	local_irq_save(flags);	/*	 * Make sure the APICBASE points to the right address	 *	 * FIXME! This will be wrong if we ever support suspend on	 * SMP! We'll need to do this as part of the CPU restore!	 */	rdmsr(MSR_IA32_APICBASE, l, h);	l &= ~MSR_IA32_APICBASE_BASE;	l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;	wrmsr(MSR_IA32_APICBASE, l, h);	apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);	apic_write(APIC_ID, apic_pm_state.apic_id);	apic_write(APIC_DFR, apic_pm_state.apic_dfr);	apic_write(APIC_LDR, apic_pm_state.apic_ldr);	apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri);	apic_write(APIC_SPIV, apic_pm_state.apic_spiv);	apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);	apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);	apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);	apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);	apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);	apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);	apic_write(APIC_TMICT, apic_pm_state.apic_tmict);	apic_write(APIC_ESR, 0);	apic_read(APIC_ESR);	apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr);	apic_write(APIC_ESR, 0);	apic_read(APIC_ESR);	local_irq_restore(flags);	return 0;}/* * This device has no shutdown method - fully functioning local APICs * are needed on every CPU up until machine_halt/restart/poweroff. */static struct sysdev_class lapic_sysclass = {	set_kset_name("lapic"),	.resume		= lapic_resume,	.suspend	= lapic_suspend,};static struct sys_device device_lapic = {	.id	= 0,	.cls	= &lapic_sysclass,};static void __devinit apic_pm_activate(void){	apic_pm_state.active = 1;}static int __init init_lapic_sysfs(void){	int error;	if (!cpu_has_apic)		return 0;	/* XXX: remove suspend/resume procs if !apic_pm_state.active? */	error = sysdev_class_register(&lapic_sysclass);	if (!error)		error = sysdev_register(&device_lapic);	return error;}device_initcall(init_lapic_sysfs);#else	/* CONFIG_PM */static void apic_pm_activate(void) { }#endif	/* CONFIG_PM *//* * Detect and enable local APICs on non-SMP boards. * Original code written by Keir Fraser. */static int __init apic_set_verbosity(char *str){	if (strcmp("debug", str) == 0)		apic_verbosity = APIC_DEBUG;	else if (strcmp("verbose", str) == 0)		apic_verbosity = APIC_VERBOSE;	else		printk(KERN_WARNING "APIC Verbosity level %s not recognised"				" use apic=verbose or apic=debug", str);	return 0;}__setup("apic=", apic_set_verbosity);static int __init detect_init_APIC (void){	u32 h, l, features;	/* Disabled by kernel option? */	if (enable_local_apic < 0)		return -1;	switch (boot_cpu_data.x86_vendor) {	case X86_VENDOR_AMD:		if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||		    (boot_cpu_data.x86 == 15))	    			break;		goto no_apic;	case X86_VENDOR_INTEL:		if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||		    (boot_cpu_data.x86 == 5 && cpu_has_apic))			break;		goto no_apic;	default:		goto no_apic;	}	if (!cpu_has_apic) {		/*		 * Over-ride BIOS and try to enable the local		 * APIC only if "lapic" specified.		 */		if (enable_local_apic <= 0) {			printk("Local APIC disabled by BIOS -- "			       "you can enable it with \"lapic\"\n");			return -1;		}		/*		 * Some BIOSes disable the local APIC in the		 * APIC_BASE MSR. This can only be done in		 * software for Intel P6 or later and AMD K7		 * (Model > 1) or later.		 */		rdmsr(MSR_IA32_APICBASE, l, h);		if (!(l & MSR_IA32_APICBASE_ENABLE)) {			printk("Local APIC disabled by BIOS -- reenabling.\n");			l &= ~MSR_IA32_APICBASE_BASE;			l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;			wrmsr(MSR_IA32_APICBASE, l, h);			enabled_via_apicbase = 1;		}	}	/*	 * The APIC feature bit should now be enabled	 * in `cpuid'	 */	features = cpuid_edx(1);	if (!(features & (1 << X86_FEATURE_APIC))) {		printk("Could not enable APIC!\n");		return -1;	}	set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;	/* The BIOS may have set up the APIC at some other address */	rdmsr(MSR_IA32_APICBASE, l, h);	if (l & MSR_IA32_APICBASE_ENABLE)		mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;	if (nmi_watchdog != NMI_NONE)		nmi_watchdog = NMI_LOCAL_APIC;	printk("Found and enabled local APIC!\n");	apic_pm_activate();	return 0;no_apic:	printk("No local APIC present or hardware disabled\n");	return -1;}void __init init_apic_mappings(void){	unsigned long apic_phys;	/*	 * If no local APIC can be found then set up a fake all	 * zeroes page to simulate the local APIC and another	 * one for the IO-APIC.	 */	if (!smp_found_config && detect_init_APIC()) {		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);		apic_phys = __pa(apic_phys);	} else		apic_phys = mp_lapic_addr;	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);	printk(KERN_DEBUG "mapped APIC to %08lx (%08lx)\n", APIC_BASE,	       apic_phys);	/*	 * Fetch the APIC ID of the BSP in case we have a	 * default configuration (or the MP table is broken).	 */	if (boot_cpu_physical_apicid == -1U)		boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));#ifdef CONFIG_X86_IO_APIC	{		unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;		int i;		for (i = 0; i < nr_ioapics; i++) {			if (smp_found_config) {				ioapic_phys = mp_ioapics[i].mpc_apicaddr;				if (!ioapic_phys) {					printk(KERN_ERR					       "WARNING: bogus zero IO-APIC "					       "address found in MPTABLE, "					       "disabling IO/APIC support!\n");					smp_found_config = 0;					skip_ioapic_setup = 1;					goto fake_ioapic_page;				}			} else {fake_ioapic_page:				ioapic_phys = (unsigned long)					      alloc_bootmem_pages(PAGE_SIZE);				ioapic_phys = __pa(ioapic_phys);			}			set_fixmap_nocache(idx, ioapic_phys);			printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n",			       __fix_to_virt(idx), ioapic_phys);			idx++;		}	}#endif}/*

⌨️ 快捷键说明

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