All of lore.kernel.org
 help / color / mirror / Atom feed
From: Will Deacon <will@kernel.org>
To: kvm@vger.kernel.org
Cc: kvmarm@lists.linux.dev, Will Deacon <will@kernel.org>,
	Alexandru Elisei <alexandru.elisei@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Andre Przywara <andre.przywara@arm.com>,
	Oliver Upton <oliver.upton@linux.dev>,
	Marc Zyngier <maz@kernel.org>
Subject: [PATCH kvmtool 4/4] arm64: Add support for protected VMs
Date: Fri, 19 Jun 2026 12:54:14 +0100	[thread overview]
Message-ID: <20260619115415.5475-5-will@kernel.org> (raw)
In-Reply-To: <20260619115415.5475-1-will@kernel.org>

Introduce a new '--protected' parameter which requests the creation of
a protected VM type from the kernel. In addition, a reserved DMA region
is advertised in the device-tree and VIRTIO_F_ACCESS_PLATFORM is
advertised so that virtio transfers can be bounced through a shared
memory window.

Signed-off-by: Will Deacon <will@kernel.org>
---
 arm64/fdt.c                         | 37 +++++++++++++++++++++++++++--
 arm64/include/kvm/fdt-arch.h        | 10 +++++++-
 arm64/include/kvm/kvm-arch.h        |  2 ++
 arm64/include/kvm/kvm-config-arch.h |  5 +++-
 arm64/kvm.c                         | 20 +++++++++++++++-
 arm64/pci.c                         |  2 ++
 6 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/arm64/fdt.c b/arm64/fdt.c
index 98f1dd9..3cbd36e 100644
--- a/arm64/fdt.c
+++ b/arm64/fdt.c
@@ -71,6 +71,19 @@ static void generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
 	_FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
 }
 
+static bool emit_dma_regions;
+void generate_dma_region_prop(void *fdt)
+{
+	if (emit_dma_regions)
+		_FDT(fdt_property_cell(fdt, "memory-region", PHANDLE_DMA));
+}
+
+static void generate_aux_props(void *fdt, u8 irq, enum irq_type irq_type)
+{
+	generate_irq_prop(fdt, irq, irq_type);
+	generate_dma_region_prop(fdt);
+}
+
 struct psci_fns {
 	u32 cpu_suspend;
 	u32 cpu_off;
@@ -103,7 +116,7 @@ static int setup_fdt(struct kvm *kvm)
 {
 	struct device_header *dev_hdr;
 	u8 staging_fdt[FDT_MAX_SIZE];
-	u64 mem_reg_prop[]	= {
+	u64 resv_mem_prop, mem_reg_prop[] = {
 		cpu_to_fdt64(kvm->arch.memory_guest_start),
 		cpu_to_fdt64(kvm->ram_size),
 	};
@@ -116,6 +129,9 @@ static int setup_fdt(struct kvm *kvm)
 	void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *)
 					= kvm->cpus[0]->generate_fdt_nodes;
 
+	/* Generate DMA regions for bouncing in protected VMs */
+	emit_dma_regions = kvm->cfg.arch.protected;
+
 	/* Create new tree without a reserve map */
 	_FDT(fdt_create(fdt, FDT_MAX_SIZE));
 	_FDT(fdt_finish_reservemap(fdt));
@@ -162,6 +178,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));
 
+	/* Reserved memory (restricted DMA pool) */
+	if (emit_dma_regions) {
+		_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(DMA_MEM_REGION_SIZE);
+		_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)
@@ -172,7 +205,7 @@ static int setup_fdt(struct kvm *kvm)
 	while (dev_hdr) {
 		generate_mmio_fdt_nodes = dev_hdr->data;
 		if (generate_mmio_fdt_nodes) {
-			generate_mmio_fdt_nodes(fdt, dev_hdr, generate_irq_prop);
+			generate_mmio_fdt_nodes(fdt, dev_hdr, generate_aux_props);
 		} else {
 			pr_debug("Missing FDT node generator for MMIO device %d",
 				 dev_hdr->dev_num);
diff --git a/arm64/include/kvm/fdt-arch.h b/arm64/include/kvm/fdt-arch.h
index 60c2d40..8a0a460 100644
--- a/arm64/include/kvm/fdt-arch.h
+++ b/arm64/include/kvm/fdt-arch.h
@@ -1,6 +1,14 @@
 #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
+};
+
+void generate_dma_region_prop(void *fdt);
 
 #endif /* ARM__FDT_H */
diff --git a/arm64/include/kvm/kvm-arch.h b/arm64/include/kvm/kvm-arch.h
index a50e6a4..e7dd526 100644
--- a/arm64/include/kvm/kvm-arch.h
+++ b/arm64/include/kvm/kvm-arch.h
@@ -87,6 +87,8 @@
 
 #define MAX_PAGE_SIZE	SZ_64K
 
+/* Size of DMA region for bouncing when running a protected guest */
+#define DMA_MEM_REGION_SIZE	SZ_32M
 
 static inline bool arm_addr_in_ioport_region(u64 phys_addr)
 {
diff --git a/arm64/include/kvm/kvm-config-arch.h b/arm64/include/kvm/kvm-config-arch.h
index d321b77..c2702d5 100644
--- a/arm64/include/kvm/kvm-config-arch.h
+++ b/arm64/include/kvm/kvm-config-arch.h
@@ -19,6 +19,7 @@ struct kvm_config_arch {
 	unsigned int	sve_max_vq;
 	bool		no_pvtime;
 	bool		psci;
+	bool		protected;
 };
 
 int irqchip_parser(const struct option *opt, const char *arg, int unset);
@@ -70,6 +71,8 @@ int sve_vl_parser(const struct option *opt, const char *arg, int unset);
 	OPT_BOOLEAN('\0', "nested", &(cfg)->nested_virt,			\
 		    "Start VCPUs in EL2 (for nested virt)"),			\
 	OPT_BOOLEAN('\0', "e2h0", &(cfg)->e2h0,					\
-		    "Create guest without VHE support"),
+		    "Create guest without VHE support"),			\
+	OPT_BOOLEAN('\0', "protected", &(cfg)->protected,			\
+			"Create a protected VM when pKVM is enabled"),
 
 #endif /* ARM_COMMON__KVM_CONFIG_ARCH_H */
diff --git a/arm64/kvm.c b/arm64/kvm.c
index c8570ce..b899ebd 100644
--- a/arm64/kvm.c
+++ b/arm64/kvm.c
@@ -6,6 +6,7 @@
 #include "kvm/fdt.h"
 #include "kvm/gic.h"
 #include "kvm/kvm-cpu.h"
+#include "kvm/virtio.h"
 
 #include "asm/smccc.h"
 
@@ -147,6 +148,9 @@ void kvm__arch_init(struct kvm *kvm)
 	kvm__arch_enable_mte(kvm);
 	kvm__setup_smccc(kvm);
 	kvm__arch_set_counter_offset(kvm);
+
+	if (kvm->cfg.arch.protected)
+		virtio_modern_enable_feat_access_platform();
 }
 
 
