aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/xen
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2011-05-01 13:17:44 +0100
committerJan Beulich <jbeulich@novell.com>2011-05-01 13:17:44 +0100
commit76ce27755b87aa5a91ce0f5a02e560ab5c0515e4 (patch)
treef2a7fcbd31e863d8a0238782c12a716bbc0f21e9 /xen/include/xen
parentf22f2fe48d144141fffd42a380383f45efbea8e3 (diff)
downloadxen-76ce27755b87aa5a91ce0f5a02e560ab5c0515e4.tar.gz
xen-76ce27755b87aa5a91ce0f5a02e560ab5c0515e4.tar.bz2
xen-76ce27755b87aa5a91ce0f5a02e560ab5c0515e4.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. Another thing to consider is whether it's worth storing the pirq number in struct pirq, to avoid passing the number and a pointer to quite a number of functions. Note that ia64, the build of which is broken currently anyway, is only partially fixed up. 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.h39
-rw-r--r--xen/include/xen/iommu.h4
-rw-r--r--xen/include/xen/irq.h34
-rw-r--r--xen/include/xen/pci.h5
-rw-r--r--xen/include/xen/radix-tree.h3
-rw-r--r--xen/include/xen/sched.h9
8 files changed, 75 insertions, 27 deletions
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index ddebbe14a9..72ec6c1c06 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
+#define free_pirq_struct xfree
+
/*
* 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 f21b02ceeb..5b2f77c63a 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 *, unsigned int pirq,
+ 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);
@@ -120,4 +129,6 @@ void hvm_maybe_deassert_evtchn_irq(void);
void hvm_assert_evtchn_irq(struct vcpu *v);
void hvm_set_callback_via(struct domain *d, uint64_t via);
+int vmsi_deliver(struct domain *, const struct hvm_pirq_dpci *);
+
#endif /* __XEN_HVM_IRQ_H__ */
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index 2dee3f2982..4d4f4c4bf3 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..be729346b7 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -135,13 +135,41 @@ 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 {
+ u16 evtchn;
+ bool_t masked;
+ 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 *, int);
+
+#define pirq_cleanup_check(info, d, pirq) \
+ ((info)->evtchn ? pirq_cleanup_check(info, d, pirq) : (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 *, int pirq, struct pirq *,
+ int will_share);
+extern void pirq_guest_unbind(struct domain *d, int pirq, 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 40c9847335..dbd9d8c262 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 pci_enable_acs(struct pci_dev *pdev);
#endif /* __XEN_PCI_H__ */
diff --git a/xen/include/xen/radix-tree.h b/xen/include/xen/radix-tree.h
index c32d5b83bd..289fe05dfc 100644
--- a/xen/include/xen/radix-tree.h
+++ b/xen/include/xen/radix-tree.h
@@ -72,6 +72,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index,
void(*node_free)(struct radix_tree_node *));
unsigned int
radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
- unsigned long first_index, unsigned int max_items);
+ unsigned long first_index, unsigned int max_items,
+ unsigned long *indexes);
#endif /* _XEN_RADIX_TREE_H */
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 17fac57dfd..2adb3262af 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -21,6 +21,7 @@
#include <xen/irq.h>
#include <xen/mm.h>
#include <xen/tasklet.h>
+#include <xen/radix-tree.h>
#include <public/mem_event.h>
#include <xen/cpumask.h>
#include <xen/nodemask.h>
@@ -234,13 +235,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;