qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 12/25] target-sparc: Add MMU_REAL_IDX


From: Artyom Tarasenko
Subject: Re: [Qemu-devel] [PATCH 12/25] target-sparc: Add MMU_REAL_IDX
Date: Mon, 11 Jan 2016 13:01:47 +0100

On Mon, Jan 11, 2016 at 12:15 PM, Artyom Tarasenko <address@hidden> wrote:
> Hi Richard,
>
> first of all, this is a very nice series.
> I really enjoy reading it, thank you very much.
> It makes the code is more readable and likely to be more performant.
> A nitpick below.
>
> On Thu, Dec 17, 2015 at 9:57 PM, Richard Henderson <address@hidden> wrote:
>> This gives us a trivial way to access physical addresses
>> (aka "real addresses", in sun4v terminology) directly from
>> qemu_ld/st, without having to go through another helper.
>>
>> This also fixes a bug in get_physical_address_code where
>> it inferred NUCLEUS from env->tl instead of from mmu_idx.
>>
>> Signed-off-by: Richard Henderson <address@hidden>
>> ---
>>  target-sparc/cpu.h        | 18 +++++++---
>>  target-sparc/mmu_helper.c | 90 
>> +++++++++++++++++++++++++++++------------------
>>  2 files changed, 69 insertions(+), 39 deletions(-)
>>
>> diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
>> index 7f4d47f..b1222a1 100644
>> --- a/target-sparc/cpu.h
>> +++ b/target-sparc/cpu.h
>> @@ -220,9 +220,9 @@ enum {
>>  #define MAX_NWINDOWS 32
>>
>>  #if !defined(TARGET_SPARC64)
>> -#define NB_MMU_MODES 2
>> +#define NB_MMU_MODES 3
>>  #else
>> -#define NB_MMU_MODES 6
>> +#define NB_MMU_MODES 7
>>  typedef struct trap_state {
>>      uint64_t tpc;
>>      uint64_t tnpc;
>> @@ -612,11 +612,13 @@ int cpu_sparc_signal_handler(int host_signum, void 
>> *pinfo, void *puc);
>>  #define MMU_MODE4_SUFFIX _nucleus
>>  #define MMU_HYPV_IDX   5
>>  #define MMU_MODE5_SUFFIX _hypv
>> +#define MMU_REAL_IDX   6
>>  #else
>>  #define MMU_USER_IDX   0
>>  #define MMU_MODE0_SUFFIX _user
>>  #define MMU_KERNEL_IDX 1
>>  #define MMU_MODE1_SUFFIX _kernel
>> +#define MMU_REAL_IDX   2
>>  #endif
>>
>>  #if defined (TARGET_SPARC64)
>> @@ -641,9 +643,17 @@ static inline int cpu_mmu_index(CPUSPARCState *env1, 
>> bool ifetch)
>>  #if defined(CONFIG_USER_ONLY)
>>      return MMU_USER_IDX;
>>  #elif !defined(TARGET_SPARC64)
>> -    return env1->psrs;
>> +    if (!(env1->mmuregs[0] & MMU_E)) {
>> +        return MMU_REAL_IDX; /* MMU disabled */
>> +    } else {
>> +        return env1->psrs;
>> +    }
>>  #else
>> -    if (env1->tl > 0) {
>> +    if (ifetch
>> +        ? !(env1->lsu & IMMU_E) || (env1->pstate & PS_RED)
>> +        : !(env1->lsu & DMMU_E)) {
>> +        return MMU_REAL_IDX; /* MMU disabled */
>> +    } else if (env1->tl > 0) {
>>          return MMU_NUCLEUS_IDX;
>>      } else if (cpu_hypervisor_mode(env1)) {
>>          return MMU_HYPV_IDX;
>> diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
>> index 7495406..105f00d 100644
>> --- a/target-sparc/mmu_helper.c
>> +++ b/target-sparc/mmu_helper.c
>> @@ -90,7 +90,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr 
>> *physical,
>>
>>      is_user = mmu_idx == MMU_USER_IDX;
>>
>> -    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
>> +    if (mmu_idx == MMU_REAL_IDX) { /* MMU bypass access */
>>          *page_size = TARGET_PAGE_SIZE;
>>          /* Boot mode: instruction fetches are taken from PROM */
>>          if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
>> @@ -492,33 +492,40 @@ static int get_physical_address_data(CPUSPARCState 
>> *env,
>>      unsigned int i;
>>      uint64_t context;
>>      uint64_t sfsr = 0;
>> +    bool is_user = false;
>>
>> -    int is_user = (mmu_idx == MMU_USER_IDX ||
>> -                   mmu_idx == MMU_USER_SECONDARY_IDX);
>> -
>> -    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
>
> ^^^^
>
> in case of ASI instructions, mmu_idx can come from dc->mem_idx, right?
> So the check may be still necessary here,
>
>> +    switch (mmu_idx) {
>> +    case MMU_REAL_IDX:
>> +        /* MMU bypass access */
>>          *physical = ultrasparc_truncate_physical(address);
>> -        *prot = PAGE_READ | PAGE_WRITE;
>> +        *prot = PAGE_EXEC | PAGE_READ | PAGE_WRITE;
>>          return 0;
>> -    }
>>
>> -    switch (mmu_idx) {
>> +    case MMU_NUCLEUS_IDX:
>> +        sfsr |= SFSR_CT_NUCLEUS;
>> +        /* fallthru */
>> +    case MMU_HYPV_IDX:
>> +        /* No context. */
>> +        context = 0;
>> +        break;
>>      case MMU_USER_IDX:
>> +        is_user = true;
>> +        /* fallthru */
>>      case MMU_KERNEL_IDX:
>> +        /* PRIMARY context */
>>          context = env->dmmu.mmu_primary_context & 0x1fff;
>>          sfsr |= SFSR_CT_PRIMARY;
>>          break;
>>      case MMU_USER_SECONDARY_IDX:
>> +        is_user = true;
>> +        /* fallthru */
>>      case MMU_KERNEL_SECONDARY_IDX:
>> +        /* PRIMARY context */
>>          context = env->dmmu.mmu_secondary_context & 0x1fff;
>>          sfsr |= SFSR_CT_SECONDARY;
>>          break;
>> -    case MMU_NUCLEUS_IDX:
>> -        sfsr |= SFSR_CT_NUCLEUS;
>> -        /* FALLTHRU */
>>      default:
>> -        context = 0;
>> -        break;
>> +        g_assert_not_reached();
>>      }
>>
>>      if (rw == 1) {
>> @@ -573,8 +580,8 @@ static int get_physical_address_data(CPUSPARCState *env,
>>              }
>>
>>              if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register 
>> */
>> -                sfsr |= SFSR_OW_BIT; /* overflow (not read before
>> -                                        another fault) */
>> +                /* overflow (not read before another fault) */
>> +                sfsr |= SFSR_OW_BIT;
>>              }
>>
>>              if (env->pstate & PS_PRIV) {
>> @@ -611,23 +618,41 @@ static int get_physical_address_code(CPUSPARCState 
>> *env,
>>      CPUState *cs = CPU(sparc_env_get_cpu(env));
>>      unsigned int i;
>>      uint64_t context;
>> +    uint64_t sfsr = 0;
>> +    bool is_user = false;
>>
>> -    int is_user = (mmu_idx == MMU_USER_IDX ||
>> -                   mmu_idx == MMU_USER_SECONDARY_IDX);
>> -
>> -    if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
>> -        /* IMMU disabled */
>
> and here.

On a second thought, IMMU check is not necessary, because there is no
ASI access for instructions.
So, here no check is necessary, only above.

Artyom
>
>> +    switch (mmu_idx) {
>> +    case MMU_REAL_IDX:
>> +        /* MMU bypass access */
>>          *physical = ultrasparc_truncate_physical(address);
>> -        *prot = PAGE_EXEC;
>> +        *prot = PAGE_EXEC | PAGE_READ | PAGE_WRITE;
>>          return 0;
>> -    }
>>
>> -    if (env->tl == 0) {
>> +    case MMU_NUCLEUS_IDX:
>> +        sfsr |= SFSR_CT_NUCLEUS;
>> +        /* fallthru */
>> +    case MMU_HYPV_IDX:
>> +        /* No context. */
>> +        context = 0;
>> +        break;
>> +    case MMU_USER_IDX:
>> +        is_user = true;
>> +        /* fallthru */
>> +    case MMU_KERNEL_IDX:
>>          /* PRIMARY context */
>>          context = env->dmmu.mmu_primary_context & 0x1fff;
>> -    } else {
>> -        /* NUCLEUS context */
>> -        context = 0;
>> +        sfsr |= SFSR_CT_PRIMARY;
>> +        break;
>> +    case MMU_USER_SECONDARY_IDX:
>> +        is_user = true;
>> +        /* fallthru */
>> +    case MMU_KERNEL_SECONDARY_IDX:
>> +        /* PRIMARY context */
>> +        context = env->dmmu.mmu_secondary_context & 0x1fff;
>> +        sfsr |= SFSR_CT_SECONDARY;
>> +        break;
>> +    default:
>> +        g_assert_not_reached();
>>      }
>>
>>      for (i = 0; i < 64; i++) {
>> @@ -638,20 +663,15 @@ static int get_physical_address_code(CPUSPARCState 
>> *env,
>>              if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
>>                  /* Fault status register */
>>                  if (env->immu.sfsr & SFSR_VALID_BIT) {
>> -                    env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read 
>> before
>> -                                                     another fault) */
>> -                } else {
>> -                    env->immu.sfsr = 0;
>> +                    /* overflow (not read before another fault) */
>> +                    sfsr |= SFSR_OW_BIT;
>>                  }
>>                  if (env->pstate & PS_PRIV) {
>> -                    env->immu.sfsr |= SFSR_PR_BIT;
>> -                }
>> -                if (env->tl > 0) {
>> -                    env->immu.sfsr |= SFSR_CT_NUCLEUS;
>> +                    sfsr |= SFSR_PR_BIT;
>>                  }
>>
>>                  /* FIXME: ASI field in SFSR must be set */
>> -                env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
>> +                env->immu.sfsr |= sfsr | SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
>>                  cs->exception_index = TT_TFAULT;
>>
>>                  env->immu.tag_access = (address & ~0x1fffULL) | context;
>> --
>> 2.5.0
>>
>>
>
>
>
> --
> Regards,
> Artyom Tarasenko
>
> SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu



reply via email to

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