From 356a2db3c6f84e8e79e5afa3913514184bff5f50 Mon Sep 17 00:00:00 2001 From: Tim 'mithro' Ansell Date: Tue, 18 Apr 2017 16:15:50 +1000 Subject: target/openrisc: Implement EVBAR register Exception Vector Base Address Register (EVBAR) - This optional register can be used to apply an offset to the exception vector addresses. The significant bits (31-12) of the vector offset address for each exception depend on the setting of the Supervision Register (SR)'s EPH bit and the Exception Vector Base Address Register (EVBAR). Its presence is indicated by the EVBARP bit in the CPU Configuration Register (CPUCFGR). Signed-off-by: Tim 'mithro' Ansell Signed-off-by: Stafford Horne --- target/openrisc/sys_helper.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 60c3193656..6ba816249b 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -39,6 +39,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 @@ -206,6 +210,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; -- cgit v1.2.3 From ef3f5b9e7f83262e1eaea884b0a562b9fa73859c Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sat, 15 Apr 2017 07:25:32 +0900 Subject: target/openrisc: add numcores and coreid support These are used to identify the processor in SMP system. Their definition has been defined in verilog cores but it not yet part of the spec but it will be soon. The proposal for this is available: https://openrisc.io/proposals/core-identifier-and-number-of-cores Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/sys_helper.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 6ba816249b..e13666bea0 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -233,6 +233,12 @@ 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(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; -- cgit v1.2.3 From d89e71e873dca0ca6d3b3adab283045a03f4ca99 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Thu, 6 Apr 2017 06:44:56 +0900 Subject: target/openrisc: implement shadow registers Shadow registers are part of the openrisc spec along with sr[cid], as part of the fast context switching feature. When exceptions occur, instead of having to save registers to the stack if enabled the CID will increment and a new set of registers will be available. This patch only implements shadow registers which can be used as extra scratch registers via the mfspr and mtspr if required. This is implemented in a way where it would be easy to add on the fast context switching, currently cid is hardcoded to 0. This is need for openrisc linux smp kernels to boot correctly. Signed-off-by: Stafford Horne --- target/openrisc/sys_helper.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index e13666bea0..fa3d6a436e 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -92,6 +92,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)) { @@ -239,6 +244,10 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, 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; -- cgit v1.2.3 From f4d1414a9385e3375d9107b29eeb75d27daf2147 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Mon, 24 Apr 2017 06:07:42 +0900 Subject: target/openrisc: Support non-busy idle state using PMR SPR The OpenRISC architecture has the Power Management Register (PMR) special purpose register to manage cpu power states. The interesting modes are: * Doze Mode (DME) - Stop cpu except timer & pic - wake on interrupt * Sleep Mode (SME) - Stop cpu and all units - wake on interrupt * Suspend Model (SUME) - Stop cpu and all units - wake on reset The linux kernel will set DME when idle. This patch implements the PMR SPR and halts the qemu cpu when there is a change to DME or SME. This means that openrisc qemu in no longer peggs a host cpu at 100%. In order for this to work we need to kick the CPU when timers are expired. Update the cpu timer to kick the cpu upon each timer event. Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/sys_helper.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'target/openrisc/sys_helper.c') diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index fa3d6a436e..abdef5d6a5 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -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)) @@ -141,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; @@ -287,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; -- cgit v1.2.3