ia64/xen-unstable
changeset 18591:ed398097c03e
x86: Move pirq logic to irq.c.
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Wed Oct 08 10:48:48 2008 +0100 (2008-10-08) |
parents | 1f85f7b216b3 |
children | 51a05fb4c601 |
files | xen/arch/x86/irq.c xen/arch/x86/physdev.c xen/include/asm-x86/irq.h |
line diff
1.1 --- a/xen/arch/x86/irq.c Wed Oct 08 10:03:47 2008 +0100 1.2 +++ b/xen/arch/x86/irq.c Wed Oct 08 10:48:48 2008 +0100 1.3 @@ -14,8 +14,11 @@ 1.4 #include <xen/sched.h> 1.5 #include <xen/keyhandler.h> 1.6 #include <xen/compat.h> 1.7 +#include <xen/iocap.h> 1.8 +#include <xen/iommu.h> 1.9 +#include <asm/msi.h> 1.10 #include <asm/current.h> 1.11 -#include <xen/iommu.h> 1.12 +#include <public/physdev.h> 1.13 1.14 /* opt_noirqbalance: If true, software IRQ balancing/affinity is disabled. */ 1.15 int opt_noirqbalance = 0; 1.16 @@ -731,6 +734,157 @@ int pirq_guest_force_unbind(struct domai 1.17 return bound; 1.18 } 1.19 1.20 +int get_free_pirq(struct domain *d, int type, int index) 1.21 +{ 1.22 + int i; 1.23 + 1.24 + ASSERT(spin_is_locked(&d->evtchn_lock)); 1.25 + 1.26 + if ( type == MAP_PIRQ_TYPE_GSI ) 1.27 + { 1.28 + for ( i = 16; i < NR_PIRQS; i++ ) 1.29 + if ( !d->arch.pirq_vector[i] ) 1.30 + break; 1.31 + if ( i == NR_PIRQS ) 1.32 + return -ENOSPC; 1.33 + } 1.34 + else 1.35 + { 1.36 + for ( i = NR_PIRQS - 1; i >= 16; i-- ) 1.37 + if ( !d->arch.pirq_vector[i] ) 1.38 + break; 1.39 + if ( i == 16 ) 1.40 + return -ENOSPC; 1.41 + } 1.42 + 1.43 + return i; 1.44 +} 1.45 + 1.46 +int map_domain_pirq( 1.47 + struct domain *d, int pirq, int vector, int type, void *data) 1.48 +{ 1.49 + int ret = 0; 1.50 + int old_vector, old_pirq; 1.51 + irq_desc_t *desc; 1.52 + unsigned long flags; 1.53 + 1.54 + ASSERT(spin_is_locked(&d->evtchn_lock)); 1.55 + 1.56 + if ( !IS_PRIV(current->domain) ) 1.57 + return -EPERM; 1.58 + 1.59 + if ( pirq < 0 || pirq >= NR_PIRQS || vector < 0 || vector >= NR_VECTORS ) 1.60 + { 1.61 + dprintk(XENLOG_G_ERR, "dom%d: invalid pirq %d or vector %d\n", 1.62 + d->domain_id, pirq, vector); 1.63 + return -EINVAL; 1.64 + } 1.65 + 1.66 + old_vector = d->arch.pirq_vector[pirq]; 1.67 + old_pirq = d->arch.vector_pirq[vector]; 1.68 + 1.69 + if ( (old_vector && (old_vector != vector) ) || 1.70 + (old_pirq && (old_pirq != pirq)) ) 1.71 + { 1.72 + dprintk(XENLOG_G_ERR, "dom%d: pirq %d or vector %d already mapped\n", 1.73 + d->domain_id, pirq, vector); 1.74 + return -EINVAL; 1.75 + } 1.76 + 1.77 + ret = irq_permit_access(d, pirq); 1.78 + if ( ret ) 1.79 + { 1.80 + dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d\n", 1.81 + d->domain_id, pirq); 1.82 + return ret; 1.83 + } 1.84 + 1.85 + desc = &irq_desc[vector]; 1.86 + spin_lock_irqsave(&desc->lock, flags); 1.87 + 1.88 + if ( type == MAP_PIRQ_TYPE_MSI ) 1.89 + { 1.90 + struct msi_info *msi = (struct msi_info *)data; 1.91 + if ( desc->handler != &no_irq_type ) 1.92 + dprintk(XENLOG_G_ERR, "dom%d: vector %d in use\n", 1.93 + d->domain_id, vector); 1.94 + desc->handler = &pci_msi_type; 1.95 + ret = pci_enable_msi(msi); 1.96 + if ( ret ) 1.97 + goto done; 1.98 + } 1.99 + 1.100 + d->arch.pirq_vector[pirq] = vector; 1.101 + d->arch.vector_pirq[vector] = pirq; 1.102 + 1.103 +done: 1.104 + spin_unlock_irqrestore(&desc->lock, flags); 1.105 + return ret; 1.106 +} 1.107 + 1.108 +/* The pirq should have been unbound before this call. */ 1.109 +int unmap_domain_pirq(struct domain *d, int pirq) 1.110 +{ 1.111 + unsigned long flags; 1.112 + irq_desc_t *desc; 1.113 + int vector, ret = 0; 1.114 + bool_t forced_unbind; 1.115 + 1.116 + if ( (pirq < 0) || (pirq >= NR_PIRQS) ) 1.117 + return -EINVAL; 1.118 + 1.119 + if ( !IS_PRIV(current->domain) ) 1.120 + return -EINVAL; 1.121 + 1.122 + ASSERT(spin_is_locked(&d->evtchn_lock)); 1.123 + 1.124 + vector = d->arch.pirq_vector[pirq]; 1.125 + if ( vector <= 0 ) 1.126 + { 1.127 + dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n", 1.128 + d->domain_id, pirq); 1.129 + ret = -EINVAL; 1.130 + goto done; 1.131 + } 1.132 + 1.133 + forced_unbind = pirq_guest_force_unbind(d, pirq); 1.134 + if ( forced_unbind ) 1.135 + dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n", 1.136 + d->domain_id, pirq); 1.137 + 1.138 + desc = &irq_desc[vector]; 1.139 + spin_lock_irqsave(&desc->lock, flags); 1.140 + 1.141 + BUG_ON(vector != d->arch.pirq_vector[pirq]); 1.142 + 1.143 + if ( desc->msi_desc ) 1.144 + pci_disable_msi(vector); 1.145 + 1.146 + if ( desc->handler == &pci_msi_type ) 1.147 + desc->handler = &no_irq_type; 1.148 + 1.149 + if ( !forced_unbind ) 1.150 + { 1.151 + d->arch.pirq_vector[pirq] = 0; 1.152 + d->arch.vector_pirq[vector] = 0; 1.153 + } 1.154 + else 1.155 + { 1.156 + d->arch.pirq_vector[pirq] = -vector; 1.157 + d->arch.vector_pirq[vector] = -pirq; 1.158 + } 1.159 + 1.160 + spin_unlock_irqrestore(&desc->lock, flags); 1.161 + 1.162 + ret = irq_deny_access(d, pirq); 1.163 + if ( ret ) 1.164 + dprintk(XENLOG_G_ERR, "dom%d: could not deny access to irq %d\n", 1.165 + d->domain_id, pirq); 1.166 + 1.167 + done: 1.168 + return ret; 1.169 +} 1.170 + 1.171 extern void dump_ioapic_irq_info(void); 1.172 1.173 static void dump_irqs(unsigned char key)
2.1 --- a/xen/arch/x86/physdev.c Wed Oct 08 10:03:47 2008 +0100 2.2 +++ b/xen/arch/x86/physdev.c Wed Oct 08 10:48:48 2008 +0100 2.3 @@ -26,168 +26,12 @@ int 2.4 ioapic_guest_write( 2.5 unsigned long physbase, unsigned int reg, u32 pval); 2.6 2.7 -static int get_free_pirq(struct domain *d, int type, int index) 2.8 -{ 2.9 - int i; 2.10 - 2.11 - ASSERT(spin_is_locked(&d->evtchn_lock)); 2.12 - 2.13 - if ( type == MAP_PIRQ_TYPE_GSI ) 2.14 - { 2.15 - for ( i = 16; i < NR_PIRQS; i++ ) 2.16 - if ( !d->arch.pirq_vector[i] ) 2.17 - break; 2.18 - if ( i == NR_PIRQS ) 2.19 - return -ENOSPC; 2.20 - } 2.21 - else 2.22 - { 2.23 - for ( i = NR_PIRQS - 1; i >= 16; i-- ) 2.24 - if ( !d->arch.pirq_vector[i] ) 2.25 - break; 2.26 - if ( i == 16 ) 2.27 - return -ENOSPC; 2.28 - } 2.29 - 2.30 - return i; 2.31 -} 2.32 - 2.33 -static int map_domain_pirq(struct domain *d, int pirq, int vector, 2.34 - struct physdev_map_pirq *map) 2.35 -{ 2.36 - int ret = 0; 2.37 - int old_vector, old_pirq; 2.38 - struct msi_info msi; 2.39 - irq_desc_t *desc; 2.40 - unsigned long flags; 2.41 - 2.42 - ASSERT(spin_is_locked(&d->evtchn_lock)); 2.43 - 2.44 - if ( !IS_PRIV(current->domain) ) 2.45 - return -EPERM; 2.46 - 2.47 - if ( pirq < 0 || pirq >= NR_PIRQS || vector < 0 || vector >= NR_VECTORS ) 2.48 - { 2.49 - dprintk(XENLOG_G_ERR, "dom%d: invalid pirq %d or vector %d\n", 2.50 - d->domain_id, pirq, vector); 2.51 - return -EINVAL; 2.52 - } 2.53 - 2.54 - old_vector = d->arch.pirq_vector[pirq]; 2.55 - old_pirq = d->arch.vector_pirq[vector]; 2.56 - 2.57 - if ( (old_vector && (old_vector != vector) ) || 2.58 - (old_pirq && (old_pirq != pirq)) ) 2.59 - { 2.60 - dprintk(XENLOG_G_ERR, "dom%d: pirq %d or vector %d already mapped\n", 2.61 - d->domain_id, pirq, vector); 2.62 - return -EINVAL; 2.63 - } 2.64 - 2.65 - ret = irq_permit_access(d, pirq); 2.66 - if ( ret ) 2.67 - { 2.68 - dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d\n", 2.69 - d->domain_id, pirq); 2.70 - return ret; 2.71 - } 2.72 - 2.73 - desc = &irq_desc[vector]; 2.74 - spin_lock_irqsave(&desc->lock, flags); 2.75 - 2.76 - if ( map && MAP_PIRQ_TYPE_MSI == map->type ) 2.77 - { 2.78 - if ( desc->handler != &no_irq_type ) 2.79 - dprintk(XENLOG_G_ERR, "dom%d: vector %d in use\n", 2.80 - d->domain_id, vector); 2.81 - desc->handler = &pci_msi_type; 2.82 - 2.83 - msi.bus = map->bus; 2.84 - msi.devfn = map->devfn; 2.85 - msi.entry_nr = map->entry_nr; 2.86 - msi.table_base = map->table_base; 2.87 - msi.vector = vector; 2.88 - 2.89 - ret = pci_enable_msi(&msi); 2.90 - if ( ret ) 2.91 - goto done; 2.92 - } 2.93 - 2.94 - d->arch.pirq_vector[pirq] = vector; 2.95 - d->arch.vector_pirq[vector] = pirq; 2.96 - 2.97 -done: 2.98 - spin_unlock_irqrestore(&desc->lock, flags); 2.99 - return ret; 2.100 -} 2.101 - 2.102 -/* The pirq should have been unbound before this call. */ 2.103 -static int unmap_domain_pirq(struct domain *d, int pirq) 2.104 -{ 2.105 - unsigned long flags; 2.106 - irq_desc_t *desc; 2.107 - int vector, ret = 0; 2.108 - bool_t forced_unbind; 2.109 - 2.110 - if ( (pirq < 0) || (pirq >= NR_PIRQS) ) 2.111 - return -EINVAL; 2.112 - 2.113 - if ( !IS_PRIV(current->domain) ) 2.114 - return -EINVAL; 2.115 - 2.116 - ASSERT(spin_is_locked(&d->evtchn_lock)); 2.117 - 2.118 - vector = d->arch.pirq_vector[pirq]; 2.119 - if ( vector <= 0 ) 2.120 - { 2.121 - dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n", 2.122 - d->domain_id, pirq); 2.123 - ret = -EINVAL; 2.124 - goto done; 2.125 - } 2.126 - 2.127 - forced_unbind = pirq_guest_force_unbind(d, pirq); 2.128 - if ( forced_unbind ) 2.129 - dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n", 2.130 - d->domain_id, pirq); 2.131 - 2.132 - desc = &irq_desc[vector]; 2.133 - spin_lock_irqsave(&desc->lock, flags); 2.134 - 2.135 - BUG_ON(vector != d->arch.pirq_vector[pirq]); 2.136 - 2.137 - if ( desc->msi_desc ) 2.138 - pci_disable_msi(vector); 2.139 - 2.140 - if ( desc->handler == &pci_msi_type ) 2.141 - desc->handler = &no_irq_type; 2.142 - 2.143 - if ( !forced_unbind ) 2.144 - { 2.145 - d->arch.pirq_vector[pirq] = 0; 2.146 - d->arch.vector_pirq[vector] = 0; 2.147 - } 2.148 - else 2.149 - { 2.150 - d->arch.pirq_vector[pirq] = -vector; 2.151 - d->arch.vector_pirq[vector] = -pirq; 2.152 - } 2.153 - 2.154 - spin_unlock_irqrestore(&desc->lock, flags); 2.155 - 2.156 - ret = irq_deny_access(d, pirq); 2.157 - if ( ret ) 2.158 - dprintk(XENLOG_G_ERR, "dom%d: could not deny access to irq %d\n", 2.159 - d->domain_id, pirq); 2.160 - 2.161 - done: 2.162 - return ret; 2.163 -} 2.164 - 2.165 static int physdev_map_pirq(struct physdev_map_pirq *map) 2.166 { 2.167 struct domain *d; 2.168 int vector, pirq, ret = 0; 2.169 + struct msi_info _msi; 2.170 + void *map_data = NULL; 2.171 2.172 if ( !IS_PRIV(current->domain) ) 2.173 return -EPERM; 2.174 @@ -206,6 +50,7 @@ static int physdev_map_pirq(struct physd 2.175 goto free_domain; 2.176 } 2.177 2.178 + /* Verify or get vector. */ 2.179 switch ( map->type ) 2.180 { 2.181 case MAP_PIRQ_TYPE_GSI: 2.182 @@ -220,15 +65,16 @@ static int physdev_map_pirq(struct physd 2.183 if ( !vector ) 2.184 { 2.185 dprintk(XENLOG_G_ERR, "dom%d: map irq with no vector %d\n", 2.186 - d->domain_id, map->index); 2.187 + d->domain_id, vector); 2.188 ret = -EINVAL; 2.189 goto free_domain; 2.190 } 2.191 break; 2.192 + 2.193 case MAP_PIRQ_TYPE_MSI: 2.194 vector = map->index; 2.195 - if ( vector == -1 ) 2.196 - vector = assign_irq_vector(AUTO_ASSIGN); 2.197 + if ( vector == -1 ) 2.198 + vector = assign_irq_vector(AUTO_ASSIGN); 2.199 2.200 if ( vector < 0 || vector >= NR_VECTORS ) 2.201 { 2.202 @@ -237,13 +83,23 @@ static int physdev_map_pirq(struct physd 2.203 ret = -EINVAL; 2.204 goto free_domain; 2.205 } 2.206 + 2.207 + _msi.bus = map->bus; 2.208 + _msi.devfn = map->devfn; 2.209 + _msi.entry_nr = map->entry_nr; 2.210 + _msi.table_base = map->table_base; 2.211 + _msi.vector = vector; 2.212 + map_data = &_msi; 2.213 break; 2.214 + 2.215 default: 2.216 - dprintk(XENLOG_G_ERR, "dom%d: wrong map_pirq type %x\n", d->domain_id, map->type); 2.217 + dprintk(XENLOG_G_ERR, "dom%d: wrong map_pirq type %x\n", 2.218 + d->domain_id, map->type); 2.219 ret = -EINVAL; 2.220 goto free_domain; 2.221 } 2.222 2.223 + /* Verify or get pirq. */ 2.224 spin_lock(&d->evtchn_lock); 2.225 if ( map->pirq < 0 ) 2.226 { 2.227 @@ -285,10 +141,10 @@ static int physdev_map_pirq(struct physd 2.228 } 2.229 2.230 2.231 - ret = map_domain_pirq(d, pirq, vector, map); 2.232 - 2.233 + ret = map_domain_pirq(d, pirq, vector, map->type, map_data); 2.234 if ( !ret ) 2.235 map->pirq = pirq; 2.236 + 2.237 done: 2.238 spin_unlock(&d->evtchn_lock); 2.239 free_domain: 2.240 @@ -442,7 +298,8 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H 2.241 irq_op.vector = assign_irq_vector(irq); 2.242 2.243 spin_lock(&dom0->evtchn_lock); 2.244 - ret = map_domain_pirq(dom0, irq_op.irq, irq_op.vector, NULL); 2.245 + ret = map_domain_pirq(dom0, irq_op.irq, irq_op.vector, 2.246 + MAP_PIRQ_TYPE_GSI, NULL); 2.247 spin_unlock(&dom0->evtchn_lock); 2.248 2.249 if ( copy_to_guest(arg, &irq_op, 1) != 0 )
3.1 --- a/xen/include/asm-x86/irq.h Wed Oct 08 10:03:47 2008 +0100 3.2 +++ b/xen/include/asm-x86/irq.h Wed Oct 08 10:48:48 2008 +0100 3.3 @@ -52,6 +52,11 @@ extern atomic_t irq_mis_count; 3.4 int pirq_acktype(struct domain *d, int irq); 3.5 int pirq_shared(struct domain *d , int irq); 3.6 3.7 +int map_domain_pirq(struct domain *d, int pirq, int vector, int type, 3.8 + void *data); 3.9 +int unmap_domain_pirq(struct domain *d, int pirq); 3.10 +int get_free_pirq(struct domain *d, int type, int index); 3.11 + 3.12 #define domain_irq_to_vector(d, irq) ((d)->arch.pirq_vector[(irq)]) 3.13 #define domain_vector_to_irq(d, vec) ((d)->arch.vector_pirq[(vec)]) 3.14