aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2011-06-23 11:32:43 +0100
committerJan Beulich <jbeulich@novell.com>2011-06-23 11:32:43 +0100
commitc24536b636f23e4d3202968fcad129d979881e2c (patch)
treee3e188d484b371f8770714bc0453f6395d6da241 /xen/include
parenteebfd58f212c5fb75e602ac1aa126863452375da (diff)
downloadxen-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.h18
-rw-r--r--xen/include/asm-x86/domain.h3
-rw-r--r--xen/include/asm-x86/hvm/hvm.h3
-rw-r--r--xen/include/asm-x86/irq.h21
-rw-r--r--xen/include/xen/domain.h6
-rw-r--r--xen/include/xen/event.h2
-rw-r--r--xen/include/xen/hvm/irq.h37
-rw-r--r--xen/include/xen/iommu.h4
-rw-r--r--xen/include/xen/irq.h36
-rw-r--r--xen/include/xen/pci.h5
-rw-r--r--xen/include/xen/sched.h9
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;