lkml.org 
[lkml]   [2021]   [Oct]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC 13/16] KVM: selftests: add support for creating SEV-SNP guests
Date
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@amd.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
\
 
 \ /
  Last update: 2021-10-06 01:47    [W:0.787 / U:24.652 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site