All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thara Gopinath <tgopinath@linux.microsoft.com>
To: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
	decui@microsoft.com, tglx@kernel.org, mingo@redhat.com,
	bp@alien8.de, dave.hansen@linux.intel.com, hpa@zytor.com,
	ardb@kernel.org, ilias.apalodimas@linaro.org
Cc: James.Bottomley@HansenPartnership.com,
	"longli@microsoft.com--cc=tzimmermann"@suse.de,
	javierm@redhat.com, lszubowi@redhat.com,
	francescopompo2@gmail.com, tgopinath@microsoft.com,
	x86@kernel.org, linux-hyperv@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-efi@vger.kernel.org,
	Thara Gopinath <tgopinath@linux.microsoft.com>,
	Anna Trikalinou <atrikalinou@microsoft.com>
Subject: [RFC PATCH 03/12] drivers: hv: Reserve memory for VSM secure kernel during early boot
Date: Tue,  1 Sep 2026 09:55:17 -0700	[thread overview]
Message-ID: <20260901165647.3160413-4-tgopinath@linux.microsoft.com> (raw)
In-Reply-To: <20260901165647.3160413-1-tgopinath@linux.microsoft.com>

The VSM secure kernel runs in VTL1 and cannot use the normal Linux
kernel memory allocators — its memory must be reserved before the
general-purpose allocator takes ownership of the physical address space.

Add hv_vsm_securekernel.c to handle this early boot reservation. The
driver parses a new "securekernel=<size>[K|M|G][@<addr>]" kernel command
line argument to allow explicit control over the reserved region's size
and base address. If the argument is absent or specifies a region smaller
than the computed minimum, the driver falls back to an automatic
allocation.

The minimum reservation is calculated as:

  16 MB (base) + (num_possible_cpus * 4 MB per-CPU)

Memory is reserved via memblock_phys_alloc_range() with 2 MB alignment
(SECKERNEL_ALIGN) and registered as an IORESOURCE_SYSTEM_RAM entry named
"vsm" in the iomem resource tree so it is visible in /proc/iomem and
protected from reuse.

The reservation is skipped if sk_res.start is already set, preventing
duplicate reservations if the setup hook is called more than once.

Co-developed-by: Anna Trikalinou <atrikalinou@microsoft.com>
Signed-off-by: Anna Trikalinou <atrikalinou@microsoft.com>
Signed-off-by: Thara Gopinath <tgopinath@linux.microsoft.com>
---
 drivers/hv/Makefile              |   1 +
 drivers/hv/hv_vsm_securekernel.c | 188 +++++++++++++++++++++++++++++++
 2 files changed, 189 insertions(+)
 create mode 100644 drivers/hv/hv_vsm_securekernel.c

diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
index 888a748cc7cb9..880c570832381 100644
--- a/drivers/hv/Makefile
+++ b/drivers/hv/Makefile
@@ -25,3 +25,4 @@ obj-$(subst m,y,$(CONFIG_MSHV_ROOT)) += hv_proc.o
 ifneq ($(CONFIG_MSHV_ROOT)$(CONFIG_MSHV_VTL),)
 	obj-y += mshv_common.o
 endif
