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

📄 io_apic.c

📁 自己根据lkd和情境分析
💻 C
📖 第 1 页 / 共 3 页
字号:
	int apic, idx, pin;	for (apic = 0; apic < nr_ioapics; apic++) {		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {			idx = find_irq_entry(apic,pin,mp_INT);			if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))				return irq_trigger(idx);		}	}	/*	 * nonexistent IRQs are edge default	 */	return 0;}int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 };static int __init assign_irq_vector(int irq){	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;	if (IO_APIC_VECTOR(irq) > 0)		return IO_APIC_VECTOR(irq);next:	current_vector += 8;	if (current_vector == SYSCALL_VECTOR)		goto next;	if (current_vector > FIRST_SYSTEM_VECTOR) {		offset++;		current_vector = FIRST_DEVICE_VECTOR + offset;	}	if (current_vector == FIRST_SYSTEM_VECTOR)		panic("ran out of interrupt sources!");	IO_APIC_VECTOR(irq) = current_vector;	return current_vector;}extern void (*interrupt[NR_IRQS])(void);static struct hw_interrupt_type ioapic_level_irq_type;static struct hw_interrupt_type ioapic_edge_irq_type;void __init setup_IO_APIC_irqs(void){	struct IO_APIC_route_entry entry;	int apic, pin, idx, irq, first_notcon = 1, vector;	unsigned long flags;	printk(KERN_DEBUG "init IO_APIC IRQs\n");	for (apic = 0; apic < nr_ioapics; apic++) {	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {		/*		 * add it to the IO-APIC irq-routing table:		 */		memset(&entry,0,sizeof(entry));		entry.delivery_mode = dest_LowestPrio;		entry.dest_mode = INT_DELIVERY_MODE;		entry.mask = 0;				/* enable IRQ */		entry.dest.logical.logical_dest = TARGET_CPUS;		idx = find_irq_entry(apic,pin,mp_INT);		if (idx == -1) {			if (first_notcon) {				printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);				first_notcon = 0;			} else				printk(", %d-%d", mp_ioapics[apic].mpc_apicid, pin);			continue;		}		entry.trigger = irq_trigger(idx);		entry.polarity = irq_polarity(idx);		if (irq_trigger(idx)) {			entry.trigger = 1;			entry.mask = 1;			entry.dest.logical.logical_dest = TARGET_CPUS;		}		irq = pin_2_irq(idx, apic, pin);		add_pin_to_irq(irq, apic, pin);		if (!apic && !IO_APIC_IRQ(irq))			continue;		if (IO_APIC_IRQ(irq)) {			vector = assign_irq_vector(irq);			entry.vector = vector;			if (IO_APIC_irq_trigger(irq))				irq_desc[irq].handler = &ioapic_level_irq_type;			else				irq_desc[irq].handler = &ioapic_edge_irq_type;			set_intr_gate(vector, interrupt[irq]);					if (!apic && (irq < 16))				disable_8259A_irq(irq);		}		spin_lock_irqsave(&ioapic_lock, flags);		io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));		io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));		spin_unlock_irqrestore(&ioapic_lock, flags);	}	}	if (!first_notcon)		printk(" not connected.\n");}/* * Set up the 8259A-master output pin as broadcast to all * CPUs. */void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector){	struct IO_APIC_route_entry entry;	unsigned long flags;	memset(&entry,0,sizeof(entry));	disable_8259A_irq(0);	/* mask LVT0 */	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);	/*	 * We use logical delivery to get the timer IRQ	 * to the first CPU.	 */	entry.dest_mode = INT_DELIVERY_MODE;	entry.mask = 0;					/* unmask IRQ now */	entry.dest.logical.logical_dest = TARGET_CPUS;	entry.delivery_mode = dest_LowestPrio;	entry.polarity = 0;	entry.trigger = 0;	entry.vector = vector;	/*	 * The timer IRQ doesnt have to know that behind the	 * scene we have a 8259A-master in AEOI mode ...	 */	irq_desc[0].handler = &ioapic_edge_irq_type;	/*	 * Add it to the IO-APIC irq-routing table:	 */	spin_lock_irqsave(&ioapic_lock, flags);	io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));	io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));	spin_unlock_irqrestore(&ioapic_lock, flags);	enable_8259A_irq(0);}void __init UNEXPECTED_IO_APIC(void){	printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n");	printk(KERN_WARNING "          to linux-smp@vger.kernel.org\n");}void __init print_IO_APIC(void){	int apic, i;	struct IO_APIC_reg_00 reg_00;	struct IO_APIC_reg_01 reg_01;	struct IO_APIC_reg_02 reg_02;	unsigned long flags; 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);	for (i = 0; i < nr_ioapics; i++)		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",		       mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);	/*	 * We are a bit conservative about what we expect.  We have to	 * know about every hardware change ASAP.	 */	printk(KERN_INFO "testing the IO APIC.......................\n");	for (apic = 0; apic < nr_ioapics; apic++) {	spin_lock_irqsave(&ioapic_lock, flags);	*(int *)&reg_00 = io_apic_read(apic, 0);	*(int *)&reg_01 = io_apic_read(apic, 1);	if (reg_01.version >= 0x10)		*(int *)&reg_02 = io_apic_read(apic, 2);	spin_unlock_irqrestore(&ioapic_lock, flags);	printk("\n");	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);	printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)&reg_00);	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.ID);	if (reg_00.__reserved_1 || reg_00.__reserved_2)		UNEXPECTED_IO_APIC();	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.entries);	if (	(reg_01.entries != 0x0f) && /* older (Neptune) boards */		(reg_01.entries != 0x17) && /* typical ISA+PCI boards */		(reg_01.entries != 0x1b) && /* Compaq Proliant boards */		(reg_01.entries != 0x1f) && /* dual Xeon boards */		(reg_01.entries != 0x22) && /* bigger Xeon boards */		(reg_01.entries != 0x2E) &&		(reg_01.entries != 0x3F)	)		UNEXPECTED_IO_APIC();	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.PRQ);	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.version);	if (	(reg_01.version != 0x01) && /* 82489DX IO-APICs */		(reg_01.version != 0x10) && /* oldest IO-APICs */		(reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */		(reg_01.version != 0x13) && /* Xeon IO-APICs */		(reg_01.version != 0x20)    /* Intel P64H (82806 AA) */	)		UNEXPECTED_IO_APIC();	if (reg_01.__reserved_1 || reg_01.__reserved_2)		UNEXPECTED_IO_APIC();	if (reg_01.version >= 0x10) {		printk(KERN_DEBUG ".... register #02: %08X\n", *(int *)&reg_02);		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.arbitration);		if (reg_02.__reserved_1 || reg_02.__reserved_2)			UNEXPECTED_IO_APIC();	}	printk(KERN_DEBUG ".... IRQ redirection table:\n");	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"			  " Stat Dest Deli Vect:   \n");	for (i = 0; i <= reg_01.entries; i++) {		struct IO_APIC_route_entry entry;		spin_lock_irqsave(&ioapic_lock, flags);		*(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);		*(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);		spin_unlock_irqrestore(&ioapic_lock, flags);		printk(KERN_DEBUG " %02x %03X %02X  ",			i,			entry.dest.logical.logical_dest,			entry.dest.physical.physical_dest		);		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",			entry.mask,			entry.trigger,			entry.irr,			entry.polarity,			entry.delivery_status,			entry.dest_mode,			entry.delivery_mode,			entry.vector		);	}	}	printk(KERN_DEBUG "IRQ to pin mappings:\n");	for (i = 0; i < NR_IRQS; i++) {		struct irq_pin_list *entry = irq_2_pin + i;		if (entry->pin < 0)			continue;		printk(KERN_DEBUG "IRQ%d ", i);		for (;;) {			printk("-> %d:%d", entry->apic, entry->pin);			if (!entry->next)				break;			entry = irq_2_pin + entry->next;		}		printk("\n");	}	printk(KERN_INFO ".................................... done.\n");	return;}static void print_APIC_bitfield (int base){	unsigned int v;	int i, j;	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);	for (i = 0; i < 8; i++) {		v = apic_read(base + i*0x10);		for (j = 0; j < 32; j++) {			if (v & (1<<j))				printk("1");			else				printk("0");		}		printk("\n");	}}void /*__init*/ print_local_APIC(void * dummy){	unsigned int v, ver, maxlvt;	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",		smp_processor_id(), hard_smp_processor_id());	v = apic_read(APIC_ID);	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(v));	v = apic_read(APIC_LVR);	printk(KERN_INFO "... APIC VERSION: %08x\n", v);	ver = GET_APIC_VERSION(v);	maxlvt = get_maxlvt();	v = apic_read(APIC_TASKPRI);	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);	if (APIC_INTEGRATED(ver)) {			/* !82489DX */		v = apic_read(APIC_ARBPRI);		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,			v & APIC_ARBPRI_MASK);		v = apic_read(APIC_PROCPRI);		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);	}	v = apic_read(APIC_EOI);	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);	v = apic_read(APIC_RRR);	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);	v = apic_read(APIC_LDR);	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);	v = apic_read(APIC_DFR);	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);	v = apic_read(APIC_SPIV);	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);	printk(KERN_DEBUG "... APIC ISR field:\n");	print_APIC_bitfield(APIC_ISR);	printk(KERN_DEBUG "... APIC TMR field:\n");	print_APIC_bitfield(APIC_TMR);	printk(KERN_DEBUG "... APIC IRR field:\n");	print_APIC_bitfield(APIC_IRR);	if (APIC_INTEGRATED(ver)) {		/* !82489DX */		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */			apic_write(APIC_ESR, 0);		v = apic_read(APIC_ESR);		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);	}	v = apic_read(APIC_ICR);	printk(KERN_DEBUG "... APIC ICR: %08x\n", v);	v = apic_read(APIC_ICR2);	printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);	v = apic_read(APIC_LVTT);	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);	if (maxlvt > 3) {                       /* PC is LVT#4. */		v = apic_read(APIC_LVTPC);		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);	}	v = apic_read(APIC_LVT0);	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);	v = apic_read(APIC_LVT1);	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);	if (maxlvt > 2) {			/* ERR is LVT#3. */		v = apic_read(APIC_LVTERR);		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);	}	v = apic_read(APIC_TMICT);	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);	v = apic_read(APIC_TMCCT);	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);	v = apic_read(APIC_TDCR);	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);	printk("\n");}void print_all_local_APICs (void){	smp_call_function(print_local_APIC, NULL, 1, 1);	print_local_APIC(NULL);}void /*__init*/ print_PIC(void){	extern spinlock_t i8259A_lock;	unsigned int v, flags;	printk(KERN_DEBUG "\nprinting PIC contents\n");	spin_lock_irqsave(&i8259A_lock, flags);	v = inb(0xa1) << 8 | inb(0x21);	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);	v = inb(0xa0) << 8 | inb(0x20);	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);	outb(0x0b,0xa0);	outb(0x0b,0x20);	v = inb(0xa0) << 8 | inb(0x20);	outb(0x0a,0xa0);	outb(0x0a,0x20);	spin_unlock_irqrestore(&i8259A_lock, flags);	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);	v = inb(0x4d1) << 8 | inb(0x4d0);	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);}static void __init enable_IO_APIC(void){	struct IO_APIC_reg_01 reg_01;	int i;	unsigned long flags;	for (i = 0; i < PIN_MAP_SIZE; i++) {		irq_2_pin[i].pin = -1;		irq_2_pin[i].next = 0;	}	if (!pirqs_enabled)		for (i = 0; i < MAX_PIRQS; i++)			pirq_entries[i] = -1;	/*	 * The number of IO-APIC IRQ registers (== #pins):	 */	for (i = 0; i < nr_ioapics; i++) {		spin_lock_irqsave(&ioapic_lock, flags);		*(int *)&reg_01 = io_apic_read(i, 1);		spin_unlock_irqrestore(&ioapic_lock, flags);		nr_ioapic_registers[i] = reg_01.entries+1;	}	/*	 * Do not trust the IO-APIC being empty at bootup	 */	clear_IO_APIC();}/* * Not an __init, needed by the reboot code */void disable_IO_APIC(void){	/*	 * Clear the IO-APIC before rebooting:	 */	clear_IO_APIC();	disconnect_bsp_APIC();}/* * function to set the IO-APIC physical IDs based on the * values stored in the MPC table. * * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999 */static void __init setup_ioapic_ids_from_mpc (void){	struct IO_APIC_reg_00 reg_00;	unsigned long phys_id_present_map = phys_cpu_present_map;	int apic;	int i;	unsigned char old_id;	unsigned long flags;	if (clustered_apic_mode)		/* We don't have a good way to do this yet - hack */		phys_id_present_map = (u_long) 0xf;	/*	 * Set the IOAPIC ID to the value stored in the MPC table.	 */	for (apic = 0; apic < nr_ioapics; apic++) {		/* Read the register 0 value */		spin_lock_irqsave(&ioapic_lock, flags);		*(int *)&reg_00 = io_apic_read(apic, 0);		spin_unlock_irqrestore(&ioapic_lock, flags);				old_id = mp_ioapics[apic].mpc_apicid;		if (mp_ioapics[apic].mpc_apicid >= 0xf) {			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",				apic, mp_ioapics[apic].mpc_apicid);			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",				reg_00.ID);			mp_ioapics[apic].mpc_apicid = reg_00.ID;		}		/*		 * Sanity check, is the ID really free? Every APIC in a		 * system must have a unique ID or we get lots of nice		 * 'stuck on smp_invalidate_needed IPI wait' messages.		 */		if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) {			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",				apic, mp_ioapics[apic].mpc_apicid);			for (i = 0; i < 0xf; i++)				if (!(phys_id_present_map & (1 << i)))					break;			if (i >= 0xf)				panic("Max APIC ID exceeded!\n");			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",				i);			phys_id_present_map |= 1 << i;			mp_ioapics[apic].mpc_apicid = i;		} else {			printk("Setting %d in the phys_id_present_map\n", mp_ioapics[apic].mpc_apicid);			phys_id_present_map |= 1 << mp_ioapics[apic].mpc_apicid;		}		/*		 * We need to adjust the IRQ routing table		 * if the ID changed.		 */		if (old_id != mp_ioapics[apic].mpc_apicid)			for (i = 0; i < mp_irq_entries; i++)				if (mp_irqs[i].mpc_dstapic == old_id)					mp_irqs[i].mpc_dstapic						= mp_ioapics[apic].mpc_apicid;		/*		 * Read the right value from the MPC table and		 * write it into the ID register.	 	 */		printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",					mp_ioapics[apic].mpc_apicid);		reg_00.ID = mp_ioapics[apic].mpc_apicid;		spin_lock_irqsave(&ioapic_lock, flags);		io_apic_write(apic, 0, *(int *)&reg_00);

⌨️ 快捷键说明

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