Skip to content

Commit df1d019

Browse files
author
Marc Zyngier
committed
KVM: arm64: Decouple output address from the PT descriptor
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>
1 parent e645226 commit df1d019

1 file changed

Lines changed: 27 additions & 3 deletions

File tree

arch/arm64/kvm/at.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,29 @@ static bool has_52bit_pa(struct kvm_vcpu *vcpu, struct s1_walk_info *wi, u64 tcr
5656
return (tcr & (wi->regime == TR_EL2 ? TCR_EL2_DS : TCR_DS));
5757
}
5858

59+
static u64 desc_to_oa(struct s1_walk_info *wi, u64 desc)
60+
{
61+
u64 addr;
62+
63+
if (!wi->pa52bit)
64+
return desc & GENMASK_ULL(47, wi->pgshift);
65+
66+
switch (BIT(wi->pgshift)) {
67+
case SZ_4K:
68+
case SZ_16K:
69+
addr = desc & GENMASK_ULL(49, wi->pgshift);
70+
addr |= FIELD_GET(KVM_PTE_ADDR_51_50_LPA2, desc) << 50;
71+
break;
72+
case SZ_64K:
73+
default: /* IMPDEF: treat any other value as 64k */
74+
addr = desc & GENMASK_ULL(47, wi->pgshift);
75+
addr |= FIELD_GET(KVM_PTE_ADDR_51_48, desc) << 48;
76+
break;
77+
}
78+
79+
return addr;
80+
}
81+
5982
/* Return the translation regime that applies to an AT instruction */
6083
static enum trans_regime compute_translation_regime(struct kvm_vcpu *vcpu, u32 op)
6184
{
@@ -402,7 +425,7 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
402425
wr->PXNTable |= FIELD_GET(PMD_TABLE_PXN, desc);
403426
}
404427

405-
baddr = desc & GENMASK_ULL(47, wi->pgshift);
428+
baddr = desc_to_oa(wi, desc);
406429

407430
/* Check for out-of-range OA */
408431
if (check_output_size(baddr, wi))
@@ -431,7 +454,8 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
431454
goto transfault;
432455
}
433456

434-
if (check_output_size(desc & GENMASK(47, va_bottom), wi))
457+
baddr = desc_to_oa(wi, desc);
458+
if (check_output_size(baddr & GENMASK(52, va_bottom), wi))
435459
goto addrsz;
436460

437461
if (!(desc & PTE_AF)) {
@@ -444,7 +468,7 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
444468
wr->failed = false;
445469
wr->level = level;
446470
wr->desc = desc;
447-
wr->pa = desc & GENMASK(47, va_bottom);
471+
wr->pa = baddr & GENMASK(52, va_bottom);
448472
wr->pa |= va & GENMASK_ULL(va_bottom - 1, 0);
449473

450474
wr->nG = (wi->regime != TR_EL2) && (desc & PTE_NG);

0 commit comments

Comments
 (0)