qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

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 <shorne@gmail.com>

+56 -32
+1 -1
linux-user/elfload.c
··· 1052 1052 int i; 1053 1053 1054 1054 for (i = 0; i < 32; i++) { 1055 - (*regs)[i] = tswapreg(env->gpr[i]); 1055 + (*regs)[i] = tswapreg(cpu_get_gpr(env, i)); 1056 1056 } 1057 1057 (*regs)[32] = tswapreg(env->pc); 1058 1058 (*regs)[33] = tswapreg(cpu_get_sr(env));
+9 -9
linux-user/main.c
··· 2590 2590 case EXCP_SYSCALL: 2591 2591 env->pc += 4; /* 0xc00; */ 2592 2592 ret = do_syscall(env, 2593 - env->gpr[11], /* return value */ 2594 - env->gpr[3], /* r3 - r7 are params */ 2595 - env->gpr[4], 2596 - env->gpr[5], 2597 - env->gpr[6], 2598 - env->gpr[7], 2599 - env->gpr[8], 0, 0); 2593 + cpu_get_gpr(env, 11), /* return value */ 2594 + cpu_get_gpr(env, 3), /* r3 - r7 are params */ 2595 + cpu_get_gpr(env, 4), 2596 + cpu_get_gpr(env, 5), 2597 + cpu_get_gpr(env, 6), 2598 + cpu_get_gpr(env, 7), 2599 + cpu_get_gpr(env, 8), 0, 0); 2600 2600 if (ret == -TARGET_ERESTARTSYS) { 2601 2601 env->pc -= 4; 2602 2602 } else if (ret != -TARGET_QEMU_ESIGRETURN) { 2603 - env->gpr[11] = ret; 2603 + cpu_set_gpr(env, 11, ret); 2604 2604 } 2605 2605 break; 2606 2606 case EXCP_DPF: ··· 4765 4765 int i; 4766 4766 4767 4767 for (i = 0; i < 32; i++) { 4768 - env->gpr[i] = regs->gpr[i]; 4768 + cpu_set_gpr(env, i, regs->gpr[i]); 4769 4769 } 4770 4770 env->pc = regs->pc; 4771 4771 cpu_set_sr(env, regs->sr);
+3 -3
linux-user/openrisc/target_cpu.h
··· 23 23 static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp) 24 24 { 25 25 if (newsp) { 26 - env->gpr[1] = newsp; 26 + cpu_set_gpr(env, 1, newsp); 27 27 } 28 - env->gpr[11] = 0; 28 + cpu_set_gpr(env, 11, 0); 29 29 } 30 30 31 31 static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls) 32 32 { 33 - env->gpr[10] = newtls; 33 + cpu_set_gpr(env, 10, newtls); 34 34 } 35 35 36 36 #endif
+1 -1
linux-user/openrisc/target_signal.h
··· 20 20 21 21 static inline abi_ulong get_sp_from_cpustate(CPUOpenRISCState *state) 22 22 { 23 - return state->gpr[1]; 23 + return cpu_get_gpr(state, 1); 24 24 } 25 25 26 26
+9 -8
linux-user/signal.c
··· 4411 4411 CPUOpenRISCState *regs, 4412 4412 unsigned long mask) 4413 4413 { 4414 - unsigned long usp = regs->gpr[1]; 4414 + unsigned long usp = cpu_get_gpr(regs, 1); 4415 4415 4416 4416 /* copy the regs. they are first in sc so we can use sc directly */ 4417 4417 ··· 4436 4436 CPUOpenRISCState *regs, 4437 4437 size_t frame_size) 4438 4438 { 4439 - unsigned long sp = regs->gpr[1]; 4439 + unsigned long sp = cpu_get_gpr(regs, 1); 4440 4440 int onsigstack = on_sig_stack(sp); 4441 4441 4442 4442 /* redzone */ ··· 4489 4489 __put_user(0, &frame->uc.tuc_link); 4490 4490 __put_user(target_sigaltstack_used.ss_sp, 4491 4491 &frame->uc.tuc_stack.ss_sp); 4492 - __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags); 4492 + __put_user(sas_ss_flags(cpu_get_gpr(env, 1)), 4493 + &frame->uc.tuc_stack.ss_flags); 4493 4494 __put_user(target_sigaltstack_used.ss_size, 4494 4495 &frame->uc.tuc_stack.ss_size); 4495 4496 setup_sigcontext(&frame->sc, env, set->sig[0]); ··· 4512 4513 4513 4514 /* Set up registers for signal handler */ 4514 4515 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */ 4515 - env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */ 4516 - env->gpr[3] = (unsigned long)sig; /* arg 1: signo */ 4517 - env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */ 4518 - env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */ 4516 + cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */ 4517 + cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */ 4518 + cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */ 4519 + cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */ 4519 4520 4520 4521 /* actually move the usp to reflect the stacked frame */ 4521 - env->gpr[1] = (unsigned long)frame; 4522 + cpu_set_gpr(env, 1, (unsigned long)frame); 4522 4523 4523 4524 return; 4524 4525
+3 -1
target/openrisc/cpu.c
··· 52 52 s->exception_index = -1; 53 53 54 54 cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP; 55 - cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S; 55 + cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S | CPUCFGR_NSGF; 56 56 cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2)); 57 57 cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2)); 58 58 ··· 132 132 { 133 133 OpenRISCCPU *cpu = OPENRISC_CPU(obj); 134 134 135 + set_feature(cpu, OPENRISC_FEATURE_NSGF); 135 136 set_feature(cpu, OPENRISC_FEATURE_OB32S); 136 137 set_feature(cpu, OPENRISC_FEATURE_OF32S); 137 138 set_feature(cpu, OPENRISC_FEATURE_EVBAR); ··· 141 142 { 142 143 OpenRISCCPU *cpu = OPENRISC_CPU(obj); 143 144 145 + set_feature(cpu, OPENRISC_FEATURE_NSGF); 144 146 set_feature(cpu, OPENRISC_FEATURE_OB32S); 145 147 set_feature(cpu, OPENRISC_FEATURE_EVBAR); 146 148 }
+13 -2
target/openrisc/cpu.h
··· 275 275 #endif 276 276 277 277 typedef struct CPUOpenRISCState { 278 - target_ulong gpr[32]; /* General registers */ 278 + target_ulong shadow_gpr[16][32]; /* Shadow registers */ 279 + 279 280 target_ulong pc; /* Program counter */ 280 281 target_ulong ppc; /* Prev PC */ 281 282 target_ulong jmp_pc; /* Jump PC */ ··· 399 400 #define TB_FLAGS_R0_0 2 400 401 #define TB_FLAGS_OVE SR_OVE 401 402 403 + static inline uint32_t cpu_get_gpr(const CPUOpenRISCState *env, int i) 404 + { 405 + return env->shadow_gpr[0][i]; 406 + } 407 + 408 + static inline void cpu_set_gpr(CPUOpenRISCState *env, int i, uint32_t val) 409 + { 410 + env->shadow_gpr[0][i] = val; 411 + } 412 + 402 413 static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, 403 414 target_ulong *pc, 404 415 target_ulong *cs_base, uint32_t *flags) ··· 406 417 *pc = env->pc; 407 418 *cs_base = 0; 408 419 *flags = (env->dflag 409 - | (env->gpr[0] == 0 ? TB_FLAGS_R0_0 : 0) 420 + | (cpu_get_gpr(env, 0) == 0 ? TB_FLAGS_R0_0 : 0) 410 421 | (env->sr & SR_OVE)); 411 422 } 412 423
+2 -2
target/openrisc/gdbstub.c
··· 28 28 CPUOpenRISCState *env = &cpu->env; 29 29 30 30 if (n < 32) { 31 - return gdb_get_reg32(mem_buf, env->gpr[n]); 31 + return gdb_get_reg32(mem_buf, cpu_get_gpr(env, n)); 32 32 } else { 33 33 switch (n) { 34 34 case 32: /* PPC */ ··· 61 61 tmp = ldl_p(mem_buf); 62 62 63 63 if (n < 32) { 64 - env->gpr[n] = tmp; 64 + cpu_set_gpr(env, n, tmp); 65 65 } else { 66 66 switch (n) { 67 67 case 32: /* PPC */
+3 -3
target/openrisc/machine.c
··· 47 47 48 48 static const VMStateDescription vmstate_env = { 49 49 .name = "env", 50 - .version_id = 4, 51 - .minimum_version_id = 4, 50 + .version_id = 5, 51 + .minimum_version_id = 5, 52 52 .fields = (VMStateField[]) { 53 - VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32), 53 + VMSTATE_UINTTL_2DARRAY(shadow_gpr, CPUOpenRISCState, 16, 32), 54 54 VMSTATE_UINTTL(pc, CPUOpenRISCState), 55 55 VMSTATE_UINTTL(ppc, CPUOpenRISCState), 56 56 VMSTATE_UINTTL(jmp_pc, CPUOpenRISCState),
+9
target/openrisc/sys_helper.c
··· 92 92 case TO_SPR(0, 64): /* ESR */ 93 93 env->esr = rb; 94 94 break; 95 + 96 + case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */ 97 + idx = (spr - 1024); 98 + env->shadow_gpr[idx / 32][idx % 32] = rb; 99 + 95 100 case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ 96 101 idx = spr - TO_SPR(1, 512); 97 102 if (!(rb & 1)) { ··· 238 243 239 244 case TO_SPR(0, 129): /* NUMCORES */ 240 245 return 1; 246 + 247 + case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */ 248 + idx = (spr - 1024); 249 + return env->shadow_gpr[idx / 32][idx % 32]; 241 250 242 251 case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ 243 252 idx = spr - TO_SPR(1, 512);
+3 -2
target/openrisc/translate.c
··· 107 107 "mac"); 108 108 for (i = 0; i < 32; i++) { 109 109 cpu_R[i] = tcg_global_mem_new(cpu_env, 110 - offsetof(CPUOpenRISCState, gpr[i]), 110 + offsetof(CPUOpenRISCState, 111 + shadow_gpr[0][i]), 111 112 regnames[i]); 112 113 } 113 114 cpu_R0 = cpu_R[0]; ··· 1662 1663 1663 1664 cpu_fprintf(f, "PC=%08x\n", env->pc); 1664 1665 for (i = 0; i < 32; ++i) { 1665 - cpu_fprintf(f, "R%02d=%08x%c", i, env->gpr[i], 1666 + cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i), 1666 1667 (i % 4) == 3 ? '\n' : ' '); 1667 1668 } 1668 1669 }