ia64/linux-2.6.18-xen.hg

changeset 724:0729cb8b1292

prevent invalid or unsupportable PIRQs from being used (v2)

By keeping the respective irq_desc[] entries pointing to no_irq_type,
setup_irq() (and thus request_irq()) will fail for such IRQs. This
matches native behavior, which also only installs ioapic_*_type out of
ioapic_register_intr().

At the same time, make assign_irq_vector() fail not only when Xen
doesn't support the PIRQ, but also if the IRQ requested doesn't fall
in the kernel's PIRQ space.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Nov 05 15:43:55 2008 +0000 (2008-11-05)
parents 65ef40020d28
children 61ab98b5cc0e
files arch/i386/kernel/io_apic-xen.c arch/x86_64/kernel/io_apic-xen.c drivers/xen/core/evtchn.c
line diff
     1.1 --- a/arch/i386/kernel/io_apic-xen.c	Wed Nov 05 14:51:34 2008 +0000
     1.2 +++ b/arch/i386/kernel/io_apic-xen.c	Wed Nov 05 15:43:55 2008 +0000
     1.3 @@ -1216,6 +1216,9 @@ int assign_irq_vector(int irq)
     1.4  
     1.5  	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
     1.6  
     1.7 +	if (irq < PIRQ_BASE || irq - PIRQ_BASE > NR_PIRQS)
     1.8 +		return -EINVAL;
     1.9 +
    1.10  	spin_lock_irqsave(&vector_lock, flags);
    1.11  
    1.12  	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
     2.1 --- a/arch/x86_64/kernel/io_apic-xen.c	Wed Nov 05 14:51:34 2008 +0000
     2.2 +++ b/arch/x86_64/kernel/io_apic-xen.c	Wed Nov 05 15:43:55 2008 +0000
     2.3 @@ -895,6 +895,9 @@ int assign_irq_vector(int irq)
     2.4    
     2.5    	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
     2.6  
     2.7 +	if (irq < PIRQ_BASE || irq - PIRQ_BASE > NR_PIRQS)
     2.8 +		return -EINVAL;
     2.9 +
    2.10  	spin_lock_irqsave(&vector_lock, flags);
    2.11  
    2.12    	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
     3.1 --- a/drivers/xen/core/evtchn.c	Wed Nov 05 14:51:34 2008 +0000
     3.2 +++ b/drivers/xen/core/evtchn.c	Wed Nov 05 15:43:55 2008 +0000
     3.3 @@ -756,71 +756,6 @@ static struct hw_interrupt_type dynirq_t
     3.4  	.retrigger = resend_irq_on_evtchn,
     3.5  };
     3.6  
     3.7 -void evtchn_register_pirq(int irq)
     3.8 -{
     3.9 -	struct irq_desc *desc;
    3.10 -	unsigned long flags;
    3.11 -
    3.12 -	irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, 0);
    3.13 -
    3.14 -	/* Cannot call set_irq_probe(), as that's marked __init. */
    3.15 -	desc = irq_desc + irq;
    3.16 -	spin_lock_irqsave(&desc->lock, flags);
    3.17 -	desc->status &= ~IRQ_NOPROBE;
    3.18 -	spin_unlock_irqrestore(&desc->lock, flags);
    3.19 -}
    3.20 -
    3.21 -#if defined(CONFIG_X86_IO_APIC)
    3.22 -#define identity_mapped_irq(irq) (!IO_APIC_IRQ((irq) - PIRQ_BASE))
    3.23 -#elif defined(CONFIG_X86)
    3.24 -#define identity_mapped_irq(irq) (((irq) - PIRQ_BASE) < 16)
    3.25 -#else
    3.26 -#define identity_mapped_irq(irq) (1)
    3.27 -#endif
    3.28 -
    3.29 -int evtchn_map_pirq(int irq, int xen_pirq)
    3.30 -{
    3.31 -	if (irq < 0) {
    3.32 -		static DEFINE_SPINLOCK(irq_alloc_lock);
    3.33 -
    3.34 -		irq = PIRQ_BASE + NR_PIRQS - 1;
    3.35 -		spin_lock(&irq_alloc_lock);
    3.36 -		do {
    3.37 -			if (identity_mapped_irq(irq))
    3.38 -				continue;
    3.39 -			if (!index_from_irq(irq)) {
    3.40 -				BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
    3.41 -				irq_info[irq] = mk_irq_info(IRQT_PIRQ,
    3.42 -							    xen_pirq, 0);
    3.43 -				break;
    3.44 -			}
    3.45 -		} while (--irq >= PIRQ_BASE);
    3.46 -		spin_unlock(&irq_alloc_lock);
    3.47 -		if (irq < PIRQ_BASE)
    3.48 -			return -ENOSPC;
    3.49 -	} else if (!xen_pirq) {
    3.50 -		if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
    3.51 -			return -EINVAL;
    3.52 -		irq_info[irq] = IRQ_UNBOUND;
    3.53 -		return 0;
    3.54 -	} else if (type_from_irq(irq) != IRQT_PIRQ
    3.55 -		   || index_from_irq(irq) != xen_pirq) {
    3.56 -		printk(KERN_ERR "IRQ#%d is already mapped to %d:%u - "
    3.57 -				"cannot map to PIRQ#%u\n",
    3.58 -		       irq, type_from_irq(irq), index_from_irq(irq), xen_pirq);
    3.59 -		return -EINVAL;
    3.60 -	}
    3.61 -	return index_from_irq(irq) ? irq : -EINVAL;
    3.62 -}
    3.63 -
    3.64 -int evtchn_get_xen_pirq(int irq)
    3.65 -{
    3.66 -	if (identity_mapped_irq(irq))
    3.67 -		return irq;
    3.68 -	BUG_ON(type_from_irq(irq) != IRQT_PIRQ);
    3.69 -	return index_from_irq(irq);
    3.70 -}
    3.71 -
    3.72  static inline void pirq_unmask_notify(int irq)
    3.73  {
    3.74  	struct physdev_eoi eoi = { .irq = evtchn_get_xen_pirq(irq) };
    3.75 @@ -1098,6 +1033,68 @@ void irq_resume(void)
    3.76  
    3.77  }
    3.78  
    3.79 +#if defined(CONFIG_X86_IO_APIC)
    3.80 +#define identity_mapped_irq(irq) (!IO_APIC_IRQ((irq) - PIRQ_BASE))
    3.81 +#elif defined(CONFIG_X86)
    3.82 +#define identity_mapped_irq(irq) (((irq) - PIRQ_BASE) < 16)
    3.83 +#else
    3.84 +#define identity_mapped_irq(irq) (1)
    3.85 +#endif
    3.86 +
    3.87 +void evtchn_register_pirq(int irq)
    3.88 +{
    3.89 +	BUG_ON(irq < PIRQ_BASE || irq - PIRQ_BASE > NR_PIRQS);
    3.90 +	if (identity_mapped_irq(irq))
    3.91 +		return;
    3.92 +	irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, 0);
    3.93 +	irq_desc[irq].chip = &pirq_type;
    3.94 +}
    3.95 +
    3.96 +int evtchn_map_pirq(int irq, int xen_pirq)
    3.97 +{
    3.98 +	if (irq < 0) {
    3.99 +		static DEFINE_SPINLOCK(irq_alloc_lock);
   3.100 +
   3.101 +		irq = PIRQ_BASE + NR_PIRQS - 1;
   3.102 +		spin_lock(&irq_alloc_lock);
   3.103 +		do {
   3.104 +			if (identity_mapped_irq(irq))
   3.105 +				continue;
   3.106 +			if (!index_from_irq(irq)) {
   3.107 +				BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
   3.108 +				irq_info[irq] = mk_irq_info(IRQT_PIRQ,
   3.109 +							    xen_pirq, 0);
   3.110 +				break;
   3.111 +			}
   3.112 +		} while (--irq >= PIRQ_BASE);
   3.113 +		spin_unlock(&irq_alloc_lock);
   3.114 +		if (irq < PIRQ_BASE)
   3.115 +			return -ENOSPC;
   3.116 +		irq_desc[irq].chip = &pirq_type;
   3.117 +	} else if (!xen_pirq) {
   3.118 +		if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
   3.119 +			return -EINVAL;
   3.120 +		irq_desc[irq].chip = &no_irq_type;
   3.121 +		irq_info[irq] = IRQ_UNBOUND;
   3.122 +		return 0;
   3.123 +	} else if (type_from_irq(irq) != IRQT_PIRQ
   3.124 +		   || index_from_irq(irq) != xen_pirq) {
   3.125 +		printk(KERN_ERR "IRQ#%d is already mapped to %d:%u - "
   3.126 +				"cannot map to PIRQ#%u\n",
   3.127 +		       irq, type_from_irq(irq), index_from_irq(irq), xen_pirq);
   3.128 +		return -EINVAL;
   3.129 +	}
   3.130 +	return index_from_irq(irq) ? irq : -EINVAL;
   3.131 +}
   3.132 +
   3.133 +int evtchn_get_xen_pirq(int irq)
   3.134 +{
   3.135 +	if (identity_mapped_irq(irq))
   3.136 +		return irq;
   3.137 +	BUG_ON(type_from_irq(irq) != IRQT_PIRQ);
   3.138 +	return index_from_irq(irq);
   3.139 +}
   3.140 +
   3.141  void __init xen_init_IRQ(void)
   3.142  {
   3.143  	unsigned int i;
   3.144 @@ -1126,16 +1123,16 @@ void __init xen_init_IRQ(void)
   3.145  	for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_PIRQS); i++) {
   3.146  		irq_bindcount[i] = 1;
   3.147  
   3.148 +		if (!identity_mapped_irq(i))
   3.149 +			continue;
   3.150 +
   3.151  #ifdef RTC_IRQ
   3.152  		/* If not domain 0, force our RTC driver to fail its probe. */
   3.153 -		if (identity_mapped_irq(i) && ((i - PIRQ_BASE) == RTC_IRQ)
   3.154 -		    && !is_initial_xendomain())
   3.155 +		if (i - PIRQ_BASE == RTC_IRQ && !is_initial_xendomain())
   3.156  			continue;
   3.157  #endif
   3.158  
   3.159  		irq_desc[i].status = IRQ_DISABLED;
   3.160 -		if (!identity_mapped_irq(i))
   3.161 -			irq_desc[i].status |= IRQ_NOPROBE;
   3.162  		irq_desc[i].action = NULL;
   3.163  		irq_desc[i].depth = 1;
   3.164  		irq_desc[i].chip = &pirq_type;