Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions docs/man/xl.cfg.5.pod.in
Original file line number Diff line number Diff line change
Expand Up @@ -3094,6 +3094,19 @@ assigned to the domain.

=back

=over 4

=item B<viommu="N">

To enable viommu, user must specify the following option in the VM
config file:

viommu = "smmuv3"

Currently, only the "smmuv3" type is supported for ARM.

=back

=head3 x86

=over 4
Expand Down
7 changes: 7 additions & 0 deletions docs/misc/xen-command-line.pandoc
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,13 @@ This option can be specified more than once (up to 8 times at present).

Flag to enable or disable support for PCI passthrough

### viommu (arm)
> `= <boolean>`

> Default: `false`

Flag to enable or disable support for Virtual IOMMU for guests.

### pcid (x86)
> `= <boolean> | xpti=<bool>`

Expand Down
2 changes: 2 additions & 0 deletions tools/golang/xenlight/helpers.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tools/golang/xenlight/types.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions tools/include/libxl.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@
*/
#define LIBXL_HAVE_BUILDINFO_ARCH_NR_SPIS 1

/*
* libxl_domain_build_info has the arch_arm.viommu_type field.
*/
#define LIBXL_HAVE_BUILDINFO_ARM_VIOMMU 1

/*
* LIBXL_HAVE_SOFT_RESET indicates that libxl supports performing
* 'soft reset' for domains and there is 'soft_reset' shutdown reason
Expand Down
119 changes: 117 additions & 2 deletions tools/libs/light/libxl_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
{
uint32_t nr_spis = 0;
unsigned int i;
uint32_t vuart_irq, virtio_irq = 0;
bool vuart_enabled = false, virtio_enabled = false;
uint32_t vuart_irq, virtio_irq = 0, vsmmu_irq = 0;
bool vuart_enabled = false, virtio_enabled = false, vsmmu_enabled = false;
uint64_t virtio_mmio_base = GUEST_VIRTIO_MMIO_BASE;
uint32_t virtio_mmio_irq = GUEST_VIRTIO_MMIO_SPI_FIRST;
int rc;
Expand All @@ -102,6 +102,12 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
vuart_enabled = true;
}

if (d_config->num_pcidevs || d_config->b_info.device_tree) {
nr_spis += (GUEST_VSMMU_SPI - 32) + 1;
vsmmu_irq = GUEST_VSMMU_SPI;
vsmmu_enabled = true;
}

for (i = 0; i < d_config->num_disks; i++) {
libxl_device_disk *disk = &d_config->disks[i];

Expand Down Expand Up @@ -170,6 +176,11 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
return ERROR_FAIL;
}

if (vsmmu_enabled && irq == vsmmu_irq) {
LOG(ERROR, "Physical IRQ %u conflicting with vSMMUv3 SPI\n", irq);
return ERROR_FAIL;
}

if (irq < 32)
continue;

Expand Down Expand Up @@ -222,6 +233,19 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
config->arch.sve_vl = d_config->b_info.arch_arm.sve_vl / 128U;
}

switch (d_config->b_info.arch_arm.viommu_type) {
case LIBXL_VIOMMU_TYPE_NONE:
config->arch.viommu_type = XEN_DOMCTL_CONFIG_VIOMMU_NONE;
break;
case LIBXL_VIOMMU_TYPE_SMMUV3:
config->arch.viommu_type = XEN_DOMCTL_CONFIG_VIOMMU_SMMUV3;
break;
default:
LOG(ERROR, "Unknown vIOMMU type %d",
d_config->b_info.arch_arm.viommu_type);
return ERROR_FAIL;
}

return 0;
}

Expand Down Expand Up @@ -861,6 +885,45 @@ static int make_vpl011_uart_node(libxl__gc *gc, void *fdt,
return 0;
}

static int make_vsmmuv3_node(libxl__gc *gc, void *fdt,
const struct arch_info *ainfo,
struct xc_dom_image *dom)
{
int res;
const char *name = GCSPRINTF("iommu@%llx", GUEST_VSMMUV3_BASE);
gic_interrupt intr;

res = fdt_begin_node(fdt, name);
if (res) return res;

res = fdt_property_compat(gc, fdt, 1, "arm,smmu-v3");
if (res) return res;

res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS,
GUEST_ROOT_SIZE_CELLS, 1, GUEST_VSMMUV3_BASE,
GUEST_VSMMUV3_SIZE);
if (res) return res;

res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_VSMMUV3);
if (res) return res;

res = fdt_property_cell(fdt, "#iommu-cells", 1);
if (res) return res;

res = fdt_property_string(fdt, "interrupt-names", "combined");
if (res) return res;

set_interrupt(intr, GUEST_VSMMU_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);

res = fdt_property_interrupts(gc, fdt, &intr, 1);
if (res) return res;

res = fdt_end_node(fdt);
if (res) return res;

return 0;
}

static int make_vpci_node(libxl__gc *gc, void *fdt,
const struct arch_info *ainfo,
struct xc_dom_image *dom)
Expand Down Expand Up @@ -902,6 +965,10 @@ static int make_vpci_node(libxl__gc *gc, void *fdt,
GUEST_VPCI_PREFETCH_MEM_SIZE);
if (res) return res;

res = fdt_property_values(gc, fdt, "iommu-map", 4, 0,
GUEST_PHANDLE_VSMMUV3, 0, 0x10000);
if (res) return res;

res = fdt_end_node(fdt);
if (res) return res;

Expand Down Expand Up @@ -1228,6 +1295,41 @@ static int copy_partial_fdt(libxl__gc *gc, void *fdt, void *pfdt)
return 0;
}

static int modify_partial_fdt(libxl__gc *gc, void *pfdt)
{
int nodeoff, proplen, i, r;
const fdt32_t *prop;
fdt32_t *prop_c;

nodeoff = fdt_path_offset(pfdt, "/passthrough");
if (nodeoff < 0)
return nodeoff;

for (nodeoff = fdt_first_subnode(pfdt, nodeoff);
nodeoff >= 0;
nodeoff = fdt_next_subnode(pfdt, nodeoff)) {

prop = fdt_getprop(pfdt, nodeoff, "iommus", &proplen);
if (!prop)
continue;

prop_c = libxl__zalloc(gc, proplen);

for (i = 0; i < proplen / 8; ++i) {
prop_c[i * 2] = cpu_to_fdt32(GUEST_PHANDLE_VSMMUV3);
prop_c[i * 2 + 1] = prop[i * 2 + 1];
}

r = fdt_setprop(pfdt, nodeoff, "iommus", prop_c, proplen);
if (r) {
LOG(ERROR, "Can't set the iommus property in partial FDT");
return r;
}
}

return 0;
}

#else

static int check_partial_fdt(libxl__gc *gc, void *fdt, size_t size)
Expand All @@ -1246,6 +1348,13 @@ static int copy_partial_fdt(libxl__gc *gc, void *fdt, void *pfdt)
return -FDT_ERR_INTERNAL;
}

static int modify_partial_fdt(libxl__gc *gc, void *pfdt)
{
LOG(ERROR, "partial device tree not supported");

return ERROR_FAIL;
}

#endif /* ENABLE_PARTIAL_DEVICE_TREE */

