]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: Introduce host_stage2_set_owner_metadata_locked()
authorWill Deacon <will@kernel.org>
Mon, 30 Mar 2026 14:48:23 +0000 (15:48 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 30 Mar 2026 15:58:08 +0000 (16:58 +0100)
Rework host_stage2_set_owner_locked() to add a new helper function,
host_stage2_set_owner_metadata_locked(), which will allow us to store
additional metadata alongside a 3-bit owner ID for invalid host stage-2
entries.

Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
Link: https://patch.msgid.link/20260330144841.26181-23-will@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/include/asm/kvm_pgtable.h
arch/arm64/kvm/hyp/nvhe/mem_protect.c

index e36c2908bdb280c25bfa9bfd09aa6dfc92c2485a..2df22640833c64337b629d1bf1884f5f71de7f51 100644 (file)
@@ -99,8 +99,6 @@ typedef u64 kvm_pte_t;
                                         KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | \
                                         KVM_PTE_LEAF_ATTR_HI_S2_XN)
 
-#define KVM_INVALID_PTE_OWNER_MASK     GENMASK(9, 2)
-
 /* pKVM invalid pte encodings */
 #define KVM_INVALID_PTE_TYPE_MASK      GENMASK(63, 60)
 #define KVM_INVALID_PTE_ANNOT_MASK     ~(KVM_PTE_VALID | \
index aea6ec981801b21b741c1d5f3b5ce2b456b9c847..90003cbf5603bc152a8c0bd152ee1fc242d606d8 100644 (file)
@@ -549,37 +549,54 @@ static void __host_update_page_state(phys_addr_t addr, u64 size, enum pkvm_page_
                set_host_state(page, state);
 }
 
-static kvm_pte_t kvm_init_invalid_leaf_owner(u8 owner_id)
-{
-       return FIELD_PREP(KVM_INVALID_PTE_OWNER_MASK, owner_id);
-}
-
-int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id)
+#define KVM_HOST_DONATION_PTE_OWNER_MASK       GENMASK(3, 1)
+#define KVM_HOST_DONATION_PTE_EXTRA_MASK       GENMASK(59, 4)
+static int host_stage2_set_owner_metadata_locked(phys_addr_t addr, u64 size,
+                                                u8 owner_id, u64 meta)
 {
        kvm_pte_t annotation;
-       int ret = -EINVAL;
+       int ret;
 
-       if (!FIELD_FIT(KVM_INVALID_PTE_OWNER_MASK, owner_id))
+       if (owner_id == PKVM_ID_HOST)
                return -EINVAL;
 
        if (!range_is_memory(addr, addr + size))
                return -EPERM;
 
+       if (!FIELD_FIT(KVM_HOST_DONATION_PTE_OWNER_MASK, owner_id))
+               return -EINVAL;
+
+       if (!FIELD_FIT(KVM_HOST_DONATION_PTE_EXTRA_MASK, meta))
+               return -EINVAL;
+
+       annotation = FIELD_PREP(KVM_HOST_DONATION_PTE_OWNER_MASK, owner_id) |
+                    FIELD_PREP(KVM_HOST_DONATION_PTE_EXTRA_MASK, meta);
+       ret = host_stage2_try(kvm_pgtable_stage2_annotate, &host_mmu.pgt,
+                             addr, size, &host_s2_pool,
+                             KVM_HOST_INVALID_PTE_TYPE_DONATION, annotation);
+       if (!ret)
+               __host_update_page_state(addr, size, PKVM_NOPAGE);
+
+       return ret;
+}
+
+int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id)
+{
+       int ret = -EINVAL;
+
        switch (owner_id) {
        case PKVM_ID_HOST:
+               if (!range_is_memory(addr, addr + size))
+                       return -EPERM;
+
                ret = host_stage2_idmap_locked(addr, size, PKVM_HOST_MEM_PROT);
                if (!ret)
                        __host_update_page_state(addr, size, PKVM_PAGE_OWNED);
                break;
        case PKVM_ID_GUEST:
        case PKVM_ID_HYP:
-               annotation = kvm_init_invalid_leaf_owner(owner_id);
-               ret = host_stage2_try(kvm_pgtable_stage2_annotate, &host_mmu.pgt,
-                                     addr, size, &host_s2_pool,
-                                     KVM_HOST_INVALID_PTE_TYPE_DONATION,
-                                     annotation);
-               if (!ret)
-                       __host_update_page_state(addr, size, PKVM_NOPAGE);
+               ret = host_stage2_set_owner_metadata_locked(addr, size,
+                                                           owner_id, 0);
                break;
        }