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:
Stefan Hajnoczi 2017-05-05 16:21:00 +01:00
commit 317134bb54
17 changed files with 230 additions and 62 deletions

View File

@ -196,8 +196,8 @@ F: hw/nios2/
F: disas/nios2.c F: disas/nios2.c
OpenRISC OpenRISC
M: Jia Liu <proljc@gmail.com> M: Stafford Horne <shorne@gmail.com>
S: Maintained S: Odd Fixes
F: target/openrisc/ F: target/openrisc/
F: hw/openrisc/ F: hw/openrisc/
F: tests/tcg/openrisc/ F: tests/tcg/openrisc/

View File

@ -61,6 +61,7 @@ void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
} }
next = now + (uint64_t)wait * TIMER_PERIOD; next = now + (uint64_t)wait * TIMER_PERIOD;
timer_mod(cpu->env.timer, next); timer_mod(cpu->env.timer, next);
qemu_cpu_kick(CPU(cpu));
} }
void cpu_openrisc_count_start(OpenRISCCPU *cpu) void cpu_openrisc_count_start(OpenRISCCPU *cpu)

View File

@ -18,6 +18,8 @@
VMSTATE_UINT64_EQUAL_V(_f, _s, _v) VMSTATE_UINT64_EQUAL_V(_f, _s, _v)
#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \ #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \
VMSTATE_UINT64_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) \ #define VMSTATE_UINTTL_TEST(_f, _s, _t) \
VMSTATE_UINT64_TEST(_f, _s, _t) VMSTATE_UINT64_TEST(_f, _s, _t)
#define vmstate_info_uinttl vmstate_info_uint64 #define vmstate_info_uinttl vmstate_info_uint64
@ -37,6 +39,8 @@
VMSTATE_UINT32_EQUAL_V(_f, _s, _v) VMSTATE_UINT32_EQUAL_V(_f, _s, _v)
#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \ #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \
VMSTATE_UINT32_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) \ #define VMSTATE_UINTTL_TEST(_f, _s, _t) \
VMSTATE_UINT32_TEST(_f, _s, _t) VMSTATE_UINT32_TEST(_f, _s, _t)
#define vmstate_info_uinttl vmstate_info_uint32 #define vmstate_info_uinttl vmstate_info_uint32
@ -48,5 +52,8 @@
VMSTATE_UINTTL_EQUAL_V(_f, _s, 0) VMSTATE_UINTTL_EQUAL_V(_f, _s, 0)
#define VMSTATE_UINTTL_ARRAY(_f, _s, _n) \ #define VMSTATE_UINTTL_ARRAY(_f, _s, _n) \
VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, 0) 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 #endif

View File

@ -500,6 +500,19 @@ extern const VMStateInfo vmstate_info_qtailq;
.offset = vmstate_offset_array(_state, _field, _type, _num),\ .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) { \ #define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
.name = (stringify(_field)), \ .name = (stringify(_field)), \
.num_offset = vmstate_offset_value(_state, _field_num, uint8_t), \ .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, \ VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version, \
_vmsd, _type) _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) \ #define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) \
VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _state, NULL, _version, _info, \ VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _state, NULL, _version, _info, \
_size) _size)

View File

@ -1052,7 +1052,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
int i; int i;
for (i = 0; i < 32; 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)[32] = tswapreg(env->pc);
(*regs)[33] = tswapreg(cpu_get_sr(env)); (*regs)[33] = tswapreg(cpu_get_sr(env));

View File

