Tag edgar/xilinx-next-2018-05-29-v1.for-upstream

-----BEGIN PGP SIGNATURE-----
 
 iQEcBAABCAAGBQJbDRY2AAoJECnFlngPa8qDhSgH/jVtKCwHfLfMkFFy4++OP4S3
 9VtJYNm5PX4QJrpRvpuDIzYU6B3WuYvwTyoNg4lbUy7IBR8zqa6b1+fz66S64N8o
 DgkTH6cLlirY52aJbVxLiSqOsCgAx8kWhcWIetraw1Q9tS2ur8pWqcsyawwPhFEo
 +Ck8rl8IvSlzxYWCKshipKliKOjLjrUlIcUlN7OrW+FN8qVCxhcGSVRGDEQVcFvF
 DtM/KI68x97rK8KSRSqHSC926/AV90cUxsz4KQcieL6Aj8bA4RDC0BtSTaV2GxrY
 DmaB9rsvlnb8y9awB6X7gcN4QrPpbp5h07B6eWxZRM2p83Tkg06oUZS1hrNW4zk=
 =uquA
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/edgar/tags/edgar/xilinx-next-2018-05-29-v1.for-upstream' into staging

Tag edgar/xilinx-next-2018-05-29-v1.for-upstream

# gpg: Signature made Tue 29 May 2018 09:58:30 BST
# gpg:                using RSA key 29C596780F6BCA83
# gpg: Good signature from "Edgar E. Iglesias (Xilinx key) <edgar.iglesias@xilinx.com>"
# gpg:                 aka "Edgar E. Iglesias <edgar.iglesias@gmail.com>"
# Primary key fingerprint: AC44 FEDC 14F7 F1EB EDBF  4151 29C5 9678 0F6B CA83

* remotes/edgar/tags/edgar/xilinx-next-2018-05-29-v1.for-upstream: (38 commits)
  target-microblaze: Consolidate MMU enabled checks
  target-microblaze: cpu_mmu_index: Fixup indentation
  target-microblaze: Use tcg_gen_movcond in eval_cond_jmp
  target-microblaze: Convert env_btarget to i64
  target-microblaze: Remove argument b in eval_cc()
  target-microblaze: Use table based condition-codes conversion
  target-microblaze: mmu: Cleanup debug log messages
  target-microblaze: Simplify address computation using tcg_gen_addi_i32()
  target-microblaze: Allow address sizes between 32 and 64 bits
  target-microblaze: Add support for extended access to TLBLO
  target-microblaze: dec_msr: Plug a temp leak
  target-microblaze: mmu: Add a configurable output address mask
  target-microblaze: mmu: Prepare for 64-bit addresses
  target-microblaze: mmu: Remove unused register state
  target-microblaze: mmu: Add R_TBLX_MISS macros
  target-microblaze: Implement MFSE EAR
  target-microblaze: Add Extended Addressing
  target-microblaze: Setup for 64bit addressing
  target-microblaze: Make special registers 64-bit
  target-microblaze: dec_msr: Fix MTS to FSR
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-05-29 13:01:11 +01:00
commit e609fa71e8
10 changed files with 594 additions and 565 deletions

1
configure vendored
View File

@ -6844,6 +6844,7 @@ case "$target_name" in
microblaze|microblazeel)
TARGET_ARCH=microblaze
bflt="yes"
echo "TARGET_ABI32=y" >> $config_target_mak
;;
mips|mipsel)
TARGET_ARCH=mips

View File

