aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/xen
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/xen
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/xen')
-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
7 files changed, 73 insertions, 26 deletions
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;