On Wed, Jan 22, 2014 at 6:12 AM, Peter Maydell <peter.maydell@xxxxxxxxxx> wrote: > Implement the AArch64 TTBR* registers. For v7 these were already 64 bits > to handle LPAE, but implemented as two separate uint32_t fields. > Combine them into a single uint64_t which can be used for all purposes. > Since this requires touching every use, take the opportunity to rename > the field to the architectural name. > > Signed-off-by: Peter Maydell <peter.maydell@xxxxxxxxxx> > --- > hw/arm/pxa2xx.c | 2 +- > target-arm/cpu.h | 6 ++-- > target-arm/helper.c | 95 +++++++++++++++++------------------------------------ > 3 files changed, 33 insertions(+), 70 deletions(-) > > diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c > index 02b7016..b6465d6 100644 > --- a/hw/arm/pxa2xx.c > +++ b/hw/arm/pxa2xx.c > @@ -279,7 +279,7 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri, > ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; > s->cpu->env.cp15.c1_sys = 0; > s->cpu->env.cp15.c1_coproc = 0; > - s->cpu->env.cp15.c2_base0 = 0; > + s->cpu->env.cp15.ttbr0_el1 = 0; > s->cpu->env.cp15.c3 = 0; > s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */ > s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */ > diff --git a/target-arm/cpu.h b/target-arm/cpu.h > index 6f4d174..7138882 100644 > --- a/target-arm/cpu.h > +++ b/target-arm/cpu.h > @@ -173,10 +173,8 @@ typedef struct CPUARMState { > uint32_t c1_coproc; /* Coprocessor access register. */ > uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */ > uint32_t c1_scr; /* secure config register. */ > - uint32_t c2_base0; /* MMU translation table base 0. */ > - uint32_t c2_base0_hi; /* MMU translation table base 0, high 32 bits */ > - uint32_t c2_base1; /* MMU translation table base 0. */ > - uint32_t c2_base1_hi; /* MMU translation table base 1, high 32 bits */ > + uint64_t ttbr0_el1; /* MMU translation table base 0. */ > + uint32_t ttbr1_el1; /* MMU translation table base 1. */ > uint64_t c2_control; /* MMU translation table base control. */ > uint32_t c2_mask; /* MMU translation table base selection mask. */ > uint32_t c2_base_mask; /* MMU translation table base 0 mask. */ > diff --git a/target-arm/helper.c b/target-arm/helper.c > index e2ae159..1f1dec1 100644 > --- a/target-arm/helper.c > +++ b/target-arm/helper.c > @@ -1288,6 +1288,18 @@ static int vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri, > return 0; > } > > +static int vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, > + uint64_t value) > +{ > + /* 64 bit accesses to the TTBRs can change the ASID and so we > + * must flush the TLB. > + */ > + if ((ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT)) { > + tlb_flush(env, 1); > + } With the level of complexity this if has reached, is it better to just check for this ASID change rather than make this overly conservative flush? Regards, Peter > + return raw_write(env, ri, value); > +} > + > static const ARMCPRegInfo vmsa_cp_reginfo[] = { > { .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0, > .access = PL1_RW, > @@ -1295,12 +1307,14 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = { > { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1, > .access = PL1_RW, > .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, }, > - { .name = "TTBR0", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, > - .access = PL1_RW, > - .fieldoffset = offsetof(CPUARMState, cp15.c2_base0), .resetvalue = 0, }, > - { .name = "TTBR1", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1, > - .access = PL1_RW, > - .fieldoffset = offsetof(CPUARMState, cp15.c2_base1), .resetvalue = 0, }, > + { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH, > + .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, > + .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1), > + .writefn = vmsa_ttbr_write, .resetvalue = 0 }, > + { .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH, > + .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1, > + .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1), > + .writefn = vmsa_ttbr_write, .resetvalue = 0 }, > { .name = "TCR_EL1", .state = ARM_CP_STATE_AA64, > .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2, > .access = PL1_RW, .writefn = vmsa_tcr_el1_write, > @@ -1525,56 +1539,6 @@ static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri) > env->cp15.c7_par = 0; > } > > -static int ttbr064_read(CPUARMState *env, const ARMCPRegInfo *ri, > - uint64_t *value) > -{ > - *value = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0; > - return 0; > -} > - > -static int ttbr064_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, > - uint64_t value) > -{ > - env->cp15.c2_base0_hi = value >> 32; > - env->cp15.c2_base0 = value; > - return 0; > -} > - > -static int ttbr064_write(CPUARMState *env, const ARMCPRegInfo *ri, > - uint64_t value) > -{ > - /* Writes to the 64 bit format TTBRs may change the ASID */ > - tlb_flush(env, 1); > - return ttbr064_raw_write(env, ri, value); > -} > - > -static void ttbr064_reset(CPUARMState *env, const ARMCPRegInfo *ri) > -{ > - env->cp15.c2_base0_hi = 0; > - env->cp15.c2_base0 = 0; > -} > - > -static int ttbr164_read(CPUARMState *env, const ARMCPRegInfo *ri, > - uint64_t *value) > -{ > - *value = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1; > - return 0; > -} > - > -static int ttbr164_write(CPUARMState *env, const ARMCPRegInfo *ri, > - uint64_t value) > -{ > - env->cp15.c2_base1_hi = value >> 32; > - env->cp15.c2_base1 = value; > - return 0; > -} > - > -static void ttbr164_reset(CPUARMState *env, const ARMCPRegInfo *ri) > -{ > - env->cp15.c2_base1_hi = 0; > - env->cp15.c2_base1 = 0; > -} > - > static const ARMCPRegInfo lpae_cp_reginfo[] = { > /* NOP AMAIR0/1: the override is because these clash with the rather > * broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo. > @@ -1596,12 +1560,13 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = { > .access = PL1_RW, .type = ARM_CP_64BIT, > .readfn = par64_read, .writefn = par64_write, .resetfn = par64_reset }, > { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0, > - .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr064_read, > - .writefn = ttbr064_write, .raw_writefn = ttbr064_raw_write, > - .resetfn = ttbr064_reset }, > + .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE, > + .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1), > + .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore }, > { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1, > - .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr164_read, > - .writefn = ttbr164_write, .resetfn = ttbr164_reset }, > + .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE, > + .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1), > + .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore }, > REGINFO_SENTINEL > }; > > @@ -3024,9 +2989,9 @@ static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address) > uint32_t table; > > if (address & env->cp15.c2_mask) > - table = env->cp15.c2_base1 & 0xffffc000; > + table = env->cp15.ttbr1_el1 & 0xffffc000; > else > - table = env->cp15.c2_base0 & env->cp15.c2_base_mask; > + table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask; > > table |= (address >> 18) & 0x3ffc; > return table; > @@ -3299,11 +3264,11 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address, > * we will always flush the TLB any time the ASID is changed). > */ > if (ttbr_select == 0) { > - ttbr = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0; > + ttbr = env->cp15.ttbr0_el1; > epd = extract32(env->cp15.c2_control, 7, 1); > tsz = t0sz; > } else { > - ttbr = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1; > + ttbr = env->cp15.ttbr1_el1; > epd = extract32(env->cp15.c2_control, 23, 1); > tsz = t1sz; > } > -- > 1.8.5 > > _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm