[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20211005234459.430873-14-michael.roth@amd.com>
Date: Tue, 5 Oct 2021 18:44:56 -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 13/16] KVM: selftests: add support for creating SEV-SNP guests
SEV-SNP uses an entirely different set of KVM_SEV_* ioctls to manage
guests. The needed vm_memcrypt callbacks are different as well. Address
these differences by extending the SEV library with a new set of
interfaces specific to creating/managing SEV-SNP guests.
These guests will still use a struct sev_vm under the covers, so some
existing sev_*() helpers are still applicable.
Signed-off-by: Michael Roth <michael.roth@....com>
---
.../selftests/kvm/include/x86_64/sev.h | 8 ++
tools/testing/selftests/kvm/lib/x86_64/sev.c | 77 ++++++++++++++++++-
2 files changed, 82 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/x86_64/sev.h b/tools/testing/selftests/kvm/include/x86_64/sev.h
index d2f41b131ecc..f3e088c03bdd 100644
--- a/tools/testing/selftests/kvm/include/x86_64/sev.h
+++ b/tools/testing/selftests/kvm/include/x86_64/sev.h
@@ -18,6 +18,10 @@
#define SEV_POLICY_NO_DBG (1UL << 0)
#define SEV_POLICY_ES (1UL << 2)
+#define SNP_POLICY_SMT (1ULL << 16)
+#define SNP_POLICY_RSVD (1ULL << 17)
+#define SNP_POLICY_DBG (1ULL << 19)
+
#define SEV_GUEST_ASSERT(sync, token, _cond) do { \
if (!(_cond)) \
sev_guest_abort(sync, token, 0); \
@@ -59,4 +63,8 @@ void sev_vm_launch(struct sev_vm *sev);
void sev_vm_measure(struct sev_vm *sev, uint8_t *measurement);
void sev_vm_launch_finish(struct sev_vm *sev);
+struct sev_vm *sev_snp_vm_create(uint64_t policy, uint64_t npages);
+void sev_snp_vm_free(struct sev_vm *sev);
+void sev_snp_vm_launch(struct sev_vm *sev);
+
#endif /* SELFTEST_KVM_SEV_H */
diff --git a/tools/testing/selftests/kvm/lib/x86_64/sev.c b/tools/testing/selftests/kvm/lib/x86_64/sev.c
index d01b0f637ced..939d7d5dff41 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/sev.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/sev.c
@@ -20,6 +20,7 @@ struct sev_vm {
int fd;
int enc_bit;
uint32_t sev_policy;
+ uint64_t snp_policy;
};
/* Helpers for coordinating between guests and test harness. */
@@ -119,6 +120,12 @@ void kvm_sev_ioctl(struct sev_vm *sev, int cmd, void *data)
/* Local helpers. */
+static bool sev_snp_enabled(struct sev_vm *sev)
+{
+ /* RSVD is always 1 for SNP guests. */
+ return sev->snp_policy & SNP_POLICY_RSVD;
+}
+
static void
sev_register_user_range(struct sev_vm *sev, void *hva, uint64_t size)
{
@@ -147,6 +154,21 @@ sev_encrypt_phy_range(struct sev_vm *sev, vm_paddr_t gpa, uint64_t size)
kvm_sev_ioctl(sev, KVM_SEV_LAUNCH_UPDATE_DATA, &ksev_update_data);
}
+static void
+sev_snp_encrypt_phy_range(struct sev_vm *sev, vm_paddr_t gpa, uint64_t size)
+{
+ struct kvm_sev_snp_launch_update update_data = {0};
+
+ pr_debug("encrypt_phy_range: addr: 0x%lx, size: %lu\n", gpa, size);
+
+ update_data.uaddr = (__u64)addr_gpa2hva(sev->vm, gpa);
+ update_data.start_gfn = gpa >> PAGE_SHIFT;
+ update_data.len = size;
+ update_data.page_type = KVM_SEV_SNP_PAGE_TYPE_NORMAL;
+
+ kvm_sev_ioctl(sev, KVM_SEV_SNP_LAUNCH_UPDATE, &update_data);
+}
+
static void sev_encrypt(struct sev_vm *sev)
{
struct sparsebit *enc_phy_pages;
@@ -171,9 +193,14 @@ static void sev_encrypt(struct sev_vm *sev)
if (pg_cnt <= 0)
pg_cnt = 1;
- sev_encrypt_phy_range(sev,
- gpa_start + pg * vm_get_page_size(vm),
- pg_cnt * vm_get_page_size(vm));
+ if (sev_snp_enabled(sev))
+ sev_snp_encrypt_phy_range(sev,
+ gpa_start + pg * vm_get_page_size(vm),
+ pg_cnt * vm_get_page_size(vm));
+ else
+ sev_encrypt_phy_range(sev,
+ gpa_start + pg * vm_get_page_size(vm),
+ pg_cnt * vm_get_page_size(vm));
pg += pg_cnt;
}
@@ -308,3 +335,47 @@ void sev_vm_launch_finish(struct sev_vm *sev)
TEST_ASSERT(ksev_status.state == SEV_GSTATE_RUNNING,
"Unexpected guest state: %d", ksev_status.state);
}
+
+/* SEV-SNP VM implementation. */
+
+struct sev_vm *sev_snp_vm_create(uint64_t policy, uint64_t npages)
+{
+ struct kvm_snp_init init = {0};
+ struct sev_vm *sev;
+ struct kvm_vm *vm;
+
+ vm = vm_create(VM_MODE_DEFAULT, 0, O_RDWR);
+ sev = sev_common_create(vm);
+ if (!sev)
+ return NULL;
+ sev->snp_policy = policy | SNP_POLICY_RSVD;
+
+ kvm_sev_ioctl(sev, KVM_SEV_SNP_INIT, &init);
+ vm_set_memory_encryption(vm, true, true, sev->enc_bit);
+ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 0, 0, npages, 0);
+ sev_register_user_range(sev, addr_gpa2hva(vm, 0), npages * vm_get_page_size(vm));
+
+ pr_info("SEV-SNP guest created, policy: 0x%lx, size: %lu KB\n",
+ sev->snp_policy, npages * vm_get_page_size(vm) / 1024);
+
+ return sev;
+}
+
+void sev_snp_vm_free(struct sev_vm *sev)
+{
+ kvm_vm_free(sev->vm);
+ sev_common_free(sev);
+}
+
+void sev_snp_vm_launch(struct sev_vm *sev)
+{
+ struct kvm_sev_snp_launch_start launch_start = {0};
+ struct kvm_sev_snp_launch_update launch_finish = {0};
+
+ launch_start.policy = sev->snp_policy;
+ kvm_sev_ioctl(sev, KVM_SEV_SNP_LAUNCH_START, &launch_start);
+
+ sev_encrypt(sev);
+
+ kvm_sev_ioctl(sev, KVM_SEV_SNP_LAUNCH_FINISH, &launch_finish);
+}
--
2.25.1
Powered by blists - more mailing lists