+obj-$(subst m,y,$(CONFIG_HYPERV_VSM)) += hv_vsm_securekernel.o
diff --git a/drivers/hv/hv_vsm_securekernel.c b/drivers/hv/hv_vsm_securekernel.c
new file mode 100644
index 0000000000000..f90f6204b4d18
--- /dev/null
+++ b/drivers/hv/hv_vsm_securekernel.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024, Microsoft Corporation.
+ *
+ * Authors:
+ *   Anna Trikalinou <atrikalinou@microsoft.com>
+ *   Thara Gopinath <tgopinath@linux.microsoft.com>
+ */
+
+#include <linux/memblock.h>
+
+/* Define Memory Reservation for Secure Kernel */
+#define SECKERNEL_ALIGN			SZ_2M
+#define SECKERNEL_ADDR_MAX		(max_low_pfn_mapped << PAGE_SHIFT)
+/* Secure kernel map (16MB minimum)
+ * Region		Offset		Size
+ * VSM PAGES		0		< 2MB
+ * SKERNEL		?(ELF)		16MB+ (based on config)
+ */
+#define SECKERNEL_BASE_SIZE		(16 * 1024 * 1024)
+#define SECKERNEL_PERCPU_SIZE		(4 * 1024 * 1024)
+
+/* Estimate amount of memory needed for Secure Kernel */
+#define SECKERNEL_MIN_SIZE (SECKERNEL_BASE_SIZE + num_possible_cpus() * SECKERNEL_PERCPU_SIZE)
+
+struct resource sk_res = {
+	.name  = "vsm",
+	.start = 0,
+	.end   = 0,
+	.flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
+	.desc  = IORES_DESC_RESERVED
+};
+
+/*
+ * That function parses "simple" securekernel command lines like
+ *
+ *	securekernel=size[@offset]
+ *
+ * It returns 0 on success and -EINVAL on failure.
+ */
+static int __init parse_securekernel_simple(char *cmdline,
+					    unsigned long long *securekernel_size,
+					    unsigned long long *securekernel_base)
+{
+	char *cur = cmdline;
+
+	*securekernel_size = memparse(cmdline, &cur);
+	if (cmdline == cur) {
+		pr_warn("securekernel: memory value expected\n");
+		return -EINVAL;
+	}
+
+	if (*cur == '@') {
+		*securekernel_base = memparse(cur + 1, &cur);
+	} else if (*cur != ' ' && *cur != '\0') {
+		pr_warn("securekernel: unrecognized char: %c\n", *cur);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static __init char *get_last_securekernel(char *cmdline, const char *name)
+{
+	char *p = cmdline, *sk_cmdline = NULL;
+
+	/* find securekernel and use the last one if there are more */
+	p = strstr(p, name);
+	while (p) {
+		sk_cmdline = p;
+		p = strstr(p + 1, name);
+	}
+
+	if (!sk_cmdline)
+		return NULL;
+
+	return sk_cmdline;
+}
+
+static int __init __parse_securekernel(char *cmdline,
+				       unsigned long long *securekernel_size,
+				       unsigned long long *securekernel_base,
+				       const char *name)
+{
+	char *sk_cmdline;
+
+	if (!securekernel_size || !securekernel_base)
+		return -EINVAL;
+
+	*securekernel_size = 0;
+	*securekernel_base = 0;
+
+	sk_cmdline = get_last_securekernel(cmdline, name);
+
+	if (!sk_cmdline)
+		return -EINVAL;
+
+	sk_cmdline += strlen(name);
+
+	return parse_securekernel_simple(sk_cmdline, securekernel_size, securekernel_base);
+}
+
+/*
+ * That function is the entry point for command line parsing and should be
+ * called from the arch-specific code.
+ */
+static int __init parse_securekernel(char *cmdline,
+				     unsigned long long *securekernel_size,
+				     unsigned long long *securekernel_base)
+{
+	return __parse_securekernel(cmdline, securekernel_size, securekernel_base,
+					"securekernel=");
+}
+
+static int __init hv_vsm_seckernel_mem_init(char *__unused)
+{
+	unsigned long long securekernel_size = 0, securekernel_base = 0;
+	int ret;
+
+	/* Secure Kernel memory is already reserved. Avoid duplicate reservation */
+	if (sk_res.start)
+		return 0;
+	/*
+	 * Reserve Secure Kernel memory.
+	 * Check command line first, if secure kernel memory was defined
+	 */
+	ret = parse_securekernel(boot_command_line, &securekernel_size,
+				 &securekernel_base);
+
+	if (ret != 0 || securekernel_size < SECKERNEL_MIN_SIZE) {
+		if (ret != 0)
+			pr_info("%s: securekernel cmd line not defined. Falling back to default.\n",
+				__func__);
+		else if (securekernel_size < SECKERNEL_MIN_SIZE)
+			pr_info("%s: securekernel cmd line too small. Falling back to default.\n",
+				__func__);
+
+		securekernel_size = SECKERNEL_MIN_SIZE;
+		securekernel_base = 0;
+	}
+
+	/* If securekernel_base was specified from command line,
+	 * try to reserve memory starting from that address
+	 */
+	if (securekernel_base) {
+		unsigned long long start, end;
+
+		end = securekernel_base + securekernel_size;
+		if (end >  SECKERNEL_ADDR_MAX || end < securekernel_base) {
+			pr_warn("%s: Invalid Securekernel base address %llx. Falling back to default.\n",
+				__func__, securekernel_base);
+			securekernel_base = 0;
+		} else {
+			start = memblock_phys_alloc_range(securekernel_size, SECKERNEL_ALIGN,
+							  securekernel_base,
+							  securekernel_base + securekernel_size);
+			if (start != securekernel_base) {
+				pr_warn("%s: memory reservation @ %llx failed-memory is in use\n",
+					__func__, securekernel_base);
+				pr_warn("%s:Falling back to default mem allocation\n", __func__);
+				securekernel_base = 0;
+			}
+		}
+	}
+	/* Default: Find the base address automatically */
+	if (!securekernel_base) {
+		securekernel_base = memblock_phys_alloc_range(securekernel_size, SECKERNEL_ALIGN,
+							      0, SECKERNEL_ADDR_MAX);
+		if (!securekernel_base) {
+			pr_err("%s: Securekernel reservation failed-VSM will not be enabled.\n",
+			       __func__);
+			return -EINVAL;
+		}
+	}
+
+	pr_info("Reserving %ldMB of memory at 0x%llx(%ld MB) for securekernel(System RAM:%ldMB)\n",
+		(unsigned long)(securekernel_size >> 20),
+		securekernel_base,
+		(unsigned long)(securekernel_base >> 20),
+		(unsigned long)(memblock_phys_mem_size() >> 20));
+
+	sk_res.start = securekernel_base;
+	sk_res.end   = securekernel_base + securekernel_size - 1;
+	insert_resource(&iomem_resource, &sk_res);
+
+	return 0;
+}
+__setup("securekernel", hv_vsm_seckernel_mem_init);
-- 
2.34.1


  parent reply	other threads:[~2026-09-01 16:57 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-01 16:55 [RFC PATCH 00/12] Introduce LVBS support for Hyper-V guests Thara Gopinath
2026-09-01 16:55 ` [RFC PATCH 01/12] drivers: hv: Add HYPERV_VSM kconfig option Thara Gopinath
2026-09-01 16:55 ` [RFC PATCH 02/12] drivers: hv: hv_common: Allocate Hyper-V output arg page when VSM is enabled Thara Gopinath
2026-09-01 17:12   ` sashiko-bot
2026-09-01 22:56     ` Wei Liu
2026-09-01 16:55 ` Thara Gopinath [this message]
2026-09-01 17:10   ` [RFC PATCH 03/12] drivers: hv: Reserve memory for VSM secure kernel during early boot sashiko-bot
2026-09-02  0:59   ` Wei Liu
2026-09-02 13:38     ` Thara Gopinath
2026-09-01 16:55 ` [RFC PATCH 04/12] firmware: efi: libstub: x86-stub: Enable VSM awareness in efi os indications variable Thara Gopinath
2026-09-01 17:09   ` sashiko-bot
2026-09-02  1:09   ` Wei Liu
2026-09-02 14:23     ` Thara Gopinath
2026-09-01 16:55 ` [RFC PATCH 05/12] include: hyperv: hvgdk_mini.h: Add VTL-specific structures and bits Thara Gopinath
2026-09-01 16:55 ` [RFC PATCH 06/12] drivers: hv: Add VSM boot driver and enable VTL1 at the partition level Thara Gopinath
2026-09-01 17:24   ` sashiko-bot
2026-09-02  1:16   ` Wei Liu
2026-09-02 14:28     ` Thara Gopinath
2026-09-02  4:43   ` Wei Liu
2026-09-04 13:23     ` Thara Gopinath
2026-09-01 16:55 ` [RFC PATCH 07/12] drivers: hv: hv_vsm_boot: load secure kernel image from firmware Thara Gopinath
2026-09-01 17:20   ` sashiko-bot
2026-09-02  4:37   ` Wei Liu
2026-09-02 16:22     ` Thara Gopinath
2026-09-02 22:58       ` Wei Liu
2026-09-01 16:55 ` [RFC PATCH 08/12] arch: x86: hyperv: Build initial vCPU context for VTL1 secure kernel Thara Gopinath
2026-09-01 17:25   ` sashiko-bot
2026-09-01 16:55 ` [RFC PATCH 09/12] drivers: hv: hv_vsm_boot: Enable VTL1 on the boot processor Thara Gopinath
2026-09-01 17:36   ` sashiko-bot
2026-09-01 16:55 ` [RFC PATCH 10/12] arch: x86: hyperv: hv_vtl_vsm: Introduce vtlcall Thara Gopinath
2026-09-01 16:55 ` [RFC PATCH 11/12] drivers: hv: hv_vsm_boot: Boot primary processor in VTL1 Thara Gopinath
2026-09-01 17:35   ` sashiko-bot
2026-09-01 16:55 ` [RFC PATCH 12/12] drivers: hv: hv_vsm_boot: Boot secondary processors " Thara Gopinath
2026-09-01 17:44   ` sashiko-bot

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=20260901165647.3160413-4-tgopinath@linux.microsoft.com \
    --to=tgopinath@linux.microsoft.com \
    --cc="longli@microsoft.com--cc=tzimmermann"@suse.de \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=ardb@kernel.org \
    --cc=atrikalinou@microsoft.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=decui@microsoft.com \
    --cc=francescopompo2@gmail.com \
    --cc=haiyangz@microsoft.com \
    --cc=hpa@zytor.com \
    --cc=ilias.apalodimas@linaro.org \
    --cc=javierm@redhat.com \
    --cc=kys@microsoft.com \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lszubowi@redhat.com \
    --cc=mingo@redhat.com \
    --cc=tglx@kernel.org \
    --cc=tgopinath@microsoft.com \
    --cc=wei.liu@kernel.org \
    --cc=x86@kernel.org \
    /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.