Openrisc Features and Fixes for qemu 2.10
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJZCnjJAAoJEMOzHC1eZifkjegP/ieGXCOfRQxLkr7SzWvigjWx HYUCqZ55Qt2nlirKV30Y7sSxuWnHKthgAvp/9/E/d1UGuFjvao9iia0Aet3elh4B bq8BM3LTBTnwknHc2tgHaNyP7VHsNZkCmMsESSEO6NexjnmXIoWxqbdAQ8FdYXpN evzz2pa1uTLju1gu7gDe3gIUBJjqiIOTmsjIkzIj7v9IqHOYKdGlJQSnZ+AHbQJn nRs+uqxN8sKaAILHmteXTEL1v1xhMJGKSY212m0OnUImlJrNgjAFGHKjSD4p8+6h /k4msQXCjdNo5NKu/0S3N8MKYaWTdcHohe4fnevV2fgdUpljLLm0RBNwP0wWi8Gp SZZ4GgeKGioCuqew1OdrhUNEQ+je3o4wdNYH243vVx3AIxXKS/EVIYhjNqDQLJ9M HGD+zcjcplpUlZ9dOXgWXK6yff2GUORPZJw8BLnDeRxjJA0xTefaK3qA5gWqJXrY HahUi0G4fJNZeROaBemcQ4+nPXfz55Ti4jp4Y3l5QqzvRidSZkdEoRfrnyMYP3/C 6RmR/iRQLjEGStKEqeqGMqhJ9Gn2aAkU+l+h4394fzS6CQulPOFZEkjobcAd2/5O lxXilhQOrAVlW8OIQzuGfIbuLdSFh55vurq8bwrMi8leeJ/AIbColun8PnO5E6Zd +1m4x+gT7IIv4QfMoerL =zXGN -----END PGP SIGNATURE----- Merge remote-tracking branch 'shorne/tags/pull-or-20170504' into staging Openrisc Features and Fixes for qemu 2.10 # gpg: Signature made Thu 04 May 2017 01:41:45 AM BST # gpg: using RSA key 0xC3B31C2D5E6627E4 # gpg: Good signature from "Stafford Horne <shorne@gmail.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: D9C4 7354 AEF8 6C10 3A25 EFF1 C3B3 1C2D 5E66 27E4 * shorne/tags/pull-or-20170504: target/openrisc: Support non-busy idle state using PMR SPR target/openrisc: Remove duplicate features property target/openrisc: Implement full vmstate serialization migration: Add VMSTATE_STRUCT_2DARRAY() target/openrisc: implement shadow registers migration: Add VMSTATE_UINTTL_2DARRAY() target/openrisc: add numcores and coreid support target/openrisc: Fixes for memory debugging target/openrisc: Implement EPH bit target/openrisc: Implement EVBAR register MAINTAINERS: Add myself as openrisc maintainer Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
317134bb54
@ -196,8 +196,8 @@ F: hw/nios2/
|
||||
F: disas/nios2.c
|
||||
|
||||
OpenRISC
|
||||
M: Jia Liu <proljc@gmail.com>
|
||||
S: Maintained
|
||||
M: Stafford Horne <shorne@gmail.com>
|
||||
S: Odd Fixes
|
||||
F: target/openrisc/
|
||||
F: hw/openrisc/
|
||||
F: tests/tcg/openrisc/
|
||||
|
@ -61,6 +61,7 @@ void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
|
||||
}
|
||||
next = now + (uint64_t)wait * TIMER_PERIOD;
|
||||
timer_mod(cpu->env.timer, next);
|
||||
qemu_cpu_kick(CPU(cpu));
|
||||
}
|
||||
|
||||
void cpu_openrisc_count_start(OpenRISCCPU *cpu)
|
||||
|
@ -18,6 +18,8 @@
|
||||
VMSTATE_UINT64_EQUAL_V(_f, _s, _v)
|
||||
#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \
|
||||
VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v)
|
||||
#define VMSTATE_UINTTL_2DARRAY_V(_f, _s, _n1, _n2, _v) \
|
||||
VMSTATE_UINT64_2DARRAY_V(_f, _s, _n1, _n2, _v)
|
||||
#define VMSTATE_UINTTL_TEST(_f, _s, _t) \
|
||||
VMSTATE_UINT64_TEST(_f, _s, _t)
|
||||
#define vmstate_info_uinttl vmstate_info_uint64
|
||||
@ -37,6 +39,8 @@
|
||||
VMSTATE_UINT32_EQUAL_V(_f, _s, _v)
|
||||
#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \
|
||||
VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)
|
||||
#define VMSTATE_UINTTL_2DARRAY_V(_f, _s, _n1, _n2, _v) \
|
||||
VMSTATE_UINT32_2DARRAY_V(_f, _s, _n1, _n2, _v)
|
||||
#define VMSTATE_UINTTL_TEST(_f, _s, _t) \
|
||||
VMSTATE_UINT32_TEST(_f, _s, _t)
|
||||
#define vmstate_info_uinttl vmstate_info_uint32
|
||||
@ -48,5 +52,8 @@
|
||||
VMSTATE_UINTTL_EQUAL_V(_f, _s, 0)
|
||||
#define VMSTATE_UINTTL_ARRAY(_f, _s, _n) \
|
||||
VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, 0)
|
||||
#define VMSTATE_UINTTL_2DARRAY(_f, _s, _n1, _n2) \
|
||||
VMSTATE_UINTTL_2DARRAY_V(_f, _s, _n1, _n2, 0)
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -500,6 +500,19 @@ extern const VMStateInfo vmstate_info_qtailq;
|
||||
.offset = vmstate_offset_array(_state, _field, _type, _num),\
|
||||
}
|
||||
|
||||
#define VMSTATE_STRUCT_2DARRAY_TEST(_field, _state, _n1, _n2, _test, \
|
||||
_version, _vmsd, _type) { \
|
||||
.name = (stringify(_field)), \
|
||||
.num = (_n1) * (_n2), \
|
||||
.field_exists = (_test), \
|
||||
.version_id = (_version), \
|
||||
.vmsd = &(_vmsd), \
|
||||
.size = sizeof(_type), \
|
||||
.flags = VMS_STRUCT | VMS_ARRAY, \
|
||||
.offset = vmstate_offset_2darray(_state, _field, _type, \
|
||||
_n1, _n2), \
|
||||
}
|
||||
|
||||
#define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
|
||||
.name = (stringify(_field)), \
|
||||
.num_offset = vmstate_offset_value(_state, _field_num, uint8_t), \
|
||||
@ -747,6 +760,11 @@ extern const VMStateInfo vmstate_info_qtailq;
|
||||
VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version, \
|
||||
_vmsd, _type)
|
||||
|
||||
#define VMSTATE_STRUCT_2DARRAY(_field, _state, _n1, _n2, _version, \
|
||||
_vmsd, _type) \
|
||||
VMSTATE_STRUCT_2DARRAY_TEST(_field, _state, _n1, _n2, NULL, \
|
||||
_version, _vmsd, _type)
|
||||
|
||||
#define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) \
|
||||
VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _state, NULL, _version, _info, \
|
||||
_size)
|
||||
|
@ -1052,7 +1052,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
(*regs)[i] = tswapreg(env->gpr[i]);
|
||||
(*regs)[i] = tswapreg(cpu_get_gpr(env, i));
|
||||
}
|
||||
(*regs)[32] = tswapreg(env->pc);
|
||||
(*regs)[33] = tswapreg(cpu_get_sr(env));
|
||||
|
@ -2590,17 +2590,17 @@ void cpu_loop(CPUOpenRISCState *env)
|
||||
case EXCP_SYSCALL:
|
||||
env->pc += 4; /* 0xc00; */
|
||||
ret = do_syscall(env,
|
||||
env->gpr[11], /* return value */
|
||||
env->gpr[3], /* r3 - r7 are params */
|
||||
env->gpr[4],
|
||||
env->gpr[5],
|
||||
env->gpr[6],
|
||||
env->gpr[7],
|
||||
env->gpr[8], 0, 0);
|
||||
cpu_get_gpr(env, 11), /* return value */
|
||||
cpu_get_gpr(env, 3), /* r3 - r7 are params */
|
||||
cpu_get_gpr(env, 4),
|
||||
cpu_get_gpr(env, 5),
|
||||
cpu_get_gpr(env, 6),
|
||||
cpu_get_gpr(env, 7),
|
||||
cpu_get_gpr(env, 8), 0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->gpr[11] = ret;
|
||||
cpu_set_gpr(env, 11, ret);
|
||||
}
|
||||
break;
|
||||
case EXCP_DPF:
|
||||
@ -4765,7 +4765,7 @@ int main(int argc, char **argv, char **envp)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
env->gpr[i] = regs->gpr[i];
|
||||
cpu_set_gpr(env, i, regs->gpr[i]);
|
||||
}
|
||||
env->pc = regs->pc;
|
||||
cpu_set_sr(env, regs->sr);
|
||||
|
@ -23,14 +23,14 @@
|
||||
static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
|
||||
{
|
||||
if (newsp) {
|
||||
env->gpr[1] = newsp;
|
||||
cpu_set_gpr(env, 1, newsp);
|
||||
}
|
||||
env->gpr[11] = 0;
|
||||
cpu_set_gpr(env, 11, 0);
|
||||
}
|
||||
|
||||
static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls)
|
||||
{
|
||||
env->gpr[10] = newtls;
|
||||
cpu_set_gpr(env, 10, newtls);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -20,7 +20,7 @@ typedef struct target_sigaltstack {
|
||||
|
||||
static inline abi_ulong get_sp_from_cpustate(CPUOpenRISCState *state)
|
||||
{
|
||||
return state->gpr[1];
|
||||
return cpu_get_gpr(state, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4411,7 +4411,7 @@ static void setup_sigcontext(struct target_sigcontext *sc,
|
||||
CPUOpenRISCState *regs,
|
||||
unsigned long mask)
|
||||
{
|
||||
unsigned long usp = regs->gpr[1];
|
||||
unsigned long usp = cpu_get_gpr(regs, 1);
|
||||
|
||||
/* copy the regs. they are first in sc so we can use sc directly */
|
||||
|
||||
@ -4436,7 +4436,7 @@ static inline abi_ulong get_sigframe(struct target_sigaction *ka,
|
||||
CPUOpenRISCState *regs,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long sp = regs->gpr[1];
|
||||
unsigned long sp = cpu_get_gpr(regs, 1);
|
||||
int onsigstack = on_sig_stack(sp);
|
||||
|
||||
/* redzone */
|
||||
@ -4489,7 +4489,8 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
__put_user(0, &frame->uc.tuc_link);
|
||||
__put_user(target_sigaltstack_used.ss_sp,
|
||||
&frame->uc.tuc_stack.ss_sp);
|
||||
__put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
|
||||
__put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
|
||||
&frame->uc.tuc_stack.ss_flags);
|
||||
__put_user(target_sigaltstack_used.ss_size,
|
||||
&frame->uc.tuc_stack.ss_size);
|
||||
setup_sigcontext(&frame->sc, env, set->sig[0]);
|
||||
@ -4512,13 +4513,13 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
|
||||
env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
|
||||
env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
|
||||
env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
|
||||
env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
|
||||
cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
|
||||
cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
|
||||
cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
|
||||
cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
|
||||
|
||||
/* actually move the usp to reflect the stacked frame */
|
||||
env->gpr[1] = (unsigned long)frame;
|
||||
cpu_set_gpr(env, 1, (unsigned long)frame);
|
||||
|
||||
return;
|
||||
|
||||
|
@ -51,8 +51,8 @@ static void openrisc_cpu_reset(CPUState *s)
|
||||
cpu->env.lock_addr = -1;
|
||||
s->exception_index = -1;
|
||||
|
||||
cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
|
||||
cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S;
|
||||
cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP |
|
||||
UPR_PMP;
|
||||
cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
|
||||
cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
|
||||
|
||||
@ -65,12 +65,6 @@ static void openrisc_cpu_reset(CPUState *s)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void set_feature(OpenRISCCPU *cpu, int feature)
|
||||
{
|
||||
cpu->feature |= feature;
|
||||
cpu->env.cpucfgr = cpu->feature;
|
||||
}
|
||||
|
||||
static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
@ -132,15 +126,15 @@ static void or1200_initfn(Object *obj)
|
||||
{
|
||||
OpenRISCCPU *cpu = OPENRISC_CPU(obj);
|
||||
|
||||
set_feature(cpu, OPENRISC_FEATURE_OB32S);
|
||||
set_feature(cpu, OPENRISC_FEATURE_OF32S);
|
||||
cpu->env.cpucfgr = CPUCFGR_NSGF | CPUCFGR_OB32S | CPUCFGR_OF32S |
|
||||
CPUCFGR_EVBARP;
|
||||
}
|
||||
|
||||
static void openrisc_any_initfn(Object *obj)
|
||||
{
|
||||
OpenRISCCPU *cpu = OPENRISC_CPU(obj);
|
||||
|
||||
set_feature(cpu, OPENRISC_FEATURE_OB32S);
|
||||
cpu->env.cpucfgr = CPUCFGR_NSGF | CPUCFGR_OB32S | CPUCFGR_EVBARP;
|
||||
}
|
||||
|
||||
typedef struct OpenRISCCPUInfo {
|
||||
|
@ -111,6 +111,11 @@ enum {
|
||||
CPUCFGR_OF32S = (1 << 7),
|
||||
CPUCFGR_OF64S = (1 << 8),
|
||||
CPUCFGR_OV64S = (1 << 9),
|
||||
/* CPUCFGR_ND = (1 << 10), */
|
||||
/* CPUCFGR_AVRP = (1 << 11), */
|
||||
CPUCFGR_EVBARP = (1 << 12),
|
||||
/* CPUCFGR_ISRP = (1 << 13), */
|
||||
/* CPUCFGR_AECSRP = (1 << 14), */
|
||||
};
|
||||
|
||||
/* DMMU configure register */
|
||||
@ -135,6 +140,15 @@ enum {
|
||||
IMMUCFGR_HTR = (1 << 11),
|
||||
};
|
||||
|
||||
/* Power management register */
|
||||
enum {
|
||||
PMR_SDF = (15 << 0),
|
||||
PMR_DME = (1 << 4),
|
||||
PMR_SME = (1 << 5),
|
||||
PMR_DCGE = (1 << 6),
|
||||
PMR_SUME = (1 << 7),
|
||||
};
|
||||
|
||||
/* Float point control status register */
|
||||
enum {
|
||||
FPCSR_FPEE = 1,
|
||||
@ -191,17 +205,6 @@ enum {
|
||||
SR_SCE = (1 << 17),
|
||||
};
|
||||
|
||||
/* OpenRISC Hardware Capabilities */
|
||||
enum {
|
||||
OPENRISC_FEATURE_NSGF = (15 << 0),
|
||||
OPENRISC_FEATURE_CGF = (1 << 4),
|
||||
OPENRISC_FEATURE_OB32S = (1 << 5),
|
||||
OPENRISC_FEATURE_OB64S = (1 << 6),
|
||||
OPENRISC_FEATURE_OF32S = (1 << 7),
|
||||
OPENRISC_FEATURE_OF64S = (1 << 8),
|
||||
OPENRISC_FEATURE_OV64S = (1 << 9),
|
||||
};
|
||||
|
||||
/* Tick Timer Mode Register */
|
||||
enum {
|
||||
TTMR_TP = (0xfffffff),
|
||||
@ -269,7 +272,8 @@ typedef struct CPUOpenRISCTLBContext {
|
||||
#endif
|
||||
|
||||
typedef struct CPUOpenRISCState {
|
||||
target_ulong gpr[32]; /* General registers */
|
||||
target_ulong shadow_gpr[16][32]; /* Shadow registers */
|
||||
|
||||
target_ulong pc; /* Program counter */
|
||||
target_ulong ppc; /* Prev PC */
|
||||
target_ulong jmp_pc; /* Jump PC */
|
||||
@ -285,10 +289,11 @@ typedef struct CPUOpenRISCState {
|
||||
uint32_t sr; /* Supervisor register, without SR_{F,CY,OV} */
|
||||
uint32_t vr; /* Version register */
|
||||
uint32_t upr; /* Unit presence register */
|
||||
uint32_t cpucfgr; /* CPU configure register */
|
||||
uint32_t dmmucfgr; /* DMMU configure register */
|
||||
uint32_t immucfgr; /* IMMU configure register */
|
||||
uint32_t esr; /* Exception supervisor register */
|
||||
uint32_t evbar; /* Exception vector base address register */
|
||||
uint32_t pmr; /* Power Management Register */
|
||||
uint32_t fpcsr; /* Float register */
|
||||
float_status fp_status;
|
||||
|
||||
@ -303,6 +308,8 @@ typedef struct CPUOpenRISCState {
|
||||
CPU_COMMON
|
||||
|
||||
/* Fields from here on are preserved across CPU reset. */
|
||||
uint32_t cpucfgr; /* CPU configure register */
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
CPUOpenRISCTLBContext * tlb;
|
||||
|
||||
@ -329,7 +336,6 @@ typedef struct OpenRISCCPU {
|
||||
|
||||
CPUOpenRISCState env;
|
||||
|
||||
uint32_t feature; /* CPU Capabilities */
|
||||
} OpenRISCCPU;
|
||||
|
||||
static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
|
||||
@ -392,6 +398,16 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
|
||||
#define TB_FLAGS_R0_0 2
|
||||
#define TB_FLAGS_OVE SR_OVE
|
||||
|
||||
static inline uint32_t cpu_get_gpr(const CPUOpenRISCState *env, int i)
|
||||
{
|
||||
return env->shadow_gpr[0][i];
|
||||
}
|
||||
|
||||
static inline void cpu_set_gpr(CPUOpenRISCState *env, int i, uint32_t val)
|
||||
{
|
||||
env->shadow_gpr[0][i] = val;
|
||||
}
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
|
||||
target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
@ -399,7 +415,7 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
|
||||
*pc = env->pc;
|
||||
*cs_base = 0;
|
||||
*flags = (env->dflag
|
||||
| (env->gpr[0] == 0 ? TB_FLAGS_R0_0 : 0)
|
||||
| (cpu_get_gpr(env, 0) == 0 ? TB_FLAGS_R0_0 : 0)
|
||||
| (env->sr & SR_OVE));
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
CPUOpenRISCState *env = &cpu->env;
|
||||
|
||||
if (n < 32) {
|
||||
return gdb_get_reg32(mem_buf, env->gpr[n]);
|
||||
return gdb_get_reg32(mem_buf, cpu_get_gpr(env, n));
|
||||
} else {
|
||||
switch (n) {
|
||||
case 32: /* PPC */
|
||||
@ -61,7 +61,7 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
tmp = ldl_p(mem_buf);
|
||||
|
||||
if (n < 32) {
|
||||
env->gpr[n] = tmp;
|
||||
cpu_set_gpr(env, n, tmp);
|
||||
} else {
|
||||
switch (n) {
|
||||
case 32: /* PPC */
|
||||
|
@ -60,12 +60,21 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
|
||||
env->sr |= SR_SM;
|
||||
env->sr &= ~SR_IEE;
|
||||
env->sr &= ~SR_TEE;
|
||||
env->pmr &= ~PMR_DME;
|
||||
env->pmr &= ~PMR_SME;
|
||||
env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
|
||||
env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
|
||||
env->lock_addr = -1;
|
||||
|
||||
if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
|
||||
env->pc = (cs->exception_index << 8);
|
||||
hwaddr vect_pc = cs->exception_index << 8;
|
||||
if (env->cpucfgr & CPUCFGR_EVBARP) {
|
||||
vect_pc |= env->evbar;
|
||||
}
|
||||
if (env->sr & SR_EPH) {
|
||||
vect_pc |= 0xf0000000;
|
||||
}
|
||||
env->pc = vect_pc;
|
||||
} else {
|
||||
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
|
||||
}
|
||||
|
@ -24,6 +24,63 @@
|
||||
#include "hw/boards.h"
|
||||
#include "migration/cpu.h"
|
||||
|
||||
static int env_post_load(void *opaque, int version_id)
|
||||
{
|
||||
CPUOpenRISCState *env = opaque;
|
||||
|
||||
/* Restore MMU handlers */
|
||||
if (env->sr & SR_DME) {
|
||||
env->tlb->cpu_openrisc_map_address_data =
|
||||
&cpu_openrisc_get_phys_data;
|
||||
} else {
|
||||
env->tlb->cpu_openrisc_map_address_data =
|
||||
&cpu_openrisc_get_phys_nommu;
|
||||
}
|
||||
|
||||
if (env->sr & SR_IME) {
|
||||
env->tlb->cpu_openrisc_map_address_code =
|
||||
&cpu_openrisc_get_phys_code;
|
||||
} else {
|
||||
env->tlb->cpu_openrisc_map_address_code =
|
||||
&cpu_openrisc_get_phys_nommu;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_tlb_entry = {
|
||||
.name = "tlb_entry",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINTTL(mr, OpenRISCTLBEntry),
|
||||
VMSTATE_UINTTL(tr, OpenRISCTLBEntry),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_cpu_tlb = {
|
||||
.name = "cpu_tlb",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT_2DARRAY(itlb, CPUOpenRISCTLBContext,
|
||||
ITLB_WAYS, ITLB_SIZE, 0,
|
||||
vmstate_tlb_entry, OpenRISCTLBEntry),
|
||||
VMSTATE_STRUCT_2DARRAY(dtlb, CPUOpenRISCTLBContext,
|
||||
DTLB_WAYS, DTLB_SIZE, 0,
|
||||
vmstate_tlb_entry, OpenRISCTLBEntry),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
#define VMSTATE_CPU_TLB(_f, _s) \
|
||||
VMSTATE_STRUCT_POINTER(_f, _s, vmstate_cpu_tlb, CPUOpenRISCTLBContext)
|
||||
|
||||
|
||||
static int get_sr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||
{
|
||||
CPUOpenRISCState *env = opaque;
|
||||
@ -47,10 +104,11 @@ static const VMStateInfo vmstate_sr = {
|
||||
|
||||
static const VMStateDescription vmstate_env = {
|
||||
.name = "env",
|
||||
.version_id = 4,
|
||||
.minimum_version_id = 4,
|
||||
.version_id = 6,
|
||||
.minimum_version_id = 6,
|
||||
.post_load = env_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32),
|
||||
VMSTATE_UINTTL_2DARRAY(shadow_gpr, CPUOpenRISCState, 16, 32),
|
||||
VMSTATE_UINTTL(pc, CPUOpenRISCState),
|
||||
VMSTATE_UINTTL(ppc, CPUOpenRISCState),
|
||||
VMSTATE_UINTTL(jmp_pc, CPUOpenRISCState),
|
||||
@ -79,9 +137,21 @@ static const VMStateDescription vmstate_env = {
|
||||
VMSTATE_UINT32(cpucfgr, CPUOpenRISCState),
|
||||
VMSTATE_UINT32(dmmucfgr, CPUOpenRISCState),
|
||||
VMSTATE_UINT32(immucfgr, CPUOpenRISCState),
|
||||
VMSTATE_UINT32(evbar, CPUOpenRISCState),
|
||||
VMSTATE_UINT32(pmr, CPUOpenRISCState),
|
||||
VMSTATE_UINT32(esr, CPUOpenRISCState),
|
||||
VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
|
||||
VMSTATE_UINT64(mac, CPUOpenRISCState),
|
||||
|
||||
VMSTATE_CPU_TLB(tlb, CPUOpenRISCState),
|
||||
|
||||
VMSTATE_TIMER_PTR(timer, CPUOpenRISCState),
|
||||
VMSTATE_UINT32(ttmr, CPUOpenRISCState),
|
||||
VMSTATE_UINT32(ttcr, CPUOpenRISCState),
|
||||
|
||||
VMSTATE_UINT32(picmr, CPUOpenRISCState),
|
||||
VMSTATE_UINT32(picsr, CPUOpenRISCState),
|
||||
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
@ -124,7 +124,7 @@ static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu,
|
||||
{
|
||||
int ret = TLBRET_MATCH;
|
||||
|
||||
if (rw == 2) { /* ITLB */
|
||||
if (rw == MMU_INST_FETCH) { /* ITLB */
|
||||
*physical = 0;
|
||||
ret = cpu->env.tlb->cpu_openrisc_map_address_code(cpu, physical,
|
||||
prot, address, rw);
|
||||
@ -221,12 +221,28 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
|
||||
hwaddr phys_addr;
|
||||
int prot;
|
||||
int miss;
|
||||
|
||||
if (cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0)) {
|
||||
return -1;
|
||||
/* Check memory for any kind of address, since during debug the
|
||||
gdb can ask for anything, check data tlb for address */
|
||||
miss = cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0);
|
||||
|
||||
/* Check instruction tlb */
|
||||
if (miss) {
|
||||
miss = cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr,
|
||||
MMU_INST_FETCH);
|
||||
}
|
||||
|
||||
return phys_addr;
|
||||
/* Last, fall back to a plain address */
|
||||
if (miss) {
|
||||
miss = cpu_openrisc_get_phys_nommu(cpu, &phys_addr, &prot, addr, 0);
|
||||
}
|
||||
|
||||
if (miss) {
|
||||
return -1;
|
||||
} else {
|
||||
return phys_addr;
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_openrisc_mmu_init(OpenRISCCPU *cpu)
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exception.h"
|
||||
|
||||
#define TO_SPR(group, number) (((group) << 11) + (number))
|
||||
|
||||
@ -39,6 +40,10 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
||||
env->vr = rb;
|
||||
break;
|
||||
|
||||
case TO_SPR(0, 11): /* EVBAR */
|
||||
env->evbar = rb;
|
||||
break;
|
||||
|
||||
case TO_SPR(0, 16): /* NPC */
|
||||
cpu_restore_state(cs, GETPC());
|
||||
/* ??? Mirror or1ksim in not trashing delayed branch state
|
||||
@ -88,6 +93,11 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
||||
case TO_SPR(0, 64): /* ESR */
|
||||
env->esr = rb;
|
||||
break;
|
||||
|
||||
case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */
|
||||
idx = (spr - 1024);
|
||||
env->shadow_gpr[idx / 32][idx % 32] = rb;
|
||||
|
||||
case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
|
||||
idx = spr - TO_SPR(1, 512);
|
||||
if (!(rb & 1)) {
|
||||
@ -132,6 +142,15 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
||||
case TO_SPR(5, 2): /* MACHI */
|
||||
env->mac = deposit64(env->mac, 32, 32, rb);
|
||||
break;
|
||||
case TO_SPR(8, 0): /* PMR */
|
||||
env->pmr = rb;
|
||||
if (env->pmr & PMR_DME || env->pmr & PMR_SME) {
|
||||
cpu_restore_state(cs, GETPC());
|
||||
env->pc += 4;
|
||||
cs->halted = 1;
|
||||
raise_exception(cpu, EXCP_HALTED);
|
||||
}
|
||||
break;
|
||||
case TO_SPR(9, 0): /* PICMR */
|
||||
env->picmr |= rb;
|
||||
break;
|
||||
@ -206,6 +225,9 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
||||
case TO_SPR(0, 4): /* IMMUCFGR */
|
||||
return env->immucfgr;
|
||||
|
||||
case TO_SPR(0, 11): /* EVBAR */
|
||||
return env->evbar;
|
||||
|
||||
case TO_SPR(0, 16): /* NPC (equals PC) */
|
||||
cpu_restore_state(cs, GETPC());
|
||||
return env->pc;
|
||||
@ -226,6 +248,16 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
||||
case TO_SPR(0, 64): /* ESR */
|
||||
return env->esr;
|
||||
|
||||
case TO_SPR(0, 128): /* COREID */
|
||||
return 0;
|
||||
|
||||
case TO_SPR(0, 129): /* NUMCORES */
|
||||
return 1;
|
||||
|
||||
case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */
|
||||
idx = (spr - 1024);
|
||||
return env->shadow_gpr[idx / 32][idx % 32];
|
||||
|
||||
case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
|
||||
idx = spr - TO_SPR(1, 512);
|
||||
return env->tlb->dtlb[0][idx].mr;
|
||||
@ -265,6 +297,9 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
||||
return env->mac >> 32;
|
||||
break;
|
||||
|
||||
case TO_SPR(8, 0): /* PMR */
|
||||
return env->pmr;
|
||||
|
||||
case TO_SPR(9, 0): /* PICMR */
|
||||
return env->picmr;
|
||||
|
||||
|
@ -107,7 +107,8 @@ void openrisc_translate_init(void)
|
||||
"mac");
|
||||
for (i = 0; i < 32; i++) {
|
||||
cpu_R[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUOpenRISCState, gpr[i]),
|
||||
offsetof(CPUOpenRISCState,
|
||||
shadow_gpr[0][i]),
|
||||
regnames[i]);
|
||||
}
|
||||
cpu_R0 = cpu_R[0];
|
||||
@ -1662,7 +1663,7 @@ void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
|
||||
|
||||
cpu_fprintf(f, "PC=%08x\n", env->pc);
|
||||
for (i = 0; i < 32; ++i) {
|
||||
cpu_fprintf(f, "R%02d=%08x%c", i, env->gpr[i],
|
||||
cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
|
||||
(i % 4) == 3 ? '\n' : ' ');
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user