From: Jeremi Piotrowski <jpiotrowski@linux.microsoft.com>
To: linux-kernel@vger.kernel.org
Cc: Jeremi Piotrowski <jpiotrowski@linux.microsoft.com>,
Wei Liu <wei.liu@kernel.org>, Dexuan Cui <decui@microsoft.com>,
Tianyu Lan <Tianyu.Lan@microsoft.com>,
Michael Kelley <mikelley@microsoft.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, linux-hyperv@vger.kernel.org,
Brijesh Singh <brijesh.singh@amd.com>,
Michael Roth <michael.roth@amd.com>,
Ashish Kalra <ashish.kalra@amd.com>,
Tom Lendacky <thomas.lendacky@amd.com>
Subject: [RFC PATCH v1 3/6] x86/sev: Maintain shadow rmptable on Hyper-V
Date: Mon, 23 Jan 2023 16:51:25 +0000 [thread overview]
Message-ID: <20230123165128.28185-4-jpiotrowski@linux.microsoft.com> (raw)
In-Reply-To: <20230123165128.28185-1-jpiotrowski@linux.microsoft.com>
Hyper-V can expose the SEV-SNP feature to guests, and manages the
system-wide RMP (Reverse Map) table. The SNP implementation in the
kernel needs access to the rmptable for tracking pages and deciding
when/how to issue rmpupdate/psmash. When running as a Hyper-V guest
with SNP support, an rmptable is allocated by the kernel during boot for
this purpose. Keep the table in sync with issued rmpupdate/psmash
instructions.
The logic for how to update the rmptable comes from "AMD64 Architecture
Programmer’s Manual, Volume 3" which describes the psmash and rmpupdate
instructions. To ensure correctness of the SNP host code, the most
important fields are "assigned" and "page size".
Signed-off-by: Jeremi Piotrowski <jpiotrowski@linux.microsoft.com>
---
arch/x86/kernel/sev.c | 59 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index 95404c7e5150..edec1ccb80b1 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -26,6 +26,7 @@
#include <linux/iommu.h>
#include <linux/amd-iommu.h>
+#include <asm/mshyperv.h>
#include <asm/cpu_entry_area.h>
#include <asm/stacktrace.h>
#include <asm/sev.h>
@@ -2566,6 +2567,11 @@ int snp_lookup_rmpentry(u64 pfn, int *level)
}
EXPORT_SYMBOL_GPL(snp_lookup_rmpentry);
+static bool hv_no_rmp_table(void)
+{
+ return ms_hyperv.nested_features & HV_X64_NESTED_NO_RMP_TABLE;
+}
+
static bool virt_snp_msr(void)
{
return boot_cpu_has(X86_FEATURE_NESTED_VIRT_SNP_MSR);
@@ -2584,6 +2590,26 @@ static u64 virt_psmash(u64 paddr)
return ret;
}
+static void snp_update_rmptable_psmash(u64 pfn)
+{
+ int level;
+ struct rmpentry *entry = __snp_lookup_rmpentry(pfn, &level);
+
+ if (WARN_ON(IS_ERR_OR_NULL(entry)))
+ return;
+
+ if (level == PG_LEVEL_2M) {
+ int i;
+
+ entry->info.pagesize = RMP_PG_SIZE_4K;
+ for (i = 1; i < PTRS_PER_PMD; i++) {
+ struct rmpentry *it = &entry[i];
+ *it = *entry;
+ it->info.gpa = entry->info.gpa + i * PAGE_SIZE;
+ }
+ }
+}
+
/*
* psmash is used to smash a 2MB aligned page into 4K
* pages while preserving the Validated bit in the RMP.
@@ -2601,6 +2627,8 @@ int psmash(u64 pfn)
if (virt_snp_msr()) {
ret = virt_psmash(paddr);
+ if (!ret && hv_no_rmp_table())
+ snp_update_rmptable_psmash(pfn);
} else {
/* Binutils version 2.36 supports the PSMASH mnemonic. */
asm volatile(".byte 0xF3, 0x0F, 0x01, 0xFF"
@@ -2638,6 +2666,35 @@ static u64 virt_rmpupdate(unsigned long paddr, struct rmp_state *val)
return ret;
}
+static void snp_update_rmptable_rmpupdate(u64 pfn, int level, struct rmp_state *val)
+{
+ int prev_level;
+ struct rmpentry *entry = __snp_lookup_rmpentry(pfn, &prev_level);
+
+ if (WARN_ON(IS_ERR_OR_NULL(entry)))
+ return;
+
+ if (level > PG_LEVEL_4K) {
+ int i;
+ struct rmpentry tmp_rmp = {
+ .info = {
+ .assigned = val->assigned,
+ },
+ };
+ for (i = 1; i < PTRS_PER_PMD; i++)
+ entry[i] = tmp_rmp;
+ }
+ if (!val->assigned) {
+ memset(entry, 0, sizeof(*entry));
+ } else {
+ entry->info.assigned = val->assigned;
+ entry->info.pagesize = val->pagesize;
+ entry->info.immutable = val->immutable;
+ entry->info.gpa = val->gpa;
+ entry->info.asid = val->asid;
+ }
+}
+
static int rmpupdate(u64 pfn, struct rmp_state *val)
{
unsigned long paddr = pfn << PAGE_SHIFT;
@@ -2666,6 +2723,8 @@ static int rmpupdate(u64 pfn, struct rmp_state *val)
if (virt_snp_msr()) {
ret = virt_rmpupdate(paddr, val);
+ if (!ret && hv_no_rmp_table())
+ snp_update_rmptable_rmpupdate(pfn, level, val);
} else {
/* Binutils version 2.36 supports the RMPUPDATE mnemonic. */
asm volatile(".byte 0xF2, 0x0F, 0x01, 0xFE"
--
2.25.1
next prev parent reply other threads:[~2023-01-23 16:52 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-23 16:51 [RFC PATCH v1 0/6] Support nested SNP KVM guests on Hyper-V Jeremi Piotrowski
2023-01-23 16:51 ` [RFC PATCH v1 1/6] x86/hyperv: Allocate RMP table during boot Jeremi Piotrowski
2023-01-28 19:26 ` Michael Kelley (LINUX)
2023-01-30 15:03 ` Jeremi Piotrowski
2023-01-23 16:51 ` [RFC PATCH v1 2/6] x86/sev: Add support for NestedVirtSnpMsr Jeremi Piotrowski
2023-01-28 19:48 ` Michael Kelley (LINUX)
2023-01-30 15:25 ` Jeremi Piotrowski
2023-01-30 15:39 ` Michael Kelley (LINUX)
2023-01-23 16:51 ` Jeremi Piotrowski [this message]
2023-01-29 4:37 ` [RFC PATCH v1 3/6] x86/sev: Maintain shadow rmptable on Hyper-V Michael Kelley (LINUX)
2023-01-30 16:51 ` Jeremi Piotrowski
2023-01-23 16:51 ` [RFC PATCH v1 4/6] x86/amd: Configure necessary MSRs for SNP during CPU init when running as a guest Jeremi Piotrowski
2023-01-29 4:44 ` Michael Kelley (LINUX)
2023-01-30 17:25 ` Jeremi Piotrowski
2023-01-23 16:51 ` [RFC PATCH v1 5/6] iommu/amd: Don't fail snp_enable when running virtualized Jeremi Piotrowski
2023-01-23 16:51 ` [RFC PATCH v1 6/6] crypto: ccp - Introduce quirk to always reclaim pages after SEV-legacy commands Jeremi Piotrowski
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=20230123165128.28185-4-jpiotrowski@linux.microsoft.com \
--to=jpiotrowski@linux.microsoft.com \
--cc=Tianyu.Lan@microsoft.com \
--cc=ashish.kalra@amd.com \
--cc=bp@alien8.de \
--cc=brijesh.singh@amd.com \
--cc=dave.hansen@linux.intel.com \
--cc=decui@microsoft.com \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=mikelley@microsoft.com \
--cc=mingo@redhat.com \
--cc=tglx@linutronix.de \
--cc=thomas.lendacky@amd.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).