On Wed, 2016-01-27 at 21:13 +1100, David Gibson wrote: > ppc_store_slb updates the SLB for PPC cpus with 64-bit hash MMUs. > Currently it takes two parameters, which contain values encoded as > the > register arguments to the slbmte instruction, one register contains > the > ESID portion of the SLBE and also the slot number, the other contains > the > VSID portion of the SLBE. > > We're shortly going to want to do some SLB updates from other code > where > it is more convenient to supply the slot number and ESID separately, > so > rework this function and its callers to work this way. > > As a bonus, this slightly simplifies the emulation of segment > registers for > when running a 32-bit OS on a 64-bit CPU. > > Signed-off-by: David Gibson <da...@gibson.dropbear.id.au>
Acked-by: Benjamin Herrenschmidt <b...@kernel.crashing.org> > --- > target-ppc/kvm.c | 2 +- > target-ppc/mmu-hash64.c | 24 +++++++++++++----------- > target-ppc/mmu-hash64.h | 3 ++- > target-ppc/mmu_helper.c | 14 +++++--------- > 4 files changed, 21 insertions(+), 22 deletions(-) > > diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c > index 98d7ba6..0f45380 100644 > --- a/target-ppc/kvm.c > +++ b/target-ppc/kvm.c > @@ -1205,7 +1205,7 @@ int kvm_arch_get_registers(CPUState *cs) > * Only restore valid entries > */ > if (rb & SLB_ESID_V) { > - ppc_store_slb(cpu, rb, rs); > + ppc_store_slb(cpu, rb & 0xfff, rb & ~0xfffULL, rs); > } > } > #endif > diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c > index 03e25fd..6e05643 100644 > --- a/target-ppc/mmu-hash64.c > +++ b/target-ppc/mmu-hash64.c > @@ -135,28 +135,30 @@ void helper_slbie(CPUPPCState *env, > target_ulong addr) > } > } > > -int ppc_store_slb(PowerPCCPU *cpu, target_ulong rb, target_ulong rs) > +int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot, > + target_ulong esid, target_ulong vsid) > { > CPUPPCState *env = &cpu->env; > - int slot = rb & 0xfff; > ppc_slb_t *slb = &env->slb[slot]; > > - if (rb & (0x1000 - env->slb_nr)) { > - return -1; /* Reserved bits set or slot too high */ > + if (slot >= env->slb_nr) { > + return -1; /* Bad slot number */ > + } > + if (esid & ~(SLB_ESID_ESID | SLB_ESID_V)) { > + return -1; /* Reserved bits set */ > } > - if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) { > + if (vsid & (SLB_VSID_B & ~SLB_VSID_B_1T)) { > return -1; /* Bad segment size */ > } > - if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) > { > + if ((vsid & SLB_VSID_B) && !(env->mmu_model & > POWERPC_MMU_1TSEG)) { > return -1; /* 1T segment on MMU that doesn't support it */ > } > > - /* Mask out the slot number as we store the entry */ > - slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V); > - slb->vsid = rs; > + slb->esid = esid; > + slb->vsid = vsid; > > LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" > PRIx64 > - " %016" PRIx64 "\n", __func__, slot, rb, rs, > + " %016" PRIx64 "\n", __func__, slot, esid, vsid, > slb->esid, slb->vsid); > > return 0; > @@ -196,7 +198,7 @@ void helper_store_slb(CPUPPCState *env, > target_ulong rb, target_ulong rs) > { > PowerPCCPU *cpu = ppc_env_get_cpu(env); > > - if (ppc_store_slb(cpu, rb, rs) < 0) { > + if (ppc_store_slb(cpu, rb & 0xfff, rb & ~0xfffULL, rs) < 0) { > helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM, > POWERPC_EXCP_INVAL); > } > diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h > index 6e3de7e..24fd2c4 100644 > --- a/target-ppc/mmu-hash64.h > +++ b/target-ppc/mmu-hash64.h > @@ -6,7 +6,8 @@ > #ifdef TARGET_PPC64 > void ppc_hash64_check_page_sizes(PowerPCCPU *cpu, Error **errp); > void dump_slb(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU > *cpu); > -int ppc_store_slb(PowerPCCPU *cpu, target_ulong rb, target_ulong > rs); > +int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot, > + target_ulong esid, target_ulong vsid); > hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong > addr); > int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, target_ulong > address, int rw, > int mmu_idx); > diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c > index 0ab73bc..c040b17 100644 > --- a/target-ppc/mmu_helper.c > +++ b/target-ppc/mmu_helper.c > @@ -2088,21 +2088,17 @@ void helper_store_sr(CPUPPCState *env, > target_ulong srnum, target_ulong value) > (int)srnum, value, env->sr[srnum]); > #if defined(TARGET_PPC64) > if (env->mmu_model & POWERPC_MMU_64) { > - uint64_t rb = 0, rs = 0; > + uint64_t esid, vsid; > > /* ESID = srnum */ > - rb |= ((uint32_t)srnum & 0xf) << 28; > - /* Set the valid bit */ > - rb |= SLB_ESID_V; > - /* Index = ESID */ > - rb |= (uint32_t)srnum; > + esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V; > > /* VSID = VSID */ > - rs |= (value & 0xfffffff) << 12; > + vsid = (value & 0xfffffff) << 12; > /* flags = flags */ > - rs |= ((value >> 27) & 0xf) << 8; > + vsid |= ((value >> 27) & 0xf) << 8; > > - ppc_store_slb(cpu, rb, rs); > + ppc_store_slb(cpu, srnum, esid, vsid); > } else > #endif > if (env->sr[srnum] != value) {