diff options
author | Jan Beulich <jbeulich@novell.com> | 2011-06-23 11:32:43 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@novell.com> | 2011-06-23 11:32:43 +0100 |
commit | c24536b636f23e4d3202968fcad129d979881e2c (patch) | |
tree | e3e188d484b371f8770714bc0453f6395d6da241 /xen/include | |
parent | eebfd58f212c5fb75e602ac1aa126863452375da (diff) | |
download | xen-c24536b636f23e4d3202968fcad129d979881e2c.tar.gz xen-c24536b636f23e4d3202968fcad129d979881e2c.tar.bz2 xen-c24536b636f23e4d3202968fcad129d979881e2c.zip |
replace d->nr_pirqs sized arrays with radix tree
With this it is questionable whether retaining struct domain's
nr_pirqs is actually necessary - the value now only serves for bounds
checking, and this boundary could easily be nr_irqs.
Note that ia64, the build of which is broken currently anyway, is only
being partially fixed up.
v2: adjustments for split setup/teardown of translation data
v3: re-sync with radix tree implementation changes
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/include')
-rw-r--r-- | xen/include/asm-ia64/domain.h | 18 | ||||
-rw-r--r-- | xen/include/asm-x86/domain.h | 3 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/hvm.h | 3 | ||||
-rw-r--r-- | xen/include/asm-x86/irq.h | 21 | ||||
-rw-r--r-- | xen/include/xen/domain.h | 6 | ||||
-rw-r--r-- | xen/include/xen/event.h | 2 | ||||
-rw-r--r-- | xen/include/xen/hvm/irq.h | 37 | ||||
-rw-r--r-- | xen/include/xen/iommu.h | 4 | ||||
-rw-r--r-- | xen/include/xen/irq.h | 36 | ||||
-rw-r--r-- | xen/include/xen/pci.h | 5 | ||||
-rw-r--r-- | xen/include/xen/sched.h | 9 |
11 files changed, 111 insertions, 33 deletions
diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index e5b71e0011..a1dae862bc 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -11,6 +11,7 @@ #include <xen/list.h> #include <xen/cpumask.h> #include <xen/mm.h> +#include <xen/hvm/irq.h> #include <asm/fpswa.h> #include <xen/rangeset.h> @@ -316,6 +317,23 @@ struct arch_vcpu { cpumask_t cache_coherent_map; }; +struct arch_pirq { + struct hvm_pirq_dpci dpci; +}; + +#define pirq_dpci(pirq) ((pirq) ? &(pirq)->arch.dpci : NULL) +#define dpci_pirq(dpci) container_of(dpci, struct pirq, arch.dpci) + +#define alloc_pirq_struct(d) ({ \ + struct pirq *pirq = xmalloc(struct pirq); \ + if ( pirq ) \ + { \ + memset(pirq, 0, sizeof(*pirq)); \ + pt_pirq_init(d, &pirq->arch.dpci); \ + } \ + pirq; \ +}) + #include <asm/uaccess.h> /* for KERNEL_DS */ #include <asm/pgtable.h> diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 9d30fe5ea2..382e2dbcb2 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -275,9 +275,6 @@ struct arch_domain /* NB. protected by d->event_lock and by irq_desc[irq].lock */ struct radix_tree_root irq_pirq; - int *pirq_irq; - /* pirq to emulated irq */ - int *pirq_emuirq; /* Maximum physical-address bitwidth supported by this guest. */ unsigned int physaddr_bitsize; diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index b3394ae28c..47f9bc9ab8 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -204,7 +204,8 @@ int vmsi_deliver( struct domain *d, int vector, uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t trig_mode); -int vmsi_deliver_pirq(struct domain *d, int pirq); +struct hvm_pirq_dpci; +int vmsi_deliver_pirq(struct domain *d, const struct hvm_pirq_dpci *); int hvm_girq_dest_2_vcpu_id(struct domain *d, uint8_t dest, uint8_t dest_mode); #define hvm_paging_enabled(v) \ diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h index 5399cb55c4..bf62e8bcc5 100644 --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -7,6 +7,7 @@ #include <asm/atomic.h> #include <xen/cpumask.h> #include <xen/smp.h> +#include <xen/hvm/irq.h> #include <irq_vectors.h> #include <asm/percpu.h> @@ -105,6 +106,20 @@ extern unsigned int io_apic_irqs; DECLARE_PER_CPU(unsigned int, irq_count); +struct pirq; +struct arch_pirq { + int irq; + union { + struct hvm_pirq { + int emuirq; + struct hvm_pirq_dpci dpci; + } hvm; + }; +}; + +#define pirq_dpci(pirq) ((pirq) ? &(pirq)->arch.hvm.dpci : NULL) +#define dpci_pirq(pd) container_of(pd, struct pirq, arch.hvm.dpci) + int pirq_shared(struct domain *d , int irq); int map_domain_pirq(struct domain *d, int pirq, int irq, int type, @@ -114,7 +129,7 @@ int get_free_pirq(struct domain *d, int type, int index); void free_domain_pirqs(struct domain *d); int map_domain_emuirq_pirq(struct domain *d, int pirq, int irq); int unmap_domain_pirq_emuirq(struct domain *d, int pirq); -int hvm_domain_use_pirq(struct domain *d, int irq); +bool_t hvm_domain_use_pirq(const struct domain *, const struct pirq *); /* A cpu has been removed from cpu_online_mask. Re-set irq affinities. */ void fixup_irqs(void); @@ -149,13 +164,13 @@ void irq_set_affinity(struct irq_desc *, const cpumask_t *mask); int init_domain_irq_mapping(struct domain *); void cleanup_domain_irq_mapping(struct domain *); -#define domain_pirq_to_irq(d, pirq) ((d)->arch.pirq_irq[pirq]) +#define domain_pirq_to_irq(d, pirq) pirq_field(d, pirq, arch.irq) #define domain_irq_to_pirq(d, irq) ({ \ void *__ret = radix_tree_lookup(&(d)->arch.irq_pirq, irq); \ __ret ? radix_tree_ptr_to_int(__ret) : 0; \ }) #define PIRQ_ALLOCATED -1 -#define domain_pirq_to_emuirq(d, pirq) ((d)->arch.pirq_emuirq[pirq]) +#define domain_pirq_to_emuirq(d, pirq) pirq_field(d, pirq, arch.hvm.emuirq) #define domain_emuirq_to_pirq(d, emuirq) ({ \ void *__ret = radix_tree_lookup(&(d)->arch.hvm_domain.emuirq_pirq, \ emuirq); \ diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index ddebbe14a9..765e1328fa 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -38,6 +38,12 @@ struct vcpu_guest_context *alloc_vcpu_guest_context(void); void free_vcpu_guest_context(struct vcpu_guest_context *); #endif +/* Allocate/free a PIRQ structure. */ +#ifndef alloc_pirq_struct +struct pirq *alloc_pirq_struct(struct domain *); +#endif +void free_pirq_struct(void *); + /* * Initialise/destroy arch-specific details of a VCPU. * - vcpu_initialise() is called after the basic generic fields of the diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index f39207c8d0..257cb3a5f0 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -36,7 +36,7 @@ void send_guest_global_virq(struct domain *d, int virq); * @pirq: Physical IRQ number * Returns TRUE if the delivery port was already pending. */ -int send_guest_pirq(struct domain *d, int pirq); +int send_guest_pirq(struct domain *, const struct pirq *); /* Send a notification from a given domain's event-channel port. */ int evtchn_send(struct domain *d, unsigned int lport); diff --git a/xen/include/xen/hvm/irq.h b/xen/include/xen/hvm/irq.h index e20cdcf1a8..b91c48de9b 100644 --- a/xen/include/xen/hvm/irq.h +++ b/xen/include/xen/hvm/irq.h @@ -25,7 +25,7 @@ #include <xen/types.h> #include <xen/spinlock.h> #include <xen/tasklet.h> -#include <asm/irq.h> +#include <xen/timer.h> #include <public/hvm/save.h> struct dev_intx_gsi_link { @@ -38,11 +38,15 @@ struct dev_intx_gsi_link { #define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0 #define _HVM_IRQ_DPCI_MACH_MSI_SHIFT 1 +#define _HVM_IRQ_DPCI_MAPPED_SHIFT 2 +#define _HVM_IRQ_DPCI_EOI_LATCH_SHIFT 3 #define _HVM_IRQ_DPCI_GUEST_PCI_SHIFT 4 #define _HVM_IRQ_DPCI_GUEST_MSI_SHIFT 5 #define _HVM_IRQ_DPCI_TRANSLATE_SHIFT 15 #define HVM_IRQ_DPCI_MACH_PCI (1 << _HVM_IRQ_DPCI_MACH_PCI_SHIFT) #define HVM_IRQ_DPCI_MACH_MSI (1 << _HVM_IRQ_DPCI_MACH_MSI_SHIFT) +#define HVM_IRQ_DPCI_MAPPED (1 << _HVM_IRQ_DPCI_MAPPED_SHIFT) +#define HVM_IRQ_DPCI_EOI_LATCH (1 << _HVM_IRQ_DPCI_EOI_LATCH_SHIFT) #define HVM_IRQ_DPCI_GUEST_PCI (1 << _HVM_IRQ_DPCI_GUEST_PCI_SHIFT) #define HVM_IRQ_DPCI_GUEST_MSI (1 << _HVM_IRQ_DPCI_GUEST_MSI_SHIFT) #define HVM_IRQ_DPCI_TRANSLATE (1 << _HVM_IRQ_DPCI_TRANSLATE_SHIFT) @@ -63,14 +67,6 @@ struct hvm_gmsi_info { int dest_vcpu_id; /* -1 :multi-dest, non-negative: dest_vcpu_id */ }; -struct hvm_mirq_dpci_mapping { - uint32_t flags; - int pending; - struct list_head digl_list; - struct domain *dom; - struct hvm_gmsi_info gmsi; -}; - struct hvm_girq_dpci_mapping { struct list_head list; uint8_t device; @@ -88,20 +84,33 @@ struct hvm_girq_dpci_mapping { /* Protected by domain's event_lock */ struct hvm_irq_dpci { - /* Machine IRQ to guest device/intx mapping. */ - unsigned long *mapping; - struct hvm_mirq_dpci_mapping *mirq; - unsigned long *dirq_mask; /* Guest IRQ to guest device/intx mapping. */ struct list_head girq[NR_HVM_IRQS]; /* Record of mapped ISA IRQs */ DECLARE_BITMAP(isairq_map, NR_ISAIRQS); /* Record of mapped Links */ uint8_t link_cnt[NR_LINK]; - struct timer *hvm_timer; struct tasklet dirq_tasklet; }; +/* Machine IRQ to guest device/intx mapping. */ +struct hvm_pirq_dpci { + uint32_t flags; + bool_t masked; + uint16_t pending; + struct list_head digl_list; + struct domain *dom; + struct hvm_gmsi_info gmsi; + struct timer timer; +}; + +void pt_pirq_init(struct domain *, struct hvm_pirq_dpci *); +bool_t pt_pirq_cleanup_check(struct hvm_pirq_dpci *); +int pt_pirq_iterate(struct domain *d, + int (*cb)(struct domain *, + struct hvm_pirq_dpci *, void *arg), + void *arg); + /* Modify state of a PCI INTx wire. */ void hvm_pci_intx_assert( struct domain *d, unsigned int device, unsigned int intx); diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index d4c94d0c16..a8a60f9ae3 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -88,7 +88,9 @@ int iommu_unmap_page(struct domain *d, unsigned long gfn); void iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, int order, int present); void iommu_set_pgd(struct domain *d); void iommu_domain_teardown(struct domain *d); -int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq); + +struct pirq; +int hvm_do_IRQ_dpci(struct domain *, struct pirq *); int dpci_ioport_intercept(ioreq_t *p); int pt_irq_create_bind_vtd(struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind); diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h index 02456e4a80..b771fa2d75 100644 --- a/xen/include/xen/irq.h +++ b/xen/include/xen/irq.h @@ -3,6 +3,7 @@ #include <xen/config.h> #include <xen/cpumask.h> +#include <xen/rcupdate.h> #include <xen/spinlock.h> #include <xen/time.h> #include <xen/list.h> @@ -135,13 +136,42 @@ extern void no_action(int cpl, void *dev_id, struct cpu_user_regs *regs); struct domain; struct vcpu; -extern int pirq_guest_eoi(struct domain *d, int irq); + +struct pirq { + int pirq; + u16 evtchn; + bool_t masked; + struct rcu_head rcu_head; + struct arch_pirq arch; +}; + +#define pirq_info(d, p) ((struct pirq *)radix_tree_lookup(&(d)->pirq_tree, p)) + +/* Use this instead of pirq_info() if the structure may need allocating. */ +extern struct pirq *pirq_get_info(struct domain *, int pirq); + +#define pirq_field(d, p, f) ({ \ + const struct pirq *__pi = pirq_info(d, p); \ + __pi ? __pi->f : 0; \ +}) +#define pirq_to_evtchn(d, pirq) pirq_field(d, pirq, evtchn) +#define pirq_masked(d, pirq) pirq_field(d, pirq, masked) + +void pirq_cleanup_check(struct pirq *, struct domain *); + +#define pirq_cleanup_check(pirq, d) \ + ((pirq)->evtchn ? pirq_cleanup_check(pirq, d) : (void)0) + +extern void pirq_guest_eoi(struct domain *, struct pirq *); +extern void desc_guest_eoi(struct domain *, struct irq_desc *, struct pirq *); extern int pirq_guest_unmask(struct domain *d); -extern int pirq_guest_bind(struct vcpu *v, int irq, int will_share); -extern void pirq_guest_unbind(struct domain *d, int irq); +extern int pirq_guest_bind(struct vcpu *, struct pirq *, int will_share); +extern void pirq_guest_unbind(struct domain *d, struct pirq *); extern void pirq_set_affinity(struct domain *d, int irq, const cpumask_t *); extern irq_desc_t *domain_spin_lock_irq_desc( struct domain *d, int irq, unsigned long *pflags); +extern irq_desc_t *pirq_spin_lock_irq_desc( + struct domain *, const struct pirq *, unsigned long *pflags); static inline void set_native_irq_info(unsigned int irq, const cpumask_t *mask) { diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h index 79082d1721..49eabbcd49 100644 --- a/xen/include/xen/pci.h +++ b/xen/include/xen/pci.h @@ -117,8 +117,9 @@ int pci_find_cap_offset(u8 bus, u8 dev, u8 func, u8 cap); int pci_find_next_cap(u8 bus, unsigned int devfn, u8 pos, int cap); int pci_find_ext_capability(int seg, int bus, int devfn, int cap); -int msixtbl_pt_register(struct domain *d, int pirq, uint64_t gtable); -void msixtbl_pt_unregister(struct domain *d, int pirq); +struct pirq; +int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable); +void msixtbl_pt_unregister(struct domain *, struct pirq *); void msixtbl_pt_cleanup(struct domain *d); void pci_enable_acs(struct pci_dev *pdev); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index e3eab706a3..902cd07418 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -12,6 +12,7 @@ #include <xen/rcupdate.h> #include <xen/cpumask.h> #include <xen/nodemask.h> +#include <xen/radix-tree.h> #include <xen/multicall.h> #include <public/xen.h> #include <public/domctl.h> @@ -227,13 +228,11 @@ struct domain struct grant_table *grant_table; /* - * Interrupt to event-channel mappings. Updates should be protected by the - * domain's event-channel spinlock. Read accesses can also synchronise on - * the lock, but races don't usually matter. + * Interrupt to event-channel mappings and other per-guest-pirq data. + * Protected by the domain's event-channel spinlock. */ unsigned int nr_pirqs; - u16 *pirq_to_evtchn; - unsigned long *pirq_mask; + struct radix_tree_root pirq_tree; /* I/O capabilities (access to IRQs and memory-mapped I/O). */ struct rangeset *iomem_caps; |