@ -105,7 +105,7 @@ void cpu_loop(CPUMBState *env)
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
default:
printf ("Unhandled hw-exception: 0x%x\n",
printf("Unhandled hw-exception: 0x%" PRIx64 "\n",
env->sregs[SR_ESR] & ESR_EC_MASK);
cpu_dump_state(cs, stderr, fprintf, 0);
exit(EXIT_FAILURE);

View File

@ -72,6 +72,9 @@ static const struct {
{NULL, 0},
};
/* If no specific version gets selected, default to the following. */
#define DEFAULT_CPU_VERSION "10.0"
static void mb_cpu_set_pc(CPUState *cs, vaddr value)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
@ -125,6 +128,7 @@ static void mb_cpu_reset(CPUState *s)
env->mmu.c_mmu = 3;
env->mmu.c_mmu_tlb_access = 3;
env->mmu.c_mmu_zones = 16;
env->mmu.c_addr_mask = MAKE_64BIT_MASK(0, cpu->cfg.addr_size);
#endif
}
@ -141,6 +145,7 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env;
uint8_t version_code = 0;
const char *version;
int i = 0;
Error *local_err = NULL;
@ -150,6 +155,12 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
return;
}
if (cpu->cfg.addr_size < 32 || cpu->cfg.addr_size > 64) {
error_setg(errp, "addr-size %d is out of range (32 - 64)",
cpu->cfg.addr_size);
return;
}
qemu_init_vcpu(cs);
env->pvr.regs[0] = PVR0_USE_EXC_MASK \
@ -162,8 +173,9 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
| PVR2_FPU_EXC_MASK \
| 0;
for (i = 0; mb_cpu_lookup[i].name && cpu->cfg.version; i++) {
if (strcmp(mb_cpu_lookup[i].name, cpu->cfg.version) == 0) {
version = cpu->cfg.version ? cpu->cfg.version : DEFAULT_CPU_VERSION;
for (i = 0; mb_cpu_lookup[i].name && version; i++) {
if (strcmp(mb_cpu_lookup[i].name, version) == 0) {
version_code = mb_cpu_lookup[i].version_id;
break;
}
@ -195,8 +207,10 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
env->pvr.regs[5] |= cpu->cfg.dcache_writeback ?
PVR5_DCACHE_WRITEBACK_MASK : 0;
env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family. */
env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
env->pvr.regs[10] = 0x0c000000 | /* Default to spartan 3a dsp family. */
(cpu->cfg.addr_size - 32) << PVR10_ASIZE_SHIFT;
env->pvr.regs[11] = (cpu->cfg.use_mmu ? PVR11_USE_MMU : 0) |
16 << 17;
mcc->parent_realize(dev, errp);
}
@ -226,6 +240,14 @@ static Property mb_properties[] = {
DEFINE_PROP_UINT32("base-vectors", MicroBlazeCPU, cfg.base_vectors, 0),
DEFINE_PROP_BOOL("use-stack-protection", MicroBlazeCPU, cfg.stackprot,
false),
/*
* This is the C_ADDR_SIZE synth-time configuration option of the
* MicroBlaze cores. Supported values range between 32 and 64.
*
* When set to > 32, 32bit MicroBlaze can emit load/stores
* with extended addressing.
*/
DEFINE_PROP_UINT8("addr-size", MicroBlazeCPU, cfg.addr_size, 32),
/* If use-fpu > 0 - FPU is enabled
* If use-fpu = 2 - Floating point conversion and square root instructions
* are enabled

View File

@ -23,7 +23,7 @@
#include "qemu-common.h"
#include "cpu-qom.h"
#define TARGET_LONG_BITS 32
#define TARGET_LONG_BITS 64
#define CPUArchState struct CPUMBState
@ -203,6 +203,7 @@ typedef struct CPUMBState CPUMBState;
/* Target family PVR mask */
#define PVR10_TARGET_FAMILY_MASK 0xFF000000
#define PVR10_ASIZE_SHIFT 18
/* MMU descrtiption */
#define PVR11_USE_MMU 0xC0000000
@ -238,19 +239,19 @@ typedef struct CPUMBState CPUMBState;
struct CPUMBState {
uint32_t debug;
uint32_t btaken;
uint32_t btarget;
uint64_t btarget;
uint32_t bimm;
uint32_t imm;
uint32_t regs[33];
uint32_t sregs[24];
uint32_t regs[32];
uint64_t sregs[14];
float_status fp_status;
/* Stack protectors. Yes, it's a hw feature. */
uint32_t slr, shr;
/* lwx/swx reserved address */
#define RES_ADDR_NONE 0xffffffff /* Use 0xffffffff to indicate no reservation */
uint32_t res_addr;
target_ulong res_addr;
uint32_t res_val;
/* Internal flags. */
@ -277,7 +278,7 @@ struct CPUMBState {
/* These fields are preserved on reset. */
struct {
uint32_t regs[16];
uint32_t regs[13];
} pvr;
};
@ -297,6 +298,7 @@ struct MicroBlazeCPU {
struct {
bool stackprot;
uint32_t base_vectors;
uint8_t addr_size;
uint8_t use_fpu;
uint8_t use_hw_mul;
bool use_barrel;
@ -340,8 +342,8 @@ int cpu_mb_signal_handler(int host_signum, void *pinfo,
/* FIXME: MB uses variable pages down to 1K but linux only uses 4k. */
#define TARGET_PAGE_BITS 12
#define TARGET_PHYS_ADDR_SPACE_BITS 32
#define TARGET_VIRT_ADDR_SPACE_BITS 32
#define TARGET_PHYS_ADDR_SPACE_BITS 64
#define TARGET_VIRT_ADDR_SPACE_BITS 64
#define CPU_RESOLVING_TYPE TYPE_MICROBLAZE_CPU
@ -358,12 +360,16 @@ int cpu_mb_signal_handler(int host_signum, void *pinfo,
static inline int cpu_mmu_index (CPUMBState *env, bool ifetch)
{
/* Are we in nommu mode?. */
if (!(env->sregs[SR_MSR] & MSR_VM))
return MMU_NOMMU_IDX;
MicroBlazeCPU *cpu = mb_env_get_cpu(env);
if (env->sregs[SR_MSR] & MSR_UM)
/* Are we in nommu mode?. */
if (!(env->sregs[SR_MSR] & MSR_VM) || !cpu->cfg.use_mmu) {
return MMU_NOMMU_IDX;
}
if (env->sregs[SR_MSR] & MSR_UM) {
return MMU_USER_IDX;
}
return MMU_KERNEL_IDX;
}

View File

@ -54,22 +54,12 @@ int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env;
unsigned int hit;
unsigned int mmu_available;
int r = 1;
int prot;
mmu_available = 0;
if (cpu->cfg.use_mmu) {
mmu_available = 1;
if ((cpu->cfg.pvr == C_PVR_FULL) &&
(env->pvr.regs[11] & PVR11_USE_MMU) != PVR11_USE_MMU) {
mmu_available = 0;
}
}
/* Translate if the MMU is available and enabled. */
if (mmu_available && (env->sregs[SR_MSR] & MSR_VM)) {
target_ulong vaddr, paddr;
if (mmu_idx != MMU_NOMMU_IDX) {
uint32_t vaddr, paddr;
struct microblaze_mmu_lookup lu;
hit = mmu_translate(&env->mmu, &lu, address, rw, mmu_idx);
@ -152,7 +142,8 @@ void mb_cpu_do_interrupt(CPUState *cs)
env->sregs[SR_MSR] |= MSR_EIP;
qemu_log_mask(CPU_LOG_INT,
"hw exception at pc=%x ear=%x esr=%x iflags=%x\n",
"hw exception at pc=%" PRIx64 " ear=%" PRIx64 " "
"esr=%" PRIx64 " iflags=%x\n",
env->sregs[SR_PC], env->sregs[SR_EAR],
env->sregs[SR_ESR], env->iflags);
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
@ -175,7 +166,8 @@ void mb_cpu_do_interrupt(CPUState *cs)
/* was the branch immprefixed?. */
if (env->bimm) {
qemu_log_mask(CPU_LOG_INT,
"bimm exception at pc=%x iflags=%x\n",
"bimm exception at pc=%" PRIx64 " "
"iflags=%x\n",
env->sregs[SR_PC], env->iflags);
env->regs[17] -= 4;
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
@ -193,7 +185,8 @@ void mb_cpu_do_interrupt(CPUState *cs)
env->sregs[SR_MSR] |= MSR_EIP;
qemu_log_mask(CPU_LOG_INT,
"exception at pc=%x ear=%x iflags=%x\n",
"exception at pc=%" PRIx64 " ear=%" PRIx64 " "
"iflags=%x\n",
env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags);
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
env->iflags &= ~(IMM_FLAG | D_FLAG);
@ -230,7 +223,8 @@ void mb_cpu_do_interrupt(CPUState *cs)
}
#endif
qemu_log_mask(CPU_LOG_INT,
"interrupt at pc=%x msr=%x %x iflags=%x\n",
"interrupt at pc=%" PRIx64 " msr=%" PRIx64 " %x "
"iflags=%x\n",
env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags);
env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM \
@ -248,7 +242,8 @@ void mb_cpu_do_interrupt(CPUState *cs)
assert(!(env->iflags & D_FLAG));
t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1;
qemu_log_mask(CPU_LOG_INT,
"break at pc=%x msr=%x %x iflags=%x\n",
"break at pc=%" PRIx64 " msr=%" PRIx64 " %x "
"iflags=%x\n",
env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags);
log_cpu_state_mask(CPU_LOG_INT, cs, 0);
env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
@ -274,9 +269,10 @@ hwaddr mb_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
CPUMBState *env = &cpu->env;
target_ulong vaddr, paddr = 0;
struct microblaze_mmu_lookup lu;
int mmu_idx = cpu_mmu_index(env, false);
unsigned int hit;
if (env->sregs[SR_MSR] & MSR_VM) {
if (mmu_idx != MMU_NOMMU_IDX) {
hit = mmu_translate(&env->mmu, &lu, addr, 0, 0);
if (hit) {
vaddr = addr & TARGET_PAGE_MASK;

View File

@ -25,12 +25,12 @@ DEF_HELPER_3(fcmp_ge, i32, env, i32, i32)
DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_NO_RWG_SE, i32, i32, i32)
#if !defined(CONFIG_USER_ONLY)
DEF_HELPER_2(mmu_read, i32, env, i32)
DEF_HELPER_3(mmu_write, void, env, i32, i32)
DEF_HELPER_3(mmu_read, i32, env, i32, i32)
DEF_HELPER_4(mmu_write, void, env, i32, i32, i32)
#endif
DEF_HELPER_5(memalign, void, env, i32, i32, i32, i32)
DEF_HELPER_2(stackprot, void, env, i32)
DEF_HELPER_5(memalign, void, env, tl, i32, i32, i32)
DEF_HELPER_2(stackprot, void, env, tl)
DEF_HELPER_2(get, i32, i32, i32)
DEF_HELPER_3(put, void, i32, i32, i32)

View File

@ -22,8 +22,6 @@
#include "cpu.h"
#include "exec/exec-all.h"
#define D(x)
static unsigned int tlb_decode_size(unsigned int f)
{
static const unsigned int sizes[] = {
@ -81,34 +79,29 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu,
{
unsigned int i, hit = 0;
unsigned int tlb_ex = 0, tlb_wr = 0, tlb_zsel;
unsigned int tlb_size;
uint32_t tlb_tag, tlb_rpn, mask, t0;
uint64_t tlb_tag, tlb_rpn, mask;
uint32_t tlb_size, t0;
lu->err = ERR_MISS;
for (i = 0; i < ARRAY_SIZE(mmu->rams[RAM_TAG]); i++) {
uint32_t t, d;
uint64_t t, d;
/* Lookup and decode. */
t = mmu->rams[RAM_TAG][i];
D(qemu_log("TLB %d valid=%d\n", i, t & TLB_VALID));
if (t & TLB_VALID) {
tlb_size = tlb_decode_size((t & TLB_PAGESZ_MASK) >> 7);
if (tlb_size < TARGET_PAGE_SIZE) {
qemu_log("%d pages not supported\n", tlb_size);
qemu_log_mask(LOG_UNIMP, "%d pages not supported\n", tlb_size);
abort();
}
mask = ~(tlb_size - 1);
mask = ~((uint64_t)tlb_size - 1);
tlb_tag = t & TLB_EPN_MASK;
if ((vaddr & mask) != (tlb_tag & mask)) {
D(qemu_log("TLB %d vaddr=%x != tag=%x\n",
i, vaddr & mask, tlb_tag & mask));
continue;
}
if (mmu->tids[i]
&& ((mmu->regs[MMU_R_PID] & 0xff) != mmu->tids[i])) {
D(qemu_log("TLB %d pid=%x != tid=%x\n",
i, mmu->regs[MMU_R_PID], mmu->tids[i]));
continue;
}
@ -123,7 +116,8 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu,
t0 &= 0x3;
if (tlb_zsel > mmu->c_mmu_zones) {
qemu_log_mask(LOG_GUEST_ERROR, "tlb zone select out of range! %d\n", tlb_zsel);
qemu_log_mask(LOG_GUEST_ERROR,
"tlb zone select out of range! %d\n", tlb_zsel);
t0 = 1; /* Ignore. */
}
@ -164,6 +158,7 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu,
tlb_rpn = d & TLB_RPN_MASK;
lu->vaddr = tlb_tag;
lu->paddr = tlb_rpn & mmu->c_addr_mask;
lu->paddr = tlb_rpn;
lu->size = tlb_size;
lu->err = ERR_HIT;
@ -173,13 +168,14 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu,
}
}
done:
D(qemu_log("MMU vaddr=%x rw=%d tlb_wr=%d tlb_ex=%d hit=%d\n",
vaddr, rw, tlb_wr, tlb_ex, hit));
qemu_log_mask(CPU_LOG_MMU,
"MMU vaddr=%" PRIx64 " rw=%d tlb_wr=%d tlb_ex=%d hit=%d\n",
vaddr, rw, tlb_wr, tlb_ex, hit);
return hit;
}
/* Writes/reads to the MMU's special regs end up here. */
uint32_t mmu_read(CPUMBState *env, uint32_t rn)
uint32_t mmu_read(CPUMBState *env, bool ext, uint32_t rn)
{
unsigned int i;
uint32_t r = 0;
@ -188,50 +184,65 @@ uint32_t mmu_read(CPUMBState *env, uint32_t rn)
qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n");
return 0;
}
if (ext && rn != MMU_R_TLBLO) {
qemu_log_mask(LOG_GUEST_ERROR, "Extended access only to TLBLO.\n");
return 0;
}
switch (rn) {
/* Reads to HI/LO trig reads from the mmu rams. */
case MMU_R_TLBLO:
case MMU_R_TLBHI:
if (!(env->mmu.c_mmu_tlb_access & 1)) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn);
qemu_log_mask(LOG_GUEST_ERROR,
"Invalid access to MMU reg %d\n", rn);
return 0;
}
i = env->mmu.regs[MMU_R_TLBX] & 0xff;
r = env->mmu.rams[rn & 1][i];
r = extract64(env->mmu.rams[rn & 1][i], ext * 32, 32);
if (rn == MMU_R_TLBHI)
env->mmu.regs[MMU_R_PID] = env->mmu.tids[i];
break;
case MMU_R_PID:
case MMU_R_ZPR:
if (!(env->mmu.c_mmu_tlb_access & 1)) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn);
qemu_log_mask(LOG_GUEST_ERROR,
"Invalid access to MMU reg %d\n", rn);
return 0;
}
r = env->mmu.regs[rn];
break;
case MMU_R_TLBX:
r = env->mmu.regs[rn];
break;
case MMU_R_TLBSX:
qemu_log_mask(LOG_GUEST_ERROR, "TLBSX is write-only.\n");
break;
default:
r = env->mmu.regs[rn];
qemu_log_mask(LOG_GUEST_ERROR, "Invalid MMU register %d.\n", rn);
break;
}
D(qemu_log("%s rn=%d=%x\n", __func__, rn, r));
qemu_log_mask(CPU_LOG_MMU, "%s rn=%d=%x\n", __func__, rn, r);
return r;
}
void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v)
void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v)
{
MicroBlazeCPU *cpu = mb_env_get_cpu(env);
uint64_t tmp64;
unsigned int i;
D(qemu_log("%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn]));
qemu_log_mask(CPU_LOG_MMU,
"%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_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n");
return;
}
if (ext && rn != MMU_R_TLBLO) {
qemu_log_mask(LOG_GUEST_ERROR, "Extended access only to TLBLO.\n");
return;
}
switch (rn) {
/* Writes to HI/LO trig writes to the mmu rams. */
@ -240,18 +251,19 @@ void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v)
i = env->mmu.regs[MMU_R_TLBX] & 0xff;
if (rn == MMU_R_TLBHI) {
if (i < 3 && !(v & TLB_VALID) && qemu_loglevel_mask(~0))
qemu_log_mask(LOG_GUEST_ERROR, "invalidating index %x at pc=%x\n",
qemu_log_mask(LOG_GUEST_ERROR,
"invalidating index %x at pc=%" PRIx64 "\n",
i, env->sregs[SR_PC]);
env->mmu.tids[i] = env->mmu.regs[MMU_R_PID] & 0xff;
mmu_flush_idx(env, i);
}
env->mmu.rams[rn & 1][i] = v;
D(qemu_log("%s ram[%d][%d]=%x\n", __func__, rn & 1, i, v));
tmp64 = env->mmu.rams[rn & 1][i];
env->mmu.rams[rn & 1][i] = deposit64(tmp64, ext * 32, 32, v);
break;
case MMU_R_ZPR:
if (env->mmu.c_mmu_tlb_access <= 1) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn);
qemu_log_mask(LOG_GUEST_ERROR,
"Invalid access to MMU reg %d\n", rn);
return;
}
@ -264,7 +276,8 @@ void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v)
break;
case MMU_R_PID:
if (env->mmu.c_mmu_tlb_access <= 1) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn);
qemu_log_mask(LOG_GUEST_ERROR,
"Invalid access to MMU reg %d\n", rn);
return;
}
@ -283,7 +296,8 @@ void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v)
int hit;
if (env->mmu.c_mmu_tlb_access <= 1) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn);
qemu_log_mask(LOG_GUEST_ERROR,
"Invalid access to MMU reg %d\n", rn);
return;
}
@ -291,12 +305,13 @@ void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v)
v & TLB_EPN_MASK, 0, cpu_mmu_index(env, false));
if (hit) {
env->mmu.regs[MMU_R_TLBX] = lu.idx;
} else
env->mmu.regs[MMU_R_TLBX] |= 0x80000000;
} else {
env->mmu.regs[MMU_R_TLBX] |= R_TBLX_MISS_MASK;
}
break;
}
default:
env->mmu.regs[rn] = v;
qemu_log_mask(LOG_GUEST_ERROR, "Invalid MMU register %d.\n", rn);
break;
}
}

