Skip to content

Commit 80cbfd7

Browse files
author
Marc Zyngier
committed
KVM: arm64: Honor UX/PX attributes for EL2 S1 mappings
Now that we potentially have two bits to deal with when setting execution permissions, make sure we correctly handle them when both when building the page tables and when reading back from them. Reported-by: Alexandru Elisei <alexandru.elisei@arm.com> Reviewed-by: Fuad Tabba <tabba@google.com> Reviewed-by: Joey Gouly <joey.gouly@arm.com> Tested-by: Fuad Tabba <tabba@google.com> Link: https://patch.msgid.link/20251210173024.561160-7-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent 9d2de51 commit 80cbfd7

2 files changed

Lines changed: 24 additions & 12 deletions

File tree

arch/arm64/include/asm/kvm_pgtable.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,9 @@ typedef u64 kvm_pte_t;
8787

8888
#define KVM_PTE_LEAF_ATTR_HI_SW GENMASK(58, 55)
8989

90-
#define __KVM_PTE_LEAF_ATTR_HI_S1_XN BIT(54)
91-
#define __KVM_PTE_LEAF_ATTR_HI_S1_UXN BIT(54)
92-
#define __KVM_PTE_LEAF_ATTR_HI_S1_PXN BIT(53)
93-
94-
#define KVM_PTE_LEAF_ATTR_HI_S1_XN \
95-
({ cpus_have_final_cap(ARM64_KVM_HVHE) ? \
96-
(__KVM_PTE_LEAF_ATTR_HI_S1_UXN | \
97-
__KVM_PTE_LEAF_ATTR_HI_S1_PXN) : \
98-
__KVM_PTE_LEAF_ATTR_HI_S1_XN; })
90+
#define KVM_PTE_LEAF_ATTR_HI_S1_XN BIT(54)
91+
#define KVM_PTE_LEAF_ATTR_HI_S1_UXN BIT(54)
92+
#define KVM_PTE_LEAF_ATTR_HI_S1_PXN BIT(53)
9993

10094
#define KVM_PTE_LEAF_ATTR_HI_S2_XN GENMASK(54, 53)
10195

arch/arm64/kvm/hyp/pgtable.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ static int hyp_set_prot_attr(enum kvm_pgtable_prot prot, kvm_pte_t *ptep)
342342
if (!(prot & KVM_PGTABLE_PROT_R))
343343
return -EINVAL;
344344

345+
if (!cpus_have_final_cap(ARM64_KVM_HVHE))
346+
prot &= ~KVM_PGTABLE_PROT_UX;
347+
345348
if (prot & KVM_PGTABLE_PROT_X) {
346349
if (prot & KVM_PGTABLE_PROT_W)
347350
return -EINVAL;
@@ -351,8 +354,16 @@ static int hyp_set_prot_attr(enum kvm_pgtable_prot prot, kvm_pte_t *ptep)
351354

352355
if (system_supports_bti_kernel())
353356
attr |= KVM_PTE_LEAF_ATTR_HI_S1_GP;
357+
}
358+
359+
if (cpus_have_final_cap(ARM64_KVM_HVHE)) {
360+
if (!(prot & KVM_PGTABLE_PROT_PX))
361+
attr |= KVM_PTE_LEAF_ATTR_HI_S1_PXN;
362+
if (!(prot & KVM_PGTABLE_PROT_UX))
363+
attr |= KVM_PTE_LEAF_ATTR_HI_S1_UXN;
354364
} else {
355-
attr |= KVM_PTE_LEAF_ATTR_HI_S1_XN;
365+
if (!(prot & KVM_PGTABLE_PROT_PX))
366+
attr |= KVM_PTE_LEAF_ATTR_HI_S1_XN;
356367
}
357368

358369
attr |= FIELD_PREP(KVM_PTE_LEAF_ATTR_LO_S1_AP, ap);
@@ -373,8 +384,15 @@ enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte)
373384
if (!kvm_pte_valid(pte))
374385
return prot;
375386

376-
if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_XN))
377-
prot |= KVM_PGTABLE_PROT_X;
387+
if (cpus_have_final_cap(ARM64_KVM_HVHE)) {
388+
if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_PXN))
389+
prot |= KVM_PGTABLE_PROT_PX;
390+
if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_UXN))
391+
prot |= KVM_PGTABLE_PROT_UX;
392+
} else {
393+
if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_XN))
394+
prot |= KVM_PGTABLE_PROT_PX;
395+
}
378396

379397
ap = FIELD_GET(KVM_PTE_LEAF_ATTR_LO_S1_AP, pte);
380398
if (ap == KVM_PTE_LEAF_ATTR_LO_S1_AP_RO)

0 commit comments

Comments
 (0)