@@ -99,6 +99,9 @@ static long capabilities_op(struct pv_iommu_capabilities *cap, struct domain *d)
cap->max_pasid = 0; /* TODO */
cap->cap_flags = 0;
+ if ( !dom_iommu(d)->no_dma )
+ cap->cap_flags |= IOMMUCAP_default_identity;
+
cap->pgsize_mask = PAGE_SIZE_4K;
return 0;
@@ -55,6 +55,7 @@ static bool __hwdom_initdata iommu_hwdom_none;
bool __hwdom_initdata iommu_hwdom_strict;
bool __read_mostly iommu_hwdom_passthrough;
bool __hwdom_initdata iommu_hwdom_inclusive;
+bool __read_mostly iommu_hwdom_no_dma = false;
int8_t __hwdom_initdata iommu_hwdom_reserved = -1;
#ifndef iommu_hap_pt_share
@@ -172,6 +173,8 @@ static int __init cf_check parse_dom0_iommu_param(const char *s)
iommu_hwdom_reserved = val;
else if ( !cmdline_strcmp(s, "none") )
iommu_hwdom_none = true;
+ else if ( (val = parse_boolean("dma", s, ss)) >= 0 )
+ iommu_hwdom_no_dma = !val;
else
rc = -EINVAL;
@@ -329,6 +332,13 @@ int iommu_domain_init(struct domain *d, unsigned int opts)
if ( !is_hardware_domain(d) || iommu_hwdom_strict )
hd->need_sync = !iommu_use_hap_pt(d);
+ if ( hd->no_dma )
+ {
+ /* No-DMA mode is exclusive with HAP and sync_pt. */
+ hd->hap_pt_share = false;
+ hd->need_sync = false;
+ }
+
ASSERT(!(hd->need_sync && hd->hap_pt_share));
hd->allow_pv_iommu = true;
@@ -529,6 +529,10 @@ void __hwdom_init arch_iommu_hwdom_init(struct domain *d)
if ( iommu_hwdom_reserved == -1 )
iommu_hwdom_reserved = 1;
+ if ( iommu_hwdom_no_dma )
+ /* Skip special mappings with no-dma mode */
+ return;
+
if ( iommu_hwdom_inclusive )
{
printk(XENLOG_WARNING
@@ -106,6 +106,7 @@ extern bool iommu_debug;
extern bool amd_iommu_perdev_intremap;
extern bool iommu_hwdom_strict, iommu_hwdom_passthrough, iommu_hwdom_inclusive;
+extern bool iommu_hwdom_no_dma;
extern int8_t iommu_hwdom_reserved;
extern unsigned int iommu_dev_iotlb_timeout;
@@ -411,6 +412,8 @@ struct domain_iommu {
/* SAF-2-safe enum constant in arithmetic operation */
DECLARE_BITMAP(features, IOMMU_FEAT_count);
+ /* Do the IOMMU block all DMA on default context (implies !has_pt_share) ? */
+ bool no_dma;
/* Is the domain allowed to use PV-IOMMU ? */
bool allow_pv_iommu;
This feature exposed through `dom0-iommu=no-dma` prevents the devices of default context to have access to domain's memory. This basically enforces DMA protection by default. The domain will need to prepare a specific IOMMU context to do DMA. This feature needs the guest to provide a PV-IOMMU driver. Signed-off-by: Teddy Astie <teddy.astie@vates.tech> --- xen/common/pv-iommu.c | 3 +++ xen/drivers/passthrough/iommu.c | 10 ++++++++++ xen/drivers/passthrough/x86/iommu.c | 4 ++++ xen/include/xen/iommu.h | 3 +++ 4 files changed, 20 insertions(+)