mirror of https://github.com/xqemu/xqemu.git
microblaze: MMU shows more respect to synthesis config.
The microblaze MMU can be synthesized in different configurations. Have the MMU model show more respect to the chosen configuration. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
parent
968a40f6fa
commit
3c50a71fc9
|
@ -127,6 +127,16 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu,
|
||||||
tlb_zsel = (d >> 4) & 0xf;
|
tlb_zsel = (d >> 4) & 0xf;
|
||||||
t0 = mmu->regs[MMU_R_ZPR] >> (30 - (tlb_zsel * 2));
|
t0 = mmu->regs[MMU_R_ZPR] >> (30 - (tlb_zsel * 2));
|
||||||
t0 &= 0x3;
|
t0 &= 0x3;
|
||||||
|
|
||||||
|
if (tlb_zsel > mmu->c_mmu_zones) {
|
||||||
|
qemu_log("tlb zone select out of range! %d\n", tlb_zsel);
|
||||||
|
t0 = 1; /* Ignore. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mmu->c_mmu == 1) {
|
||||||
|
t0 = 1; /* Zones are disabled. */
|
||||||
|
}
|
||||||
|
|
||||||
switch (t0) {
|
switch (t0) {
|
||||||
case 0:
|
case 0:
|
||||||
if (mmu_idx == MMU_USER_IDX)
|
if (mmu_idx == MMU_USER_IDX)
|
||||||
|
@ -142,9 +152,9 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu,
|
||||||
tlb_ex = 1;
|
tlb_ex = 1;
|
||||||
tlb_wr = 1;
|
tlb_wr = 1;
|
||||||
break;
|
break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lu->err = ERR_PROT;
|
lu->err = ERR_PROT;
|
||||||
lu->prot = PAGE_READ;
|
lu->prot = PAGE_READ;
|
||||||
if (tlb_wr)
|
if (tlb_wr)
|
||||||
|
@ -180,15 +190,33 @@ uint32_t mmu_read(CPUState *env, uint32_t rn)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
uint32_t r;
|
uint32_t r;
|
||||||
|
|
||||||
|
if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) {
|
||||||
|
qemu_log("MMU access on MMU-less system\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (rn) {
|
switch (rn) {
|
||||||
/* Reads to HI/LO trig reads from the mmu rams. */
|
/* Reads to HI/LO trig reads from the mmu rams. */
|
||||||
case MMU_R_TLBLO:
|
case MMU_R_TLBLO:
|
||||||
case MMU_R_TLBHI:
|
case MMU_R_TLBHI:
|
||||||
|
if (!(env->mmu.c_mmu_tlb_access & 1)) {
|
||||||
|
qemu_log("Invalid access to MMU reg %d\n", rn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
i = env->mmu.regs[MMU_R_TLBX] & 0xff;
|
i = env->mmu.regs[MMU_R_TLBX] & 0xff;
|
||||||
r = env->mmu.rams[rn & 1][i];
|
r = env->mmu.rams[rn & 1][i];
|
||||||
if (rn == MMU_R_TLBHI)
|
if (rn == MMU_R_TLBHI)
|
||||||
env->mmu.regs[MMU_R_PID] = env->mmu.tids[i];
|
env->mmu.regs[MMU_R_PID] = env->mmu.tids[i];
|
||||||
break;
|
break;
|
||||||
|
case MMU_R_PID:
|
||||||
|
case MMU_R_ZPR:
|
||||||
|
if (!(env->mmu.c_mmu_tlb_access & 1)) {
|
||||||
|
qemu_log("Invalid access to MMU reg %d\n", rn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
r = env->mmu.regs[rn];
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
r = env->mmu.regs[rn];
|
r = env->mmu.regs[rn];
|
||||||
break;
|
break;
|
||||||
|
@ -202,6 +230,11 @@ void mmu_write(CPUState *env, uint32_t rn, uint32_t v)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
D(qemu_log("%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn]));
|
D(qemu_log("%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn]));
|
||||||
|
|
||||||
|
if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) {
|
||||||
|
qemu_log("MMU access on MMU-less system\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (rn) {
|
switch (rn) {
|
||||||
/* Writes to HI/LO trig writes to the mmu rams. */
|
/* Writes to HI/LO trig writes to the mmu rams. */
|
||||||
case MMU_R_TLBLO:
|
case MMU_R_TLBLO:
|
||||||
|
@ -219,6 +252,11 @@ void mmu_write(CPUState *env, uint32_t rn, uint32_t v)
|
||||||
D(qemu_log("%s ram[%d][%d]=%x\n", __func__, rn & 1, i, v));
|
D(qemu_log("%s ram[%d][%d]=%x\n", __func__, rn & 1, i, v));
|
||||||
break;
|
break;
|
||||||
case MMU_R_ZPR:
|
case MMU_R_ZPR:
|
||||||
|
if (env->mmu.c_mmu_tlb_access <= 1) {
|
||||||
|
qemu_log("Invalid access to MMU reg %d\n", rn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Changes to the zone protection reg flush the QEMU TLB.
|
/* Changes to the zone protection reg flush the QEMU TLB.
|
||||||
Fortunately, these are very uncommon. */
|
Fortunately, these are very uncommon. */
|
||||||
if (v != env->mmu.regs[rn]) {
|
if (v != env->mmu.regs[rn]) {
|
||||||
|
@ -227,6 +265,11 @@ void mmu_write(CPUState *env, uint32_t rn, uint32_t v)
|
||||||
env->mmu.regs[rn] = v;
|
env->mmu.regs[rn] = v;
|
||||||
break;
|
break;
|
||||||
case MMU_R_PID:
|
case MMU_R_PID:
|
||||||
|
if (env->mmu.c_mmu_tlb_access <= 1) {
|
||||||
|
qemu_log("Invalid access to MMU reg %d\n", rn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (v != env->mmu.regs[rn]) {
|
if (v != env->mmu.regs[rn]) {
|
||||||
mmu_change_pid(env, v);
|
mmu_change_pid(env, v);
|
||||||
env->mmu.regs[rn] = v;
|
env->mmu.regs[rn] = v;
|
||||||
|
@ -236,6 +279,12 @@ void mmu_write(CPUState *env, uint32_t rn, uint32_t v)
|
||||||
{
|
{
|
||||||
struct microblaze_mmu_lookup lu;
|
struct microblaze_mmu_lookup lu;
|
||||||
int hit;
|
int hit;
|
||||||
|
|
||||||
|
if (env->mmu.c_mmu_tlb_access <= 1) {
|
||||||
|
qemu_log("Invalid access to MMU reg %d\n", rn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
hit = mmu_translate(&env->mmu, &lu,
|
hit = mmu_translate(&env->mmu, &lu,
|
||||||
v & TLB_EPN_MASK, 0, cpu_mmu_index(env));
|
v & TLB_EPN_MASK, 0, cpu_mmu_index(env));
|
||||||
if (hit) {
|
if (hit) {
|
||||||
|
@ -252,5 +301,8 @@ void mmu_write(CPUState *env, uint32_t rn, uint32_t v)
|
||||||
|
|
||||||
void mmu_init(struct microblaze_mmu *mmu)
|
void mmu_init(struct microblaze_mmu *mmu)
|
||||||
{
|
{
|
||||||
memset(mmu, 0, sizeof *mmu);
|
int i;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(mmu->regs); i++) {
|
||||||
|
mmu->regs[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,11 @@ struct microblaze_mmu
|
||||||
/* We keep a separate ram for the tids to avoid the 48 bit tag width. */
|
/* We keep a separate ram for the tids to avoid the 48 bit tag width. */
|
||||||
uint8_t tids[TLB_ENTRIES];
|
uint8_t tids[TLB_ENTRIES];
|
||||||
/* Control flops. */
|
/* Control flops. */
|
||||||
uint32_t regs[8];;
|
uint32_t regs[8];
|
||||||
|
|
||||||
|
int c_mmu;
|
||||||
|
int c_mmu_tlb_access;
|
||||||
|
int c_mmu_zones;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct microblaze_mmu_lookup
|
struct microblaze_mmu_lookup
|
||||||
|
|
|
@ -1454,7 +1454,12 @@ CPUState *cpu_mb_init (const char *cpu_model)
|
||||||
| PVR2_USE_MUL64_MASK \
|
| PVR2_USE_MUL64_MASK \
|
||||||
| 0;
|
| 0;
|
||||||
env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family. */
|
env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family. */
|
||||||
env->pvr.regs[11] = PVR11_USE_MMU;
|
env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
env->mmu.c_mmu = 3;
|
||||||
|
env->mmu.c_mmu_tlb_access = 3;
|
||||||
|
env->mmu.c_mmu_zones = 16;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (tcg_initialized)
|
if (tcg_initialized)
|
||||||
return env;
|
return env;
|
||||||
|
|
Loading…
Reference in New Issue