Commit 80cbfd71 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

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: default avatarAlexandru Elisei <alexandru.elisei@arm.com>
Reviewed-by: default avatarFuad Tabba <tabba@google.com>
Reviewed-by: default avatarJoey Gouly <joey.gouly@arm.com>
Tested-by: default avatarFuad Tabba <tabba@google.com>
Link: https://patch.msgid.link/20251210173024.561160-7-maz@kernel.org


Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent 9d2de518
Loading
Loading
Loading
Loading
+3 −9
Original line number Diff line number Diff line
@@ -87,15 +87,9 @@ typedef u64 kvm_pte_t;

#define KVM_PTE_LEAF_ATTR_HI_SW		GENMASK(58, 55)

#define __KVM_PTE_LEAF_ATTR_HI_S1_XN	BIT(54)
#define __KVM_PTE_LEAF_ATTR_HI_S1_UXN	BIT(54)
#define __KVM_PTE_LEAF_ATTR_HI_S1_PXN	BIT(53)

#define KVM_PTE_LEAF_ATTR_HI_S1_XN					\
	({ cpus_have_final_cap(ARM64_KVM_HVHE) ?			\
			(__KVM_PTE_LEAF_ATTR_HI_S1_UXN |		\
			 __KVM_PTE_LEAF_ATTR_HI_S1_PXN) :		\
			__KVM_PTE_LEAF_ATTR_HI_S1_XN; })
#define KVM_PTE_LEAF_ATTR_HI_S1_XN	BIT(54)
#define KVM_PTE_LEAF_ATTR_HI_S1_UXN	BIT(54)
#define KVM_PTE_LEAF_ATTR_HI_S1_PXN	BIT(53)

#define KVM_PTE_LEAF_ATTR_HI_S2_XN	GENMASK(54, 53)

+21 −3
Original line number Diff line number Diff line
@@ -342,6 +342,9 @@ static int hyp_set_prot_attr(enum kvm_pgtable_prot prot, kvm_pte_t *ptep)
	if (!(prot & KVM_PGTABLE_PROT_R))
		return -EINVAL;

	if (!cpus_have_final_cap(ARM64_KVM_HVHE))
		prot &= ~KVM_PGTABLE_PROT_UX;

	if (prot & KVM_PGTABLE_PROT_X) {
		if (prot & KVM_PGTABLE_PROT_W)
			return -EINVAL;
@@ -351,7 +354,15 @@ static int hyp_set_prot_attr(enum kvm_pgtable_prot prot, kvm_pte_t *ptep)

		if (system_supports_bti_kernel())
			attr |= KVM_PTE_LEAF_ATTR_HI_S1_GP;
	}

	if (cpus_have_final_cap(ARM64_KVM_HVHE)) {
		if (!(prot & KVM_PGTABLE_PROT_PX))
			attr |= KVM_PTE_LEAF_ATTR_HI_S1_PXN;
		if (!(prot & KVM_PGTABLE_PROT_UX))
			attr |= KVM_PTE_LEAF_ATTR_HI_S1_UXN;
	} else {
		if (!(prot & KVM_PGTABLE_PROT_PX))
			attr |= KVM_PTE_LEAF_ATTR_HI_S1_XN;
	}

@@ -373,8 +384,15 @@ enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte)
	if (!kvm_pte_valid(pte))
		return prot;

	if (cpus_have_final_cap(ARM64_KVM_HVHE)) {
		if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_PXN))
			prot |= KVM_PGTABLE_PROT_PX;
		if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_UXN))
			prot |= KVM_PGTABLE_PROT_UX;
	} else {
		if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_XN))
		prot |= KVM_PGTABLE_PROT_X;
			prot |= KVM_PGTABLE_PROT_PX;
	}

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