2022-08-10 16:14:04

by Peter Gonda

[permalink] [raw]
Subject: [V3 00/11] KVM: selftests: Add simple SEV test

This patch series combines the work Michael Roth has done in supporting
SEV guests in selftests and the work Sean Christopherson suggested to
allow ucalls from SEV guests. And the work Sean has sent to consolidate
the ucall boilerplate code. Along with a very simple version of the
SEV selftests Michael originally proposed.

V3
* Addressed more of andrew.jones@ in ucall patches.
* Fix build in non-x86 archs.

V2
* Dropped RFC tag
* Correctly separated Sean's ucall patches into 2 as originally
intended.
* Addressed andrew.jones@ in ucall patches.
* Fixed ucall pool usage to work for other archs

V1
* https://lore.kernel.org/all/[email protected]/

Michael Roth (6):
KVM: selftests: move vm_phy_pages_alloc() earlier in file
KVM: selftests: sparsebit: add const where appropriate
KVM: selftests: add hooks for managing encrypted guest memory
KVM: selftests: handle encryption bits in page tables
KVM: selftests: add support for encrypted vm_vaddr_* allocations
KVM: selftests: add library for creating/interacting with SEV guests

Peter Gonda (3):
tools: Add atomic_test_and_set_bit()
KVM: selftests: Add ucall pool based implementation
KVM: selftests: Add simple sev vm testing

Sean Christopherson (2):
KVM: selftests: Consolidate common code for popuplating
KVM: selftests: Consolidate boilerplate code in get_ucall()

tools/arch/x86/include/asm/atomic.h | 7 +
tools/include/asm-generic/atomic-gcc.h | 15 +
tools/testing/selftests/kvm/.gitignore | 1 +
tools/testing/selftests/kvm/Makefile | 3 +
.../selftests/kvm/include/kvm_util_base.h | 25 ++
.../testing/selftests/kvm/include/sparsebit.h | 36 +--
.../selftests/kvm/include/ucall_common.h | 14 +-
.../selftests/kvm/include/x86_64/sev.h | 47 +++
.../testing/selftests/kvm/lib/aarch64/ucall.c | 38 +--
tools/testing/selftests/kvm/lib/kvm_util.c | 267 +++++++++++++-----
tools/testing/selftests/kvm/lib/riscv/ucall.c | 43 +--
tools/testing/selftests/kvm/lib/s390x/ucall.c | 40 +--
tools/testing/selftests/kvm/lib/sparsebit.c | 48 ++--
.../testing/selftests/kvm/lib/ucall_common.c | 139 +++++++++
.../selftests/kvm/lib/x86_64/processor.c | 15 +-
tools/testing/selftests/kvm/lib/x86_64/sev.c | 249 ++++++++++++++++
.../testing/selftests/kvm/lib/x86_64/ucall.c | 39 +--
.../selftests/kvm/x86_64/sev_all_boot_test.c | 131 +++++++++
18 files changed, 911 insertions(+), 246 deletions(-)
create mode 100644 tools/testing/selftests/kvm/include/x86_64/sev.h
create mode 100644 tools/testing/selftests/kvm/lib/ucall_common.c
create mode 100644 tools/testing/selftests/kvm/lib/x86_64/sev.c
create mode 100644 tools/testing/selftests/kvm/x86_64/sev_all_boot_test.c

--
2.37.1.559.g78731f0fdb-goog


2022-08-10 16:18:25

by Peter Gonda

[permalink] [raw]
Subject: [V3 07/11] KVM: selftests: Consolidate boilerplate code in get_ucall()

From: Sean Christopherson <[email protected]>

Consolidate the actual copying of a ucall struct from guest=>host into
the common get_ucall(). Return a host virtual address instead of a guest
virtual address even though the addr_gva2hva() part could be moved to
get_ucall() too. Conceptually, get_ucall() is invoked from the host and
should return a host virtual address (and returning NULL for "nothing to
see here" is far superior to returning 0).

Use pointer shenanigans instead of an unnecessary bounce buffer when the
caller of get_ucall() provides a valid pointer.

Signed-off-by: Sean Christopherson <[email protected]>
Signed-off-by: Peter Gonda <[email protected]>
---
.../selftests/kvm/include/ucall_common.h | 8 ++------
.../testing/selftests/kvm/lib/aarch64/ucall.c | 14 +++-----------
tools/testing/selftests/kvm/lib/riscv/ucall.c | 19 +++----------------
tools/testing/selftests/kvm/lib/s390x/ucall.c | 16 +++-------------
.../testing/selftests/kvm/lib/ucall_common.c | 19 +++++++++++++++++++
.../testing/selftests/kvm/lib/x86_64/ucall.c | 16 +++-------------
6 files changed, 33 insertions(+), 59 deletions(-)

diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/testing/selftests/kvm/include/ucall_common.h
index 5a85f5318bbe..63bfc60be995 100644
--- a/tools/testing/selftests/kvm/include/ucall_common.h
+++ b/tools/testing/selftests/kvm/include/ucall_common.h
@@ -27,9 +27,10 @@ struct ucall {
void ucall_arch_init(struct kvm_vm *vm, void *arg);
void ucall_arch_uninit(struct kvm_vm *vm);
void ucall_arch_do_ucall(vm_vaddr_t uc);
-uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc);
+void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu);

