[PATCH 00/16] KVM: arm64: Implement unshare hypercall for pkvm

From: Quentin Perret
Date: Wed Oct 13 2021 - 11:58:38 EST


Hi all,

This series implements an unshare hypercall at EL2 in nVHE protected
mode, and makes use of it to unmmap guest-specific data-structures from
EL2 stage-1 during guest tear-down. Crucially, the implementation of the
share and unshare hypercall implements page refcounts at EL2 to avoid
accidentally unmapping data-structures that overlap a common page.

This series has two main benefits. Firstly it allows EL2 to track the
state of shared pages cleanly, as they can now transition from SHARED
back to OWNED. This will simplify permission checks once e.g. pkvm
implements a donation hcall to provide memory to protected guests, as
there should then be no reason for the host to donate a page that is
currently marked shared. And secondly, it avoids having dangling
mappings in the hypervisor's stage-1, which should be a good idea from
a security perspective as the hypervisor is obviously running with
elevated privileges. And perhaps worth noting is that this also
refactors the EL2 page-tracking checks in a more scalable way, which
should allow to implement other memory transitions (host donating memory
to a guest, a guest sharing back with the host, ...) much more easily in
the future.

The series is organized as follows:

- patches 01-05 refactor the implementation of the existing share
hypercall;

- patches 06-10 introduce infrastructure to allow unmapping pages from
EL2 stage-1;

- patches 11-14 allow to refcount pages that are shared more than once
with EL2;

- patches 15-16 add the unshare hypercall, and make use of it when
tearing down guests.

This has been lightly tested on Qemu, by spawning and powering off a
guest 50 times.

Feedback welcome :) !

Thanks,
Quentin

Quentin Perret (11):
KVM: arm64: Avoid remapping the SVE state in the hyp stage-1
KVM: arm64: Introduce kvm_share_hyp()
KVM: arm64: Accept page ranges in pkvm share hypercall
KVM: arm64: Provide {get,put}_page() stubs for early hyp allocator
KVM: arm64: Refcount hyp stage-1 pgtable pages
KVM: arm64: Fixup hyp stage-1 refcount
KVM: arm64: Back hyp_vmemmap for all of memory
KVM: arm64: Move hyp refcount helpers to header files
KVM: arm64: Refcount shared pages at EL2
KVM: arm64: pkvm: Introduce an unshare hypercall
KVM: arm64: pkvm: Unshare guest structs during teardown

Will Deacon (5):
KVM: arm64: Introduce do_share() helper for memory sharing between
components
KVM: arm64: Implement __pkvm_host_share_hyp() using do_share()
KVM: arm64: Hook up ->page_count() for hypervisor stage-1 page-table
KVM: arm64: Implement kvm_pgtable_hyp_unmap() at EL2
KVM: arm64: Move double-sharing logic into hyp-specific function

arch/arm64/include/asm/kvm_asm.h | 1 +
arch/arm64/include/asm/kvm_host.h | 2 +
arch/arm64/include/asm/kvm_mmu.h | 2 +
arch/arm64/include/asm/kvm_pgtable.h | 21 +
arch/arm64/kvm/arm.c | 17 +-
arch/arm64/kvm/fpsimd.c | 25 +-
arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 8 +-
arch/arm64/kvm/hyp/include/nvhe/memory.h | 18 +
arch/arm64/kvm/hyp/include/nvhe/mm.h | 29 +-
arch/arm64/kvm/hyp/nvhe/early_alloc.c | 5 +
arch/arm64/kvm/hyp/nvhe/hyp-main.c | 12 +-
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 596 ++++++++++++++++--
arch/arm64/kvm/hyp/nvhe/mm.c | 31 +-
arch/arm64/kvm/hyp/nvhe/page_alloc.c | 22 +-
arch/arm64/kvm/hyp/nvhe/setup.c | 39 +-
arch/arm64/kvm/hyp/pgtable.c | 80 ++-
arch/arm64/kvm/hyp/reserved_mem.c | 17 +-
arch/arm64/kvm/mmu.c | 48 +-
arch/arm64/kvm/reset.c | 13 +-
19 files changed, 814 insertions(+), 172 deletions(-)

--
2.33.0.882.g93a45727a2-goog