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  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue,  5 Oct 2021 18:44:57 -0500
From:   Michael Roth <michael.roth@....com>
To:     linux-kselftest@...r.kernel.org
Cc:     kvm@...r.kernel.org, linux-kernel@...r.kernel.org, x86@...nel.org,
        Nathan Tempelman <natet@...gle.com>,
        Marc Orr <marcorr@...gle.com>,
        Steve Rutherford <srutherford@...gle.com>,
        Sean Christopherson <seanjc@...gle.com>,
        Mingwei Zhang <mizhang@...gle.com>,
        Brijesh Singh <brijesh.singh@....com>,
        Tom Lendacky <thomas.lendacky@....com>,
        Varad Gautam <varad.gautam@...e.com>,
        Shuah Khan <shuah@...nel.org>,
        Vitaly Kuznetsov <vkuznets@...hat.com>,
        David Woodhouse <dwmw@...zon.co.uk>,
        Ricardo Koller <ricarkol@...gle.com>,
        Jim Mattson <jmattson@...gle.com>,
        Wanpeng Li <wanpengli@...cent.com>,
        Joerg Roedel <joro@...tes.org>,
        Thomas Gleixner <tglx@...utronix.de>,
        Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>,
        "H . Peter Anvin" <hpa@...or.com>
Subject: [RFC 14/16] KVM: selftests: add helpers for SEV-SNP-related instructions/exits

Extend the existing sev_exitlib with helpers for handling pvalidate
instructions and issuing page-state changes via the GHCB MSR protocol.

Subsequent SEV-SNP-related tests will make use of these in guest code.

Signed-off-by: Michael Roth <michael.roth@....com>
---
 .../kvm/include/x86_64/sev_exitlib.h          |  6 ++
 .../selftests/kvm/lib/x86_64/sev_exitlib.c    | 77 +++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/tools/testing/selftests/kvm/include/x86_64/sev_exitlib.h b/tools/testing/selftests/kvm/include/x86_64/sev_exitlib.h
index 4b67b4004dfa..5c7356f9e925 100644
--- a/tools/testing/selftests/kvm/include/x86_64/sev_exitlib.h
+++ b/tools/testing/selftests/kvm/include/x86_64/sev_exitlib.h
@@ -8,7 +8,13 @@
 #ifndef SELFTEST_KVM_SEV_EXITLIB_H
 #define SELFTEST_KVM_SEV_EXITLIB_H
 
+#define PVALIDATE_NO_UPDATE 255
+
 int sev_es_handle_vc(void *ghcb, u64 ghcb_gpa, struct ex_regs *regs);
 void sev_es_terminate(int reason);
+void snp_register_ghcb(u64 ghcb_gpa);
+void snp_psc_set_shared(u64 gpa);
+void snp_psc_set_private(u64 gpa);
+int snp_pvalidate(void *ptr, bool rmp_psize, bool validate);
 
 #endif /* SELFTEST_KVM_SEV_EXITLIB_H */
diff --git a/tools/testing/selftests/kvm/lib/x86_64/sev_exitlib.c b/tools/testing/selftests/kvm/lib/x86_64/sev_exitlib.c
index b3f7b0297e5b..546b402d5015 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/sev_exitlib.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/sev_exitlib.c
@@ -51,6 +51,19 @@
 #define GHCB_REG_GPA_RESP(resp) ((resp) & GENMASK_ULL(11, 0))
 #define GHCB_REG_GPA_RESP_VAL(resp) ((resp) >> 12)
 
+/* GHCB MSR protocol for Page State Change */
+#define GHCB_PSC_REQ_PRIVATE		1
+#define GHCB_PSC_REQ_SHARED		2
+#define GHCB_PSC_REQ_PSMASH		3
+#define GHCB_PSC_REQ_UNSMASH		4
+#define GHCB_PSC_REQ_CODE		0x14UL
+#define GHCB_PSC_REQ(gfn, op)		\
+	(((unsigned long)((op) & 0xf) << 52) |  \
+	 ((unsigned long)((gfn) & ~(1ULL << 40)) << 12) | \
+	 GHCB_PSC_REQ_CODE)
+#define GHCB_PSC_RESP_CODE		0x15UL
+#define GHCB_PSC_RESP(resp)		((resp) & GENMASK_ULL(11, 0))
+
 /* GHCB format/accessors */
 
 struct ghcb {
@@ -247,3 +260,67 @@ int sev_es_handle_vc(void *ghcb, u64 ghcb_gpa, struct ex_regs *regs)
 
 	return handle_vc_cpuid(ghcb, ghcb_gpa, regs);
 }
+
+void snp_register_ghcb(u64 ghcb_gpa)
+{
+	u64 gfn = ghcb_gpa >> PAGE_SHIFT;
+	u64 resp;
+
+	sev_es_wrmsr_ghcb(GHCB_REG_GPA_REQ(gfn));
+	VMGEXIT();
+
+	resp = sev_es_rdmsr_ghcb();
+	if (GHCB_REG_GPA_RESP(resp) != GHCB_REG_GPA_RESP_CODE ||
+	    GHCB_REG_GPA_RESP_VAL(resp) != gfn)
+		sev_es_terminate(GHCB_TERMINATE_REASON_UNSPEC);
+}
+
+static void snp_psc_request(u64 gfn, int op)
+{
+	u64 resp;
+
+	sev_es_wrmsr_ghcb(GHCB_PSC_REQ(gfn, op));
+	VMGEXIT();
+
+	resp = sev_es_rdmsr_ghcb();
+	if (GHCB_PSC_RESP(resp) != GHCB_PSC_RESP_CODE)
+		sev_es_terminate(GHCB_TERMINATE_REASON_UNSPEC);
+}
+
+void snp_psc_set_shared(u64 gpa)
+{
+	snp_psc_request(gpa >> PAGE_SHIFT, GHCB_PSC_REQ_SHARED);
+}
+
+void snp_psc_set_private(u64 gpa)
+{
+	snp_psc_request(gpa >> PAGE_SHIFT, GHCB_PSC_REQ_PRIVATE);
+}
+
+/* From arch/x86/include/asm/asm.h */
+#ifdef __GCC_ASM_FLAG_OUTPUTS__
+# define CC_SET(c) "\n\t/* output condition code " #c "*/\n"
+# define CC_OUT(c) "=@cc" #c
+#else
+# define CC_SET(c) "\n\tset" #c " %[_cc_" #c "]\n"
+# define CC_OUT(c) [_cc_ ## c] "=qm"
+#endif
+
+int snp_pvalidate(void *ptr, bool rmp_psize, bool validate)
+{
+	uint64_t gva = (uint64_t)ptr;
+	bool no_rmpupdate;
+	int rc;
+
+	/* "pvalidate" mnemonic support in binutils 2.36 and newer */
+	asm volatile(".byte 0xF2, 0x0F, 0x01, 0xFF\n\t"
+		     CC_SET(c)
+		     : CC_OUT(c) (no_rmpupdate), "=a"(rc)
+		     : "a"(gva), "c"(rmp_psize), "d"(validate)
+		     : "memory", "cc");
+
+	if (no_rmpupdate)
+		return PVALIDATE_NO_UPDATE;
+
+	return rc;
+}
-- 
2.25.1

Powered by blists - more mailing lists