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

📄 io_apic_64.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			break;		}		case 3: /* low active */		{			polarity = 1;			break;		}		default: /* invalid */		{			printk(KERN_WARNING "broken BIOS!!\n");			polarity = 1;			break;		}	}	return polarity;}static int MPBIOS_trigger(int idx){	int bus = mp_irqs[idx].mpc_srcbus;	int trigger;	/*	 * Determine IRQ trigger mode (edge or level sensitive):	 */	switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)	{		case 0: /* conforms, ie. bus-type dependent */			if (test_bit(bus, mp_bus_not_pci))				trigger = default_ISA_trigger(idx);			else				trigger = default_PCI_trigger(idx);			break;		case 1: /* edge */		{			trigger = 0;			break;		}		case 2: /* reserved */		{			printk(KERN_WARNING "broken BIOS!!\n");			trigger = 1;			break;		}		case 3: /* level */		{			trigger = 1;			break;		}		default: /* invalid */		{			printk(KERN_WARNING "broken BIOS!!\n");			trigger = 0;			break;		}	}	return trigger;}static inline int irq_polarity(int idx){	return MPBIOS_polarity(idx);}static inline int irq_trigger(int idx){	return MPBIOS_trigger(idx);}static int pin_2_irq(int idx, int apic, int pin){	int irq, i;	int bus = mp_irqs[idx].mpc_srcbus;	/*	 * Debugging check, we are in big trouble if this message pops up!	 */	if (mp_irqs[idx].mpc_dstirq != pin)		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");	if (test_bit(bus, mp_bus_not_pci)) {		irq = mp_irqs[idx].mpc_srcbusirq;	} else {		/*		 * PCI IRQs are mapped in order		 */		i = irq = 0;		while (i < apic)			irq += nr_ioapic_registers[i++];		irq += pin;	}	BUG_ON(irq >= NR_IRQS);	return irq;}static int __assign_irq_vector(int irq, cpumask_t mask){	/*	 * NOTE! The local APIC isn't very good at handling	 * multiple interrupts at the same interrupt level.	 * As the interrupt level is determined by taking the	 * vector number and shifting that right by 4, we	 * want to spread these out a bit so that they don't	 * all fall in the same interrupt level.	 *	 * Also, we've got to be careful not to trash gate	 * 0x80, because int 0x80 is hm, kind of importantish. ;)	 */	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;	unsigned int old_vector;	int cpu;	struct irq_cfg *cfg;	BUG_ON((unsigned)irq >= NR_IRQS);	cfg = &irq_cfg[irq];	/* Only try and allocate irqs on cpus that are present */	cpus_and(mask, mask, cpu_online_map);	if ((cfg->move_in_progress) || cfg->move_cleanup_count)		return -EBUSY;	old_vector = cfg->vector;	if (old_vector) {		cpumask_t tmp;		cpus_and(tmp, cfg->domain, mask);		if (!cpus_empty(tmp))			return 0;	}	for_each_cpu_mask(cpu, mask) {		cpumask_t domain, new_mask;		int new_cpu;		int vector, offset;		domain = vector_allocation_domain(cpu);		cpus_and(new_mask, domain, cpu_online_map);		vector = current_vector;		offset = current_offset;next:		vector += 8;		if (vector >= FIRST_SYSTEM_VECTOR) {			/* If we run out of vectors on large boxen, must share them. */			offset = (offset + 1) % 8;			vector = FIRST_DEVICE_VECTOR + offset;		}		if (unlikely(current_vector == vector))			continue;		if (vector == IA32_SYSCALL_VECTOR)			goto next;		for_each_cpu_mask(new_cpu, new_mask)			if (per_cpu(vector_irq, new_cpu)[vector] != -1)				goto next;		/* Found one! */		current_vector = vector;		current_offset = offset;		if (old_vector) {			cfg->move_in_progress = 1;			cfg->old_domain = cfg->domain;		}		for_each_cpu_mask(new_cpu, new_mask)			per_cpu(vector_irq, new_cpu)[vector] = irq;		cfg->vector = vector;		cfg->domain = domain;		return 0;	}	return -ENOSPC;}static int assign_irq_vector(int irq, cpumask_t mask){	int err;	unsigned long flags;	spin_lock_irqsave(&vector_lock, flags);	err = __assign_irq_vector(irq, mask);	spin_unlock_irqrestore(&vector_lock, flags);	return err;}static void __clear_irq_vector(int irq){	struct irq_cfg *cfg;	cpumask_t mask;	int cpu, vector;	BUG_ON((unsigned)irq >= NR_IRQS);	cfg = &irq_cfg[irq];	BUG_ON(!cfg->vector);	vector = cfg->vector;	cpus_and(mask, cfg->domain, cpu_online_map);	for_each_cpu_mask(cpu, mask)		per_cpu(vector_irq, cpu)[vector] = -1;	cfg->vector = 0;	cfg->domain = CPU_MASK_NONE;}void __setup_vector_irq(int cpu){	/* Initialize vector_irq on a new cpu */	/* This function must be called with vector_lock held */	int irq, vector;	/* Mark the inuse vectors */	for (irq = 0; irq < NR_IRQS; ++irq) {		if (!cpu_isset(cpu, irq_cfg[irq].domain))			continue;		vector = irq_cfg[irq].vector;		per_cpu(vector_irq, cpu)[vector] = irq;	}	/* Mark the free vectors */	for (vector = 0; vector < NR_VECTORS; ++vector) {		irq = per_cpu(vector_irq, cpu)[vector];		if (irq < 0)			continue;		if (!cpu_isset(cpu, irq_cfg[irq].domain))			per_cpu(vector_irq, cpu)[vector] = -1;	}}static struct irq_chip ioapic_chip;static void ioapic_register_intr(int irq, unsigned long trigger){	if (trigger) {		irq_desc[irq].status |= IRQ_LEVEL;		set_irq_chip_and_handler_name(irq, &ioapic_chip,					      handle_fasteoi_irq, "fasteoi");	} else {		irq_desc[irq].status &= ~IRQ_LEVEL;		set_irq_chip_and_handler_name(irq, &ioapic_chip,					      handle_edge_irq, "edge");	}}static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,			      int trigger, int polarity){	struct irq_cfg *cfg = irq_cfg + irq;	struct IO_APIC_route_entry entry;	cpumask_t mask;	if (!IO_APIC_IRQ(irq))		return;	mask = TARGET_CPUS;	if (assign_irq_vector(irq, mask))		return;	cpus_and(mask, cfg->domain, mask);	apic_printk(APIC_VERBOSE,KERN_DEBUG		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "		    "IRQ %d Mode:%i Active:%i)\n",		    apic, mp_ioapics[apic].mpc_apicid, pin, cfg->vector,		    irq, trigger, polarity);	/*	 * add it to the IO-APIC irq-routing table:	 */	memset(&entry,0,sizeof(entry));	entry.delivery_mode = INT_DELIVERY_MODE;	entry.dest_mode = INT_DEST_MODE;	entry.dest = cpu_mask_to_apicid(mask);	entry.mask = 0;				/* enable IRQ */	entry.trigger = trigger;	entry.polarity = polarity;	entry.vector = cfg->vector;	/* Mask level triggered irqs.	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.	 */	if (trigger)		entry.mask = 1;	ioapic_register_intr(irq, trigger);	if (irq < 16)		disable_8259A_irq(irq);	ioapic_write_entry(apic, pin, entry);}static void __init setup_IO_APIC_irqs(void){	int apic, pin, idx, irq, first_notcon = 1;	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");	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) {			if (first_notcon) {				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);				first_notcon = 0;			} else				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin);			continue;		}		if (!first_notcon) {			apic_printk(APIC_VERBOSE, " not connected.\n");			first_notcon = 1;		}		irq = pin_2_irq(idx, apic, pin);		add_pin_to_irq(irq, apic, pin);		setup_IO_APIC_irq(apic, pin, irq,				  irq_trigger(idx), irq_polarity(idx));	}	}	if (!first_notcon)		apic_printk(APIC_VERBOSE, " not connected.\n");}/* * Set up the 8259A-master output pin as broadcast to all * CPUs. */static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, 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(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_DEST_MODE;	entry.mask = 0;					/* unmask IRQ now */	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);	entry.delivery_mode = INT_DELIVERY_MODE;	entry.polarity = 0;	entry.trigger = 0;	entry.vector = vector;	/*	 * The timer IRQ doesn't have to know that behind the	 * scene we have a 8259A-master in AEOI mode ...	 */	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");	/*	 * Add it to the IO-APIC irq-routing table:	 */	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);	enable_8259A_irq(0);}void __apicdebuginit print_IO_APIC(void){	int apic, i;	union IO_APIC_reg_00 reg_00;	union IO_APIC_reg_01 reg_01;	union IO_APIC_reg_02 reg_02;	unsigned long flags;	if (apic_verbosity == APIC_QUIET)		return;	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);	reg_00.raw = io_apic_read(apic, 0);	reg_01.raw = io_apic_read(apic, 1);	if (reg_01.bits.version >= 0x10)		reg_02.raw = 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", reg_00.raw);	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);	if (reg_01.bits.version >= 0x10) {		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);	}	printk(KERN_DEBUG ".... IRQ redirection table:\n");	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"			  " Stat Dmod Deli Vect:   \n");	for (i = 0; i <= reg_01.bits.entries; i++) {		struct IO_APIC_route_entry entry;		entry = ioapic_read_entry(apic, i);		printk(KERN_DEBUG " %02x %03X ",			i,			entry.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;}#if 0static __apicdebuginit void print_APIC_bitfield (int base){	unsigned int v;	int i, j;	if (apic_verbosity == APIC_QUIET)		return;	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 __apicdebuginit print_local_APIC(void * dummy){	unsigned int v, ver, maxlvt;	if (apic_verbosity == APIC_QUIET)		return;	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);	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);	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){	on_each_cpu(print_local_APIC, NULL, 1, 1);}void __apicdebuginit print_PIC(void){	unsigned int v;	unsigned long flags;	if (apic_verbosity == APIC_QUIET)		return;

⌨️ 快捷键说明

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