]> www.infradead.org Git - users/hch/misc.git/commitdiff
KVM: arm64: Decouple output address from the PT descriptor
authorMarc Zyngier <maz@kernel.org>
Sun, 27 Jul 2025 17:46:02 +0000 (18:46 +0100)
committerMarc Zyngier <maz@kernel.org>
Sat, 20 Sep 2025 10:05:12 +0000 (11:05 +0100)
Add a helper converting the descriptor into a nicely formed OA,
irrespective of the in-descriptor representation (< 52bit, LPA
or LPA2).

Reviewed-by: Oliver Upton <oliver.upton@linux.dev>
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/at.c

index e02e467fc2ccd005fb08f5b4c181ef7fe1587012..bdb2c3e22f248e32d70bd9fa62a9206bdbd7025d 100644 (file)
@@ -56,6 +56,29 @@ static bool has_52bit_pa(struct kvm_vcpu *vcpu, struct s1_walk_info *wi, u64 tcr
        return (tcr & (wi->regime == TR_EL2 ? TCR_EL2_DS : TCR_DS));
 }
 
+static u64 desc_to_oa(struct s1_walk_info *wi, u64 desc)
+{
+       u64 addr;
+
+       if (!wi->pa52bit)
+               return desc & GENMASK_ULL(47, wi->pgshift);
+
+       switch (BIT(wi->pgshift)) {
+       case SZ_4K:
+       case SZ_16K:
+               addr = desc & GENMASK_ULL(49, wi->pgshift);
+               addr |= FIELD_GET(KVM_PTE_ADDR_51_50_LPA2, desc) << 50;
+               break;
+       case SZ_64K:
+       default:            /* IMPDEF: treat any other value as 64k */
+               addr = desc & GENMASK_ULL(47, wi->pgshift);
+               addr |= FIELD_GET(KVM_PTE_ADDR_51_48, desc) << 48;
+               break;
+       }
+
+       return addr;
+}
+
 /* Return the translation regime that applies to an AT instruction */
 static enum trans_regime compute_translation_regime(struct kvm_vcpu *vcpu, u32 op)
 {
@@ -402,7 +425,7 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
                        wr->PXNTable |= FIELD_GET(PMD_TABLE_PXN, desc);
                }
 
-               baddr = desc & GENMASK_ULL(47, wi->pgshift);
+               baddr = desc_to_oa(wi, desc);
 
                /* Check for out-of-range OA */
                if (check_output_size(baddr, wi))
@@ -431,7 +454,8 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
                        goto transfault;
        }
 
-       if (check_output_size(desc & GENMASK(47, va_bottom), wi))
+       baddr = desc_to_oa(wi, desc);
+       if (check_output_size(baddr & GENMASK(52, va_bottom), wi))
                goto addrsz;
 
        if (!(desc & PTE_AF)) {
@@ -444,7 +468,7 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
        wr->failed = false;
        wr->level = level;
        wr->desc = desc;
-       wr->pa = desc & GENMASK(47, va_bottom);
+       wr->pa = baddr & GENMASK(52, va_bottom);
        wr->pa |= va & GENMASK_ULL(va_bottom - 1, 0);
 
        wr->nG = (wi->regime != TR_EL2) && (desc & PTE_NG);