diff options
| author | Oliver Upton <oupton@kernel.org> | 2025-11-24 11:01:50 -0800 |
|---|---|---|
| committer | Oliver Upton <oupton@kernel.org> | 2025-12-01 00:44:02 -0800 |
| commit | fabf321cba4be0d0dcbb39e97c3deb572fec2f8d (patch) | |
| tree | cfbe8c9dd56659535bd5b6f236456f513746badb /arch/arm64 | |
| parent | 977d1bf15c5179276d93468abbc00a224908ff72 (diff) | |
KVM: arm64: Handle endianness in read helper for emulated PTW
Implementing FEAT_HAFDBS means adding another descriptor accessor that
needs to deal with the guest-configured endianness. Prepare by moving
the endianness handling into the read accessor and out of the main body
of the S1/S2 PTWs.
Reviewed-by: Marc Zyngier <maz@kernel.org>
Tested-by: Marc Zyngier <maz@kernel.org>
Link: https://msgid.link/20251124190158.177318-9-oupton@kernel.org
Signed-off-by: Oliver Upton <oupton@kernel.org>
Diffstat (limited to 'arch/arm64')
| -rw-r--r-- | arch/arm64/kvm/at.c | 25 | ||||
| -rw-r--r-- | arch/arm64/kvm/nested.c | 32 |
2 files changed, 39 insertions, 18 deletions
diff --git a/arch/arm64/kvm/at.c b/arch/arm64/kvm/at.c index be26d5aa668c..a295a37dd3b1 100644 --- a/arch/arm64/kvm/at.c +++ b/arch/arm64/kvm/at.c @@ -362,6 +362,24 @@ transfault: return -EFAULT; } +static int kvm_read_s1_desc(struct kvm_vcpu *vcpu, u64 pa, u64 *desc, + struct s1_walk_info *wi) +{ + u64 val; + int r; + + r = kvm_read_guest(vcpu->kvm, pa, &val, sizeof(val)); + if (r) + return r; + + if (wi->be) + *desc = be64_to_cpu((__force __be64)val); + else + *desc = le64_to_cpu((__force __le64)val); + + return 0; +} + static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi, struct s1_walk_result *wr, u64 va) { @@ -414,17 +432,12 @@ static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi, return ret; } - ret = kvm_read_guest(vcpu->kvm, ipa, &desc, sizeof(desc)); + ret = kvm_read_s1_desc(vcpu, ipa, &desc, wi); if (ret) { fail_s1_walk(wr, ESR_ELx_FSC_SEA_TTW(level), false); return ret; } - if (wi->be) - desc = be64_to_cpu((__force __be64)desc); - else - desc = le64_to_cpu((__force __le64)desc); - /* Invalid descriptor */ if (!(desc & BIT(0))) goto transfault; diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index 94eff8307aad..75d26c0ba3e0 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -197,9 +197,26 @@ static int check_output_size(struct s2_walk_info *wi, phys_addr_t output) return 0; } -static int read_guest_s2_desc(struct kvm_vcpu *vcpu, phys_addr_t pa, u64 *desc) +static int read_guest_s2_desc(struct kvm_vcpu *vcpu, phys_addr_t pa, u64 *desc, + struct s2_walk_info *wi) { - return kvm_read_guest(vcpu->kvm, pa, desc, sizeof(*desc)); + u64 val; + int r; + + r = kvm_read_guest(vcpu->kvm, pa, &val, sizeof(val)); + if (r) + return r; + + /* + * Handle reversedescriptors if endianness differs between the + * host and the guest hypervisor. + */ + if (wi->be) + *desc = be64_to_cpu((__force __be64)val); + else + *desc = le64_to_cpu((__force __le64)val); + + return 0; } /* @@ -260,19 +277,10 @@ static int walk_nested_s2_pgd(struct kvm_vcpu *vcpu, phys_addr_t ipa, >> (addr_bottom - 3); paddr = base_addr | index; - ret = read_guest_s2_desc(vcpu, paddr, &desc); + ret = read_guest_s2_desc(vcpu, paddr, &desc, wi); if (ret < 0) return ret; - /* - * Handle reversedescriptors if endianness differs between the - * host and the guest hypervisor. - */ - if (wi->be) - desc = be64_to_cpu((__force __be64)desc); - else - desc = le64_to_cpu((__force __le64)desc); - /* Check for valid descriptor at this point */ if (!(desc & 1) || ((desc & 3) == 1 && level == 3)) { out->esr = compute_fsc(level, ESR_ELx_FSC_FAULT); |