#define FDT_MAX_SIZE (1<<20)
Expand Down Expand Up @@ -1368,6 +1477,12 @@ static int libxl__prepare_dtb(libxl__gc *gc, libxl_domain_config *d_config,
if (d_config->num_pcidevs)
FDT( make_vpci_node(gc, fdt, ainfo, dom) );

if (info->arch_arm.viommu_type == LIBXL_VIOMMU_TYPE_SMMUV3) {
FDT( make_vsmmuv3_node(gc, fdt, ainfo, dom) );
if (pfdt)
FDT( modify_partial_fdt(gc, pfdt) );
}

for (i = 0; i < d_config->num_disks; i++) {
libxl_device_disk *disk = &d_config->disks[i];

Expand Down
8 changes: 7 additions & 1 deletion tools/libs/light/libxl_types.idl
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,11 @@ libxl_sve_type = Enumeration("sve_type", [
(2048, "2048")
], init_val = "LIBXL_SVE_TYPE_DISABLED")

libxl_viommu_type = Enumeration("viommu_type", [
(0, "none"),
(1, "smmuv3")
], init_val = "LIBXL_VIOMMU_TYPE_NONE")

libxl_rdm_reserve = Struct("rdm_reserve", [
("strategy", libxl_rdm_reserve_strategy),
("policy", libxl_rdm_reserve_policy),
Expand Down Expand Up @@ -723,7 +728,8 @@ libxl_domain_build_info = Struct("domain_build_info",[
("arch_arm", Struct(None, [("gic_version", libxl_gic_version),
("vuart", libxl_vuart_type),
("sve_vl", libxl_sve_type),
("nr_spis", uint32),
("nr_spis", uint32, {'init_val': 'LIBXL_NR_SPIS_DEFAULT'}),
("viommu_type", libxl_viommu_type),
])),
("arch_x86", Struct(None, [("msr_relaxed", libxl_defbool),
])),
Expand Down
13 changes: 13 additions & 0 deletions tools/xl/xl_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -2975,6 +2975,19 @@ void parse_config_data(const char *config_source,
if (!xlu_cfg_get_long (config, "nr_spis", &l, 0))
b_info->arch_arm.nr_spis = l;

xlu_cfg_get_defbool(config, "trap_unmapped_accesses",
&b_info->trap_unmapped_accesses, 0);


if (!xlu_cfg_get_string (config, "viommu", &buf, 1)) {
e = libxl_viommu_type_from_string(buf, &b_info->arch_arm.viommu_type);
if (e) {
fprintf(stderr,
"Unknown vIOMMU type \"%s\" specified\n", buf);
exit(-ERROR_FAIL);
}
}

parse_vkb_list(config, d_config);

d_config->virtios = NULL;
Expand Down
Loading