qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-arm] [Qemu-devel] [PATCH] target/arm: Handle page table walk l


From: Philippe Mathieu-Daudé
Subject: Re: [Qemu-arm] [Qemu-devel] [PATCH] target/arm: Handle page table walk load failures correctly
Date: Fri, 15 Dec 2017 13:57:43 -0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0

On 12/15/2017 01:24 PM, Peter Maydell wrote:
> Instead of ignoring the response from address_space_ld*()
> (indicating an attempt to read a page table descriptor from
> an invalid physical address), use it to report the failure
> correctly.
> 
> Since this is another couple of locations where we need to
> decide the value of the ARMMMUFaultInfo ea bit based on a
> MemTxResult, we factor out that operation into a helper
> function.
> 
> Signed-off-by: Peter Maydell <address@hidden>

Reviewed-by: Philippe Mathieu-Daudé <address@hidden>

> ---
> Now we've fixed the get-phys-addr functions to always report
> errors via the ARMMMUFaultInfo struct, it's pretty easy to
> detect and report external aborts on translation table walks.
> 
>  target/arm/internals.h | 10 ++++++++++
>  target/arm/helper.c    | 39 ++++++++++++++++++++++++++++++++++-----
>  target/arm/op_helper.c |  7 +------
>  3 files changed, 45 insertions(+), 11 deletions(-)
> 
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 876854d..89f5d2f 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -687,6 +687,16 @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo 
> *fi)
>      return fsc;
>  }
>  
> +static inline bool arm_extabort_type(MemTxResult result)
> +{
> +    /* The EA bit in syndromes and fault status registers is an
> +     * IMPDEF classification of external aborts. ARM implementations
> +     * usually use this to indicate AXI bus Decode error (0) or
> +     * Slave error (1); in QEMU we follow that.
> +     */
> +    return result != MEMTX_DECODE_ERROR;
> +}
> +
>  /* Do a page table walk and add page to TLB if possible */
>  bool arm_tlb_fill(CPUState *cpu, vaddr address,
>                    MMUAccessType access_type, int mmu_idx,
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index d1395f9..2575a83 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -8305,6 +8305,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, 
> ARMMMUIdx mmu_idx,
>          ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
>                                   &txattrs, &s2prot, &s2size, fi, NULL);
>          if (ret) {
> +            assert(fi->type != ARMFault_None);
>              fi->s2addr = addr;
>              fi->stage2 = true;
>              fi->s1ptw = true;
> @@ -8328,7 +8329,9 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, 
> bool is_secure,
>      ARMCPU *cpu = ARM_CPU(cs);
>      CPUARMState *env = &cpu->env;
>      MemTxAttrs attrs = {};
> +    MemTxResult result = MEMTX_OK;
>      AddressSpace *as;
> +    uint32_t data;
>  
>      attrs.secure = is_secure;
>      as = arm_addressspace(cs, attrs);
> @@ -8337,10 +8340,16 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr 
> addr, bool is_secure,
>          return 0;
>      }
>      if (regime_translation_big_endian(env, mmu_idx)) {
> -        return address_space_ldl_be(as, addr, attrs, NULL);
> +        data = address_space_ldl_be(as, addr, attrs, &result);
>      } else {
> -        return address_space_ldl_le(as, addr, attrs, NULL);
> +        data = address_space_ldl_le(as, addr, attrs, &result);
>      }
> +    if (result == MEMTX_OK) {
> +        return data;
> +    }
> +    fi->type = ARMFault_SyncExternalOnWalk;
> +    fi->ea = arm_extabort_type(result);
> +    return 0;
>  }
>  
>  static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
> @@ -8349,7 +8358,9 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, 
> bool is_secure,
>      ARMCPU *cpu = ARM_CPU(cs);
>      CPUARMState *env = &cpu->env;
>      MemTxAttrs attrs = {};
> +    MemTxResult result = MEMTX_OK;
>      AddressSpace *as;
> +    uint32_t data;
>  
>      attrs.secure = is_secure;
>      as = arm_addressspace(cs, attrs);
> @@ -8358,10 +8369,16 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr 
> addr, bool is_secure,
>          return 0;
>      }
>      if (regime_translation_big_endian(env, mmu_idx)) {
> -        return address_space_ldq_be(as, addr, attrs, NULL);
> +        data = address_space_ldq_be(as, addr, attrs, &result);
>      } else {
> -        return address_space_ldq_le(as, addr, attrs, NULL);
> +        data = address_space_ldq_le(as, addr, attrs, &result);
> +    }
> +    if (result == MEMTX_OK) {
> +        return data;
>      }
> +    fi->type = ARMFault_SyncExternalOnWalk;
> +    fi->ea = arm_extabort_type(result);
> +    return 0;
>  }
>  
>  static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
> @@ -8390,6 +8407,9 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t 
> address,
>      }
>      desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
>                         mmu_idx, fi);
> +    if (fi->type != ARMFault_None) {
> +        goto do_fault;
> +    }
>      type = (desc & 3);
>      domain = (desc >> 5) & 0x0f;
>      if (regime_el(env, mmu_idx) == 1) {
> @@ -8426,6 +8446,9 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t 
> address,
>          }
>          desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
>                             mmu_idx, fi);
> +        if (fi->type != ARMFault_None) {
> +            goto do_fault;
> +        }
>          switch (desc & 3) {
>          case 0: /* Page translation fault.  */
>              fi->type = ARMFault_Translation;
> @@ -8508,6 +8531,9 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t 
> address,
>      }
>      desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
>                         mmu_idx, fi);
> +    if (fi->type != ARMFault_None) {
> +        goto do_fault;
> +    }
>      type = (desc & 3);
>      if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
>          /* Section translation fault, or attempt to use the encoding
> @@ -8559,6 +8585,9 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t 
> address,
>          table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
>          desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
>                             mmu_idx, fi);
> +        if (fi->type != ARMFault_None) {
> +            goto do_fault;
> +        }
>          ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
>          switch (desc & 3) {
>          case 0: /* Page translation fault.  */
> @@ -8964,7 +8993,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, 
> target_ulong address,
>          descaddr &= ~7ULL;
>          nstable = extract32(tableattrs, 4, 1);
>          descriptor = arm_ldq_ptw(cs, descaddr, !nstable, mmu_idx, fi);
> -        if (fi->s1ptw) {
> +        if (fi->type != ARMFault_None) {
>              goto do_fault;
>          }
>  
> diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
> index c2bb4f3..2f35ff7 100644
> --- a/target/arm/op_helper.c
> +++ b/target/arm/op_helper.c
> @@ -226,12 +226,7 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr 
> physaddr,
>          cpu_restore_state(cs, retaddr);
>      }
>  
> -    /* The EA bit in syndromes and fault status registers is an
> -     * IMPDEF classification of external aborts. ARM implementations
> -     * usually use this to indicate AXI bus Decode error (0) or
> -     * Slave error (1); in QEMU we follow that.
> -     */
> -    fi.ea = (response != MEMTX_DECODE_ERROR);
> +    fi.ea = arm_extabort_type(response);
>      fi.type = ARMFault_SyncExternal;
>      deliver_fault(cpu, addr, access_type, mmu_idx, &fi);
>  }
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]