Re: [PATCH v4 09/18] KVM: arm64: selftests: Add guest support to get the vcpuid

From: Oliver Upton
Date: Thu Sep 09 2021 - 01:09:17 EST


On Thu, Sep 09, 2021 at 01:38:09AM +0000, Raghavendra Rao Ananta wrote:
> At times, such as when in the interrupt handler, the guest wants
> to get the vcpuid that it's running on. As a result, introduce
> get_vcpuid() that returns the vcpuid of the calling vcpu. At its
> backend, the VMM prepares a map of vcpuid and mpidr during VM
> initialization and exports the map to the guest for it to read.
>
> Signed-off-by: Raghavendra Rao Ananta <rananta@xxxxxxxxxx>
> ---
> .../selftests/kvm/include/aarch64/processor.h | 3 ++
> .../selftests/kvm/lib/aarch64/processor.c | 46 +++++++++++++++++++
> 2 files changed, 49 insertions(+)
>
> diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h
> index b6088c3c67a3..150f63101f4c 100644
> --- a/tools/testing/selftests/kvm/include/aarch64/processor.h
> +++ b/tools/testing/selftests/kvm/include/aarch64/processor.h
> @@ -133,6 +133,7 @@ void vm_install_exception_handler(struct kvm_vm *vm,
> int vector, handler_fn handler);
> void vm_install_sync_handler(struct kvm_vm *vm,
> int vector, int ec, handler_fn handler);
> +void vm_vcpuid_map_init(struct kvm_vm *vm);
>
> static inline void cpu_relax(void)
> {
> @@ -194,4 +195,6 @@ static inline void local_irq_disable(void)
> asm volatile("msr daifset, #3" : : : "memory");
> }
>
> +int get_vcpuid(void);
> +

I believe both of these functions could use some documentation. The
former has implicit ordering requirements (can only be called after all
vCPUs are created) and the latter can only be used within a guest.

> #endif /* SELFTEST_KVM_PROCESSOR_H */
> diff --git a/tools/testing/selftests/kvm/lib/aarch64/processor.c b/tools/testing/selftests/kvm/lib/aarch64/processor.c
> index 632b74d6b3ca..9844b62227b1 100644
> --- a/tools/testing/selftests/kvm/lib/aarch64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/aarch64/processor.c
> @@ -13,9 +13,17 @@
> #include "processor.h"
>
> #define DEFAULT_ARM64_GUEST_STACK_VADDR_MIN 0xac0000
> +#define VM_VCPUID_MAP_INVAL -1
>
> static vm_vaddr_t exception_handlers;
>
> +struct vm_vcpuid_map {
> + uint64_t mpidr;
> + int vcpuid;
> +};
> +
> +static struct vm_vcpuid_map vcpuid_map[KVM_MAX_VCPUS];
> +

Hmm.

I'm not too big of a fan that the KVM_MAX_VCPUS macro is defined in the
KVM selftests. Really, userspace should discover the limit from the
kernel. Especially when we want to write tests that test behavior at
KVM's limit.

That being said, there are more instances of these static allocations in
the selftests code, so you aren't to be blamed.

Related: commit 074c82c8f7cf ("kvm: x86: Increase MAX_VCPUS to 1024")
has raised this limit.

> static uint64_t page_align(struct kvm_vm *vm, uint64_t v)
> {
> return (v + vm->page_size) & ~(vm->page_size - 1);
> @@ -426,3 +434,41 @@ void vm_install_exception_handler(struct kvm_vm *vm, int vector,
> assert(vector < VECTOR_NUM);
> handlers->exception_handlers[vector][0] = handler;
> }
> +
> +void vm_vcpuid_map_init(struct kvm_vm *vm)
> +{
> + int i = 0;
> + struct vcpu *vcpu;
> + struct vm_vcpuid_map *map;
> +
> + list_for_each_entry(vcpu, &vm->vcpus, list) {
> + map = &vcpuid_map[i++];
> + map->vcpuid = vcpu->id;
> + get_reg(vm, vcpu->id,
> + ARM64_SYS_KVM_REG(SYS_MPIDR_EL1), &map->mpidr);
> + map->mpidr &= MPIDR_HWID_BITMASK;
> + }
> +
> + if (i < KVM_MAX_VCPUS)
> + vcpuid_map[i].vcpuid = VM_VCPUID_MAP_INVAL;
> +
> + sync_global_to_guest(vm, vcpuid_map);
> +}
> +
> +int get_vcpuid(void)

nit: guest_get_vcpuid()

> +{
> + int i, vcpuid;
> + uint64_t mpidr = read_sysreg(mpidr_el1) & MPIDR_HWID_BITMASK;
> +
> + for (i = 0; i < KVM_MAX_VCPUS; i++) {
> + vcpuid = vcpuid_map[i].vcpuid;
> + GUEST_ASSERT_1(vcpuid != VM_VCPUID_MAP_INVAL, mpidr);
> +
> + if (mpidr == vcpuid_map[i].mpidr)
> + return vcpuid;
> + }
> +
> + /* We should not be reaching here */
> + GUEST_ASSERT_1(0, mpidr);
> + return -1;
> +}
> --
> 2.33.0.153.gba50c8fa24-goog
>