void ucall(uint64_t cmd, int nargs, ...);
+uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc);

static inline void ucall_init(struct kvm_vm *vm, void *arg)
{
@@ -41,11 +42,6 @@ static inline void ucall_uninit(struct kvm_vm *vm)
ucall_arch_uninit(vm);
}

-static inline uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
-{
- return ucall_arch_get_ucall(vcpu, uc);
-}
-
#define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \
ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4)
#define GUEST_SYNC(stage) ucall(UCALL_SYNC, 2, "hello", stage)
diff --git a/tools/testing/selftests/kvm/lib/aarch64/ucall.c b/tools/testing/selftests/kvm/lib/aarch64/ucall.c
index 1c81a6a5c1f2..132c0e98bf49 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/ucall.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c
@@ -75,13 +75,9 @@ void ucall_arch_do_ucall(vm_vaddr_t uc)
WRITE_ONCE(*ucall_exit_mmio_addr, (vm_vaddr_t)&uc);
}

-uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
+void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu)
{
struct kvm_run *run = vcpu->run;
- struct ucall ucall = {};
-
- if (uc)
- memset(uc, 0, sizeof(*uc));

if (run->exit_reason == KVM_EXIT_MMIO &&
run->mmio.phys_addr == (uint64_t)ucall_exit_mmio_addr) {
@@ -90,12 +86,8 @@ uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
TEST_ASSERT(run->mmio.is_write && run->mmio.len == 8,
"Unexpected ucall exit mmio address access");
memcpy(&gva, run->mmio.data, sizeof(gva));
- memcpy(&ucall, addr_gva2hva(vcpu->vm, gva), sizeof(ucall));
-
- vcpu_run_complete_io(vcpu);
- if (uc)
- memcpy(uc, &ucall, sizeof(ucall));
+ return addr_gva2hva(vcpu->vm, gva);
}

- return ucall.cmd;
+ return NULL;
}
diff --git a/tools/testing/selftests/kvm/lib/riscv/ucall.c b/tools/testing/selftests/kvm/lib/riscv/ucall.c
index b1598f418c1f..37e091d4366e 100644
--- a/tools/testing/selftests/kvm/lib/riscv/ucall.c
+++ b/tools/testing/selftests/kvm/lib/riscv/ucall.c
@@ -51,27 +51,15 @@ void ucall_arch_do_ucall(vm_vaddr_t uc)
uc, 0, 0, 0, 0, 0);
}

-uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
+void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu)
{
struct kvm_run *run = vcpu->run;
- struct ucall ucall = {};
-
- if (uc)
- memset(uc, 0, sizeof(*uc));

if (run->exit_reason == KVM_EXIT_RISCV_SBI &&
run->riscv_sbi.extension_id == KVM_RISCV_SELFTESTS_SBI_EXT) {
switch (run->riscv_sbi.function_id) {
case KVM_RISCV_SELFTESTS_SBI_UCALL:
- memcpy(&ucall,
- addr_gva2hva(vcpu->vm, run->riscv_sbi.args[0]),
- sizeof(ucall));
-
- vcpu_run_complete_io(vcpu);
- if (uc)
- memcpy(uc, &ucall, sizeof(ucall));
-
- break;
+ return addr_gva2hva(vcpu->vm, run->riscv_sbi.args[0]);
case KVM_RISCV_SELFTESTS_SBI_UNEXP:
vcpu_dump(stderr, vcpu, 2);
TEST_ASSERT(0, "Unexpected trap taken by guest");
@@ -80,6 +68,5 @@ uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
break;
}
}
-
- return ucall.cmd;
+ return NULL;
}
diff --git a/tools/testing/selftests/kvm/lib/s390x/ucall.c b/tools/testing/selftests/kvm/lib/s390x/ucall.c
index 114cb4af295f..0f695a031d35 100644
--- a/tools/testing/selftests/kvm/lib/s390x/ucall.c
+++ b/tools/testing/selftests/kvm/lib/s390x/ucall.c
@@ -20,13 +20,9 @@ void ucall_arch_do_ucall(vm_vaddr_t uc)
asm volatile ("diag 0,%0,0x501" : : "a"(uc) : "memory");
}

-uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
+void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu)
{
struct kvm_run *run = vcpu->run;
- struct ucall ucall = {};
-
- if (uc)
- memset(uc, 0, sizeof(*uc));

if (run->exit_reason == KVM_EXIT_S390_SIEIC &&
run->s390_sieic.icptcode == 4 &&
@@ -34,13 +30,7 @@ uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
(run->s390_sieic.ipb >> 16) == 0x501) {
int reg = run->s390_sieic.ipa & 0xf;

- memcpy(&ucall, addr_gva2hva(vcpu->vm, run->s.regs.gprs[reg]),
- sizeof(ucall));
-
- vcpu_run_complete_io(vcpu);
- if (uc)
- memcpy(uc, &ucall, sizeof(ucall));
+ return addr_gva2hva(vcpu->vm, run->s.regs.gprs[reg]);
}
-
- return ucall.cmd;
+ return NULL;
}
diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing/selftests/kvm/lib/ucall_common.c
index 2395c7f1d543..ced480860746 100644
--- a/tools/testing/selftests/kvm/lib/ucall_common.c
+++ b/tools/testing/selftests/kvm/lib/ucall_common.c
@@ -18,3 +18,22 @@ void ucall(uint64_t cmd, int nargs, ...)

ucall_arch_do_ucall((vm_vaddr_t)&uc);
}
+
+uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
+{
+ struct ucall ucall;
+ void *addr;
+
+ if (!uc)
+ uc = &ucall;
+
+ addr = ucall_arch_get_ucall(vcpu);
+ if (addr) {
+ memcpy(uc, addr, sizeof(*uc));
+ vcpu_run_complete_io(vcpu);
+ } else {
+ memset(uc, 0, sizeof(*uc));
+ }
+
+ return uc->cmd;
+}
diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing/selftests/kvm/lib/x86_64/ucall.c
index 9f532dba1003..ead9946399ab 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c
@@ -22,25 +22,15 @@ void ucall_arch_do_ucall(vm_vaddr_t uc)
: : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax", "memory");
}

-uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
+void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu)
{
struct kvm_run *run = vcpu->run;
- struct ucall ucall = {};
-
- if (uc)
- memset(uc, 0, sizeof(*uc));

if (run->exit_reason == KVM_EXIT_IO && run->io.port == UCALL_PIO_PORT) {
struct kvm_regs regs;

vcpu_regs_get(vcpu, &regs);
- memcpy(&ucall, addr_gva2hva(vcpu->vm, (vm_vaddr_t)regs.rdi),
- sizeof(ucall));
-
- vcpu_run_complete_io(vcpu);
- if (uc)
- memcpy(uc, &ucall, sizeof(ucall));
+ return addr_gva2hva(vcpu->vm, regs.rdi);
}
-
- return ucall.cmd;
+ return NULL;
}
--
2.37.1.559.g78731f0fdb-goog

2022-08-16 15:47:22

by Andrew Jones

[permalink] [raw]
Subject: Re: [V3 07/11] KVM: selftests: Consolidate boilerplate code in get_ucall()

On Wed, Aug 10, 2022 at 08:20:29AM -0700, Peter Gonda wrote:
> From: Sean Christopherson <[email protected]>
>
> Consolidate the actual copying of a ucall struct from guest=>host into
> the common get_ucall(). Return a host virtual address instead of a guest
> virtual address even though the addr_gva2hva() part could be moved to
> get_ucall() too. Conceptually, get_ucall() is invoked from the host and
> should return a host virtual address (and returning NULL for "nothing to
> see here" is far superior to returning 0).
>
> Use pointer shenanigans instead of an unnecessary bounce buffer when the
> caller of get_ucall() provides a valid pointer.
>
> Signed-off-by: Sean Christopherson <[email protected]>
> Signed-off-by: Peter Gonda <[email protected]>
> ---
> .../selftests/kvm/include/ucall_common.h | 8 ++------
> .../testing/selftests/kvm/lib/aarch64/ucall.c | 14 +++-----------
> tools/testing/selftests/kvm/lib/riscv/ucall.c | 19 +++----------------
> tools/testing/selftests/kvm/lib/s390x/ucall.c | 16 +++-------------
> .../testing/selftests/kvm/lib/ucall_common.c | 19 +++++++++++++++++++
> .../testing/selftests/kvm/lib/x86_64/ucall.c | 16 +++-------------
> 6 files changed, 33 insertions(+), 59 deletions(-)
>

Reviewed-by: Andrew Jones <[email protected]>