All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Roth <michael.roth@amd.com>
To: linux-kselftest@vger.kernel.org
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	x86@kernel.org, Nathan Tempelman <natet@google.com>,
	Marc Orr <marcorr@google.com>,
	Steve Rutherford <srutherford@google.com>,
	Sean Christopherson <seanjc@google.com>,
	Mingwei Zhang <mizhang@google.com>,
	Brijesh Singh <brijesh.singh@amd.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Varad Gautam <varad.gautam@suse.com>,
	Shuah Khan <shuah@kernel.org>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	David Woodhouse <dwmw@amazon.co.uk>,
	Ricardo Koller <ricarkol@google.com>,
	Jim Mattson <jmattson@google.com>,
	Wanpeng Li <wanpengli@tencent.com>,
	Joerg Roedel <joro@8bytes.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	"H . Peter Anvin" <hpa@zytor.com>
Subject: [RFC 07/16] KVM: selftests: add SEV boot tests
Date: Wed,  6 Oct 2021 15:37:26 -0500	[thread overview]
Message-ID: <20211006203726.13402-1-michael.roth@amd.com> (raw)
In-Reply-To: <20211005234459.430873-1-michael.roth@amd.com>

A common aspect of booting SEV guests is checking related CPUID/MSR
bits and accessing shared/private memory. Add a basic test to cover
this.

This test will be expanded to cover basic boot of SEV-ES and SEV-SNP in
subsequent patches.

Signed-off-by: Michael Roth <michael.roth@amd.com>
---
 tools/testing/selftests/kvm/.gitignore        |   1 +
 tools/testing/selftests/kvm/Makefile          |   1 +
 .../selftests/kvm/x86_64/sev_all_boot_test.c  | 252 ++++++++++++++++++
 3 files changed, 254 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c

diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore
index 0709af0144c8..824f100bec2a 100644
--- a/tools/testing/selftests/kvm/.gitignore
+++ b/tools/testing/selftests/kvm/.gitignore
@@ -38,6 +38,7 @@
 /x86_64/xen_vmcall_test
 /x86_64/xss_msr_test
 /x86_64/vmx_pmu_msrs_test
+/x86_64/sev_all_boot_test
 /access_tracking_perf_test
 /demand_paging_test
 /dirty_log_test
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index c7a5e1c69e0c..aa8901bdbd22 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -72,6 +72,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/tsc_msrs_test
 TEST_GEN_PROGS_x86_64 += x86_64/vmx_pmu_msrs_test
 TEST_GEN_PROGS_x86_64 += x86_64/xen_shinfo_test
 TEST_GEN_PROGS_x86_64 += x86_64/xen_vmcall_test
+TEST_GEN_PROGS_x86_64 += x86_64/sev_all_boot_test
 TEST_GEN_PROGS_x86_64 += access_tracking_perf_test
 TEST_GEN_PROGS_x86_64 += demand_paging_test
 TEST_GEN_PROGS_x86_64 += dirty_log_test