@ -2590,17 +2590,17 @@ void cpu_loop(CPUOpenRISCState *env)
case EXCP_SYSCALL: case EXCP_SYSCALL:
env->pc += 4; /* 0xc00; */ env->pc += 4; /* 0xc00; */
ret = do_syscall(env, ret = do_syscall(env,
env->gpr[11], /* return value */ cpu_get_gpr(env, 11), /* return value */
env->gpr[3], /* r3 - r7 are params */ cpu_get_gpr(env, 3), /* r3 - r7 are params */
env->gpr[4], cpu_get_gpr(env, 4),
env->gpr[5], cpu_get_gpr(env, 5),
env->gpr[6], cpu_get_gpr(env, 6),
env->gpr[7], cpu_get_gpr(env, 7),
env->gpr[8], 0, 0); cpu_get_gpr(env, 8), 0, 0);
if (ret == -TARGET_ERESTARTSYS) { if (ret == -TARGET_ERESTARTSYS) {
env->pc -= 4; env->pc -= 4;
} else if (ret != -TARGET_QEMU_ESIGRETURN) { } else if (ret != -TARGET_QEMU_ESIGRETURN) {
env->gpr[11] = ret; cpu_set_gpr(env, 11, ret);
} }
break; break;
case EXCP_DPF: case EXCP_DPF:
@ -4765,7 +4765,7 @@ int main(int argc, char **argv, char **envp)
int i; int i;
for (i = 0; i < 32; 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; env->pc = regs->pc;
cpu_set_sr(env, regs->sr); cpu_set_sr(env, regs->sr);

View File

@ -23,14 +23,14 @@
static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp) static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
{ {
if (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) static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls)
{ {
env->gpr[10] = newtls; cpu_set_gpr(env, 10, newtls);
} }
#endif #endif

View File

@ -20,7 +20,7 @@ typedef struct target_sigaltstack {
static inline abi_ulong get_sp_from_cpustate(CPUOpenRISCState *state) static inline abi_ulong get_sp_from_cpustate(CPUOpenRISCState *state)
{ {
return state->gpr[1]; return cpu_get_gpr(state, 1);
} }

View File

@ -4411,7 +4411,7 @@ static void setup_sigcontext(struct target_sigcontext *sc,
CPUOpenRISCState *regs, CPUOpenRISCState *regs,
unsigned long mask) 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 */ /* 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, CPUOpenRISCState *regs,
size_t frame_size) size_t frame_size)
{ {
unsigned long sp = regs->gpr[1]; unsigned long sp = cpu_get_gpr(regs, 1);
int onsigstack = on_sig_stack(sp); int onsigstack = on_sig_stack(sp);
/* redzone */ /* 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(0, &frame->uc.tuc_link);
__put_user(target_sigaltstack_used.ss_sp, __put_user(target_sigaltstack_used.ss_sp,
&frame->uc.tuc_stack.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, __put_user(target_sigaltstack_used.ss_size,
&frame->uc.tuc_stack.ss_size); &frame->uc.tuc_stack.ss_size);
setup_sigcontext(&frame->sc, env, set->sig[0]); 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 */ /* Set up registers for signal handler */
env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */ env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */ cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */
env->gpr[3] = (unsigned long)sig; /* arg 1: signo */ cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */
env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */ cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */
env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */ cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */
/* actually move the usp to reflect the stacked frame */ /* actually move the usp to reflect the stacked frame */
env->gpr[1] = (unsigned long)frame; cpu_set_gpr(env, 1, (unsigned long)frame);
return; return;

View File

@ -51,8 +51,8 @@ static void openrisc_cpu_reset(CPUState *s)
cpu->env.lock_addr = -1; cpu->env.lock_addr = -1;
s->exception_index = -1; s->exception_index = -1;
cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP; cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP |
cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S; UPR_PMP;
cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2)); cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_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 #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) static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp)
{ {
CPUState *cs = CPU(dev); CPUState *cs = CPU(dev);
@ -132,15 +126,15 @@ static void or1200_initfn(Object *obj)
{ {
OpenRISCCPU *cpu = OPENRISC_CPU(obj); OpenRISCCPU *cpu = OPENRISC_CPU(obj);
set_feature(cpu, OPENRISC_FEATURE_OB32S); cpu->env.cpucfgr = CPUCFGR_NSGF | CPUCFGR_OB32S | CPUCFGR_OF32S |
set_feature(cpu, OPENRISC_FEATURE_OF32S); CPUCFGR_EVBARP;
} }
static void openrisc_any_initfn(Object *obj) static void openrisc_any_initfn(Object *obj)
{ {
OpenRISCCPU *cpu = OPENRISC_CPU(obj); OpenRISCCPU *cpu = OPENRISC_CPU(obj);
set_feature(cpu, OPENRISC_FEATURE_OB32S); cpu->env.cpucfgr = CPUCFGR_NSGF | CPUCFGR_OB32S | CPUCFGR_EVBARP;
} }
typedef struct OpenRISCCPUInfo { typedef struct OpenRISCCPUInfo {

View File

@ -111,6 +111,11 @@ enum {
CPUCFGR_OF32S = (1 << 7), CPUCFGR_OF32S = (1 << 7),
CPUCFGR_OF64S = (1 << 8), CPUCFGR_OF64S = (1 << 8),
CPUCFGR_OV64S = (1 << 9), 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 */ /* DMMU configure register */
@ -135,6 +140,15 @@ enum {
IMMUCFGR_HTR = (1 << 11), 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 */ /* Float point control status register */
enum { enum {
FPCSR_FPEE = 1, FPCSR_FPEE = 1,
@ -191,17 +205,6 @@ enum {
SR_SCE = (1 << 17), 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 */ /* Tick Timer Mode Register */
enum { enum {
TTMR_TP = (0xfffffff), TTMR_TP = (0xfffffff),
@ -269,7 +272,8 @@ typedef struct CPUOpenRISCTLBContext {
#endif #endif
typedef struct CPUOpenRISCState { typedef struct CPUOpenRISCState {
target_ulong gpr[32]; /* General registers */ target_ulong shadow_gpr[16][32]; /* Shadow registers */
target_ulong pc; /* Program counter */ target_ulong pc; /* Program counter */
target_ulong ppc; /* Prev PC */ target_ulong ppc; /* Prev PC */
target_ulong jmp_pc; /* Jump 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 sr; /* Supervisor register, without SR_{F,CY,OV} */
uint32_t vr; /* Version register */ uint32_t vr; /* Version register */
uint32_t upr; /* Unit presence register */ uint32_t upr; /* Unit presence register */
uint32_t cpucfgr; /* CPU configure register */
uint32_t dmmucfgr; /* DMMU configure register */ uint32_t dmmucfgr; /* DMMU configure register */
uint32_t immucfgr; /* IMMU configure register */ uint32_t immucfgr; /* IMMU configure register */
uint32_t esr; /* Exception supervisor 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 */ uint32_t fpcsr; /* Float register */
float_status fp_status; float_status fp_status;
@ -303,6 +308,8 @@ typedef struct CPUOpenRISCState {
CPU_COMMON CPU_COMMON
/* Fields from here on are preserved across CPU reset. */ /* Fields from here on are preserved across CPU reset. */
uint32_t cpucfgr; /* CPU configure register */
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
CPUOpenRISCTLBContext * tlb; CPUOpenRISCTLBContext * tlb;
@ -329,7 +336,6 @@ typedef struct OpenRISCCPU {
CPUOpenRISCState env; CPUOpenRISCState env;
uint32_t feature; /* CPU Capabilities */
} OpenRISCCPU; } OpenRISCCPU;
static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env) 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_R0_0 2
#define TB_FLAGS_OVE SR_OVE #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, static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
target_ulong *pc, target_ulong *pc,
target_ulong *cs_base, uint32_t *flags) target_ulong *cs_base, uint32_t *flags)
@ -399,7 +415,7 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
*pc = env->pc; *pc = env->pc;
*cs_base = 0; *cs_base = 0;
*flags = (env->dflag *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)); | (env->sr & SR_OVE));
} }

View File

@ -28,7 +28,7 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
CPUOpenRISCState *env = &cpu->env; CPUOpenRISCState *env = &cpu->env;
if (n < 32) { if (n < 32) {
return gdb_get_reg32(mem_buf, env->gpr[n]); return gdb_get_reg32(mem_buf, cpu_get_gpr(env, n));
} else { } else {
switch (n) { switch (n) {
case 32: /* PPC */ 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); tmp = ldl_p(mem_buf);
if (n < 32) { if (n < 32) {
env->gpr[n] = tmp; cpu_set_gpr(env, n, tmp);
} else { } else {
switch (n) { switch (n) {
case 32: /* PPC */ case 32: /* PPC */

View File

@ -60,12 +60,21 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
env->sr |= SR_SM; env->sr |= SR_SM;
env->sr &= ~SR_IEE; env->sr &= ~SR_IEE;
env->sr &= ~SR_TEE; 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_data = &cpu_openrisc_get_phys_nommu;
env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
env->lock_addr = -1; env->lock_addr = -1;
if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) { 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 { } else {
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
} }

View File

@ -24,6 +24,63 @@
#include "hw/boards.h" #include "hw/boards.h"
#include "migration/cpu.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) static int get_sr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
{ {
CPUOpenRISCState *env = opaque; CPUOpenRISCState *env = opaque;
@ -47,10 +104,11 @@ static const VMStateInfo vmstate_sr = {
static const VMStateDescription vmstate_env = { static const VMStateDescription vmstate_env = {
.name = "env", .name = "env",
.version_id = 4, .version_id = 6,
.minimum_version_id = 4, .minimum_version_id = 6,
.post_load = env_post_load,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32), VMSTATE_UINTTL_2DARRAY(shadow_gpr, CPUOpenRISCState, 16, 32),
VMSTATE_UINTTL(pc, CPUOpenRISCState), VMSTATE_UINTTL(pc, CPUOpenRISCState),
VMSTATE_UINTTL(ppc, CPUOpenRISCState), VMSTATE_UINTTL(ppc, CPUOpenRISCState),
VMSTATE_UINTTL(jmp_pc, CPUOpenRISCState), VMSTATE_UINTTL(jmp_pc, CPUOpenRISCState),
@ -79,9 +137,21 @@ static const VMStateDescription vmstate_env = {
VMSTATE_UINT32(cpucfgr, CPUOpenRISCState), VMSTATE_UINT32(cpucfgr, CPUOpenRISCState),
VMSTATE_UINT32(dmmucfgr, CPUOpenRISCState), VMSTATE_UINT32(dmmucfgr, CPUOpenRISCState),
VMSTATE_UINT32(immucfgr, CPUOpenRISCState), VMSTATE_UINT32(immucfgr, CPUOpenRISCState),
VMSTATE_UINT32(evbar, CPUOpenRISCState),
VMSTATE_UINT32(pmr, CPUOpenRISCState),
VMSTATE_UINT32(esr, CPUOpenRISCState), VMSTATE_UINT32(esr, CPUOpenRISCState),
VMSTATE_UINT32(fpcsr, CPUOpenRISCState), VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
VMSTATE_UINT64(mac, 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() VMSTATE_END_OF_LIST()
} }
}; };

View File

@ -124,7 +124,7 @@ static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu,
{ {
int ret = TLBRET_MATCH; int ret = TLBRET_MATCH;
if (rw == 2) { /* ITLB */ if (rw == MMU_INST_FETCH) { /* ITLB */
*physical = 0; *physical = 0;
ret = cpu->env.tlb->cpu_openrisc_map_address_code(cpu, physical, ret = cpu->env.tlb->cpu_openrisc_map_address_code(cpu, physical,
prot, address, rw); prot, address, rw);
@ -221,12 +221,28 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
OpenRISCCPU *cpu = OPENRISC_CPU(cs); OpenRISCCPU *cpu = OPENRISC_CPU(cs);
hwaddr phys_addr; hwaddr phys_addr;
int prot; int prot;
int miss;
if (cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0)) { /* Check memory for any kind of address, since during debug the
return -1; 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) void cpu_openrisc_mmu_init(OpenRISCCPU *cpu)

View File

@ -22,6 +22,7 @@
#include "cpu.h" #include "cpu.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exception.h"
#define TO_SPR(group, number) (((group) << 11) + (number)) #define TO_SPR(group, number) (((group) << 11) + (number))
@ -39,6 +40,10 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
env->vr = rb; env->vr = rb;
break; break;
case TO_SPR(0, 11): /* EVBAR */
env->evbar = rb;
break;
case TO_SPR(0, 16): /* NPC */ case TO_SPR(0, 16): /* NPC */
cpu_restore_state(cs, GETPC()); cpu_restore_state(cs, GETPC());
/* ??? Mirror or1ksim in not trashing delayed branch state /* ??? Mirror or1ksim in not trashing delayed branch state
@ -88,6 +93,11 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
case TO_SPR(0, 64): /* ESR */ case TO_SPR(0, 64): /* ESR */
env->esr = rb; env->esr = rb;
break; 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 */ case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
idx = spr - TO_SPR(1, 512); idx = spr - TO_SPR(1, 512);
if (!(rb & 1)) { if (!(rb & 1)) {
@ -132,6 +142,15 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
case TO_SPR(5, 2): /* MACHI */ case TO_SPR(5, 2): /* MACHI */
env->mac = deposit64(env->mac, 32, 32, rb); env->mac = deposit64(env->mac, 32, 32, rb);
break; 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 */ case TO_SPR(9, 0): /* PICMR */
env->picmr |= rb; env->picmr |= rb;
break; break;
@ -206,6 +225,9 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
case TO_SPR(0, 4): /* IMMUCFGR */ case TO_SPR(0, 4): /* IMMUCFGR */
return env->immucfgr; return env->immucfgr;
case TO_SPR(0, 11): /* EVBAR */
return env->evbar;
case TO_SPR(0, 16): /* NPC (equals PC) */ case TO_SPR(0, 16): /* NPC (equals PC) */
cpu_restore_state(cs, GETPC()); cpu_restore_state(cs, GETPC());
return env->pc; return env->pc;
@ -226,6 +248,16 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
case TO_SPR(0, 64): /* ESR */ case TO_SPR(0, 64): /* ESR */
return env->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 */ case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
idx = spr - TO_SPR(1, 512); idx = spr - TO_SPR(1, 512);
return env->tlb->dtlb[0][idx].mr; return env->tlb->dtlb[0][idx].mr;
@ -265,6 +297,9 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
return env->mac >> 32; return env->mac >> 32;
break; break;
case TO_SPR(8, 0): /* PMR */
return env->pmr;
case TO_SPR(9, 0): /* PICMR */ case TO_SPR(9, 0): /* PICMR */
return env->picmr; return env->picmr;

View File

@ -107,7 +107,8 @@ void openrisc_translate_init(void)
"mac"); "mac");
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
cpu_R[i] = tcg_global_mem_new(cpu_env, cpu_R[i] = tcg_global_mem_new(cpu_env,
offsetof(CPUOpenRISCState, gpr[i]), offsetof(CPUOpenRISCState,
shadow_gpr[0][i]),
regnames[i]); regnames[i]);
} }
cpu_R0 = cpu_R[0]; 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); cpu_fprintf(f, "PC=%08x\n", env->pc);
for (i = 0; i < 32; ++i) { 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' : ' '); (i % 4) == 3 ? '\n' : ' ');
} }
} }