On 12/04/2024 09:42, Steven Price wrote:
Add the KVM_CAP_ARM_RME_CREATE_FD ioctl to create a realm. This involves
delegating pages to the RMM to hold the Realm Descriptor (RD) and for
the base level of the Realm Translation Tables (RTT). A VMID also need
to be picked, since the RMM has a separate VMID address space a
dedicated allocator is added for this purpose.
KVM_CAP_ARM_RME_CONFIG_REALM is provided to allow configuring the realm
before it is created.
Co-developed-by: Suzuki K Poulose <suzuki.poulose@xxxxxxx>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@xxxxxxx>
Signed-off-by: Steven Price <steven.price@xxxxxxx>
Signed-off-by: Jean-Philippe Brucker <jean-philippe@xxxxxxxxxx>
---
arch/arm64/include/asm/kvm_emulate.h | 5 +
arch/arm64/include/asm/kvm_rme.h | 19 ++
arch/arm64/kvm/arm.c | 18 ++
arch/arm64/kvm/mmu.c | 15 +-
arch/arm64/kvm/rme.c | 282 +++++++++++++++++++++++++++
5 files changed, 337 insertions(+), 2 deletions(-)
@@ -1014,6 +1018,13 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
struct kvm_pgtable *pgt = NULL;
write_lock(&kvm->mmu_lock);
+ if (kvm_is_realm(kvm) &&
+ (kvm_realm_state(kvm) != REALM_STATE_DEAD &&
+ kvm_realm_state(kvm) != REALM_STATE_NONE)) {
+ /* TODO: teardown rtts */
+ write_unlock(&kvm->mmu_lock);
+ return;
+ }
pgt = mmu->pgt;
if (pgt) {
mmu->pgd_phys = 0;
See my comment below.
...
+
+void kvm_destroy_realm(struct kvm *kvm)
+{
...
+ for (i = 0; i < pgt->pgd_pages; i++) {
+ phys_addr_t pgd_phys = kvm->arch.mmu.pgd_phys + i * PAGE_SIZE;
+
+ if (WARN_ON(rmi_granule_undelegate(pgd_phys)))
+ return;
I think we need to either:
a. memset() the root RTT pages to 0 here.
OR
b. for Realms, avoid walking the page table triggered via
kvm_pgtable_stage2_destroy()->kvm_pgtable_walk().
Even though the root RTTs are all empty (invalid entries, written using
RMM's memory encryption.), the Host might be seeing "garbage" which
might look like "valid" entries and thus triggering crashes.
I prefer not walking the RTTs for a Realm and thus simply skip the walk.
Suzuki
+ }
+
+ WRITE_ONCE(realm->state, REALM_STATE_DEAD);
+
+ kvm_free_stage2_pgd(&kvm->arch.mmu);
+}
+
+int kvm_init_realm_vm(struct kvm *kvm)
+{
+ struct realm_params *params;
+
+ params = (struct realm_params *)get_zeroed_page(GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+
+ /* Default parameters, not exposed to user space */
+ params->s2sz = VTCR_EL2_IPA(kvm->arch.mmu.vtcr);
+ kvm->arch.realm.params = params;
+ return 0;
+}
+
int kvm_init_rme(void)
{
+ int ret;
+
if (PAGE_SIZE != SZ_4K)
/* Only 4k page size on the host is supported */
return 0;
@@ -46,6 +321,13 @@ int kvm_init_rme(void)
/* Continue without realm support */
return 0;
+ if (WARN_ON(rmi_features(0, &rmm_feat_reg0)))
+ return 0;
+
+ ret = rme_vmid_init();
+ if (ret)
+ return ret;
+
/* Future patch will enable static branch kvm_rme_is_available */
return 0;