[PATCH] ARM/arm64: KVM: fix use of WnR bit in kvm_is_write_fault()
Ard Biesheuvel
ard.biesheuvel at linaro.org
Tue Sep 9 03:01:43 PDT 2014
On 9 September 2014 11:35, Marc Zyngier <marc.zyngier at arm.com> wrote:
> Hi Ard,
>
>
> On 2014-09-08 21:29, Ard Biesheuvel wrote:
>>
>> The ISS encoding for an exception from a Data Abort has a WnR
>> bit[6] that indicates whether the Data Abort was caused by a
>> read or a write instruction. While there are several fields
>> in the encoding that are only valid if the ISV bit[24] is set,
>> WnR is not one of them, so we can read it unconditionally.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
>> ---
>>
>> This fixes an issue I observed with UEFI running under QEMU/KVM using
>> NOR flash emulation and the upcoming KVM_CAP_READONLY_MEM support, where
>> NOR flash reads were mistaken for NOR flash writes, resulting in all read
>> accesses to go through the MMIO emulation layer.
>>
>> arch/arm/include/asm/kvm_mmu.h | 5 +----
>> arch/arm64/include/asm/kvm_mmu.h | 5 +----
>> 2 files changed, 2 insertions(+), 8 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/kvm_mmu.h
>> b/arch/arm/include/asm/kvm_mmu.h
>> index 5cc0b0f5f72f..fad5648980ad 100644
>> --- a/arch/arm/include/asm/kvm_mmu.h
>> +++ b/arch/arm/include/asm/kvm_mmu.h
>> @@ -83,10 +83,7 @@ static inline bool kvm_is_write_fault(unsigned long
>> hsr)
>> unsigned long hsr_ec = hsr >> HSR_EC_SHIFT;
>> if (hsr_ec == HSR_EC_IABT)
>> return false;
>> - else if ((hsr & HSR_ISV) && !(hsr & HSR_WNR))
>> - return false;
>> - else
>> - return true;
>> + return hsr & HSR_WNR;
>> }
>>
>> static inline void kvm_clean_pgd(pgd_t *pgd)
>> diff --git a/arch/arm64/include/asm/kvm_mmu.h
>> b/arch/arm64/include/asm/kvm_mmu.h
>> index 8e138c7c53ac..09fd9e4c13d8 100644
>> --- a/arch/arm64/include/asm/kvm_mmu.h
>> +++ b/arch/arm64/include/asm/kvm_mmu.h
>> @@ -100,10 +100,7 @@ static inline bool kvm_is_write_fault(unsigned long
>> esr)
>> if (esr_ec == ESR_EL2_EC_IABT)
>> return false;
>>
>> - if ((esr & ESR_EL2_ISV) && !(esr & ESR_EL2_WNR))
>> - return false;
>> -
>> - return true;
>> + return esr & ESR_EL2_WNR;
>> }
>>
>> static inline void kvm_clean_pgd(pgd_t *pgd) {}
>
>
> Nice catch. One thing though.
>
> This is a case where code duplication has led to this glaring bug:
> On both arm and arm64, kvm_emulate.h has code that implements this
> correctly, just that we failed to use it. Blame me.
>
> I think this should be rewritten entierely in mmu.c, with something like
> this (fully untested, of course):
>
> static bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
> {
> if (kvm_vcpu_trap_is_iabt(vcpu))
> return false;
>
> return kvm_vcpu_dabt_iswrite(vcpu);
> }
>
> Care to respin it?
>
Will do.
More information about the linux-arm-kernel
mailing list