|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 4/4] xen/x86: Rework inclusion between struct pirq and struct hvm_pirq_dpci
From: Julien Grall <jgrall@xxxxxxxxxx>
At the moment, alloc_pirq_struct() relies on the field 'arch' to be the
last member of the structure.
As this is used for computing the size of the structure, the value will
be miscomputed if a new field is added afterwards.
Such quirkiness makes quite difficult to understand how struct pirq
works. Given that struct hvm_pirq_dpci is only used in combination of a
struct pirq, we can inverse the inclusion. i.e pirq will now be
contained in struct hvm_pirq_dpci.
As the field pirq.arch.hvm.emuirq is as well HVM specific, this is now
moved in struct hvm_pirq_dpci.
There is a few side effects with this changes:
- We now need to distinguish between PIRQ allocated for HVM and PV
guests. This is to allow us to know what we are freeing.
- container_of is not able to cater with const and non-const at the
same time. So we need to introduce two macros (const and
non-const).
Lastly all the HVM specific pirq code can now be moved in hvm/irq.h
allowing use to drop the include from irq.h. This is one less header
included treewide.
Signed-off-by: Julien Grall <jgrall@xxxxxxxxxx>
---
xen/arch/arm/irq.c | 5 +++++
xen/arch/x86/hvm/irq.c | 7 ++++---
xen/arch/x86/irq.c | 39 ++++++++++++++++++++++++-----------
xen/common/domain.c | 7 +------
xen/drivers/passthrough/io.c | 1 +
xen/include/asm-x86/hvm/irq.h | 19 +++++++++++++++++
xen/include/asm-x86/irq.h | 19 +++--------------
xen/include/xen/domain.h | 3 +++
8 files changed, 63 insertions(+), 37 deletions(-)
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 3877657a52..fd108ea3a5 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -582,6 +582,11 @@ struct pirq *alloc_pirq_struct(struct domain *d)
return NULL;
}
+void arch_free_pirq_struct(struct rcu_head *head)
+{
+ ASSERT_UNREACHABLE();
+}
+
/*
* These are all unreachable given an alloc_pirq_struct
* which returns NULL, all callers try to lookup struct pirq first
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index c684422b24..e0bb0a8b90 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -29,7 +29,8 @@
bool hvm_domain_use_pirq(const struct domain *d, const struct pirq *pirq)
{
- return is_hvm_domain(d) && pirq && pirq->arch.hvm.emuirq != IRQ_UNBOUND;
+ return is_hvm_domain(d) && pirq &&
+ const_pirq_dpci(pirq)->emuirq != IRQ_UNBOUND;
}
/* Must be called with hvm_domain->irq_lock hold */
@@ -396,7 +397,7 @@ int hvm_inject_msi(struct domain *d, uint64_t addr,
uint32_t data)
struct pirq *info = pirq_info(d, pirq);
/* if it is the first time, allocate the pirq */
- if ( !info || info->arch.hvm.emuirq == IRQ_UNBOUND )
+ if ( !info || pirq_dpci(info)->emuirq == IRQ_UNBOUND )
{
int rc;
@@ -409,7 +410,7 @@ int hvm_inject_msi(struct domain *d, uint64_t addr,
uint32_t data)
if ( !info )
return -EBUSY;
}
- else if ( info->arch.hvm.emuirq != IRQ_MSI_EMU )
+ else if ( pirq_dpci(info)->emuirq != IRQ_MSI_EMU )
return -EINVAL;
send_guest_pirq(d, info);
return 0;
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 310ac00a60..3e01101f88 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1286,22 +1286,37 @@ void cleanup_domain_irq_mapping(struct domain *d)
struct pirq *alloc_pirq_struct(struct domain *d)
{
- size_t sz = is_hvm_domain(d) ? sizeof(struct pirq) :
- offsetof(struct pirq, arch.hvm);
- struct pirq *pirq = xzalloc_bytes(sz);
+ struct pirq *pirq;
- if ( pirq )
+ if ( is_hvm_domain(d) )
{
- if ( is_hvm_domain(d) )
+ struct hvm_pirq_dpci *dpci = xzalloc(struct hvm_pirq_dpci);
+
+ if ( dpci )
{
- pirq->arch.hvm.emuirq = IRQ_UNBOUND;
- pt_pirq_init(d, &pirq->arch.hvm.dpci);
+ pt_pirq_init(d, dpci);
+ pirq = dpci_pirq(dpci);
+ pirq->arch.hvm = true;
}
+ else
+ pirq = NULL;
}
+ else
+ pirq = xzalloc(struct pirq);
return pirq;
}
+void arch_free_pirq_struct(struct rcu_head *head)
+{
+ struct pirq *pirq = container_of(head, struct pirq, rcu_head);
+
+ if ( pirq->arch.hvm )
+ xfree(pirq_dpci(pirq));
+ else
+ xfree(pirq);
+}
+
void (pirq_cleanup_check)(struct pirq *pirq, struct domain *d)
{
/*
@@ -1315,9 +1330,9 @@ void (pirq_cleanup_check)(struct pirq *pirq, struct
domain *d)
if ( is_hvm_domain(d) )
{
- if ( pirq->arch.hvm.emuirq != IRQ_UNBOUND )
+ if ( pirq_dpci(pirq)->emuirq != IRQ_UNBOUND )
return;
- if ( !pt_pirq_cleanup_check(&pirq->arch.hvm.dpci) )
+ if ( !pt_pirq_cleanup_check(pirq_dpci(pirq)) )
return;
}
@@ -2029,7 +2044,7 @@ static inline bool is_free_pirq(const struct domain *d,
const struct pirq *pirq)
{
return !pirq || (!pirq->arch.irq && (!is_hvm_domain(d) ||
- pirq->arch.hvm.emuirq == IRQ_UNBOUND));
+ const_pirq_dpci(pirq)->emuirq == IRQ_UNBOUND));
}
int get_free_pirq(struct domain *d, int type)
@@ -2724,7 +2739,7 @@ int map_domain_emuirq_pirq(struct domain *d, int pirq,
int emuirq)
return err;
}
}
- info->arch.hvm.emuirq = emuirq;
+ pirq_dpci(info)->emuirq = emuirq;
return 0;
}
@@ -2754,7 +2769,7 @@ int unmap_domain_pirq_emuirq(struct domain *d, int pirq)
info = pirq_info(d, pirq);
if ( info )
{
- info->arch.hvm.emuirq = IRQ_UNBOUND;
+ pirq_dpci(info)->emuirq = IRQ_UNBOUND;
pirq_cleanup_check(info, d);
}
if ( emuirq != IRQ_PT )
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 0b1103fdb2..7f04da79e6 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -1625,16 +1625,11 @@ struct pirq *pirq_get_info(struct domain *d, int pirq)
return info;
}
-static void _free_pirq_struct(struct rcu_head *head)
-{
- xfree(container_of(head, struct pirq, rcu_head));
-}
-
void free_pirq_struct(void *ptr)
{
struct pirq *pirq = ptr;
- call_rcu(&pirq->rcu_head, _free_pirq_struct);
+ call_rcu(&pirq->rcu_head, arch_free_pirq_struct);
}
struct migrate_info {
diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c
index b292e79382..e7b288b4aa 100644
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -769,6 +769,7 @@ int pt_irq_destroy_bind(
void pt_pirq_init(struct domain *d, struct hvm_pirq_dpci *dpci)
{
+ dpci->emuirq = IRQ_UNBOUND;
INIT_LIST_HEAD(&dpci->digl_list);
dpci->gmsi.dest_vcpu_id = -1;
}
diff --git a/xen/include/asm-x86/hvm/irq.h b/xen/include/asm-x86/hvm/irq.h
index 5b7e90c179..0ccfaad53b 100644
--- a/xen/include/asm-x86/hvm/irq.h
+++ b/xen/include/asm-x86/hvm/irq.h
@@ -21,6 +21,7 @@
#ifndef __ASM_X86_HVM_IRQ_H__
#define __ASM_X86_HVM_IRQ_H__
+#include <xen/irq.h>
#include <xen/timer.h>
#include <asm/hvm/hvm.h>
@@ -171,8 +172,26 @@ struct hvm_pirq_dpci {
struct hvm_gmsi_info gmsi;
struct timer timer;
struct list_head softirq_list;
+ int emuirq;
+ struct pirq pirq;
};
+#define pirq_dpci(p) \
+ ((p) ? container_of(p, struct hvm_pirq_dpci, pirq) : NULL)
+#define const_pirq_dpci(p) \
+ ((p) ? container_of(p, const struct hvm_pirq_dpci, pirq) : NULL)
+
+#define dpci_pirq(pd) (&(pd)->pirq)
+
+#define domain_pirq_to_emuirq(d, p) ({ \
+ struct pirq *__pi = pirq_info(d, p); \
+ __pi ? pirq_dpci(__pi)->emuirq : IRQ_UNBOUND; \
+})
+#define domain_emuirq_to_pirq(d, emuirq) ({ \
+ void *__ret = radix_tree_lookup(&(d)->arch.hvm.emuirq_pirq, emuirq);\
+ __ret ? radix_tree_ptr_to_int(__ret) : IRQ_UNBOUND; \
+})
+
void pt_pirq_init(struct domain *, struct hvm_pirq_dpci *);
bool pt_pirq_cleanup_check(struct hvm_pirq_dpci *);
int pt_pirq_iterate(struct domain *d,
diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h
index 44aefc8f03..07a63bae04 100644
--- a/xen/include/asm-x86/irq.h
+++ b/xen/include/asm-x86/irq.h
@@ -8,7 +8,6 @@
#include <xen/cpumask.h>
#include <xen/percpu.h>
#include <xen/smp.h>
-#include <asm/hvm/irq.h>
extern unsigned int nr_irqs_gsi;
extern unsigned int nr_irqs;
@@ -133,17 +132,10 @@ DECLARE_PER_CPU(unsigned int, irq_count);
struct arch_pirq {
int irq;
- union {
- struct hvm_pirq {
- int emuirq;
- struct hvm_pirq_dpci dpci;
- } hvm;
- };
+ /* Is the PIRQ associated to an HVM domain? */
+ bool 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,
@@ -198,12 +190,7 @@ void cleanup_domain_irq_mapping(struct domain *);
__ret ? radix_tree_ptr_to_int(__ret) : 0; \
})
#define PIRQ_ALLOCATED -1
-#define domain_pirq_to_emuirq(d, pirq) pirq_field(d, pirq, \
- arch.hvm.emuirq, IRQ_UNBOUND)
-#define domain_emuirq_to_pirq(d, emuirq) ({ \
- void *__ret = radix_tree_lookup(&(d)->arch.hvm.emuirq_pirq, emuirq);\
- __ret ? radix_tree_ptr_to_int(__ret) : IRQ_UNBOUND; \
-})
+
#define IRQ_UNBOUND -1
#define IRQ_PT -2
#define IRQ_MSI_EMU -3
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 89bf0a1721..99aea630d4 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -42,6 +42,9 @@ void free_vcpu_struct(struct vcpu *v);
/* Allocate/free a PIRQ structure. */
struct pirq *alloc_pirq_struct(struct domain *);
+
+/* Per-arch callback used by the RCU */
+void arch_free_pirq_struct(struct rcu_head *head);
void free_pirq_struct(void *);
/*
--
2.24.0
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |