target/ppc: Eliminate htab_base and htab_mask variables

CPUPPCState includes fields htab_base and htab_mask which store the base
address (GPA) and size (as a mask) of the guest's hashed page table (HPT).
These are set when the SDR1 register is updated.

Keeping these in sync with the SDR1 is actually a little bit fiddly, and
probably not useful for performance, since keeping them expands the size of
CPUPPCState.  It also makes some upcoming changes harder to implement.

This patch removes these fields, in favour of calculating them directly
from the SDR1 contents when necessary.

This does make a change to the behaviour of attempting to write a bad value
(invalid HPT size) to the SDR1 with an mtspr instruction.  Previously, the
bad value would be stored in SDR1 and could be retrieved with a later
mfspr, but the HPT size as used by the softmmu would be, clamped to the
allowed values.  Now, writing a bad value is treated as a no-op.  An error
message is printed in both new and old versions.

I'm not sure which behaviour, if either, matches real hardware.  I don't
think it matters that much, since it's pretty clear that if an OS writes
a bad value to SDR1, it's not going to boot.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
This commit is contained in:
David Gibson 2017-02-24 16:36:44 +11:00
parent 7222b94a83
commit 36778660d7
8 changed files with 73 additions and 62 deletions

View File

@ -50,9 +50,9 @@ static bool has_spr(PowerPCCPU *cpu, int spr)
static inline bool valid_ptex(PowerPCCPU *cpu, target_ulong ptex) static inline bool valid_ptex(PowerPCCPU *cpu, target_ulong ptex)
{ {
/* /*
* hash value/pteg group index is normalized by htab_mask * hash value/pteg group index is normalized by HPT mask
*/ */
if (((ptex & ~7ULL) / HPTES_PER_GROUP) & ~cpu->env.htab_mask) { if (((ptex & ~7ULL) / HPTES_PER_GROUP) & ~ppc_hash64_hpt_mask(cpu)) {
return false; return false;
} }
return true; return true;

View File

@ -306,14 +306,6 @@ union ppc_tlb_t {
#define TLB_MAS 3 #define TLB_MAS 3
#endif #endif
#define SDR_32_HTABORG 0xFFFF0000UL
#define SDR_32_HTABMASK 0x000001FFUL
#if defined(TARGET_PPC64)
#define SDR_64_HTABORG 0xFFFFFFFFFFFC0000ULL
#define SDR_64_HTABSIZE 0x000000000000001FULL
#endif /* defined(TARGET_PPC64 */
typedef struct ppc_slb_t ppc_slb_t; typedef struct ppc_slb_t ppc_slb_t;
struct ppc_slb_t { struct ppc_slb_t {
uint64_t esid; uint64_t esid;
@ -1006,9 +998,6 @@ struct CPUPPCState {
/* tcg TLB needs flush (deferred slb inval instruction typically) */ /* tcg TLB needs flush (deferred slb inval instruction typically) */
#endif #endif
/* segment registers */ /* segment registers */
hwaddr htab_base;
/* mask used to normalize hash value to PTEG index */
hwaddr htab_mask;
target_ulong sr[32]; target_ulong sr[32];
/* externally stored hash table */ /* externally stored hash table */
uint8_t *external_htab; uint8_t *external_htab;

View File

@ -229,7 +229,6 @@ static int cpu_post_load(void *opaque, int version_id)
} }
if (!env->external_htab) { if (!env->external_htab) {
/* Restore htab_base and htab_mask variables */
ppc_store_sdr1(env, env->spr[SPR_SDR1]); ppc_store_sdr1(env, env->spr[SPR_SDR1]);
} }

View File

@ -304,9 +304,9 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash) hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash)
{ {
CPUPPCState *env = &cpu->env; target_ulong mask = ppc_hash32_hpt_mask(cpu);
return (hash * HASH_PTEG_SIZE_32) & env->htab_mask; return (hash * HASH_PTEG_SIZE_32) & mask;
} }
static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off, static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off,
@ -339,7 +339,6 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
target_ulong sr, target_ulong eaddr, target_ulong sr, target_ulong eaddr,
ppc_hash_pte32_t *pte) ppc_hash_pte32_t *pte)
{ {
CPUPPCState *env = &cpu->env;
hwaddr pteg_off, pte_offset; hwaddr pteg_off, pte_offset;
hwaddr hash; hwaddr hash;
uint32_t vsid, pgidx, ptem; uint32_t vsid, pgidx, ptem;
@ -353,21 +352,22 @@ static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx
" htab_mask " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
" hash " TARGET_FMT_plx "\n", " hash " TARGET_FMT_plx "\n",
env->htab_base, env->htab_mask, hash); ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
/* Primary PTEG lookup */ /* Primary PTEG lookup */
qemu_log_mask(CPU_LOG_MMU, "0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx qemu_log_mask(CPU_LOG_MMU, "0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
" vsid=%" PRIx32 " ptem=%" PRIx32 " vsid=%" PRIx32 " ptem=%" PRIx32
" hash=" TARGET_FMT_plx "\n", " hash=" TARGET_FMT_plx "\n",
env->htab_base, env->htab_mask, vsid, ptem, hash); ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu),
vsid, ptem, hash);
pteg_off = get_pteg_offset32(cpu, hash); pteg_off = get_pteg_offset32(cpu, hash);
pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 0, ptem, pte); pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 0, ptem, pte);
if (pte_offset == -1) { if (pte_offset == -1) {
/* Secondary PTEG lookup */ /* Secondary PTEG lookup */
qemu_log_mask(CPU_LOG_MMU, "1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx qemu_log_mask(CPU_LOG_MMU, "1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
" vsid=%" PRIx32 " api=%" PRIx32 " vsid=%" PRIx32 " api=%" PRIx32
" hash=" TARGET_FMT_plx "\n", env->htab_base, " hash=" TARGET_FMT_plx "\n", ppc_hash32_hpt_base(cpu),
env->htab_mask, vsid, ptem, ~hash); ppc_hash32_hpt_mask(cpu), vsid, ptem, ~hash);
pteg_off = get_pteg_offset32(cpu, ~hash); pteg_off = get_pteg_offset32(cpu, ~hash);
pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 1, ptem, pte); pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 1, ptem, pte);
} }

View File

@ -44,6 +44,8 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw,
/* /*
* Hash page table definitions * Hash page table definitions
*/ */
#define SDR_32_HTABORG 0xFFFF0000UL
#define SDR_32_HTABMASK 0x000001FFUL
#define HPTES_PER_GROUP 8 #define HPTES_PER_GROUP 8
#define HASH_PTE_SIZE_32 8 #define HASH_PTE_SIZE_32 8
@ -65,42 +67,54 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw,
#define HPTE32_R_WIMG 0x00000078 #define HPTE32_R_WIMG 0x00000078
#define HPTE32_R_PP 0x00000003 #define HPTE32_R_PP 0x00000003
static inline hwaddr ppc_hash32_hpt_base(PowerPCCPU *cpu)
{
return cpu->env.spr[SPR_SDR1] & SDR_32_HTABORG;
}
static inline hwaddr ppc_hash32_hpt_mask(PowerPCCPU *cpu)
{
return ((cpu->env.spr[SPR_SDR1] & SDR_32_HTABMASK) << 16) | 0xFFFF;
}
static inline target_ulong ppc_hash32_load_hpte0(PowerPCCPU *cpu, static inline target_ulong ppc_hash32_load_hpte0(PowerPCCPU *cpu,
hwaddr pte_offset) hwaddr pte_offset)
{ {
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
target_ulong base = ppc_hash32_hpt_base(cpu);
assert(!env->external_htab); /* Not supported on 32-bit for now */ assert(!env->external_htab); /* Not supported on 32-bit for now */
return ldl_phys(CPU(cpu)->as, env->htab_base + pte_offset); return ldl_phys(CPU(cpu)->as, base + pte_offset);
} }
static inline target_ulong ppc_hash32_load_hpte1(PowerPCCPU *cpu, static inline target_ulong ppc_hash32_load_hpte1(PowerPCCPU *cpu,
hwaddr pte_offset) hwaddr pte_offset)
{ {
target_ulong base = ppc_hash32_hpt_base(cpu);
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
assert(!env->external_htab); /* Not supported on 32-bit for now */ assert(!env->external_htab); /* Not supported on 32-bit for now */
return ldl_phys(CPU(cpu)->as, return ldl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2);
env->htab_base + pte_offset + HASH_PTE_SIZE_32 / 2);
} }
static inline void ppc_hash32_store_hpte0(PowerPCCPU *cpu, static inline void ppc_hash32_store_hpte0(PowerPCCPU *cpu,
hwaddr pte_offset, target_ulong pte0) hwaddr pte_offset, target_ulong pte0)
{ {
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
target_ulong base = ppc_hash32_hpt_base(cpu);
assert(!env->external_htab); /* Not supported on 32-bit for now */ assert(!env->external_htab); /* Not supported on 32-bit for now */
stl_phys(CPU(cpu)->as, env->htab_base + pte_offset, pte0); stl_phys(CPU(cpu)->as, base + pte_offset, pte0);
} }
static inline void ppc_hash32_store_hpte1(PowerPCCPU *cpu, static inline void ppc_hash32_store_hpte1(PowerPCCPU *cpu,
hwaddr pte_offset, target_ulong pte1) hwaddr pte_offset, target_ulong pte1)
{ {
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
target_ulong base = ppc_hash32_hpt_base(cpu);
assert(!env->external_htab); /* Not supported on 32-bit for now */ assert(!env->external_htab); /* Not supported on 32-bit for now */
stl_phys(CPU(cpu)->as, stl_phys(CPU(cpu)->as, base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1);
env->htab_base + pte_offset + HASH_PTE_SIZE_32 / 2, pte1);
} }
typedef struct { typedef struct {

View File

@ -304,15 +304,13 @@ void ppc_hash64_set_sdr1(PowerPCCPU *cpu, target_ulong value,
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
target_ulong htabsize = value & SDR_64_HTABSIZE; target_ulong htabsize = value & SDR_64_HTABSIZE;
env->spr[SPR_SDR1] = value;
if (htabsize > 28) { if (htabsize > 28) {
error_setg(errp, error_setg(errp,
"Invalid HTABSIZE 0x" TARGET_FMT_lx" stored in SDR1", "Invalid HTABSIZE 0x" TARGET_FMT_lx" stored in SDR1",
htabsize); htabsize);
htabsize = 28; return;
} }
env->htab_mask = (1ULL << (htabsize + 18 - 7)) - 1; env->spr[SPR_SDR1] = value;
env->htab_base = value & SDR_64_HTABORG;
} }
void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift, void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift,
@ -333,10 +331,6 @@ void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift,
return; return;
} }
/* Not strictly necessary, but makes it clearer that an external
* htab is in use when debugging */
env->htab_base = -1;
if (kvm_enabled()) { if (kvm_enabled()) {
if (kvmppc_put_books_sregs(cpu) < 0) { if (kvmppc_put_books_sregs(cpu) < 0) {
error_setg(errp, "Unable to update SDR1 in KVM"); error_setg(errp, "Unable to update SDR1 in KVM");
@ -450,10 +444,11 @@ const ppc_hash_pte64_t *ppc_hash64_map_hptes(PowerPCCPU *cpu,
* accessible PTEG. * accessible PTEG.
*/ */
hptes = (ppc_hash_pte64_t *)(cpu->env.external_htab + pte_offset); hptes = (ppc_hash_pte64_t *)(cpu->env.external_htab + pte_offset);
} else if (cpu->env.htab_base) { } else if (ppc_hash64_hpt_base(cpu)) {
hwaddr base = ppc_hash64_hpt_base(cpu);
hwaddr plen = n * HASH_PTE_SIZE_64; hwaddr plen = n * HASH_PTE_SIZE_64;
hptes = address_space_map(CPU(cpu)->as, cpu->env.htab_base + pte_offset, hptes = address_space_map(CPU(cpu)->as, base + pte_offset,
&plen, false); &plen, false);
if (plen < (n * HASH_PTE_SIZE_64)) { if (plen < (n * HASH_PTE_SIZE_64)) {
hw_error("%s: Unable to map all requested HPTEs\n", __func__); hw_error("%s: Unable to map all requested HPTEs\n", __func__);
} }
@ -514,13 +509,12 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash,
target_ulong ptem, target_ulong ptem,
ppc_hash_pte64_t *pte, unsigned *pshift) ppc_hash_pte64_t *pte, unsigned *pshift)
{ {
CPUPPCState *env = &cpu->env;
int i; int i;
const ppc_hash_pte64_t *pteg; const ppc_hash_pte64_t *pteg;
target_ulong pte0, pte1; target_ulong pte0, pte1;
target_ulong ptex; target_ulong ptex;
ptex = (hash & env->htab_mask) * HPTES_PER_GROUP; ptex = (hash & ppc_hash64_hpt_mask(cpu)) * HPTES_PER_GROUP;
pteg = ppc_hash64_map_hptes(cpu, ptex, HPTES_PER_GROUP); pteg = ppc_hash64_map_hptes(cpu, ptex, HPTES_PER_GROUP);
if (!pteg) { if (!pteg) {
return -1; return -1;
@ -598,14 +592,15 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
qemu_log_mask(CPU_LOG_MMU, qemu_log_mask(CPU_LOG_MMU,
"htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx "htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
" hash " TARGET_FMT_plx "\n", " hash " TARGET_FMT_plx "\n",
env->htab_base, env->htab_mask, hash); ppc_hash64_hpt_base(cpu), ppc_hash64_hpt_mask(cpu), hash);
/* Primary PTEG lookup */ /* Primary PTEG lookup */
qemu_log_mask(CPU_LOG_MMU, qemu_log_mask(CPU_LOG_MMU,
"0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx "0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
" vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
" hash=" TARGET_FMT_plx "\n", " hash=" TARGET_FMT_plx "\n",
env->htab_base, env->htab_mask, vsid, ptem, hash); ppc_hash64_hpt_base(cpu), ppc_hash64_hpt_mask(cpu),
vsid, ptem, hash);
ptex = ppc_hash64_pteg_search(cpu, hash, sps, ptem, pte, pshift); ptex = ppc_hash64_pteg_search(cpu, hash, sps, ptem, pte, pshift);
if (ptex == -1) { if (ptex == -1) {
@ -614,8 +609,8 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
qemu_log_mask(CPU_LOG_MMU, qemu_log_mask(CPU_LOG_MMU,
"1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx "1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
" vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
" hash=" TARGET_FMT_plx "\n", env->htab_base, " hash=" TARGET_FMT_plx "\n", ppc_hash64_hpt_base(cpu),
env->htab_mask, vsid, ptem, ~hash); ppc_hash64_hpt_mask(cpu), vsid, ptem, ~hash);
ptex = ppc_hash64_pteg_search(cpu, ~hash, sps, ptem, pte, pshift); ptex = ppc_hash64_pteg_search(cpu, ~hash, sps, ptem, pte, pshift);
} }
@ -933,9 +928,9 @@ void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
stq_p(env->external_htab + offset, pte0); stq_p(env->external_htab + offset, pte0);
stq_p(env->external_htab + offset + HASH_PTE_SIZE_64 / 2, pte1); stq_p(env->external_htab + offset + HASH_PTE_SIZE_64 / 2, pte1);
} else { } else {
stq_phys(CPU(cpu)->as, env->htab_base + offset, pte0); hwaddr base = ppc_hash64_hpt_base(cpu);
stq_phys(CPU(cpu)->as, stq_phys(CPU(cpu)->as, base + offset, pte0);
env->htab_base + offset + HASH_PTE_SIZE_64 / 2, pte1); stq_phys(CPU(cpu)->as, base + offset + HASH_PTE_SIZE_64 / 2, pte1);
} }
} }

View File

@ -56,6 +56,9 @@ void ppc_hash64_update_rmls(CPUPPCState *env);
* Hash page table definitions * Hash page table definitions
*/ */
#define SDR_64_HTABORG 0xFFFFFFFFFFFC0000ULL
#define SDR_64_HTABSIZE 0x000000000000001FULL
#define HPTES_PER_GROUP 8 #define HPTES_PER_GROUP 8
#define HASH_PTE_SIZE_64 16 #define HASH_PTE_SIZE_64 16
#define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP) #define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)
@ -91,6 +94,16 @@ void ppc_hash64_update_rmls(CPUPPCState *env);
#define HPTE64_V_1TB_SEG 0x4000000000000000ULL #define HPTE64_V_1TB_SEG 0x4000000000000000ULL
#define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL #define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL
static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
{
return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG;
}
static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
{
return (1ULL << ((cpu->env.spr[SPR_SDR1] & SDR_64_HTABSIZE) + 18 - 7)) - 1;
}
void ppc_hash64_set_sdr1(PowerPCCPU *cpu, target_ulong value, void ppc_hash64_set_sdr1(PowerPCCPU *cpu, target_ulong value,
Error **errp); Error **errp);
void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift, void ppc_hash64_set_external_hpt(PowerPCCPU *cpu, void *hpt, int shift,

View File

@ -466,6 +466,7 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
target_ulong eaddr, int rw, int type) target_ulong eaddr, int rw, int type)
{ {
PowerPCCPU *cpu = ppc_env_get_cpu(env);
hwaddr hash; hwaddr hash;
target_ulong vsid; target_ulong vsid;
int ds, pr, target_page_bits; int ds, pr, target_page_bits;
@ -503,7 +504,7 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx
" htab_mask " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
" hash " TARGET_FMT_plx "\n", " hash " TARGET_FMT_plx "\n",
env->htab_base, env->htab_mask, hash); ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
ctx->hash[0] = hash; ctx->hash[0] = hash;
ctx->hash[1] = ~hash; ctx->hash[1] = ~hash;
@ -518,9 +519,11 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
uint32_t a0, a1, a2, a3; uint32_t a0, a1, a2, a3;
qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
"\n", env->htab_base, env->htab_mask + 0x80); "\n", ppc_hash32_hpt_base(cpu),
for (curaddr = env->htab_base; ppc_hash32_hpt_mask(env) + 0x80);
curaddr < (env->htab_base + env->htab_mask + 0x80); for (curaddr = ppc_hash32_hpt_base(cpu);
curaddr < (ppc_hash32_hpt_base(cpu)
+ ppc_hash32_hpt_mask(cpu) + 0x80);
curaddr += 16) { curaddr += 16) {
a0 = ldl_phys(cs->as, curaddr); a0 = ldl_phys(cs->as, curaddr);
a1 = ldl_phys(cs->as, curaddr + 4); a1 = ldl_phys(cs->as, curaddr + 4);
@ -1205,12 +1208,13 @@ static void mmu6xx_dump_BATs(FILE *f, fprintf_function cpu_fprintf,
static void mmu6xx_dump_mmu(FILE *f, fprintf_function cpu_fprintf, static void mmu6xx_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
CPUPPCState *env) CPUPPCState *env)
{ {
PowerPCCPU *cpu = ppc_env_get_cpu(env);
ppc6xx_tlb_t *tlb; ppc6xx_tlb_t *tlb;
target_ulong sr; target_ulong sr;
int type, way, entry, i; int type, way, entry, i;
cpu_fprintf(f, "HTAB base = 0x%"HWADDR_PRIx"\n", env->htab_base); cpu_fprintf(f, "HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
cpu_fprintf(f, "HTAB mask = 0x%"HWADDR_PRIx"\n", env->htab_mask); cpu_fprintf(f, "HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
cpu_fprintf(f, "\nSegment registers:\n"); cpu_fprintf(f, "\nSegment registers:\n");
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
@ -1592,9 +1596,9 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem; env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
tlb_miss: tlb_miss:
env->error_code |= ctx.key << 19; env->error_code |= ctx.key << 19;
env->spr[SPR_HASH1] = env->htab_base + env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
get_pteg_offset32(cpu, ctx.hash[0]); get_pteg_offset32(cpu, ctx.hash[0]);
env->spr[SPR_HASH2] = env->htab_base + env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
get_pteg_offset32(cpu, ctx.hash[1]); get_pteg_offset32(cpu, ctx.hash[1]);
break; break;
case POWERPC_MMU_SOFT_74xx: case POWERPC_MMU_SOFT_74xx:
@ -1999,7 +2003,6 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
{ {
qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value); qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
assert(!env->external_htab); assert(!env->external_htab);
env->spr[SPR_SDR1] = value;
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
if (env->mmu_model & POWERPC_MMU_64) { if (env->mmu_model & POWERPC_MMU_64) {
PowerPCCPU *cpu = ppc_env_get_cpu(env); PowerPCCPU *cpu = ppc_env_get_cpu(env);
@ -2009,14 +2012,12 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
if (local_err) { if (local_err) {
error_report_err(local_err); error_report_err(local_err);
error_free(local_err); error_free(local_err);
return;
} }
} else
#endif /* defined(TARGET_PPC64) */
{
/* FIXME: Should check for valid HTABMASK values */
env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
env->htab_base = value & SDR_32_HTABORG;
} }
#endif /* defined(TARGET_PPC64) */
/* FIXME: Should check for valid HTABMASK values in 32-bit case */
env->spr[SPR_SDR1] = value;
} }
/* Segment registers load and store */ /* Segment registers load and store */