lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <bf64a2c41e53e0b0d0c4f7295298da28136df98f.1746037489.git.sergii.dmytruk@3mdeb.com>
Date: Thu,  1 May 2025 01:44:51 +0300
From: Sergii Dmytruk <sergii.dmytruk@...eb.com>
To: linux-kernel@...r.kernel.org
Cc: trenchboot-devel@...glegroups.com,
	Joerg Roedel <joro@...tes.org>,
	Suravee Suthikulpanit <suravee.suthikulpanit@....com>
Subject: [RFC PATCH v2 9/9] psp: Perform kernel portion of DRTM procedures

From: Jagannathan Raman <jag.raman@...cle.com>

GRUB and AMD-SL would have executed the SKINIT instruction and performed
DRTM setup procedures. As part of DRTM, GRUB sets up TMRs to cover the
whole of the system's physical memory regions. The Kernel should release
these TMRs to facilitate communication between devices and drivers. TMRs
are released after the Kernel sets up IOMMU.

Releasing TMRs concludes DRTM. The Kernel should also execute
DRTM_CMD_TPM_LOCALITY_ACCESS to lock TPM locality two before removing
TMRs. But this prevents the Kernel's TPM driver (which loads
subsequently) from extending PCRs. As such, we are skipping the TPM
locality access command.

Signed-off-by: Jagannathan Raman <jag.raman@...cle.com>
Signed-off-by: Ross Philipson <ross.philipson@...cle.com>
Signed-off-by: Sergii Dmytruk <sergii.dmytruk@...eb.com>
---
 arch/x86/kernel/Makefile  |   1 +
 arch/x86/kernel/sl-psp.c  | 239 ++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/slaunch.c |   4 +-
 drivers/iommu/amd/init.c  |  12 ++
 4 files changed, 255 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/kernel/sl-psp.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index bed87b1c49a2..8ccad4f5c129 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -84,6 +84,7 @@ obj-y				+= step.o
 obj-$(CONFIG_INTEL_TXT)		+= tboot.o
 obj-$(CONFIG_SECURE_LAUNCH)	+= slaunch.o
 obj-$(CONFIG_SECURE_LAUNCH)	+= slmodule.o
+obj-$(CONFIG_SECURE_LAUNCH)	+= sl-psp.o
 obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
 obj-y				+= stacktrace.o
 obj-y				+= cpu/
