mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 18:05:37 +00:00
target-ppc: Fix htab_mask calculation
Correctly update the htab_mask using the return value of KVM_PPC_ALLOCATE_HTAB ioctl. Also we don't update sdr1 on GET_SREGS for HV. We check for external htab and if found true, we don't need to update sdr1 Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> [ fixed pte group offset computation in ppc_hash64_htab_lookup() that caused TCG to fail, Greg Kurz <gkurz@linux.vnet.ibm.com> ] Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
3707cd62db
commit
f3c75d42ad
|
@ -749,7 +749,13 @@ static void spapr_cpu_reset(void *opaque)
|
|||
env->external_htab = (void *)1;
|
||||
}
|
||||
env->htab_base = -1;
|
||||
env->htab_mask = HTAB_SIZE(spapr) - 1;
|
||||
/*
|
||||
* htab_mask is the mask used to normalize hash value to PTEG index.
|
||||
* htab_shift is log2 of hash table size.
|
||||
* We have 8 hpte per group, and each hpte is 16 bytes.
|
||||
* ie have 128 bytes per hpte entry.
|
||||
*/
|
||||
env->htab_mask = (1ULL << ((spapr)->htab_shift - 7)) - 1;
|
||||
env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab |
|
||||
(spapr->htab_shift - 18);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,17 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
|
|||
return rb;
|
||||
}
|
||||
|
||||
static inline bool valid_pte_index(CPUPPCState *env, target_ulong pte_index)
|
||||
{
|
||||
/*
|
||||
* hash value/pteg group index is normalized by htab_mask
|
||||
*/
|
||||
if (((pte_index & ~7ULL) / HPTES_PER_GROUP) & ~env->htab_mask) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
target_ulong opcode, target_ulong *args)
|
||||
{
|
||||
|
@ -91,7 +102,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||
|
||||
pteh &= ~0x60ULL;
|
||||
|
||||
if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
|
||||
if (!valid_pte_index(env, pte_index)) {
|
||||
return H_PARAMETER;
|
||||
}
|
||||
if (likely((flags & H_EXACT) == 0)) {
|
||||
|
@ -136,7 +147,7 @@ static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex,
|
|||
hwaddr hpte;
|
||||
target_ulong v, r, rb;
|
||||
|
||||
if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
|
||||
if (!valid_pte_index(env, ptex)) {
|
||||
return REMOVE_PARM;
|
||||
}
|
||||
|
||||
|
@ -262,7 +273,7 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||
hwaddr hpte;
|
||||
target_ulong v, r, rb;
|
||||
|
||||
if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
|
||||
if (!valid_pte_index(env, pte_index)) {
|
||||
return H_PARAMETER;
|
||||
}
|
||||
|
||||
|
@ -299,7 +310,7 @@ static target_ulong h_read(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||
uint8_t *hpte;
|
||||
int i, ridx, n_entries = 1;
|
||||
|
||||
if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
|
||||
if (!valid_pte_index(env, pte_index)) {
|
||||
return H_PARAMETER;
|
||||
}
|
||||
|
||||
|
|
|
@ -966,6 +966,7 @@ struct CPUPPCState {
|
|||
#endif
|
||||
/* segment registers */
|
||||
hwaddr htab_base;
|
||||
/* mask used to normalize hash value to PTEG index */
|
||||
hwaddr htab_mask;
|
||||
target_ulong sr[32];
|
||||
/* externally stored hash table */
|
||||
|
|
|
@ -1031,7 +1031,9 @@ int kvm_arch_get_registers(CPUState *cs)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ppc_store_sdr1(env, sregs.u.s.sdr1);
|
||||
if (!env->external_htab) {
|
||||
ppc_store_sdr1(env, sregs.u.s.sdr1);
|
||||
}
|
||||
|
||||
/* Sync SLB */
|
||||
#ifdef TARGET_PPC64
|
||||
|
|
|
@ -70,7 +70,9 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
|
|||
qemu_get_betls(f, &env->pb[i]);
|
||||
for (i = 0; i < 1024; i++)
|
||||
qemu_get_betls(f, &env->spr[i]);
|
||||
ppc_store_sdr1(env, sdr1);
|
||||
if (!env->external_htab) {
|
||||
ppc_store_sdr1(env, sdr1);
|
||||
}
|
||||
qemu_get_be32s(f, &env->vscr);
|
||||
qemu_get_be64s(f, &env->spe_acc);
|
||||
qemu_get_be32s(f, &env->spe_fscr);
|
||||
|
@ -179,9 +181,10 @@ static int cpu_post_load(void *opaque, int version_id)
|
|||
env->IBAT[1][i+4] = env->spr[SPR_IBAT4U + 2*i + 1];
|
||||
}
|
||||
|
||||
/* Restore htab_base and htab_mask variables */
|
||||
ppc_store_sdr1(env, env->spr[SPR_SDR1]);
|
||||
|
||||
if (!env->external_htab) {
|
||||
/* Restore htab_base and htab_mask variables */
|
||||
ppc_store_sdr1(env, env->spr[SPR_SDR1]);
|
||||
}
|
||||
hreg_compute_hflags(env);
|
||||
hreg_compute_mem_idx(env);
|
||||
|
||||
|
|
|
@ -38,7 +38,9 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
|
|||
|
||||
void helper_store_sdr1(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
ppc_store_sdr1(env, val);
|
||||
if (!env->external_htab) {
|
||||
ppc_store_sdr1(env, val);
|
||||
}
|
||||
}
|
||||
|
||||
void helper_store_hid0_601(CPUPPCState *env, target_ulong val)
|
||||
|
|
|
@ -375,7 +375,7 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
|
|||
" vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
|
||||
" hash=" TARGET_FMT_plx "\n",
|
||||
env->htab_base, env->htab_mask, vsid, ptem, hash);
|
||||
pteg_off = (hash * HASH_PTEG_SIZE_64) & env->htab_mask;
|
||||
pteg_off = (hash & env->htab_mask) * HASH_PTEG_SIZE_64;
|
||||
pte_offset = ppc_hash64_pteg_search(env, pteg_off, 0, ptem, pte);
|
||||
|
||||
if (pte_offset == -1) {
|
||||
|
@ -385,7 +385,7 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
|
|||
" hash=" TARGET_FMT_plx "\n", env->htab_base,
|
||||
env->htab_mask, vsid, ptem, ~hash);
|
||||
|
||||
pteg_off = (~hash * HASH_PTEG_SIZE_64) & env->htab_mask;
|
||||
pteg_off = (~hash & env->htab_mask) * HASH_PTEG_SIZE_64;
|
||||
pte_offset = ppc_hash64_pteg_search(env, pteg_off, 1, ptem, pte);
|
||||
}
|
||||
|
||||
|
|
|
@ -2014,6 +2014,7 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
|
|||
void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
|
||||
{
|
||||
LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
|
||||
assert(!env->external_htab);
|
||||
if (env->spr[SPR_SDR1] != value) {
|
||||
env->spr[SPR_SDR1] = value;
|
||||
#if defined(TARGET_PPC64)
|
||||
|
@ -2025,7 +2026,7 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
|
|||
" stored in SDR1\n", htabsize);
|
||||
htabsize = 28;
|
||||
}
|
||||
env->htab_mask = (1ULL << (htabsize + 18)) - 1;
|
||||
env->htab_mask = (1ULL << (htabsize + 18 - 7)) - 1;
|
||||
env->htab_base = value & SDR_64_HTABORG;
|
||||
} else
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
|
|
Loading…
Reference in a new issue