Implementation of linux user emulation for RISC-V.
Signed-off-by: Michael Clark
---
linux-user/elfload.c | 22 +++
linux-user/main.c | 130 -
linux-user/riscv/syscall_nr.h | 275 +++
linux-user/riscv/target_cpu.h | 18 +++
linux-user/riscv/target_signal.h | 23 +++
linux-user/riscv/target_structs.h | 46 ++
linux-user/riscv/target_syscall.h | 56
linux-user/riscv/termbits.h | 220
linux-user/signal.c | 260 ++
linux-user/syscall.c | 2 +
linux-user/syscall_defs.h | 13 +-
target/riscv/cpu_user.h | 29
target/riscv/user_atomic.c| 291 ++
target/riscv/user_syscall.c | 40 ++
14 files changed, 1387 insertions(+), 38 deletions(-)
create mode 100644 linux-user/riscv/syscall_nr.h
create mode 100644 linux-user/riscv/target_cpu.h
create mode 100644 linux-user/riscv/target_signal.h
create mode 100644 linux-user/riscv/target_structs.h
create mode 100644 linux-user/riscv/target_syscall.h
create mode 100644 linux-user/riscv/termbits.h
create mode 100644 target/riscv/cpu_user.h
create mode 100644 target/riscv/user_atomic.c
create mode 100644 target/riscv/user_syscall.c
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 20f3d8c..178af56 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1272,6 +1272,28 @@ static inline void init_thread(struct target_pt_regs
*regs,
#endif /* TARGET_TILEGX */
+#ifdef TARGET_RISCV
+
+#define ELF_START_MMAP 0x8000
+#define ELF_ARCH EM_RISCV
+
+#ifdef TARGET_RISCV32
+#define ELF_CLASS ELFCLASS32
+#else
+#define ELF_CLASS ELFCLASS64
+#endif
+
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
+{
+regs->sepc = infop->entry;
+regs->sp = infop->start_stack;
+}
+
+#define ELF_EXEC_PAGESIZE 4096
+
+#endif /* TARGET_RISCV */
+
#ifdef TARGET_HPPA
#define ELF_START_MMAP 0x8000
diff --git a/linux-user/main.c b/linux-user/main.c
index 71696ed..8900141 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -227,7 +227,7 @@ void cpu_loop(CPUX86State *env)
cpu_exec_end(cs);
process_queued_cpu_work(cs);
-switch(trapnr) {
+switch (trapnr) {
case 0x80:
/* linux syscall from int $0x80 */
ret = do_syscall(env,
@@ -585,7 +585,7 @@ void cpu_loop(CPUARMState *env)
cpu_exec_end(cs);
process_queued_cpu_work(cs);
-switch(trapnr) {
+switch (trapnr) {
case EXCP_UDEF:
case EXCP_NOCP:
case EXCP_INVSTATE:
@@ -1379,7 +1379,7 @@ void cpu_loop(CPUPPCState *env)
cpu_exec_end(cs);
process_queued_cpu_work(cs);
-switch(trapnr) {
+switch (trapnr) {
case POWERPC_EXCP_NONE:
/* Just go on */
break;
@@ -2251,7 +2251,7 @@ void cpu_loop(CPUMIPSState *env)
cpu_exec_end(cs);
process_queued_cpu_work(cs);
-switch(trapnr) {
+switch (trapnr) {
case EXCP_SYSCALL:
env->active_tc.PC += 4;
# ifdef TARGET_ABI_MIPSO32
@@ -2957,7 +2957,7 @@ void cpu_loop(CPUM68KState *env)
cpu_exec_end(cs);
process_queued_cpu_work(cs);
-switch(trapnr) {
+switch (trapnr) {
case EXCP_ILLEGAL:
{
if (ts->sim_syscalls) {
@@ -3640,6 +3640,121 @@ void cpu_loop(CPUTLGState *env)
#endif
+#ifdef TARGET_RISCV
+
+void cpu_loop(CPURISCVState *env)
+{
+CPUState *cs = CPU(riscv_env_get_cpu(env));
+int trapnr, signum, sigcode;
+target_ulong sigaddr;
+target_ulong ret;
+
+for (;;) {
+cpu_exec_start(cs);
+trapnr = cpu_exec(cs);
+cpu_exec_end(cs);
+
+signum = 0;
+sigcode = 0;
+sigaddr = 0;
+
+switch (trapnr) {
+case EXCP_INTERRUPT:
+/* just indicate that signals should be handled asap */
+break;
+case RISCV_EXCP_U_ECALL:
+env->pc += 4;
+if (env->gpr[xA7] == TARGET_NR_arch_specific_syscall + 15) {
+/* kernel-assisted AMO not suitable for do_syscall */
+start_exclusive();
+ret = riscv_flush_icache_syscall(env,
+ env->gpr[xA7],
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+ env->gpr[xA3]);
+end_exclusive();
+} else {
+ret = do_syscall(env,
+ env->gpr[xA7],
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+