From: Nikunj A Dadhania <nikunj@amd.com>
To: <linux-kernel@vger.kernel.org>, <thomas.lendacky@amd.com>,
<x86@kernel.org>, <kvm@vger.kernel.org>
Cc: <bp@alien8.de>, <mingo@redhat.com>, <tglx@linutronix.de>,
<dave.hansen@linux.intel.com>, <dionnaglaze@google.com>,
<pgonda@google.com>, <seanjc@google.com>, <pbonzini@redhat.com>,
<nikunj@amd.com>
Subject: [PATCH v5 09/14] x86/sev: Add Secure TSC support for SNP guests
Date: Mon, 30 Oct 2023 12:06:47 +0530 [thread overview]
Message-ID: <20231030063652.68675-10-nikunj@amd.com> (raw)
In-Reply-To: <20231030063652.68675-1-nikunj@amd.com>
Add support for Secure TSC in SNP enabled guests. Secure TSC allows
guest to securely use RDTSC/RDTSCP instructions as the parameters
being used cannot be changed by hypervisor once the guest is launched.
During the boot-up of the secondary cpus, SecureTSC enabled guests
need to query TSC info from AMD Security Processor. This communication
channel is encrypted between the AMD Security Processor and the guest,
the hypervisor is just the conduit to deliver the guest messages to
the AMD Security Processor. Each message is protected with an
AEAD (AES-256 GCM). Use minimal AES GCM library to encrypt/decrypt SNP
Guest messages to communicate with the PSP.
Signed-off-by: Nikunj A Dadhania <nikunj@amd.com>
---
arch/x86/coco/core.c | 3 ++
arch/x86/include/asm/sev-guest.h | 18 +++++++
arch/x86/include/asm/sev.h | 2 +
arch/x86/include/asm/svm.h | 6 ++-
arch/x86/kernel/sev.c | 82 ++++++++++++++++++++++++++++++++
arch/x86/mm/mem_encrypt_amd.c | 6 +++
include/linux/cc_platform.h | 8 ++++
7 files changed, 123 insertions(+), 2 deletions(-)
diff --git a/arch/x86/coco/core.c b/arch/x86/coco/core.c
index eeec9986570e..5d5d4d03c543 100644
--- a/arch/x86/coco/core.c
+++ b/arch/x86/coco/core.c
@@ -89,6 +89,9 @@ static bool noinstr amd_cc_platform_has(enum cc_attr attr)
case CC_ATTR_GUEST_SEV_SNP:
return sev_status & MSR_AMD64_SEV_SNP_ENABLED;
+ case CC_ATTR_GUEST_SECURE_TSC:
+ return sev_status & MSR_AMD64_SNP_SECURE_TSC;
+
default:
return false;
}
diff --git a/arch/x86/include/asm/sev-guest.h b/arch/x86/include/asm/sev-guest.h
index e6f94208173d..58739173eba9 100644
--- a/arch/x86/include/asm/sev-guest.h
+++ b/arch/x86/include/asm/sev-guest.h
@@ -39,6 +39,8 @@ enum msg_type {
SNP_MSG_ABSORB_RSP,
SNP_MSG_VMRK_REQ,
SNP_MSG_VMRK_RSP,
+ SNP_MSG_TSC_INFO_REQ = 17,
+ SNP_MSG_TSC_INFO_RSP,
SNP_MSG_TYPE_MAX
};
@@ -111,6 +113,22 @@ struct snp_guest_req {
u8 msg_type;
};
+struct snp_tsc_info_req {
+#define SNP_TSC_INFO_REQ_SZ 128
+ /* Must be zero filled */
+ u8 rsvd[SNP_TSC_INFO_REQ_SZ];
+} __packed;
+
+struct snp_tsc_info_resp {
+ /* Status of TSC_INFO message */
+ u32 status;
+ u32 rsvd1;
+ u64 tsc_scale;
+ u64 tsc_offset;
+ u32 tsc_factor;
+ u8 rsvd2[100];
+} __packed;
+
int snp_setup_psp_messaging(struct snp_guest_dev *snp_dev);
int snp_send_guest_request(struct snp_guest_dev *dev, struct snp_guest_req *req,
struct snp_guest_request_ioctl *rio);
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 783150458864..038a5a15d937 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -200,6 +200,7 @@ void __init __noreturn snp_abort(void);
void snp_accept_memory(phys_addr_t start, phys_addr_t end);
u64 snp_get_unsupported_features(u64 status);
u64 sev_get_status(void);
+void __init snp_secure_tsc_prepare(void);
#else
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
static inline void sev_es_ist_exit(void) { }
@@ -223,6 +224,7 @@ static inline void snp_abort(void) { }
static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
static inline u64 sev_get_status(void) { return 0; }
+static inline void __init snp_secure_tsc_prepare(void) { }
#endif
#endif
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 3ac0ffc4f3e2..ee35c0488f56 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -414,7 +414,9 @@ struct sev_es_save_area {
u8 reserved_0x298[80];
u32 pkru;
u32 tsc_aux;
- u8 reserved_0x2f0[24];
+ u64 tsc_scale;
+ u64 tsc_offset;
+ u8 reserved_0x300[8];
u64 rcx;
u64 rdx;
u64 rbx;
@@ -546,7 +548,7 @@ static inline void __unused_size_checks(void)
BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0x1c0);
BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0x248);
BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0x298);
- BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0x2f0);
+ BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0x300);
BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0x320);
BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0x380);
BUILD_BUG_RESERVED_OFFSET(sev_es_save_area, 0x3f0);
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index fb3b1feb1b84..9468809d02c7 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -76,6 +76,10 @@ static u64 sev_hv_features __ro_after_init;
/* Secrets page physical address from the CC blob */
static u64 secrets_pa __ro_after_init;
+/* Secure TSC values read using TSC_INFO SNP Guest request */
+static u64 guest_tsc_scale __ro_after_init;
+static u64 guest_tsc_offset __ro_after_init;
+
/* #VC handler runtime per-CPU data */
struct sev_es_runtime_data {
struct ghcb ghcb_page;
@@ -1393,6 +1397,78 @@ bool snp_assign_vmpck(struct snp_guest_dev *dev, unsigned int vmpck_id)
}
EXPORT_SYMBOL_GPL(snp_assign_vmpck);
+static struct snp_guest_dev tsc_snp_dev __initdata;
+
+static int __init snp_get_tsc_info(void)
+{
+ static u8 buf[SNP_TSC_INFO_REQ_SZ + AUTHTAG_LEN];
+ struct snp_guest_request_ioctl rio;
+ struct snp_tsc_info_resp tsc_resp;
+ struct snp_tsc_info_req tsc_req;
+ struct snp_guest_req req;
+ int rc, resp_len;
+
+ /*
+ * The intermediate response buffer is used while decrypting the
+ * response payload. Make sure that it has enough space to cover the
+ * authtag.
+ */
+ resp_len = sizeof(tsc_resp) + AUTHTAG_LEN;
+ if (sizeof(buf) < resp_len)
+ return -EINVAL;
+
+ memset(&tsc_req, 0, sizeof(tsc_req));
+ memset(&req, 0, sizeof(req));
+ memset(&rio, 0, sizeof(rio));
+ memset(buf, 0, sizeof(buf));
+
+ if (!snp_assign_vmpck(&tsc_snp_dev, 0))
+ return -EINVAL;
+
+ /* Initialize the PSP channel to send snp messages */
+ if (snp_setup_psp_messaging(&tsc_snp_dev))
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+
+ req.msg_version = MSG_HDR_VER;
+ req.msg_type = SNP_MSG_TSC_INFO_REQ;
+ req.vmpck_id = tsc_snp_dev.vmpck_id;
+ req.req_buf = &tsc_req;
+ req.req_sz = sizeof(tsc_req);
+ req.resp_buf = buf;
+ req.resp_sz = resp_len;
+ req.exit_code = SVM_VMGEXIT_GUEST_REQUEST;
+ rc = snp_send_guest_request(&tsc_snp_dev, &req, &rio);
+ if (rc)
+ goto err_req;
+
+ memcpy(&tsc_resp, buf, sizeof(tsc_resp));
+ pr_debug("%s: Valid response status %x scale %llx offset %llx factor %x\n",
+ __func__, tsc_resp.status, tsc_resp.tsc_scale, tsc_resp.tsc_offset,
+ tsc_resp.tsc_factor);
+
+ guest_tsc_scale = tsc_resp.tsc_scale;
+ guest_tsc_offset = tsc_resp.tsc_offset;
+
+err_req:
+ /* The response buffer contains the sensitive data, explicitly clear it. */
+ memzero_explicit(buf, sizeof(buf));
+ memzero_explicit(&tsc_resp, sizeof(tsc_resp));
+ memzero_explicit(&req, sizeof(req));
+
+ return rc;
+}
+
+void __init snp_secure_tsc_prepare(void)
+{
+ if (!cc_platform_has(CC_ATTR_GUEST_SECURE_TSC))
+ return;
+
+ if (snp_get_tsc_info())
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+
+ pr_debug("SecureTSC enabled\n");
+}
+
static int wakeup_cpu_via_vmgexit(int apic_id, unsigned long start_ip)
{
struct sev_es_save_area *cur_vmsa, *vmsa;
@@ -1493,6 +1569,12 @@ static int wakeup_cpu_via_vmgexit(int apic_id, unsigned long start_ip)
vmsa->vmpl = 0;
vmsa->sev_features = sev_status >> 2;
+ /* Setting Secure TSC parameters */
+ if (cc_platform_has(CC_ATTR_GUEST_SECURE_TSC)) {
+ vmsa->tsc_scale = guest_tsc_scale;
+ vmsa->tsc_offset = guest_tsc_offset;
+ }
+
/* Switch the page over to a VMSA page now that it is initialized */
ret = snp_set_vmsa(vmsa, true);
if (ret) {
diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c
index 6faea41e99b6..9935fc506e99 100644
--- a/arch/x86/mm/mem_encrypt_amd.c
+++ b/arch/x86/mm/mem_encrypt_amd.c
@@ -215,6 +215,11 @@ void __init sme_map_bootdata(char *real_mode_data)
__sme_early_map_unmap_mem(__va(cmdline_paddr), COMMAND_LINE_SIZE, true);
}
+void __init amd_enc_init(void)
+{
+ snp_secure_tsc_prepare();
+}
+
void __init sev_setup_arch(void)
{
phys_addr_t total_mem = memblock_phys_mem_size();
@@ -502,6 +507,7 @@ void __init sme_early_init(void)
x86_platform.guest.enc_status_change_finish = amd_enc_status_change_finish;
x86_platform.guest.enc_tlb_flush_required = amd_enc_tlb_flush_required;
x86_platform.guest.enc_cache_flush_required = amd_enc_cache_flush_required;
+ x86_platform.guest.enc_init = amd_enc_init;
/*
* AMD-SEV-ES intercepts the RDMSR to read the X2APIC ID in the
diff --git a/include/linux/cc_platform.h b/include/linux/cc_platform.h
index cb0d6cd1c12f..e081ca4d5da2 100644
--- a/include/linux/cc_platform.h
+++ b/include/linux/cc_platform.h
@@ -90,6 +90,14 @@ enum cc_attr {
* Examples include TDX Guest.
*/
CC_ATTR_HOTPLUG_DISABLED,
+
+ /**
+ * @CC_ATTR_GUEST_SECURE_TSC: Secure TSC is active.
+ *
+ * The platform/OS is running as a guest/virtual machine and actively
+ * using AMD SEV-SNP Secure TSC feature.
+ */
+ CC_ATTR_GUEST_SECURE_TSC,
};
#ifdef CONFIG_ARCH_HAS_CC_PLATFORM
--
2.34.1
next prev parent reply other threads:[~2023-10-30 6:38 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-30 6:36 [PATCH v5 00/14] Add Secure TSC support for SNP guests Nikunj A Dadhania
2023-10-30 6:36 ` [PATCH v5 01/14] virt: sev-guest: Use AES GCM crypto library Nikunj A Dadhania
2023-10-30 17:51 ` Tom Lendacky
2023-11-02 3:33 ` Nikunj A. Dadhania
2023-10-30 6:36 ` [PATCH v5 02/14] virt: sev-guest: Move mutex to SNP guest device structure Nikunj A Dadhania
2023-10-30 6:36 ` [PATCH v5 03/14] virt: sev-guest: Replace dev_dbg with pr_debug Nikunj A Dadhania
2023-10-30 6:36 ` [PATCH v5 04/14] virt: sev-guest: Add SNP guest request structure Nikunj A Dadhania
2023-10-30 18:16 ` Tom Lendacky
2023-11-02 4:01 ` Nikunj A. Dadhania
2023-10-30 6:36 ` [PATCH v5 05/14] virt: sev-guest: Add vmpck_id to snp_guest_dev struct Nikunj A Dadhania
2023-10-30 16:16 ` Dionna Amalie Glaze
2023-10-30 17:12 ` Tom Lendacky
2023-11-02 4:03 ` Nikunj A. Dadhania
2023-10-30 18:26 ` Tom Lendacky
2023-10-30 6:36 ` [PATCH v5 06/14] x86/sev: Cache the secrets page address Nikunj A Dadhania
2023-10-30 6:36 ` [PATCH v5 07/14] x86/sev: Move and reorganize sev guest request api Nikunj A Dadhania
2023-10-30 19:16 ` Tom Lendacky
2023-11-02 4:28 ` Nikunj A. Dadhania
2023-11-02 14:17 ` Tom Lendacky
2023-10-30 6:36 ` [PATCH v5 08/14] x86/mm: Add generic guest initialization hook Nikunj A Dadhania
2023-10-30 17:23 ` Dave Hansen
2023-11-02 4:30 ` Nikunj A. Dadhania
2023-10-30 19:19 ` Tom Lendacky
2023-11-02 5:08 ` Nikunj A. Dadhania
2023-10-30 6:36 ` Nikunj A Dadhania [this message]
2023-10-30 16:46 ` [PATCH v5 09/14] x86/sev: Add Secure TSC support for SNP guests Dionna Amalie Glaze
2023-11-02 5:13 ` Nikunj A. Dadhania
2023-10-30 20:26 ` Tom Lendacky
2023-11-02 5:36 ` Nikunj A. Dadhania
2023-11-02 14:29 ` Tom Lendacky
2023-11-02 5:41 ` Nikunj A. Dadhania
2023-11-02 10:36 ` Kirill A. Shutemov
2023-11-06 10:45 ` Nikunj A. Dadhania
2023-11-06 13:00 ` Kirill A. Shutemov
2023-10-30 6:36 ` [PATCH v5 10/14] x86/sev: Change TSC MSR behavior for Secure TSC enabled guests Nikunj A Dadhania
2023-10-30 6:36 ` [PATCH v5 11/14] x86/sev: Prevent RDTSC/RDTSCP interception " Nikunj A Dadhania
2023-10-30 20:32 ` Tom Lendacky
2023-11-02 5:47 ` Nikunj A. Dadhania
2023-10-30 6:36 ` [PATCH v5 12/14] x86/kvmclock: Skip kvmclock when Secure TSC is available Nikunj A Dadhania
2023-10-30 21:00 ` Tom Lendacky
2023-11-02 5:39 ` Nikunj A. Dadhania
2023-10-30 6:36 ` [PATCH v5 13/14] x86/tsc: Mark Secure TSC as reliable clocksource Nikunj A Dadhania
2023-10-30 17:18 ` Dave Hansen
2023-11-02 5:53 ` Nikunj A. Dadhania
2023-11-02 10:33 ` Kirill A. Shutemov
2023-11-02 12:07 ` Nikunj A. Dadhania
2023-11-02 12:16 ` Nikunj A. Dadhania
2023-11-02 12:38 ` Kirill A. Shutemov
2023-11-06 11:53 ` Nikunj A. Dadhania
2023-11-06 13:03 ` Kirill A. Shutemov
2023-10-30 6:36 ` [PATCH v5 14/14] x86/sev: Enable Secure TSC for SNP guests Nikunj A Dadhania
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=20231030063652.68675-10-nikunj@amd.com \
--to=nikunj@amd.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=dionnaglaze@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=pgonda@google.com \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--cc=thomas.lendacky@amd.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox