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

📄 iosapic.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
			goto out;		}		if (--rte->refcnt > 0)			goto out;		/* Mask the interrupt */		low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK;		iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32);		/* Remove the rte entry from the list */		list_del(&rte->rte_list);		iosapic_intr_info[vector].count--;		iosapic_free_rte(rte);		index = find_iosapic(gsi);		iosapic_lists[index].rtes_inuse--;		WARN_ON(iosapic_lists[index].rtes_inuse < 0);		trigger	 = iosapic_intr_info[vector].trigger;		polarity = iosapic_intr_info[vector].polarity;		dest     = iosapic_intr_info[vector].dest;		printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",		       gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),		       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),		       cpu_logical_id(dest), dest, vector);		if (list_empty(&iosapic_intr_info[vector].rtes)) {			/* Sanity check */			BUG_ON(iosapic_intr_info[vector].count);			/* Clear the interrupt controller descriptor */			idesc->handler = &no_irq_type;			/* Clear the interrupt information */			memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));			iosapic_intr_info[vector].low32 |= IOSAPIC_MASK;			INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);			if (idesc->action) {				printk(KERN_ERR "interrupt handlers still exist on IRQ %u\n", irq);				WARN_ON(1);			}			/* Free the interrupt vector */			free_irq_vector(vector);		}	} out:	spin_unlock(&iosapic_lock);	spin_unlock_irqrestore(&idesc->lock, flags);}/* * ACPI calls this when it finds an entry for a platform interrupt. * Note that the irq_base and IOSAPIC address must be set in iosapic_init(). */int __initiosapic_register_platform_intr (u32 int_type, unsigned int gsi,				int iosapic_vector, u16 eid, u16 id,				unsigned long polarity, unsigned long trigger){	static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"};	unsigned char delivery;	int vector, mask = 0;	unsigned int dest = ((id << 8) | eid) & 0xffff;	switch (int_type) {	      case ACPI_INTERRUPT_PMI:		vector = iosapic_vector;		/*		 * since PMI vector is alloc'd by FW(ACPI) not by kernel,		 * we need to make sure the vector is available		 */		iosapic_reassign_vector(vector);		delivery = IOSAPIC_PMI;		break;	      case ACPI_INTERRUPT_INIT:		vector = assign_irq_vector(AUTO_ASSIGN);		if (vector < 0)			panic("%s: out of interrupt vectors!\n", __FUNCTION__);		delivery = IOSAPIC_INIT;		break;	      case ACPI_INTERRUPT_CPEI:		vector = IA64_CPE_VECTOR;		delivery = IOSAPIC_LOWEST_PRIORITY;		mask = 1;		break;	      default:		printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type);		return -1;	}	register_intr(gsi, vector, delivery, polarity, trigger);	printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",	       int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",	       int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),	       cpu_logical_id(dest), dest, vector);	set_rte(gsi, vector, dest, mask);	return vector;}/* * ACPI calls this when it finds an entry for a legacy ISA IRQ override. * Note that the gsi_base and IOSAPIC address must be set in iosapic_init(). */void __initiosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,			  unsigned long polarity,			  unsigned long trigger){	int vector;	unsigned int dest = cpu_physical_id(smp_processor_id());	vector = isa_irq_to_vector(isa_irq);	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);	DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",	    isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level",	    polarity == IOSAPIC_POL_HIGH ? "high" : "low",	    cpu_logical_id(dest), dest, vector);	set_rte(gsi, vector, dest, 1);}void __initiosapic_system_init (int system_pcat_compat){	int vector;	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) {		iosapic_intr_info[vector].low32 = IOSAPIC_MASK;		INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);	/* mark as unused */	}	pcat_compat = system_pcat_compat;	if (pcat_compat) {		/*		 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support		 * enabled.		 */		printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);		outb(0xff, 0xA1);		outb(0xff, 0x21);	}}static inline intiosapic_alloc (void){	int index;	for (index = 0; index < NR_IOSAPICS; index++)		if (!iosapic_lists[index].addr)			return index;	printk(KERN_WARNING "%s: failed to allocate iosapic\n", __FUNCTION__);	return -1;}static inline voidiosapic_free (int index){	memset(&iosapic_lists[index], 0, sizeof(iosapic_lists[0]));}static inline intiosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver){	int index;	unsigned int gsi_end, base, end;	/* check gsi range */	gsi_end = gsi_base + ((ver >> 16) & 0xff);	for (index = 0; index < NR_IOSAPICS; index++) {		if (!iosapic_lists[index].addr)			continue;		base = iosapic_lists[index].gsi_base;		end  = base + iosapic_lists[index].num_rte - 1;		if (gsi_base < base && gsi_end < base)			continue;/* OK */		if (gsi_base > end && gsi_end > end)			continue; /* OK */		return -EBUSY;	}	return 0;}int __devinitiosapic_init (unsigned long phys_addr, unsigned int gsi_base){	int num_rte, err, index;	unsigned int isa_irq, ver;	char __iomem *addr;	unsigned long flags;	spin_lock_irqsave(&iosapic_lock, flags);	{		addr = ioremap(phys_addr, 0);		ver = iosapic_version(addr);		if ((err = iosapic_check_gsi_range(gsi_base, ver))) {			iounmap(addr);			spin_unlock_irqrestore(&iosapic_lock, flags);			return err;		}		/*		 * The MAX_REDIR register holds the highest input pin		 * number (starting from 0).		 * We add 1 so that we can use it for number of pins (= RTEs)		 */		num_rte = ((ver >> 16) & 0xff) + 1;		index = iosapic_alloc();		iosapic_lists[index].addr = addr;		iosapic_lists[index].gsi_base = gsi_base;		iosapic_lists[index].num_rte = num_rte;#ifdef CONFIG_NUMA		iosapic_lists[index].node = MAX_NUMNODES;#endif	}	spin_unlock_irqrestore(&iosapic_lock, flags);	if ((gsi_base == 0) && pcat_compat) {		/*		 * Map the legacy ISA devices into the IOSAPIC data.  Some of these may		 * get reprogrammed later on with data from the ACPI Interrupt Source		 * Override table.		 */		for (isa_irq = 0; isa_irq < 16; ++isa_irq)			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);	}	return 0;}#ifdef CONFIG_HOTPLUGintiosapic_remove (unsigned int gsi_base){	int index, err = 0;	unsigned long flags;	spin_lock_irqsave(&iosapic_lock, flags);	{		index = find_iosapic(gsi_base);		if (index < 0) {			printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n",			       __FUNCTION__, gsi_base);			goto out;		}		if (iosapic_lists[index].rtes_inuse) {			err = -EBUSY;			printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",			       __FUNCTION__, gsi_base);			goto out;		}		iounmap(iosapic_lists[index].addr);		iosapic_free(index);	} out:	spin_unlock_irqrestore(&iosapic_lock, flags);	return err;}#endif /* CONFIG_HOTPLUG */#ifdef CONFIG_NUMAvoid __devinitmap_iosapic_to_node(unsigned int gsi_base, int node){	int index;	index = find_iosapic(gsi_base);	if (index < 0) {		printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",		       __FUNCTION__, gsi_base);		return;	}	iosapic_lists[index].node = node;	return;}#endif#ifndef XENstatic int __init iosapic_enable_kmalloc (void){	iosapic_kmalloc_ok = 1;	return 0;}core_initcall (iosapic_enable_kmalloc);#endif#ifdef XEN/* nop for now */void set_irq_affinity_info(unsigned int irq, int hwid, int redir) {}static int iosapic_physbase_to_id(unsigned long physbase){	int i;	unsigned long addr = physbase | __IA64_UNCACHED_OFFSET;	for (i = 0; i < NR_IOSAPICS; i++) {	    if ((unsigned long)(iosapic_lists[i].addr) == addr)		return i;	}	return -1;}int iosapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval){	int id;	unsigned long flags;	if ((id = (iosapic_physbase_to_id(physbase))) < 0)	    return id;	spin_lock_irqsave(&iosapic_lock, flags);	*pval = iosapic_read(iosapic_lists[id].addr, reg);	spin_unlock_irqrestore(&iosapic_lock, flags);	return 0;}int iosapic_guest_write(unsigned long physbase, unsigned int reg, u32 val){	unsigned int id, gsi, vec, xen_vec, dest, high32;	char rte_index;	struct iosapic *ios;	struct iosapic_intr_info *info;	struct rte_entry rte;	unsigned long flags;	if ((id = (iosapic_physbase_to_id(physbase))) < 0)	    return -EINVAL;	ios = &iosapic_lists[id];	/* Only handle first half of RTE update */	if ((reg < 0x10) || (reg & 1))	    return 0;	rte.val = val;	rte_index = IOSAPIC_RTEINDEX(reg);	vec = rte.lo.vector;#if 0	/* Take PMI/NMI/INIT/EXTINT handled by xen */ 	if (rte.delivery_mode > IOSAPIC_LOWEST_PRIORITY) {	    printk("Attempt to write IOSAPIC dest mode owned by xen!\n");	    printk("IOSAPIC/PIN = (%d/%d), lo = 0x%x\n",		id, rte_index, val);	    return -EINVAL;	}#endif	/* Sanity check. Vector should be allocated before this update */	if ((rte_index > ios->num_rte) ||	    ((vec > IA64_FIRST_DEVICE_VECTOR) &&	     (vec < IA64_LAST_DEVICE_VECTOR) &&	     (!test_bit(vec - IA64_FIRST_DEVICE_VECTOR, ia64_vector_mask))))	    return -EINVAL;	gsi = ios->gsi_base + rte_index;	xen_vec = gsi_to_vector(gsi);	if (xen_vec >= 0 && test_bit(xen_vec, ia64_xen_vector)) {		printk("WARN: GSI %d in use by Xen.\n", gsi);		return -EINVAL;	}	info = &iosapic_intr_info[vec];	spin_lock_irqsave(&irq_descp(vec)->lock, flags);	spin_lock(&iosapic_lock);	if (!gsi_vector_to_rte(gsi, vec)) {	    register_intr(gsi, vec, IOSAPIC_LOWEST_PRIORITY,		rte.lo.polarity, rte.lo.trigger);	} else if (vector_is_shared(vec)) {	    if ((info->trigger != rte.lo.trigger) ||		(info->polarity != rte.lo.polarity)) {		printk("WARN: can't override shared interrupt vec\n");	        printk("IOSAPIC/PIN = (%d/%d), ori = 0x%x, new = 0x%x\n",			id, rte_index, info->low32, rte.val);		spin_unlock(&iosapic_lock);		spin_unlock_irqrestore(&irq_descp(vec)->lock, flags);		return -EINVAL;	    }	    /* If the vector is shared and already unmasked for other	     * interrupt sources, don't mask it.	     *	     * Same check may also apply to single gsi pin, which may	     * be shared by devices belonging to different domain. But	     * let's see how to act later on demand.	     */	    if (!(info->low32 & IOSAPIC_MASK))		rte.lo.mask = 0;	}	/* time to update physical RTE */	dest = cpu_physical_id(smp_processor_id());	high32 = (dest << IOSAPIC_DEST_SHIFT);	iosapic_write(iosapic_lists[id].addr, reg + 1, high32);	iosapic_write(iosapic_lists[id].addr, reg, rte.val);	info->low32 = rte.val;	info->dest = dest;	spin_unlock(&iosapic_lock);	spin_unlock_irqrestore(&irq_descp(vec)->lock, flags);	return 0;}#endif /* XEN */

⌨️ 快捷键说明

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