@@ -463,6 +467,16 @@ void kvm__arch_validate_cfg(struct kvm *kvm)
 
 	if (kvm->cfg.arch.e2h0 && !kvm->cfg.arch.nested_virt)
 		pr_warning("--e2h0 requires --nested, ignoring");
+
+	if (kvm->cfg.arch.protected) {
+		if (kvm->cfg.virtio_transport == VIRTIO_MMIO_LEGACY ||
+		    kvm->cfg.virtio_transport == VIRTIO_PCI_LEGACY) {
+			die("Protected VMs require a modern virtio transport");
+		}
+
+		if (kvm->cfg.balloon)
+			die("Ballooning not supported with protected VMs");
+	}
 }
 
 u64 kvm__arch_default_ram_address(void)
@@ -485,6 +499,7 @@ int kvm__get_vm_type(struct kvm *kvm)
 {
 	unsigned int ipa_bits, max_ipa_bits;
 	unsigned long max_ipa;
+	int type;
 
 	/* If we're running on an old kernel, use 0 as the VM type */
 	max_ipa_bits = kvm__arch_get_ipa_limit(kvm);
@@ -500,7 +515,10 @@ 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);
 
-	return KVM_VM_TYPE_ARM_IPA_SIZE(ipa_bits);
+	type = KVM_VM_TYPE_ARM_IPA_SIZE(ipa_bits);
+	if (kvm->cfg.arch.protected)
+		type |= KVM_VM_TYPE_ARM_PROTECTED;
+	return type;
 }
 
 static int kvm__arch_free_kernel_header(struct kvm *kvm)
diff --git a/arm64/pci.c b/arm64/pci.c
index 0366783..db87db8 100644
--- a/arm64/pci.c
+++ b/arm64/pci.c
@@ -73,6 +73,8 @@ 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));
 
+	generate_dma_region_prop(fdt);
+
 	/* Generate the interrupt map ... */
 	dev_hdr = device__first_dev(DEVICE_BUS_PCI);
 	while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
-- 
2.55.0.rc0.738.g0c8ab3ebcc-goog


  parent reply	other threads:[~2026-06-19 11:54 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-19 11:54 [PATCH kvmtool 0/4] Add support for running protected VMs on arm64 Will Deacon
2026-06-19 11:54 ` [PATCH kvmtool 1/4] Sync kernel UAPI headers with v7.1 Will Deacon
2026-06-19 13:15   ` Fuad Tabba
2026-06-19 11:54 ` [PATCH kvmtool 2/4] virtio: Factor out base features for modern virtio transports Will Deacon
2026-06-19 13:15   ` Fuad Tabba
2026-06-19 16:35   ` Suzuki K Poulose
2026-06-19 11:54 ` [PATCH kvmtool 3/4] virtio: Add helper for enabling VIRTIO_F_ACCESS_PLATFORM Will Deacon
2026-06-19 13:21   ` Fuad Tabba
2026-06-19 16:36   ` Suzuki K Poulose
2026-06-19 11:54 ` Will Deacon [this message]
2026-06-19 13:49   ` [PATCH kvmtool 4/4] arm64: Add support for protected VMs Fuad Tabba
2026-06-19 13:04 ` [PATCH kvmtool 0/4] Add support for running protected VMs on arm64 Fuad Tabba

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260619115415.5475-5-will@kernel.org \
    --to=will@kernel.org \
    --cc=alexandru.elisei@arm.com \
    --cc=andre.przywara@arm.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=maz@kernel.org \
    --cc=oliver.upton@linux.dev \
    --cc=suzuki.poulose@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.