Function iommu_do_pci_domctl() is the main entry for pci-subset
iommu-related domctl-op, and shall be wrapped with CONFIG_MGMT_HYPERCALLS.
Tracking its calling chain, the following functions shall all be wrapped
with CONFIG_MGMT_HYPERCALLS:
- iommu_do_pci_domctl
- iommu_get_device_group
- xsm_get_device_group
- iommu_ops.get_device_group_id
- amd_iommu_group_id/intel_iommu_group_id
- device_assigned
- xsm_assign_device
- assign_device
- iommu_ops.assign_device
- intel_iommu_assign_device/amd_iommu_assign_device
- xsm_deassign_device
- deassign_device
- iommu_ops.reassign_device
- reassign_device_ownership/reassign_device
Otherwise all the functions will become unreachable when MGMT_HYPERCALLS=n,
and hence violating Misra rule 2.1
Signed-off-by: Penny Zheng <Penny.Zheng@amd.com>
---
v1 -> v2:
- adapt to changes of "unify DOMCTL to MGMT_HYPERCALLS"
- wrap XEN_DOMCTL_assign_device{test_assign_device,deassign_device,
get_device_group}-case transiently
---
v2 -> v3:
- make PCI_PASSTHROUGH(, then HAS_VPCI_GUEST_SUPPORT) depend on MGMT_HYPERCALLS
- add wrapping for iommu_remove_dt_device/iommu_dt_device_is_assigned_locked/
arm_smmu_detach_dev/arm_smmu_domain_remove_master
- fold commit
"xen/xsm: wrap xsm-iommu-related functions with CONFIG_MGMT_HYPERCALLS" in
- fix overly long #ifdef
- add missing wrapping in xsm/dummy.h
- address "violating Misra rule 2.1" in commit message
- remove transient wrapping of
XEN_DOMCTL_assign_device{test_assign_device,deassign_device,get_device_group}-case
---
v3 -> v4:
- move codes to wrap with a single #ifdef
- split into PCI related subset and DT subset
---
xen/drivers/passthrough/amd/pci_amd_iommu.c | 20 ++++----
xen/drivers/passthrough/pci.c | 52 +++++++++++----------
xen/drivers/passthrough/vtd/iommu.c | 6 ++-
xen/include/xsm/dummy.h | 6 ++-
xen/include/xsm/xsm.h | 12 +++--
xen/xsm/dummy.c | 6 ++-
xen/xsm/flask/hooks.c | 12 +++--
7 files changed, 68 insertions(+), 46 deletions(-)
diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c
index 3a14770855..576b36af92 100644
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c
@@ -461,6 +461,7 @@ static void amd_iommu_disable_domain_device(const struct domain *domain,
spin_unlock_irqrestore(&iommu->lock, flags);
}
+#ifdef CONFIG_MGMT_HYPERCALLS
static int cf_check reassign_device(
struct domain *source, struct domain *target, u8 devfn,
struct pci_dev *pdev)
@@ -551,6 +552,14 @@ static int cf_check amd_iommu_assign_device(
return rc;
}
+static int cf_check amd_iommu_group_id(u16 seg, u8 bus, u8 devfn)
+{
+ unsigned int bdf = PCI_BDF(bus, devfn);
+
+ return (bdf < ivrs_bdf_entries) ? get_dma_requestor_id(seg, bdf) : bdf;
+}
+#endif /* CONFIG_MGMT_HYPERCALLS */
+
static void cf_check amd_iommu_clear_root_pgtable(struct domain *d)
{
struct domain_iommu *hd = dom_iommu(d);
@@ -698,13 +707,6 @@ static int cf_check amd_iommu_remove_device(u8 devfn, struct pci_dev *pdev)
return 0;
}
-static int cf_check amd_iommu_group_id(u16 seg, u8 bus, u8 devfn)
-{
- unsigned int bdf = PCI_BDF(bus, devfn);
-
- return (bdf < ivrs_bdf_entries) ? get_dma_requestor_id(seg, bdf) : bdf;
-}
-
#include <asm/io_apic.h>
static void amd_dump_page_table_level(struct page_info *pg, int level,
@@ -772,14 +774,16 @@ static const struct iommu_ops __initconst_cf_clobber _iommu_ops = {
.quarantine_init = amd_iommu_quarantine_init,
.add_device = amd_iommu_add_device,
.remove_device = amd_iommu_remove_device,
- .assign_device = amd_iommu_assign_device,
.teardown = amd_iommu_domain_destroy,
.clear_root_pgtable = amd_iommu_clear_root_pgtable,
.map_page = amd_iommu_map_page,
.unmap_page = amd_iommu_unmap_page,
.iotlb_flush = amd_iommu_flush_iotlb_pages,
+#ifdef CONFIG_MGMT_HYPERCALLS
+ .assign_device = amd_iommu_assign_device,
.reassign_device = reassign_device,
.get_device_group_id = amd_iommu_group_id,
+#endif
.enable_x2apic = iov_enable_xt,
.update_ire_from_apic = amd_iommu_ioapic_update_ire,
.update_ire_from_msi = amd_iommu_msi_msg_update_ire,
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index 422e45f5a6..8ab229bfe7 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -878,6 +878,7 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn)
return ret;
}
+#ifdef CONFIG_MGMT_HYPERCALLS
/* Caller should hold the pcidevs_lock */
static int deassign_device(struct domain *d, uint16_t seg, uint8_t bus,
uint8_t devfn)
@@ -946,7 +947,6 @@ static int deassign_device(struct domain *d, uint16_t seg, uint8_t bus,
return ret;
}
-#ifdef CONFIG_MGMT_HYPERCALLS
int pci_release_devices(struct domain *d)
{
int combined_ret;
@@ -1484,6 +1484,7 @@ static int iommu_remove_device(struct pci_dev *pdev)
return iommu_call(hd->platform_ops, remove_device, devfn, pci_to_dev(pdev));
}
+#ifdef CONFIG_MGMT_HYPERCALLS
static int device_assigned(u16 seg, u8 bus, u8 devfn)
{
struct pci_dev *pdev;
@@ -1648,30 +1649,6 @@ static int iommu_get_device_group(
return i;
}
-void iommu_dev_iotlb_flush_timeout(struct domain *d, struct pci_dev *pdev)
-{
- pcidevs_lock();
-
- disable_ats_device(pdev);
-
- ASSERT(pdev->domain);
- if ( d != pdev->domain )
- {
- pcidevs_unlock();
- return;
- }
-
- pdev->broken = true;
-
- if ( !d->is_shutting_down && printk_ratelimit() )
- printk(XENLOG_ERR "dom%d: ATS device %pp flush failed\n",
- d->domain_id, &pdev->sbdf);
- if ( !is_hardware_domain(d) )
- domain_crash(d);
-
- pcidevs_unlock();
-}
-
int iommu_do_pci_domctl(
struct xen_domctl *domctl, struct domain *d,
XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
@@ -1805,6 +1782,31 @@ int iommu_do_pci_domctl(
return ret;
}
+#endif /* CONFIG_MGMT_HYPERCALLS */
+
+void iommu_dev_iotlb_flush_timeout(struct domain *d, struct pci_dev *pdev)
+{
+ pcidevs_lock();
+
+ disable_ats_device(pdev);
+
+ ASSERT(pdev->domain);
+ if ( d != pdev->domain )
+ {
+ pcidevs_unlock();
+ return;
+ }
+
+ pdev->broken = true;
+
+ if ( !d->is_shutting_down && printk_ratelimit() )
+ printk(XENLOG_ERR "dom%d: ATS device %pp flush failed\n",
+ d->domain_id, &pdev->sbdf);
+ if ( !is_hardware_domain(d) )
+ domain_crash(d);
+
+ pcidevs_unlock();
+}
struct segment_iter {
int (*handler)(struct pci_dev *pdev, void *arg);
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index 90f36ac22b..ad2e657bca 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -2742,6 +2742,7 @@ static int __init cf_check vtd_setup(void)
return ret;
}
+#ifdef CONFIG_MGMT_HYPERCALLS
static int cf_check reassign_device_ownership(
struct domain *source,
struct domain *target,
@@ -2937,6 +2938,7 @@ static int cf_check intel_iommu_group_id(u16 seg, u8 bus, u8 devfn)
return PCI_BDF(bus, devfn);
}
+#endif /* CONFIG_MGMT_HYPERCALLS */
static int __must_check cf_check vtd_suspend(void)
{
@@ -3245,14 +3247,16 @@ static const struct iommu_ops __initconst_cf_clobber vtd_ops = {
.add_device = intel_iommu_add_device,
.enable_device = intel_iommu_enable_device,
.remove_device = intel_iommu_remove_device,
- .assign_device = intel_iommu_assign_device,
.teardown = iommu_domain_teardown,
.clear_root_pgtable = iommu_clear_root_pgtable,
.map_page = intel_iommu_map_page,
.unmap_page = intel_iommu_unmap_page,
.lookup_page = intel_iommu_lookup_page,
+#ifdef CONFIG_MGMT_HYPERCALLS
+ .assign_device = intel_iommu_assign_device,
.reassign_device = reassign_device_ownership,
.get_device_group_id = intel_iommu_group_id,
+#endif
.enable_x2apic = intel_iommu_enable_eim,
.disable_x2apic = intel_iommu_disable_eim,
.update_ire_from_apic = io_apic_write_remap_rte,
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index a598d74f1f..83972d36b7 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -407,7 +407,8 @@ static XSM_INLINE int cf_check xsm_get_vnumainfo(
return xsm_default_action(action, current->domain, d);
}
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
+#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_MGMT_HYPERCALLS)
+#ifdef CONFIG_HAS_PCI
static XSM_INLINE int cf_check xsm_get_device_group(
XSM_DEFAULT_ARG uint32_t machine_bdf)
{
@@ -429,7 +430,8 @@ static XSM_INLINE int cf_check xsm_deassign_device(
return xsm_default_action(action, current->domain, d);
}
-#endif /* HAS_PASSTHROUGH && HAS_PCI */
+#endif /* CONFIG_HAS_PCI */
+#endif /* HAS_PASSTHROUGH && MGMT_HYPERCALLS */
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
static XSM_INLINE int cf_check xsm_assign_dtdevice(
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 154a4b8a92..f2e92645ef 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -123,11 +123,13 @@ struct xsm_ops {
int (*pci_config_permission)(struct domain *d, uint32_t machine_bdf,
uint16_t start, uint16_t end, uint8_t access);
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
+#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_MGMT_HYPERCALLS)
+#ifdef CONFIG_HAS_PCI
int (*get_device_group)(uint32_t machine_bdf);
int (*assign_device)(struct domain *d, uint32_t machine_bdf);
int (*deassign_device)(struct domain *d, uint32_t machine_bdf);
-#endif
+#endif /* CONFIG_HAS_PCI */
+#endif /* HAS_PASSTHROUGH && MGMT_HYPERCALLS */
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
int (*assign_dtdevice)(struct domain *d, const char *dtpath);
@@ -524,7 +526,8 @@ static inline int xsm_pci_config_permission(
return alternative_call(xsm_ops.pci_config_permission, d, machine_bdf, start, end, access);
}
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
+#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_MGMT_HYPERCALLS)
+#ifdef CONFIG_HAS_PCI
static inline int xsm_get_device_group(xsm_default_t def, uint32_t machine_bdf)
{
return alternative_call(xsm_ops.get_device_group, machine_bdf);
@@ -541,7 +544,8 @@ static inline int xsm_deassign_device(
{
return alternative_call(xsm_ops.deassign_device, d, machine_bdf);
}
-#endif /* HAS_PASSTHROUGH && HAS_PCI) */
+#endif /* CONFIG_HAS_PCI */
+#endif /* HAS_PASSTHROUGH && MGMT_HYPERCALLS */
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
static inline int xsm_assign_dtdevice(
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index 9774bb3bdb..0026a0963b 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -80,11 +80,13 @@ static const struct xsm_ops __initconst_cf_clobber dummy_ops = {
.pci_config_permission = xsm_pci_config_permission,
.get_vnumainfo = xsm_get_vnumainfo,
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
+#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_MGMT_HYPERCALLS)
+#ifdef CONFIG_HAS_PCI
.get_device_group = xsm_get_device_group,
.assign_device = xsm_assign_device,
.deassign_device = xsm_deassign_device,
-#endif
+#endif /* CONFIG_HAS_PCI */
+#endif /* HAS_PASSTHROUGH && MGMT_HYPERCALLS */
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
.assign_dtdevice = xsm_assign_dtdevice,
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 9b63c516e6..805a9a528e 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1388,7 +1388,8 @@ static int cf_check flask_mem_sharing(struct domain *d)
}
#endif
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
+#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_MGMT_HYPERCALLS)
+#ifdef CONFIG_HAS_PCI
static int cf_check flask_get_device_group(uint32_t machine_bdf)
{
uint32_t rsid;
@@ -1459,7 +1460,8 @@ static int cf_check flask_deassign_device(
return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE, NULL);
}
-#endif /* HAS_PASSTHROUGH && HAS_PCI */
+#endif /* CONFIG_HAS_PCI */
+#endif /* HAS_PASSTHROUGH && MGMT_HYPERCALLS */
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
static int flask_test_assign_dtdevice(const char *dtpath)
@@ -1987,11 +1989,13 @@ static const struct xsm_ops __initconst_cf_clobber flask_ops = {
.remove_from_physmap = flask_remove_from_physmap,
.map_gmfn_foreign = flask_map_gmfn_foreign,
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
+#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_MGMT_HYPERCALLS)
+#ifdef CONFIG_HAS_PCI
.get_device_group = flask_get_device_group,
.assign_device = flask_assign_device,
.deassign_device = flask_deassign_device,
-#endif
+#endif /* CONFIG_HAS_PCI */
+#endif /* HAS_PASSTHROUGH && MGMT_HYPERCALLS */
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
.assign_dtdevice = flask_assign_dtdevice,
--
2.34.1
On 21.11.2025 11:57, Penny Zheng wrote:
> xen/drivers/passthrough/amd/pci_amd_iommu.c | 20 ++++----
> xen/drivers/passthrough/pci.c | 52 +++++++++++----------
> xen/drivers/passthrough/vtd/iommu.c | 6 ++-
> xen/include/xsm/dummy.h | 6 ++-
> xen/include/xsm/xsm.h | 12 +++--
> xen/xsm/dummy.c | 6 ++-
> xen/xsm/flask/hooks.c | 12 +++--
> 7 files changed, 68 insertions(+), 46 deletions(-)
With this diffstat and there being quite a few HAS_PCI under
xen/drivers/passthrough/arm/, what's the (PCI) deal there?
> @@ -772,14 +774,16 @@ static const struct iommu_ops __initconst_cf_clobber _iommu_ops = {
> .quarantine_init = amd_iommu_quarantine_init,
> .add_device = amd_iommu_add_device,
> .remove_device = amd_iommu_remove_device,
> - .assign_device = amd_iommu_assign_device,
> .teardown = amd_iommu_domain_destroy,
> .clear_root_pgtable = amd_iommu_clear_root_pgtable,
> .map_page = amd_iommu_map_page,
> .unmap_page = amd_iommu_unmap_page,
> .iotlb_flush = amd_iommu_flush_iotlb_pages,
> +#ifdef CONFIG_MGMT_HYPERCALLS
> + .assign_device = amd_iommu_assign_device,
> .reassign_device = reassign_device,
> .get_device_group_id = amd_iommu_group_id,
> +#endif
You don't zap the hooks themselves, i.e. they end up being NULL now in
the (still only hypothetical, provided the Kconfig change will be adjusted)
case of MGMT_HYPERCALLS=n. I understand the former two hooks are still
needed for DT, but at least .get_device_group_id should be properly dealt
with in xen/iommu.h right away, imo. This would then also clarify already
here that that's the plan for the other two hooks as well.
> --- a/xen/include/xsm/dummy.h
> +++ b/xen/include/xsm/dummy.h
> @@ -407,7 +407,8 @@ static XSM_INLINE int cf_check xsm_get_vnumainfo(
> return xsm_default_action(action, current->domain, d);
> }
>
> -#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
> +#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_MGMT_HYPERCALLS)
> +#ifdef CONFIG_HAS_PCI
Why the separate #ifdef? Can't that be folded with the #if? Are there further
changes to be put inside the outer #if? (Applies again further down as well.)
> static XSM_INLINE int cf_check xsm_get_device_group(
> XSM_DEFAULT_ARG uint32_t machine_bdf)
> {
> @@ -429,7 +430,8 @@ static XSM_INLINE int cf_check xsm_deassign_device(
> return xsm_default_action(action, current->domain, d);
> }
>
> -#endif /* HAS_PASSTHROUGH && HAS_PCI */
> +#endif /* CONFIG_HAS_PCI */
> +#endif /* HAS_PASSTHROUGH && MGMT_HYPERCALLS */
>
> #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
> static XSM_INLINE int cf_check xsm_assign_dtdevice(
The DT counterpart, otoh, is separate anyway.
Jan
[Public]
> -----Original Message-----
> From: Jan Beulich <jbeulich@suse.com>
> Sent: Tuesday, November 25, 2025 11:37 PM
> To: Penny, Zheng <penny.zheng@amd.com>
> Cc: Huang, Ray <Ray.Huang@amd.com>; grygorii_strashko@epam.com; Andrew
> Cooper <andrew.cooper3@citrix.com>; Roger Pau Monné <roger.pau@citrix.com>;
> Andryuk, Jason <Jason.Andryuk@amd.com>; Daniel P. Smith
> <dpsmith@apertussolutions.com>; xen-devel@lists.xenproject.org
> Subject: Re: [PATCH v4 14/24] xen/domctl: wrap pci-subset iommu-related domctl
> op with CONFIG_MGMT_HYPERCALLS
>
> On 21.11.2025 11:57, Penny Zheng wrote:
> > xen/drivers/passthrough/amd/pci_amd_iommu.c | 20 ++++----
> > xen/drivers/passthrough/pci.c | 52 +++++++++++----------
> > xen/drivers/passthrough/vtd/iommu.c | 6 ++-
> > xen/include/xsm/dummy.h | 6 ++-
> > xen/include/xsm/xsm.h | 12 +++--
> > xen/xsm/dummy.c | 6 ++-
> > xen/xsm/flask/hooks.c | 12 +++--
> > 7 files changed, 68 insertions(+), 46 deletions(-)
>
> With this diffstat and there being quite a few HAS_PCI under
> xen/drivers/passthrough/arm/, what's the (PCI) deal there?
In arm, we have the following select chain:
HAS_VPCI_GUEST_SUPPORT if PCI_PASSTHROUGH -> HAS_VPCI -> HAS_PCI
So if we make PCI_PASSTHROUGH later depend on MGMT_HYPERCALLS, the PCI-subset for arm will also be guarded too.
I'll add description in commit message
> > --- a/xen/include/xsm/dummy.h
> > +++ b/xen/include/xsm/dummy.h
> > @@ -407,7 +407,8 @@ static XSM_INLINE int cf_check xsm_get_vnumainfo(
> > return xsm_default_action(action, current->domain, d); }
> >
> > -#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
> > +#if defined(CONFIG_HAS_PASSTHROUGH) &&
> > +defined(CONFIG_MGMT_HYPERCALLS) #ifdef CONFIG_HAS_PCI
>
> Why the separate #ifdef? Can't that be folded with the #if? Are there further changes
> to be put inside the outer #if? (Applies again further down as well.)
>
Because later in DT-subset, we want something like the following:
```
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_MGMT_HYPERCALLS)
#ifdef CONFIG_HAS_PCI
...
#endif
#ifdef CONFIG_HAS_DEVICE_TREE_DISCOVERY
...
#endif
#endif /* HAS_PASSTHROUGH && MGMT_HYPERCALLS */
Letting HAS_PASSTHROUGH && MGMT_HYPERCALLS being outer wrapper and a separate #ifdef CONFIG_HAS_PCI here could avoid extra changes in DT commit.
> > static XSM_INLINE int cf_check xsm_get_device_group(
> > XSM_DEFAULT_ARG uint32_t machine_bdf) { @@ -429,7 +430,8 @@
> > static XSM_INLINE int cf_check xsm_deassign_device(
> > return xsm_default_action(action, current->domain, d); }
> >
> > -#endif /* HAS_PASSTHROUGH && HAS_PCI */
> > +#endif /* CONFIG_HAS_PCI */
> > +#endif /* HAS_PASSTHROUGH && MGMT_HYPERCALLS */
> >
> > #if defined(CONFIG_HAS_PASSTHROUGH) &&
> > defined(CONFIG_HAS_DEVICE_TREE_DISCOVERY)
> > static XSM_INLINE int cf_check xsm_assign_dtdevice(
>
> The DT counterpart, otoh, is separate anyway.
>
> Jan
© 2016 - 2025 Red Hat, Inc.