View File

@ -28,7 +28,7 @@
#define RAM_TAG 0
/* Tag portion */
#define TLB_EPN_MASK 0xFFFFFC00 /* Effective Page Number */
#define TLB_EPN_MASK MAKE_64BIT_MASK(10, 64 - 10)
#define TLB_PAGESZ_MASK 0x00000380
#define TLB_PAGESZ(x) (((x) & 0x7) << 7)
#define PAGESZ_1K 0
@ -42,7 +42,7 @@
#define TLB_VALID 0x00000040 /* Entry is valid */
/* Data portion */
#define TLB_RPN_MASK 0xFFFFFC00 /* Real Page Number */
#define TLB_RPN_MASK MAKE_64BIT_MASK(10, 64 - 10)
#define TLB_PERM_MASK 0x00000300
#define TLB_EX 0x00000200 /* Instruction execution allowed */
#define TLB_WR 0x00000100 /* Writes permitted */
@ -54,20 +54,25 @@
#define TLB_M 0x00000002 /* Memory is coherent */
#define TLB_G 0x00000001 /* Memory is guarded from prefetch */
/* TLBX */
#define R_TBLX_MISS_SHIFT 31
#define R_TBLX_MISS_MASK (1U << R_TBLX_MISS_SHIFT)
#define TLB_ENTRIES 64
struct microblaze_mmu
{
/* Data and tag brams. */
uint32_t rams[2][TLB_ENTRIES];
uint64_t rams[2][TLB_ENTRIES];
/* We keep a separate ram for the tids to avoid the 48 bit tag width. */
uint8_t tids[TLB_ENTRIES];
/* Control flops. */
uint32_t regs[8];
uint32_t regs[3];
int c_mmu;
int c_mmu_tlb_access;
int c_mmu_zones;
uint64_t c_addr_mask; /* Mask to apply to physical addresses. */
};
struct microblaze_mmu_lookup
@ -85,6 +90,6 @@ struct microblaze_mmu_lookup
unsigned int mmu_translate(struct microblaze_mmu *mmu,
struct microblaze_mmu_lookup *lu,
target_ulong vaddr, int rw, int mmu_idx);
uint32_t mmu_read(CPUMBState *env, uint32_t rn);
void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v);
uint32_t mmu_read(CPUMBState *env, bool ea, uint32_t rn);
void mmu_write(CPUMBState *env, bool ea, uint32_t rn, uint32_t v);
void mmu_init(struct microblaze_mmu *mmu);