diff --git a/arch/x86/kernel/sl-psp.c b/arch/x86/kernel/sl-psp.c
new file mode 100644
index 000000000000..69d24f275042
--- /dev/null
+++ b/arch/x86/kernel/sl-psp.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch early setup.
+ *
+ * Copyright (c) 2024, Oracle and/or its affiliates.
+ */
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/printk.h>
+#include <linux/slaunch.h>
+#include <asm/cpufeatures.h>
+#include <asm/msr.h>
+#include <asm/pci_x86.h>
+#include <asm/svm.h>
+
+#define	DRTM_MBOX_READY_MASK		0x80000000
+#define	DRTM_MBOX_TMR_INDEX_ID_MASK	0x0F000000
+#define	DRTM_MBOX_CMD_MASK		0x00FF0000
+#define	DRTM_MBOX_STATUS_MASK		0x0000FFFF
+
+#define	DRTM_MBOX_CMD_SHIFT		16
+
+#define	DRTM_NO_ERROR			0x00000000
+#define	DRTM_NOT_SUPPORTED		0x00000001
+#define	DRTM_LAUNCH_ERROR		0x00000002
+#define	DRTM_TMR_SETUP_FAILED_ERROR	0x00000003
+#define	DRTM_TMR_DESTROY_FAILED_ERROR	0x00000004
+#define	DRTM_GET_TCG_LOGS_FAILED_ERROR	0x00000007
+#define	DRTM_OUT_OF_RESOURCES_ERROR	0x00000008
+#define	DRTM_GENERIC_ERROR		0x00000009
+#define	DRTM_INVALID_SERVICE_ID_ERROR	0x0000000A
+#define	DRTM_MEMORY_UNALIGNED_ERROR	0x0000000B
+#define	DRTM_MINIMUM_SIZE_ERROR		0x0000000C
+#define	DRTM_GET_TMR_DESCRIPTOR_FAILED	0x0000000D
+#define	DRTM_EXTEND_OSSL_DIGEST_FAILED	0x0000000E
+#define	DRTM_SETUP_NOT_ALLOWED		0x0000000F
+#define	DRTM_GET_IVRS_TABLE_FAILED	0x00000010
+
+#define DRTM_CMD_GET_CAPABILITY		0x1
+#define	DRTM_CMD_TMR_SETUP		0x2
+#define	DRTM_CMD_TMR_RELEASE		0x3
+#define	DRTM_CMD_LAUNCH			0x4
+#define	DRTM_CMD_GET_TCG_LOGS		0x7
+#define	DRTM_CMD_TPM_LOCALITY_ACCESS	0x8
+#define	DRTM_CMD_GET_TMR_DESCRIPTORS	0x9
+#define	DRTM_CMD_ALLOCATE_SHARED_MEMORY	0xA
+#define	DRTM_CMD_EXTEND_OSSL_DIGEST	0xB
+#define	DRTM_CMD_GET_IVRS_TABLE_INFO	0xC
+
+#define DRTM_TMR_INDEX_0		0
+#define DRTM_TMR_INDEX_1		1
+#define DRTM_TMR_INDEX_2		2
+#define DRTM_TMR_INDEX_3		3
+#define DRTM_TMR_INDEX_4		4
+#define DRTM_TMR_INDEX_5		5
+#define DRTM_TMR_INDEX_6		6
+#define DRTM_TMR_INDEX_7		7
+
+#define	DRTM_CMD_READY			0
+#define	DRTM_RESPONSE_READY		1
+
+static bool slaunch_psp_early_setup_done;
+
+static u32 __iomem *c2pmsg_72;
+
+static void slaunch_smn_register_read(u32 address, u32 *value)
+{
+	u32 val;
+
+	val = address;
+	pci_direct_conf1.write(0, 0, 0, 0xB8, 4, val);
+	pci_direct_conf1.read(0, 0, 0, 0xBC, 4, &val);
+
+	*value = val;
+}
+
+#define IOHC0NBCFG_SMNBASE		0x13B00000
+#define PSP_BASE_ADDR_LO_SMN_ADDRESS	(IOHC0NBCFG_SMNBASE + 0x102E0)
+
+static u32 slaunch_get_psp_bar_addr(void)
+{
+	u32 pspbaselo = 0;
+
+	slaunch_smn_register_read(PSP_BASE_ADDR_LO_SMN_ADDRESS, &pspbaselo);
+
+	/* Mask out the lower bits */
+	pspbaselo &= 0xFFF00000;
+
+	return pspbaselo;
+}
+
+static void slaunch_clear_c2pmsg_regs(void)
+{
+	if (c2pmsg_72)
+		iounmap(c2pmsg_72);
+
+	c2pmsg_72 = NULL;
+}
+
+static bool slaunch_setup_c2pmsg_regs(void)
+{
+	phys_addr_t bar2;
+
+	bar2 = (phys_addr_t)slaunch_get_psp_bar_addr();
+	if (!bar2)
+		return false;
+
+	c2pmsg_72 = ioremap(bar2 + 0x10a20, 4);
+	if (!c2pmsg_72) {
+		slaunch_clear_c2pmsg_regs();
+		return false;
+	}
+
+	return true;
+}
+
+static const char *const slaunch_status_strings[] = {
+	"DRTM_NO_ERROR",
+	"DRTM_NOT_SUPPORTED",
+	"DRTM_LAUNCH_ERROR",
+	"DRTM_TMR_SETUP_FAILED_ERROR",
+	"DRTM_TMR_DESTROY_FAILED_ERROR",
+	"UNDEFINED",
+	"UNDEFINED",
+	"DRTM_GET_TCG_LOGS_FAILED_ERROR",
+	"DRTM_OUT_OF_RESOURCES_ERROR",
+	"DRTM_GENERIC_ERROR",
+	"DRTM_INVALID_SERVICE_ID_ERROR",
+	"DRTM_MEMORY_UNALIGNED_ERROR",
+	"DRTM_MINIMUM_SIZE_ERROR",
+	"DRTM_GET_TMR_DESCRIPTOR_FAILED",
+	"DRTM_EXTEND_OSSL_DIGEST_FAILED",
+	"DRTM_SETUP_NOT_ALLOWED",
+	"DRTM_GET_IVRS_TABLE_FAILED"
+};
+
+static const char *slaunch_status_string(u32 status)
+{
+	if (status > DRTM_GET_IVRS_TABLE_FAILED)
+		return "UNDEFINED";
+
+	return slaunch_status_strings[status];
+}
+
+static bool slaunch_wait_for_psp_ready(u32 *status)
+{
+	u32 reg_val = 0;
+	int retry = 5;
+
+	if (readl(c2pmsg_72) == 0xFFFFFFFF)
+		return false;
+
+	while (--retry) {
+		reg_val = readl(c2pmsg_72);
+		if (reg_val & DRTM_MBOX_READY_MASK)
+			break;
+
+		/* TODO: select wait time appropriately */
+		mdelay(100);
+	}
+
+	if (!retry)
+		return false;
+
+	if (status)
+		*status = reg_val & 0xffff;
+
+	return true;
+}
+
+static bool slaunch_tpm_locality_access(void)
+{
+	u32 status;
+
+	writel(DRTM_CMD_TPM_LOCALITY_ACCESS << DRTM_MBOX_CMD_SHIFT, c2pmsg_72);
+
+	if (!slaunch_wait_for_psp_ready(&status)) {
+		pr_err("Failed to execute DRTM_CMD_TPM_LOCALITY_ACCESS\n");
+		return false;
+	}
+
+	if (status != DRTM_NO_ERROR) {
+		pr_err("DRTM_CMD_TPM_LOCALITY_ACCESS failed - %s",
+		       slaunch_status_string(status));
+		return false;
+	}
+
+	return true;
+}
+
+bool slaunch_psp_tmr_release(void)
+{
+	u32 status;
+
+	if (!slaunch_psp_early_setup_done)
+		return false;
+
+	writel(DRTM_CMD_TMR_RELEASE << DRTM_MBOX_CMD_SHIFT, c2pmsg_72);
+
+	if (!slaunch_wait_for_psp_ready(&status)) {
+		pr_err("Failed to execute DRTM_CMD_TMR_RELEASE_ACCESS\n");
+		return false;
+	}
+
+	if (status != DRTM_NO_ERROR) {
+		pr_err("DRTM_CMD_TMR_RELEASE failed - %s",
+		       slaunch_status_string(status));
+		return false;
+	}
+
+	return true;
+}
+
+void slaunch_psp_setup(void)
+{
+	if (slaunch_psp_early_setup_done)
+		return;
+
+	if (!slaunch_setup_c2pmsg_regs())
+		return;
+
+	if (!slaunch_wait_for_psp_ready(NULL)) {
+		pr_err("PSP not ready to take commands\n");
+		return;
+	}
+
+	slaunch_psp_early_setup_done = true;
+}
+
+void slaunch_psp_finalize(void)
+{
+	if (!slaunch_tpm_locality_access()) {
+		pr_err("PSP failed to lock TPM DRTM localities\n");
+		return;
+	}
+
+	slaunch_clear_c2pmsg_regs();
+}
diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
index a1c8be7de8d3..0a806df74586 100644
--- a/arch/x86/kernel/slaunch.c
+++ b/arch/x86/kernel/slaunch.c
@@ -701,13 +701,15 @@ static void slaunch_finalize_txt(int do_sexit)
 }
 
 /*
- * Used during kexec and on reboot paths to finalize the SKINIT.
+ * Used during kexec and on reboot paths to finalize the SKINIT PSP state.
  */
 static void slaunch_finalize_skinit(void)
 {
 	/* AMD CPUs with PSP-supported DRTM */
 	if (!slaunch_is_skinit_psp())
 		return;
+
+	slaunch_psp_finalize();
 }
 
 void slaunch_finalize(int do_sexit)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index dd9e26b7b718..c7c60183a27f 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -21,6 +21,7 @@
 #include <linux/kmemleak.h>
 #include <linux/cc_platform.h>
 #include <linux/iopoll.h>
+#include <linux/slaunch.h>
 #include <asm/pci-direct.h>
 #include <asm/iommu.h>
 #include <asm/apic.h>
@@ -3357,6 +3358,17 @@ int __init amd_iommu_enable(void)
 	if (ret)
 		return ret;
 
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+	if (slaunch_is_skinit_psp()) {
+		/* Initialize PSP access to SKINIT DRTM functions */
+		slaunch_psp_setup();
+
+		/* Release the Trusted Memory Region since IOMMU is configured */
+		if (!slaunch_psp_tmr_release())
+			return -ENODEV;
+	}
+#endif
+
 	irq_remapping_enabled = 1;
 	return amd_iommu_xt_mode;
 }
-- 
2.49.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