@@ -131,6 +131,9 @@ int kvm__get_vm_type(struct kvm *kvm)
if (ipa_bits > max_ipa_bits)
die("Memory too large for this system (needs %d bits, %d available)", ipa_bits, max_ipa_bits);
+ if (kvm->cfg.pkvm)
+ return KVM_VM_TYPE_ARM_IPA_SIZE(ipa_bits) | (1U << 8);
+
return KVM_VM_TYPE_ARM_IPA_SIZE(ipa_bits);
}
@@ -116,6 +116,7 @@ static int setup_fdt(struct kvm *kvm)
void (*)(void *, u8, enum irq_type));
void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *)
= kvm->cpus[0]->generate_fdt_nodes;
+ u64 resv_mem_prop;
/* Create new tree without a reserve map */
_FDT(fdt_create(fdt, FDT_MAX_SIZE));
@@ -163,6 +164,23 @@ static int setup_fdt(struct kvm *kvm)
_FDT(fdt_property(fdt, "reg", mem_reg_prop, sizeof(mem_reg_prop)));
_FDT(fdt_end_node(fdt));
+ if (kvm->cfg.pkvm) {
+ /* Reserved memory (restricted DMA) */
+ _FDT(fdt_begin_node(fdt, "reserved-memory"));
+ _FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
+ _FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
+ _FDT(fdt_property(fdt, "ranges", NULL, 0));
+
+ _FDT(fdt_begin_node(fdt, "restricted_dma_reserved"));
+ _FDT(fdt_property_string(fdt, "compatible", "restricted-dma-pool"));
+ resv_mem_prop = cpu_to_fdt64(SZ_8M);
+ _FDT(fdt_property(fdt, "size", &resv_mem_prop, sizeof(resv_mem_prop)));
+ _FDT(fdt_property_cell(fdt, "phandle", PHANDLE_DMA));
+ _FDT(fdt_end_node(fdt));
+
+ _FDT(fdt_end_node(fdt));
+ }
+
/* CPU and peripherals (interrupt controller, timers, etc) */
generate_cpu_nodes(fdt, kvm);
if (generate_cpu_peripheral_fdt_nodes)
@@ -1,6 +1,6 @@
#ifndef ARM__FDT_H
#define ARM__FDT_H
-enum phandles {PHANDLE_RESERVED = 0, PHANDLE_GIC, PHANDLE_MSI, PHANDLES_MAX};
+enum phandles {PHANDLE_RESERVED = 0, PHANDLE_GIC, PHANDLE_MSI, PHANDLE_DMA, PHANDLES_MAX};
#endif /* ARM__FDT_H */
@@ -74,6 +74,9 @@ void pci__generate_fdt_nodes(void *fdt, struct kvm *kvm)
if (irqchip == IRQCHIP_GICV2M || irqchip == IRQCHIP_GICV3_ITS)
_FDT(fdt_property_cell(fdt, "msi-parent", PHANDLE_MSI));
+ if (kvm->cfg.pkvm)
+ _FDT(fdt_property_cell(fdt, "memory-region", PHANDLE_DMA));
+
/* Generate the interrupt map ... */
dev_hdr = device__first_dev(DEVICE_BUS_PCI);
while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
@@ -204,6 +204,8 @@ static int mem_parser(const struct option *opt, const char *arg, int unset)
"Use legacy virtio transport"), \
OPT_BOOLEAN('\0', "restricted_mem", &(cfg)->restricted_mem, \
"Use restricted memory for guests"), \
+ OPT_BOOLEAN('\0', "pkvm", &(cfg)->pkvm, \
+ "Spawn a protected VM (pkvm)"), \
\
OPT_GROUP("Kernel options:"), \
OPT_STRING('k', "kernel", &(cfg)->kernel_filename, "kernel", \
@@ -66,6 +66,7 @@ struct kvm_config {
bool mmio_debug;
bool virtio_legacy;
bool restricted_mem;
+ bool pkvm;
};
#endif
@@ -150,6 +150,9 @@ static bool virtio_pci__common_read(struct virtio_device *vdev,
struct virtio_pci *vpci = vdev->virtio;
u64 features = 1ULL << VIRTIO_F_VERSION_1;
+ if (vpci->kvm->cfg.pkvm)
+ features |= 1ULL << VIRTIO_F_ACCESS_PLATFORM;
+
switch (offset - VPCI_CFG_COMMON_START) {
case VIRTIO_PCI_COMMON_DFSELECT:
val = vpci->device_features_sel;