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

📄 apic_64.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	unsigned int value, maxlvt;	int i, j;	value = apic_read(APIC_LVR);	BUILD_BUG_ON((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f);	/*	 * Double-check whether this APIC is really registered.	 * This is meaningless in clustered apic mode, so we skip it.	 */	if (!apic_id_registered())		BUG();	/*	 * Intel recommends to set DFR, LDR and TPR before enabling	 * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel	 * 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(APIC_TASKPRI, value);	/*	 * After a crash, we no longer service the interrupts and a pending	 * interrupt from previous kernel might still have ISR bit set.	 *	 * Most probably by now CPU has serviced that pending interrupt and	 * it might not have done the ack_APIC_irq() because it thought,	 * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it	 * does not clear the ISR bit and cpu thinks it has already serivced	 * the interrupt. Hence a vector might get locked. It was noticed	 * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.	 */	for (i = APIC_ISR_NR - 1; i >= 0; i--) {		value = apic_read(APIC_ISR + i*0x10);		for (j = 31; j >= 0; j--) {			if (value & (1<<j))				ack_APIC_irq();		}	}	/*	 * 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;	/* We always use processor focus */	/*	 * Set spurious IRQ vector	 */	value |= SPURIOUS_APIC_VECTOR;	apic_write(APIC_SPIV, value);	/*	 * Set up LVT0, LVT1:	 *	 * set up through-local-APIC on the BP's LINT0. This is not	 * strictly necessary 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() && !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(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;	apic_write(APIC_LVT1, value);	{		unsigned oldvalue;		maxlvt = get_maxlvt();		oldvalue = apic_read(APIC_ESR);		value = ERROR_APIC_VECTOR;      // enables sending errors		apic_write(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 after enabling vector: %08x, after %08x\n",			oldvalue, value);	}	nmi_watchdog_default();	setup_apic_nmi_watchdog(NULL);	apic_pm_activate();}#ifdef CONFIG_PMstatic struct {	/* 'active' is true if the local APIC was enabled by us and	   not the BIOS; this signifies that we are also responsible	   for disabling it before entering apm/acpi suspend */	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;	int maxlvt;	if (!apic_pm_state.active)		return 0;	maxlvt = get_maxlvt();	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);	if (maxlvt >= 4)		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);#ifdef CONFIG_X86_MCE_INTEL	if (maxlvt >= 5)		apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);#endif	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;	int maxlvt;	if (!apic_pm_state.active)		return 0;	maxlvt = get_maxlvt();	local_irq_save(flags);	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);#ifdef CONFIG_X86_MCE_INTEL	if (maxlvt >= 5)		apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);#endif	if (maxlvt >= 4)		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;}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 __cpuinit 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 */static int __init apic_set_verbosity(char *str){	if (str == NULL)  {		skip_ioapic_setup = 0;		ioapic_force = 1;		return 0;	}	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\n", str);		return -EINVAL;	}	return 0;}early_param("apic", apic_set_verbosity);/* * Detect and enable local APICs on non-SMP boards. * Original code written by Keir Fraser. * On AMD64 we trust the BIOS - if it says no APIC it is likely * not correctly set up (usually the APIC timer won't work etc.) */static int __init detect_init_APIC (void){	if (!cpu_has_apic) {		printk(KERN_INFO "No local APIC present\n");		return -1;	}	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;	boot_cpu_id = 0;	return 0;}#ifdef CONFIG_X86_IO_APICstatic struct resource * __init ioapic_setup_resources(void){#define IOAPIC_RESOURCE_NAME_SIZE 11	unsigned long n;	struct resource *res;	char *mem;	int i;	if (nr_ioapics <= 0)		return NULL;	n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);	n *= nr_ioapics;	mem = alloc_bootmem(n);	res = (void *)mem;	if (mem != NULL) {		memset(mem, 0, n);		mem += sizeof(struct resource) * nr_ioapics;		for (i = 0; i < nr_ioapics; i++) {			res[i].name = mem;			res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;			sprintf(mem,  "IOAPIC %u", i);			mem += IOAPIC_RESOURCE_NAME_SIZE;		}	}	ioapic_resources = res;	return res;}static int __init ioapic_insert_resources(void){	int i;	struct resource *r = ioapic_resources;	if (!r) {		printk("IO APIC resources could be not be allocated.\n");		return -1;	}	for (i = 0; i < nr_ioapics; i++) {		insert_resource(&iomem_resource, r);		r++;	}	return 0;}/* Insert the IO APIC resources after PCI initialization has occured to handle * IO APICS that are mapped in on a BAR in PCI space. */late_initcall(ioapic_insert_resources);#endifvoid __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);	apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",				APIC_BASE, apic_phys);	/* Put local APIC into the resource map. */	lapic_resource.start = apic_phys;	lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1;	insert_resource(&iomem_resource, &lapic_resource);	/*	 * Fetch the APIC ID of the BSP in case we have a	 * default configuration (or the MP table is broken).	 */	boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));	{		unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;		int i;		struct resource *ioapic_res;		ioapic_res = ioapic_setup_resources();		for (i = 0; i < nr_ioapics; i++) {			if (smp_found_config) {				ioapic_phys = mp_ioapics[i].mpc_apicaddr;			} else {				ioapic_phys = (unsigned long)					alloc_bootmem_pages(PAGE_SIZE);				ioapic_phys = __pa(ioapic_phys);			}			set_fixmap_nocache(idx, ioapic_phys);			apic_printk(APIC_VERBOSE,				    "mapped IOAPIC to %016lx (%016lx)\n",				    __fix_to_virt(idx), ioapic_phys);			idx++;			if (ioapic_res != NULL) {				ioapic_res->start = ioapic_phys;				ioapic_res->end = ioapic_phys + (4 * 1024) - 1;				ioapic_res++;			}		}	}}/* * This function sets up the local APIC timer, with a timeout of * 'clocks' APIC bus clock. During calibration we actually call * this function twice on the boot CPU, once with a bogus timeout * value, second time for real. The other (noncalibrating) CPUs * call this function only once, with the real, calibrated value. * * We do reads before writes even if unnecessary, to get around the * P5 APIC double write bug. */static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)

⌨️ 快捷键说明

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