-
Notifications
You must be signed in to change notification settings - Fork 2
ume: Add interpolation to rv64ume and custom template tags #834
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
95f83c9
fd922a7
4815745
143ecf7
b1784d9
0ae6c13
f54e597
96d71b7
f89dc79
d81708a
e98f083
22b98c4
07cd92a
7c65266
4037a28
6a745f6
f3e4ac7
d2e54fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,13 +24,14 @@ | |
| #include "signal-common.h" | ||
| #include "elf.h" | ||
|
|
||
|
|
||
| enum { | ||
| RV64UME_EXC_ILLEGAL_INSTR = 2, | ||
| RV64UME_EXC_BREAKPOINT = 3, | ||
| RV64UME_EXC_ECALL = 11, | ||
| [# th:each="exc : ${config.excIds}"] | ||
| [(${gen_arch_upper})]_EXC_[(${exc.key})] = [(${exc.value})], | ||
| [/] | ||
| }; | ||
|
|
||
| void cpu_loop(CPURV64UMEState *env) | ||
| void cpu_loop(CPU[(${gen_arch_upper})]State *env) | ||
| { | ||
| CPUState *cs = env_cpu(env); | ||
| int trapnr; | ||
|
|
@@ -50,45 +51,47 @@ void cpu_loop(CPURV64UMEState *env) | |
| case EXCP_ATOMIC: | ||
| cpu_exec_step_atomic(cs); | ||
| break; | ||
| case RV64UME_EXCP_EXC: | ||
| cause = env->arg_exc_cause; | ||
| [# th:if="${not #strings.isEmpty(config.excCauseVar)}"] | ||
| case [(${gen_arch_upper})]_EXCP_[(${config.syscallException})]: | ||
| cause = env->[(${config.excCauseVar})]; | ||
| switch (cause) { | ||
| case RV64UME_EXC_ECALL: | ||
| env->pc += 4; | ||
| if (env->x[RV64UME_REG_A7] == TARGET_NR_rv64ume_flush_icache) { | ||
| case [(${gen_arch_upper})]_EXC_[(${config.syscallInstr})]: | ||
| env->[(${pc_reg.name_lower})] += [(${config.insn_width_bytes})]; | ||
| [# th:if="${config.hasIcacheFlush}"] | ||
| if (env->[(${config.mainRegisterFile})][ [(${config.sysReg})] ] == TARGET_NR_[(${gen_arch_lower})]_flush_icache) { | ||
| /* no-op in QEMU; TB invalidation is automatic */ | ||
| ret = 0; | ||
| } else { | ||
| [/] | ||
| ret = do_syscall(env, | ||
| env->x[RV64UME_REG_A7], | ||
| env->x[RV64UME_REG_A0], | ||
| env->x[RV64UME_REG_A1], | ||
| env->x[RV64UME_REG_A2], | ||
| env->x[RV64UME_REG_A3], | ||
| env->x[RV64UME_REG_A4], | ||
| env->x[RV64UME_REG_A5], | ||
| 0, 0); | ||
| env->[(${config.mainRegisterFile})][ [(${config.sysReg})] ], | ||
| [# th:each="arg : ${config.args}"] | ||
| env->[(${config.mainRegisterFile})][ [(${arg})] ], | ||
| [/] | ||
| 0, 0); | ||
| [# th:if="${config.hasIcacheFlush}"] | ||
| } | ||
| [/] | ||
|
Comment on lines
+60
to
+74
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. major: Just assume there is no icache-flush |
||
| if (ret == -QEMU_ERESTARTSYS) { | ||
| env->pc -= 4; | ||
| env->[(${pc_reg.name_lower})] -= [(${config.insn_width_bytes})]; | ||
| } else if (ret != -QEMU_ESIGRETURN) { | ||
| env->x[RV64UME_REG_A0] = ret; | ||
| } | ||
| env->[(${config.mainRegisterFile})][ [(${config.retReg})] ] = ret; } | ||
| if (cs->singlestep_enabled) { | ||
| goto gdbstep; | ||
| } | ||
| break; | ||
| case RV64UME_EXC_ILLEGAL_INSTR: | ||
| force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); | ||
|
|
||
| case [(${gen_arch_upper})]_EXC_[(${config.illegalInstrExcName})]: | ||
| force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->[(${pc_reg.name_lower})]); | ||
| break; | ||
| case RV64UME_EXC_BREAKPOINT: | ||
| case [(${gen_arch_upper})]_EXC_[(${config.breakpointExcName})]: | ||
| case EXCP_DEBUG: | ||
| gdbstep: | ||
| force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); | ||
| gdbstep: | ||
| force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->[(${pc_reg.name_lower})]); | ||
| break; | ||
| default: | ||
| EXCP_DUMP(env, | ||
| "\nqemu: unhandled rv64ume exception cause %#x - aborting\n", | ||
| "\nqemu: unhandled [(${gen_arch_lower})] exception cause %#x - aborting\n", | ||
| cause); | ||
| exit(EXIT_FAILURE); | ||
| } | ||
|
|
@@ -98,6 +101,43 @@ void cpu_loop(CPURV64UMEState *env) | |
| trapnr); | ||
| exit(EXIT_FAILURE); | ||
| } | ||
| [/] | ||
| [# th:if="${#strings.isEmpty(config.excCauseVar)}"] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. major: This check is unnecessary, as exceptions in the ISS are always rendered as cause variables in the state. |
||
| case [(${gen_arch_upper})]_EXC_[(${config.syscallInstr})]: | ||
| env->[(${pc_reg.name_lower})] += [(${config.insn_width_bytes})]; | ||
| [# th:if="${config.hasIcacheFlush}"] | ||
| if (env->[(${config.mainRegisterFile})][ [(${config.sysReg})] ] == TARGET_NR_[(${gen_arch_lower})]_flush_icache) { | ||
| /* no-op in QEMU; TB invalidation is automatic */ | ||
| ret = 0; | ||
| } else { | ||
| [/] | ||
| ret = do_syscall(env, | ||
| env->[(${config.mainRegisterFile})][ [(${config.sysReg})] ], | ||
| [# th:each="arg : ${config.args}"] | ||
| env->[(${config.mainRegisterFile})][ [(${arg})] ], | ||
| [/] | ||
| 0, 0); | ||
| [# th:if="${config.hasIcacheFlush}"] | ||
| } | ||
| [/] | ||
| if (ret == -QEMU_ERESTARTSYS) { | ||
| env->[(${pc_reg.name_lower})] -= [(${config.insn_width_bytes})]; | ||
| } else if (ret != -QEMU_ESIGRETURN) { | ||
| env->[(${config.mainRegisterFile})][ [(${config.retReg})] ] = ret; } | ||
| if (cs->singlestep_enabled) { | ||
| goto gdbstep; | ||
| } | ||
| break; | ||
|
|
||
| case [(${gen_arch_upper})]_EXC_[(${config.illegalInstrExcName})]: | ||
| force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->[(${pc_reg.name_lower})]); | ||
| break; | ||
| case [(${gen_arch_upper})]_EXC_[(${config.breakpointExcName})]: | ||
| case EXCP_DEBUG: | ||
| gdbstep: | ||
| force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->[(${pc_reg.name_lower})]); | ||
| break; | ||
| [/] | ||
|
|
||
| process_pending_signals(env); | ||
| } | ||
|
|
@@ -109,8 +149,8 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) | |
| TaskState *ts = get_task_state(cpu); | ||
| struct image_info *info = ts->info; | ||
|
|
||
| env->pc = regs->sepc; | ||
| env->x[RV64UME_REG_SP] = regs->sp; | ||
| env->[(${pc_reg.name_lower})] = regs->[(${config.initialPc})]; | ||
| env->[(${config.mainRegisterFile})][ [(${config.spReg})] ] = regs->[(${config.initalSp})]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. major: As we just hardcode the |
||
|
|
||
| ts->stack_base = info->start_stack; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| syscall_nr_generators += { | ||
| 'rv64ume': generator(sh, | ||
| '[(${gen_arch_lower})]': generator(sh, | ||
| arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], | ||
| output: '@BASENAME@_nr.h') | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| /* | ||
| * Emulation of Linux signals for rv64ume user-mode. | ||
| * Emulation of Linux signals for [(${gen_arch_lower})] user-mode. | ||
| */ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. major: I think for now, signals are too overwhelming. Let's turn it into a bare minimum implementation that just ensures compilation succeeds. Something like this (although not tested). #include "qemu/osdep.h"
#include "qemu.h"
#include "user-internals.h"
#include "signal-common.h"
void setup_rt_frame(int sig, struct target_sigaction *ka,
target_siginfo_t *info,
target_sigset_t *set, CPU[(${gen_arch_upper})]State *env)
{
(void)ka;
(void)info;
(void)set;
(void)env;
if (sig == TARGET_SIGSEGV) {
force_sig(TARGET_SIGSEGV);
} else {
force_sig(sig);
}
}
long do_rt_sigreturn(CPU[(${gen_arch_upper})]State *env)
{
(void)env;
force_sig(TARGET_SIGSEGV);
return 0;
}
void setup_sigtramp(abi_ulong sigtramp_page)
{
(void)sigtramp_page;
}Also test if it compiles when you are removing the whole content. In that case, do that instead. |
||
|
|
||
| #include "qemu/osdep.h" | ||
|
|
@@ -9,13 +9,16 @@ | |
| #include "linux-user/trace.h" | ||
|
|
||
| /* | ||
| * Minimal sigcontext matching rv64ume state: | ||
| * Minimal sigcontext matching [(${gen_arch_lower})] state: | ||
| * - pc | ||
| * - x1..x31 (x0 is always zero and omitted) | ||
| */ | ||
| struct target_sigcontext { | ||
| abi_long pc; | ||
| abi_long gpr[31]; | ||
| abi_long [(${pc_reg.name_lower})]; | ||
|
|
||
| [# th:each="tensor : ${config.signalStateTensors}"] | ||
| abi_long [(${tensor.name_lower})][ [(${tensor.size})] ]; | ||
| [/] | ||
| }; | ||
|
|
||
| struct target_ucontext { | ||
|
|
@@ -33,7 +36,7 @@ struct target_rt_sigframe { | |
| }; | ||
|
|
||
| static abi_ulong get_sigframe(struct target_sigaction *ka, | ||
| CPURV64UMEState *regs, size_t framesize) | ||
| CPU[(${gen_arch_upper})]State *regs, size_t framesize) | ||
| { | ||
| abi_ulong sp = get_sp_from_cpustate(regs); | ||
|
|
||
|
|
@@ -42,23 +45,25 @@ static abi_ulong get_sigframe(struct target_sigaction *ka, | |
| } | ||
|
|
||
| sp = target_sigsp(sp, ka) - framesize; | ||
| sp &= ~0xf; | ||
| sp &= ~[(${config.stack_align_mask} ?: '0xf')]; | ||
|
|
||
| return sp; | ||
| } | ||
|
|
||
| static void setup_sigcontext(struct target_sigcontext *sc, CPURV64UMEState *env) | ||
| static void setup_sigcontext(struct target_sigcontext *sc, CPU[(${gen_arch_upper})]State *env) | ||
| { | ||
| int i; | ||
|
|
||
| __put_user(env->pc, &sc->pc); | ||
| for (i = 1; i < 32; i++) { | ||
| __put_user(env->x[i], &sc->gpr[i - 1]); | ||
| } | ||
| __put_user(env->[(${pc_reg.name_lower})], &sc->[(${pc_reg.name_lower})]); | ||
| [# th:each="tensor : ${config.signalStateTensors}"] | ||
| for (i = 0; i < [(${tensor.size})]; i++) { | ||
| __put_user(env->[(${tensor.name_lower})][i], &sc->[(${tensor.name_lower})][i]); | ||
| } | ||
| [/] | ||
| } | ||
|
|
||
| static void setup_ucontext(struct target_ucontext *uc, | ||
| CPURV64UMEState *env, target_sigset_t *set) | ||
| CPU[(${gen_arch_upper})]State *env, target_sigset_t *set) | ||
| { | ||
| int i; | ||
|
|
||
|
|
@@ -76,7 +81,7 @@ static void setup_ucontext(struct target_ucontext *uc, | |
|
|
||
| void setup_rt_frame(int sig, struct target_sigaction *ka, | ||
| target_siginfo_t *info, | ||
| target_sigset_t *set, CPURV64UMEState *env) | ||
| target_sigset_t *set, CPU[(${gen_arch_upper})]State *env) | ||
| { | ||
| abi_ulong frame_addr; | ||
| struct target_rt_sigframe *frame; | ||
|
|
@@ -91,12 +96,18 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| setup_ucontext(&frame->uc, env, set); | ||
| frame->info = *info; | ||
|
|
||
| env->pc = ka->_sa_handler; | ||
| env->x[RV64UME_REG_SP] = frame_addr; | ||
| env->x[RV64UME_REG_A0] = sig; | ||
| env->x[RV64UME_REG_A1] = frame_addr + offsetof(struct target_rt_sigframe, info); | ||
| env->x[RV64UME_REG_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc); | ||
| env->x[RV64UME_REG_RA] = default_rt_sigreturn; | ||
| env->[(${pc_reg.name_lower})] = ka->_sa_handler; | ||
| env->[(${config.mainRegisterFile})][ [(${config.spReg})] ] = frame_addr; | ||
| env->[(${config.mainRegisterFile})][ [(${config.args[0]})] ] = sig; | ||
| [# th:if="${#lists.size(config.args) > 1}"] | ||
| env->[(${config.mainRegisterFile})][ [(${config.args[1]})] ] = frame_addr + offsetof(struct target_rt_sigframe, info); | ||
| [/] | ||
| [# th:if="${#lists.size(config.args) > 2}"] | ||
| env->[(${config.mainRegisterFile})][ [(${config.args[2]})] ] = frame_addr + offsetof(struct target_rt_sigframe, uc); | ||
| [/] | ||
| [# th:if="${config.raReg != null}"] | ||
| env->[(${config.mainRegisterFile})][ [(${config.raReg})] ] = default_rt_sigreturn; | ||
| [/] | ||
|
|
||
| return; | ||
|
|
||
|
|
@@ -108,17 +119,19 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| force_sig(TARGET_SIGSEGV); | ||
| } | ||
|
|
||
| static void restore_sigcontext(CPURV64UMEState *env, struct target_sigcontext *sc) | ||
| static void restore_sigcontext(CPU[(${gen_arch_upper})]State *env, struct target_sigcontext *sc) | ||
| { | ||
| int i; | ||
|
|
||
| __get_user(env->pc, &sc->pc); | ||
| for (i = 1; i < 32; ++i) { | ||
| __get_user(env->x[i], &sc->gpr[i - 1]); | ||
| __get_user(env->[(${pc_reg.name_lower})], &sc->[(${pc_reg.name_lower})]); | ||
| [# th:each="tensor : ${config.signalStateTensors}"] | ||
| for (i = 0; i < [(${tensor.size})]; i++) { | ||
| __get_user(env->[(${tensor.name_lower})][i], &sc->[(${tensor.name_lower})][i]); | ||
| } | ||
| [/] | ||
| } | ||
|
|
||
| static void restore_ucontext(CPURV64UMEState *env, struct target_ucontext *uc) | ||
| static void restore_ucontext(CPU[(${gen_arch_upper})]State *env, struct target_ucontext *uc) | ||
| { | ||
| sigset_t blocked; | ||
| target_sigset_t target_set; | ||
|
|
@@ -135,12 +148,12 @@ static void restore_ucontext(CPURV64UMEState *env, struct target_ucontext *uc) | |
| restore_sigcontext(env, &uc->uc_mcontext); | ||
| } | ||
|
|
||
| long do_rt_sigreturn(CPURV64UMEState *env) | ||
| long do_rt_sigreturn(CPU[(${gen_arch_upper})]State *env) | ||
| { | ||
| struct target_rt_sigframe *frame; | ||
| abi_ulong frame_addr; | ||
|
|
||
| frame_addr = env->x[RV64UME_REG_SP]; | ||
| frame_addr = env->[(${config.mainRegisterFile})][ [(${config.spReg})] ]; | ||
| trace_user_do_sigreturn(env, frame_addr); | ||
| if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { | ||
| goto badframe; | ||
|
|
@@ -163,8 +176,8 @@ void setup_sigtramp(abi_ulong sigtramp_page) | |
| uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0); | ||
| assert(tramp != NULL); | ||
|
|
||
| __put_user(0x08b00893, tramp + 0); /* li a7, 139 = __NR_rt_sigreturn */ | ||
| __put_user(0x00000073, tramp + 1); /* ecall */ | ||
| __put_user([(${config.sigtrampLoadSyscallInstr})], tramp + 0); /* load rt_sigreturn syscall number */ | ||
| __put_user([(${config.sigtrampTrapInstr})], tramp + 1); /* syscall/trap instruction */ | ||
|
|
||
| default_rt_sigreturn = sigtramp_page; | ||
| unlock_user(tramp, sigtramp_page, 8); | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor: This whole table is currently hardcoded. However, I think we should do the dynamic interpolation in a separate PR. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,40 +1,38 @@ | ||
| #ifndef RV64UME_TARGET_CPU_H | ||
| #define RV64UME_TARGET_CPU_H | ||
| #ifndef [(${gen_arch_upper})]_TARGET_CPU_H | ||
| #define [(${gen_arch_upper})]_TARGET_CPU_H | ||
|
|
||
| //TODO: check for correct interpolattions for regs & values | ||
| enum { | ||
| RV64UME_REG_RA = 1, | ||
| RV64UME_REG_SP = 2, | ||
| RV64UME_REG_TP = 4, | ||
| RV64UME_REG_A0 = 10, | ||
| RV64UME_REG_A1 = 11, | ||
| RV64UME_REG_A2 = 12, | ||
| RV64UME_REG_A3 = 13, | ||
| RV64UME_REG_A4 = 14, | ||
| RV64UME_REG_A5 = 15, | ||
| RV64UME_REG_A7 = 17, | ||
| [(${gen_arch_upper})]_REG_RA = [(${config.raReg})], | ||
| [(${gen_arch_upper})]_REG_SP = [(${config.spReg})], | ||
| [(${gen_arch_upper})]_REG_TP = [(${config.tpReg})], | ||
|
|
||
| [# th:each="arg, stat : ${config.args}"] | ||
| [(${gen_arch_upper})]_REG_ARG[(${stat.index})] = [(${arg})], | ||
| [/] | ||
| }; | ||
|
|
||
| static inline void cpu_clone_regs_child(CPURV64UMEState *env, target_ulong newsp, | ||
| static inline void cpu_clone_regs_child(CPU[(${gen_arch_upper})]State *env, target_ulong newsp, | ||
| unsigned flags) | ||
| { | ||
| if (newsp) { | ||
| env->x[RV64UME_REG_SP] = newsp; | ||
| env->[(${register_tensors[0].name_lower})][ [(${gen_arch_upper})]_REG_SP] = newsp; | ||
| } | ||
|
|
||
| env->x[RV64UME_REG_A0] = 0; | ||
| env->[(${register_tensors[0].name_lower})][ [(${config.retReg})] ] = 0; | ||
| } | ||
|
|
||
| static inline void cpu_clone_regs_parent(CPURV64UMEState *env, unsigned flags) | ||
| static inline void cpu_clone_regs_parent(CPU[(${gen_arch_upper})]State *env, unsigned flags) | ||
| { | ||
| } | ||
|
|
||
| static inline void cpu_set_tls(CPURV64UMEState *env, target_ulong newtls) | ||
| static inline void cpu_set_tls(CPU[(${gen_arch_upper})]State *env, target_ulong newtls) | ||
| { | ||
| env->x[RV64UME_REG_TP] = newtls; | ||
| env->[(${register_tensors[0].name_lower})][ [(${gen_arch_upper})]_REG_TP] = newtls; | ||
| } | ||
|
|
||
| static inline abi_ulong get_sp_from_cpustate(CPURV64UMEState *state) | ||
| static inline abi_ulong get_sp_from_cpustate(CPU[(${gen_arch_upper})]State *state) | ||
| { | ||
| return state->x[RV64UME_REG_SP]; | ||
| return state->[(${register_tensors[0].name_lower})][ [(${gen_arch_upper})]_REG_SP]; | ||
| } | ||
| #endif |
Uh oh!
There was an error while loading. Please reload this page.