diff --git a/tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c b/tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c
new file mode 100644
index 000000000000..8df7143ac17d
--- /dev/null
+++ b/tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Basic SEV boot tests.
+ *
+ * Copyright (C) 2021 Advanced Micro Devices
+ */
+#define _GNU_SOURCE /* for program_invocation_short_name */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "test_util.h"
+
+#include "kvm_util.h"
+#include "processor.h"
+#include "svm_util.h"
+#include "linux/psp-sev.h"
+#include "sev.h"
+
+#define VCPU_ID			2
+#define PAGE_SIZE		4096
+#define PAGE_STRIDE		32
+
+#define SHARED_PAGES		8192
+#define SHARED_VADDR_MIN	0x1000000
+
+#define PRIVATE_PAGES		2048
+#define PRIVATE_VADDR_MIN	(SHARED_VADDR_MIN + SHARED_PAGES * PAGE_SIZE)
+
+#define TOTAL_PAGES		(512 + SHARED_PAGES + PRIVATE_PAGES)
+
+static void fill_buf(uint8_t *buf, size_t pages, size_t stride, uint8_t val)
+{
+	int i, j;
+
+	for (i = 0; i < pages; i++)
+		for (j = 0; j < PAGE_SIZE; j += stride)
+			buf[i * PAGE_SIZE + j] = val;
+}
+
+static bool check_buf(uint8_t *buf, size_t pages, size_t stride, uint8_t val)
+{
+	int i, j;
+
+	for (i = 0; i < pages; i++)
+		for (j = 0; j < PAGE_SIZE; j += stride)
+			if (buf[i * PAGE_SIZE + j] != val)
+				return false;
+
+	return true;
+}
+
+static void guest_test_start(struct sev_sync_data *sync)
+{
+	/* Initial guest check-in. */
+	sev_guest_sync(sync, 1, 0);
+}
+
+static void check_test_start(struct kvm_vm *vm, struct sev_sync_data *sync)
+{
+	struct kvm_run *run;
+
+	run = vcpu_state(vm, VCPU_ID);
+	vcpu_run(vm, VCPU_ID);
+
+	/* Initial guest check-in. */
+	sev_check_guest_sync(run, sync, 1);
+}
+
+static void
+guest_test_common(struct sev_sync_data *sync, uint8_t *shared_buf, uint8_t *private_buf)
+{
+	bool success;
+
+	/* Initial check-in for common. */
+	sev_guest_sync(sync, 100, 0);
+
+	/* Ensure initial shared pages are intact. */
+	success = check_buf(shared_buf, SHARED_PAGES, PAGE_STRIDE, 0x41);
+	SEV_GUEST_ASSERT(sync, 103, success);
+
+	/* Ensure initial private pages are intact/encrypted. */
+	success = check_buf(private_buf, PRIVATE_PAGES, PAGE_STRIDE, 0x42);
+	SEV_GUEST_ASSERT(sync, 104, success);
+
+	/* Ensure host userspace can't read newly-written encrypted data. */
+	fill_buf(private_buf, PRIVATE_PAGES, PAGE_STRIDE, 0x43);
+
+	sev_guest_sync(sync, 200, 0);
+
+	/* Ensure guest can read newly-written shared data from host. */
+	success = check_buf(shared_buf, SHARED_PAGES, PAGE_STRIDE, 0x44);
+	SEV_GUEST_ASSERT(sync, 201, success);
+
+	/* Ensure host can read newly-written shared data from guest. */
+	fill_buf(shared_buf, SHARED_PAGES, PAGE_STRIDE, 0x45);
+
+	sev_guest_sync(sync, 300, 0);
+}
+
+static void
+check_test_common(struct kvm_vm *vm, struct sev_sync_data *sync,
+		  uint8_t *shared_buf, uint8_t *private_buf)
+{
+	struct kvm_run *run = vcpu_state(vm, VCPU_ID);
+	bool success;
+
+	/* Initial guest check-in. */
+	vcpu_run(vm, VCPU_ID);
+	sev_check_guest_sync(run, sync, 100);
+
+	/* Ensure initial private pages are intact/encrypted. */
+	success = check_buf(private_buf, PRIVATE_PAGES, PAGE_STRIDE, 0x42);
+	TEST_ASSERT(!success, "Initial guest memory not encrypted!");
+
+	vcpu_run(vm, VCPU_ID);
+	sev_check_guest_sync(run, sync, 200);
+
+	/* Ensure host userspace can't read newly-written encrypted data. */
+	success = check_buf(private_buf, PRIVATE_PAGES, PAGE_STRIDE, 0x43);
+	TEST_ASSERT(!success, "Modified guest memory not encrypted!");
+
+	/* Ensure guest can read newly-written shared data from host. */
+	fill_buf(shared_buf, SHARED_PAGES, PAGE_STRIDE, 0x44);
+
+	vcpu_run(vm, VCPU_ID);
+	sev_check_guest_sync(run, sync, 300);
+
+	/* Ensure host can read newly-written shared data from guest. */
+	success = check_buf(shared_buf, SHARED_PAGES, PAGE_STRIDE, 0x45);
+	TEST_ASSERT(success, "Host can't read shared guest memory!");
+}
+
+static void
+guest_test_done(struct sev_sync_data *sync)
+{
+	sev_guest_done(sync, 10000, 0);
+}
+
+static void
+check_test_done(struct kvm_vm *vm, struct sev_sync_data *sync)
+{
+	struct kvm_run *run = vcpu_state(vm, VCPU_ID);
+
+	vcpu_run(vm, VCPU_ID);
+	sev_check_guest_done(run, sync, 10000);
+}
+
+static void __attribute__((__flatten__))
+guest_sev_code(struct sev_sync_data *sync, uint8_t *shared_buf, uint8_t *private_buf)
+{
+	uint32_t eax, ebx, ecx, edx;
+	uint64_t sev_status;
+
+	guest_test_start(sync);
+
+	/* Check SEV CPUID bit. */
+	eax = 0x8000001f;
+	ecx = 0;
+	cpuid(&eax, &ebx, &ecx, &edx);
+	SEV_GUEST_ASSERT(sync, 2, eax & (1 << 1));
+
+	/* Check SEV MSR bit. */
+	sev_status = rdmsr(MSR_AMD64_SEV);
+	SEV_GUEST_ASSERT(sync, 3, (sev_status & 0x1) == 1);
+
+	guest_test_common(sync, shared_buf, private_buf);
+
+	guest_test_done(sync);
+}
+
+static void
+setup_test_common(struct sev_vm *sev, void *guest_code, vm_vaddr_t *sync_vaddr,
+		  vm_vaddr_t *shared_vaddr, vm_vaddr_t *private_vaddr)
+{
+	struct kvm_vm *vm = sev_get_vm(sev);
+	uint8_t *shared_buf, *private_buf;
+
+	/* Set up VCPU and initial guest kernel. */
+	vm_vcpu_add_default(vm, VCPU_ID, guest_code);
+	kvm_vm_elf_load(vm, program_invocation_name);
+
+	/* Set up shared sync buffer. */
+	*sync_vaddr = vm_vaddr_alloc_shared(vm, PAGE_SIZE, 0);
+
+	/* Set up buffer for reserved shared memory. */
+	*shared_vaddr = vm_vaddr_alloc_shared(vm, SHARED_PAGES * PAGE_SIZE,
+					      SHARED_VADDR_MIN);
+	shared_buf = addr_gva2hva(vm, *shared_vaddr);
+	fill_buf(shared_buf, SHARED_PAGES, PAGE_STRIDE, 0x41);
+
+	/* Set up buffer for reserved private memory. */
+	*private_vaddr = vm_vaddr_alloc(vm, PRIVATE_PAGES * PAGE_SIZE,
+					PRIVATE_VADDR_MIN);
+	private_buf = addr_gva2hva(vm, *private_vaddr);
+	fill_buf(private_buf, PRIVATE_PAGES, PAGE_STRIDE, 0x42);
+}
+
+static void test_sev(void *guest_code, uint64_t policy)
+{
+	vm_vaddr_t sync_vaddr, shared_vaddr, private_vaddr;
+	uint8_t *shared_buf, *private_buf;
+	struct sev_sync_data *sync;
+	uint8_t measurement[512];
+	struct sev_vm *sev;
+	struct kvm_vm *vm;
+	int i;
+
+	sev = sev_vm_create(policy, TOTAL_PAGES);
+	if (!sev)
+		return;
+	vm = sev_get_vm(sev);
+
+	setup_test_common(sev, guest_code, &sync_vaddr, &shared_vaddr, &private_vaddr);
+
+	/* Set up guest params. */
+	vcpu_args_set(vm, VCPU_ID, 4, sync_vaddr, shared_vaddr, private_vaddr);
+
+	sync = addr_gva2hva(vm, sync_vaddr);
+	shared_buf = addr_gva2hva(vm, shared_vaddr);
+	private_buf = addr_gva2hva(vm, private_vaddr);
+
+	/* Allocations/setup done. Encrypt initial guest payload. */
+	sev_vm_launch(sev);
+
+	/* Dump the initial measurement. A test to actually verify it would be nice. */
+	sev_vm_measure(sev, measurement);
+	pr_info("guest measurement: ");
+	for (i = 0; i < 32; ++i)
+		pr_info("%02x", measurement[i]);
+	pr_info("\n");
+
+	sev_vm_launch_finish(sev);
+
+	/* Guest is ready to run. Do the tests. */
+	check_test_start(vm, sync);
+	check_test_common(vm, sync, shared_buf, private_buf);
+	check_test_done(vm, sync);
+
+	sev_vm_free(sev);
+}
+
+int main(int argc, char *argv[])
+{
+	/* SEV tests */
+	test_sev(guest_sev_code, SEV_POLICY_NO_DBG);
+	test_sev(guest_sev_code, 0);
+
+	return 0;
+}
-- 
2.25.1


  parent reply	other threads:[~2021-10-06 20:40 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-05 23:44 [RFC 00/16] KVM: selftests: Add tests for SEV, SEV-ES, and SEV-SNP guests Michael Roth
2021-10-05 23:44 ` [RFC 01/16] KVM: selftests: move vm_phy_pages_alloc() earlier in file Michael Roth
2021-10-18 15:00   ` Mingwei Zhang
2021-10-21  3:45     ` Michael Roth
2021-10-21 15:20       ` Paolo Bonzini
2021-10-26 15:52       ` Mingwei Zhang
2021-11-01 17:43         ` Mingwei Zhang
2021-10-05 23:44 ` [RFC 02/16] KVM: selftests: add hooks for managing encrypted guest memory Michael Roth
2021-10-13  2:20   ` Krish Sadhukhan
2021-10-13 15:07     ` Michael Roth
2021-10-21 15:22       ` Paolo Bonzini
2021-10-18 15:00   ` Mingwei Zhang
2021-10-21  3:37     ` Michael Roth
2021-10-21 15:22       ` Paolo Bonzini
2021-10-26 15:48       ` Mingwei Zhang
2021-11-01 17:44         ` Mingwei Zhang
2021-10-05 23:44 ` [RFC 03/16] KVM: selftests: handle encryption bits in page tables Michael Roth
2021-10-21 15:26   ` Paolo Bonzini
2021-10-24 16:49     ` Michael Roth
2021-10-25  7:34       ` Paolo Bonzini
2021-10-25 14:14         ` Michael Roth
2021-10-05 23:44 ` [RFC 09/16] KVM: selftests: account for error code in #VC exception frame Michael Roth
2021-10-05 23:44 ` [RFC 10/16] KVM: selftests: add support for creating SEV-ES guests Michael Roth
2021-10-05 23:44 ` [RFC 11/16] KVM: selftests: add library for handling SEV-ES-related exits Michael Roth
2021-10-05 23:44 ` [RFC 12/16] KVM: selftests: add SEV-ES boot tests Michael Roth
2021-10-05 23:44 ` [RFC 13/16] KVM: selftests: add support for creating SEV-SNP guests Michael Roth
2021-10-05 23:44 ` [RFC 14/16] KVM: selftests: add helpers for SEV-SNP-related instructions/exits Michael Roth
2021-10-05 23:44 ` [RFC 15/16] KVM: selftests: add SEV-SNP boot tests Michael Roth
2021-10-05 23:44 ` [RFC 16/16] KVM: selftests: add SEV-SNP tests for page-state changes Michael Roth
2021-10-06 20:28 ` [RFC 04/16] KVM: selftests: add library for creating/interacting with SEV guests Michael Roth
2021-10-06 20:59   ` Michael Roth
2021-10-06 20:36 ` [RFC 04/16] KVM: selftests: set CPUID before setting sregs in vcpu creation Michael Roth
2021-10-08 19:03   ` Nathan Tempelman
2021-10-13  1:45   ` Krish Sadhukhan
2021-10-13 15:05     ` Michael Roth
2021-10-21 15:29   ` Paolo Bonzini
2021-10-06 20:36 ` [RFC 05/16] KVM: selftests: add support for encrypted vm_vaddr_* allocations Michael Roth
2021-10-06 20:37 ` [RFC 06/16] KVM: selftests: add library for creating/interacting with SEV guests Michael Roth
2021-10-11  3:17   ` Marc Orr
2021-10-12  1:15     ` Michael Roth
2021-10-12 12:55       ` Michael Roth
2021-10-21 15:43         ` Paolo Bonzini
2021-11-04  5:25       ` Mingwei Zhang
2021-11-04 13:44         ` Tom Lendacky
2021-10-14  1:26   ` Krish Sadhukhan
2021-10-16  2:56   ` Krish Sadhukhan
2021-10-21 15:39   ` Paolo Bonzini
2021-10-25  3:58     ` Michael Roth
2021-10-06 20:37 ` Michael Roth [this message]
2021-10-16  2:55   ` [RFC 07/16] KVM: selftests: add SEV boot tests Krish Sadhukhan
2021-10-21  3:35     ` Michael Roth
2021-10-06 20:37 ` [RFC 08/16] KVM: SVM: include CR3 in initial VMSA state for SEV-ES guests Michael Roth
2021-10-21 16:43   ` Paolo Bonzini
2021-10-25  3:59     ` Michael Roth
2021-10-21 16:48 ` [RFC 00/16] KVM: selftests: Add tests for SEV, SEV-ES, and SEV-SNP guests Paolo Bonzini
2021-10-25  4:27   ` Michael Roth
2021-10-25  7:35     ` Paolo Bonzini

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=20211006203726.13402-1-michael.roth@amd.com \
    --to=michael.roth@amd.com \
    --cc=bp@alien8.de \
    --cc=brijesh.singh@amd.com \
    --cc=dwmw@amazon.co.uk \
    --cc=hpa@zytor.com \
    --cc=jmattson@google.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=marcorr@google.com \
    --cc=mingo@redhat.com \
    --cc=mizhang@google.com \
    --cc=natet@google.com \
    --cc=ricarkol@google.com \
    --cc=seanjc@google.com \
    --cc=shuah@kernel.org \
    --cc=srutherford@google.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --cc=varad.gautam@suse.com \
    --cc=vkuznets@redhat.com \
    --cc=wanpengli@tencent.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 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.