qemu-devel
[Top][All Lists]
Advanced

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

Re: [PATCH V3] target/riscv: raise exception to HS-mode at get_physical_


From: Alistair Francis
Subject: Re: [PATCH V3] target/riscv: raise exception to HS-mode at get_physical_address
Date: Wed, 14 Oct 2020 13:06:22 -0700

On Wed, Oct 14, 2020 at 3:18 AM Yifei Jiang <jiangyifei@huawei.com> wrote:
>
> VS-stage translation at get_physical_address needs to translate pte
> address by G-stage translation. But the G-stage translation error
> can not be distinguished from VS-stage translation error in
> riscv_cpu_tlb_fill. On migration, destination needs to rebuild pte,
> and this G-stage translation error must be handled by HS-mode. So
> introduce TRANSLATE_STAGE2_FAIL so that riscv_cpu_tlb_fill could
> distinguish and raise it to HS-mode.
>
> Signed-off-by: Yifei Jiang <jiangyifei@huawei.com>
> Signed-off-by: Yipeng Yin <yinyipeng1@huawei.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu.h        | 10 +++++++---
>  target/riscv/cpu_helper.c | 35 ++++++++++++++++++++++++++---------
>  2 files changed, 33 insertions(+), 12 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index de275782e6..de4705bb57 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -82,9 +82,13 @@ enum {
>
>  #define VEXT_VERSION_0_07_1 0x00000701
>
> -#define TRANSLATE_PMP_FAIL 2
> -#define TRANSLATE_FAIL 1
> -#define TRANSLATE_SUCCESS 0
> +enum {
> +    TRANSLATE_SUCCESS,
> +    TRANSLATE_FAIL,
> +    TRANSLATE_PMP_FAIL,
> +    TRANSLATE_G_STAGE_FAIL
> +};
> +
>  #define MMU_USER_IDX 3
>
>  #define MAX_RISCV_PMPS (16)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 904899054d..ae66722d32 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -316,6 +316,8 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong 
> newpriv)
>   * @physical: This will be set to the calculated physical address
>   * @prot: The returned protection attributes
>   * @addr: The virtual address to be translated
> + * @fault_pte_addr: If not NULL, this will be set to fault pte address
> + *                  when a error occurs on pte address translation.
>   * @access_type: The type of MMU access
>   * @mmu_idx: Indicates current privilege level
>   * @first_stage: Are we in first stage translation?
> @@ -324,6 +326,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong 
> newpriv)
>   */
>  static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>                                  int *prot, target_ulong addr,
> +                                target_ulong *fault_pte_addr,
>                                  int access_type, int mmu_idx,
>                                  bool first_stage, bool two_stage)
>  {
> @@ -447,11 +450,14 @@ restart:
>
>              /* Do the second stage translation on the base PTE address. */
>              int vbase_ret = get_physical_address(env, &vbase, &vbase_prot,
> -                                                 base, MMU_DATA_LOAD,
> +                                                 base, NULL, MMU_DATA_LOAD,
>                                                   mmu_idx, false, true);
>
>              if (vbase_ret != TRANSLATE_SUCCESS) {
> -                return vbase_ret;
> +                if (fault_pte_addr) {
> +                    *fault_pte_addr = (base + idx * ptesize) >> 2;
> +                }
> +                return TRANSLATE_G_STAGE_FAIL;
>              }
>
>              pte_addr = vbase + idx * ptesize;
> @@ -632,13 +638,13 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, 
> vaddr addr)
>      int prot;
>      int mmu_idx = cpu_mmu_index(&cpu->env, false);
>
> -    if (get_physical_address(env, &phys_addr, &prot, addr, 0, mmu_idx,
> +    if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx,
>                               true, riscv_cpu_virt_enabled(env))) {
>          return -1;
>      }
>
>      if (riscv_cpu_virt_enabled(env)) {
> -        if (get_physical_address(env, &phys_addr, &prot, phys_addr,
> +        if (get_physical_address(env, &phys_addr, &prot, phys_addr, NULL,
>                                   0, mmu_idx, false, true)) {
>              return -1;
>          }
> @@ -727,19 +733,30 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
> int size,
>      if (riscv_cpu_virt_enabled(env) ||
>          (riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) {
>          /* Two stage lookup */
> -        ret = get_physical_address(env, &pa, &prot, address, access_type,
> +        ret = get_physical_address(env, &pa, &prot, address,
> +                                   &env->guest_phys_fault_addr, access_type,
>                                     mmu_idx, true, true);
>
> +        /*
> +         * A G-stage exception may be triggered during two state lookup.
> +         * And the env->guest_phys_fault_addr has already been set in
> +         * get_physical_address().
> +         */
> +        if (ret == TRANSLATE_G_STAGE_FAIL) {
> +            first_stage_error = false;
> +            access_type = MMU_DATA_LOAD;
> +        }
> +
>          qemu_log_mask(CPU_LOG_MMU,
>                        "%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
>                        TARGET_FMT_plx " prot %d\n",
>                        __func__, address, ret, pa, prot);
>
> -        if (ret != TRANSLATE_FAIL) {
> +        if (ret == TRANSLATE_SUCCESS) {
>              /* Second stage lookup */
>              im_address = pa;
>
> -            ret = get_physical_address(env, &pa, &prot2, im_address,
> +            ret = get_physical_address(env, &pa, &prot2, im_address, NULL,
>                                         access_type, mmu_idx, false, true);
>
>              qemu_log_mask(CPU_LOG_MMU,
> @@ -768,8 +785,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
> size,
>          }
>      } else {
>          /* Single stage lookup */
> -        ret = get_physical_address(env, &pa, &prot, address, access_type,
> -                                   mmu_idx, true, false);
> +        ret = get_physical_address(env, &pa, &prot, address, NULL,
> +                                   access_type, mmu_idx, true, false);
>
>          qemu_log_mask(CPU_LOG_MMU,
>                        "%s address=%" VADDR_PRIx " ret %d physical "
> --
> 2.19.1
>
>



reply via email to

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