View File

@ -94,16 +94,17 @@ void helper_debug(CPUMBState *env)
{
int i;
qemu_log("PC=%8.8x\n", env->sregs[SR_PC]);
qemu_log("rmsr=%x resr=%x rear=%x debug[%x] imm=%x iflags=%x\n",
qemu_log("PC=%" PRIx64 "\n", env->sregs[SR_PC]);
qemu_log("rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " "
"debug[%x] imm=%x iflags=%x\n",
env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
env->debug, env->imm, env->iflags);
qemu_log("btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
qemu_log("btaken=%d btarget=%" PRIx64 " mode=%s(saved=%s) eip=%d ie=%d\n",
env->btaken, env->btarget,
(env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
(env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
(env->sregs[SR_MSR] & MSR_EIP),
(env->sregs[SR_MSR] & MSR_IE));
(bool)(env->sregs[SR_MSR] & MSR_EIP),
(bool)(env->sregs[SR_MSR] & MSR_IE));
for (i = 0; i < 32; i++) {
qemu_log("r%2.2d=%8.8x ", i, env->regs[i]);
if ((i + 1) % 4 == 0)
@ -439,12 +440,14 @@ uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
return 0;
}
void helper_memalign(CPUMBState *env, uint32_t addr, uint32_t dr, uint32_t wr,
void helper_memalign(CPUMBState *env, target_ulong addr,
uint32_t dr, uint32_t wr,
uint32_t mask)
{
if (addr & mask) {
qemu_log_mask(CPU_LOG_INT,
"unaligned access addr=%x mask=%x, wr=%d dr=r%d\n",
"unaligned access addr=" TARGET_FMT_lx
" mask=%x, wr=%d dr=r%d\n",
addr, mask, wr, dr);
env->sregs[SR_EAR] = addr;
env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \
@ -459,10 +462,11 @@ void helper_memalign(CPUMBState *env, uint32_t addr, uint32_t dr, uint32_t wr,
}
}
void helper_stackprot(CPUMBState *env, uint32_t addr)
void helper_stackprot(CPUMBState *env, target_ulong addr)
{
if (addr < env->slr || addr > env->shr) {
qemu_log_mask(CPU_LOG_INT, "Stack protector violation at %x %x %x\n",
qemu_log_mask(CPU_LOG_INT, "Stack protector violation at "
TARGET_FMT_lx " %x %x\n",
addr, env->slr, env->shr);
env->sregs[SR_EAR] = addr;
env->sregs[SR_ESR] = ESR_EC_STACKPROT;
@ -472,14 +476,14 @@ void helper_stackprot(CPUMBState *env, uint32_t addr)
#if !defined(CONFIG_USER_ONLY)
/* Writes/reads to the MMU's special regs end up here. */
uint32_t helper_mmu_read(CPUMBState *env, uint32_t rn)
uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn)
{
return mmu_read(env, rn);
return mmu_read(env, ext, rn);
}
void helper_mmu_write(CPUMBState *env, uint32_t rn, uint32_t v)
void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v)
{
mmu_write(env, rn, v);
mmu_write(env, ext, rn, v);
}
void mb_cpu_unassigned_access(CPUState *cs, hwaddr addr,

File diff suppressed because it is too large Load Diff