summary refs log tree commit diff stats
path: root/linux-user/nios2/cpu_loop.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-04-26 13:12:37 -0700
committerRichard Henderson <richard.henderson@linaro.org>2022-04-26 13:12:37 -0700
commit88d5814e6b02515f823086abb91dc7cdbb31c9f1 (patch)
treedcce7c9d3f084a14aca85dcef4feb65ff63a48a3 /linux-user/nios2/cpu_loop.c
parenteab18e4021b80a03729424385c506e2454cd635c (diff)
parent7f176c5a0bcb70492f3b158a36311e75f1eb87d7 (diff)
downloadfocaccia-qemu-88d5814e6b02515f823086abb91dc7cdbb31c9f1.tar.gz
focaccia-qemu-88d5814e6b02515f823086abb91dc7cdbb31c9f1.zip
Merge tag 'pull-nios2-20220426' of https://gitlab.com/rth7680/qemu into staging
Fix nios2-linux-user syscalls.
Fix nios2-linux-user sigreturn.
Enable tests for nios2-linux-user.
Remove special handling of SIGSEGV.
Check supervisor for eret, bret.
Split special registers out of env->regs[].
Clean up interrupt processing.
Raise unaligned data and destination exceptions.
Set TLBMISC fields correctly on exceptions.
Prevent writes to read-only or reserved control fields.
Use tcg_constant_tl().
Implement shadow register sets.
Implement external interrupt controller interface.
Implement vectored interrupt controller.
Enable semihosting tests for nios2-softmmu.

# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmJoNuQdHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+a0ggAhawc3tod4OTHRlRq
# rvZrJK740bNMo8rtidDnh71+IGjBiz8pXahqkE78cADtMzNmQoScwWbjht3cuMN2
# TMV0sbNDeA2OB98QzX6JTbCRtEfQAB7pyjpFvg6oXhYYSfwwhWbTR9QsYTHjq157
# ZKOprafoSlmDlgWJhlAikLdvJb07/5jgmvsLbBzu8/G/HiJ4HhHyjZxL1wNz1t/+
# 0KTAbnn3SWGDAhLGS/P6BMZKeU1EAExAwo7CtZeUbs+9QCfeM3cBAurG3WB1Vw14
# ERPoGPPrARtoNPtgQFMHu0am3HH5HtneuzJfWaLT96rrwNyTrYY0EYti1NtFDW8O
# CCz42Q==
# =MHar
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 26 Apr 2022 11:16:04 AM PDT
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate]

* tag 'pull-nios2-20220426' of https://gitlab.com/rth7680/qemu: (68 commits)
  tests/tcg/nios2: Add test-shadow-1
  tests/tcg/nios2: Add semihosting multiarch tests
  hw/nios2: Machine with a Vectored Interrupt Controller
  hw/nios2: Move memory regions into Nios2Machine
  hw/nios2: Introduce Nios2MachineState
  hw/intc: Vectored Interrupt Controller (VIC)
  linux-user/nios2: Handle various SIGILL exceptions
  target/nios2: Advance pc when raising exceptions
  target/nios2: Implement EIC interrupt processing
  target/nios2: Update helper_eret for shadow registers
  target/nios2: Implement rdprs, wrprs
  target/nios2: Introduce shadow register sets
  target/nios2: Implement Misaligned destination exception
  target/nios2: Use tcg_gen_lookup_and_goto_ptr
  target/nios2: Use gen_goto_tb for DISAS_TOO_MANY
  target/nios2: Hoist set of is_jmp into gen_goto_tb
  target/nios2: Create gen_jumpr
  target/nios2: Enable unaligned traps for system mode
  target/nios2: Drop CR_STATUS_EH from tb->flags
  target/nios2: Introduce dest_gpr
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user/nios2/cpu_loop.c')
-rw-r--r--linux-user/nios2/cpu_loop.c96
1 files changed, 46 insertions, 50 deletions
diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
index 1e93ef34e6..da77ede76b 100644
--- a/linux-user/nios2/cpu_loop.c
+++ b/linux-user/nios2/cpu_loop.c
@@ -26,7 +26,6 @@
 void cpu_loop(CPUNios2State *env)
 {
     CPUState *cs = env_cpu(env);
-    target_siginfo_t info;
     int trapnr, ret;
 
     for (;;) {
@@ -39,6 +38,30 @@ void cpu_loop(CPUNios2State *env)
             /* just indicate that signals should be handled asap */
             break;
 
+        case EXCP_DIV:
+            /* Match kernel's handle_diverror_c(). */
+            env->pc -= 4;
+            force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc);
+            break;
+
+        case EXCP_UNALIGN:
+        case EXCP_UNALIGND:
+            force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN,
+                            env->ctrl[CR_BADADDR]);
+            break;
+
+        case EXCP_ILLEGAL:
+        case EXCP_UNIMPL:
+            /* Match kernel's handle_illegal_c(). */
+            env->pc -= 4;
+            force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
+            break;
+        case EXCP_SUPERI:
+            /* Match kernel's handle_supervisor_instr(). */
+            env->pc -= 4;
+            force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc);
+            break;
+
         case EXCP_TRAP:
             switch (env->error_code) {
             case 0:
@@ -49,32 +72,41 @@ void cpu_loop(CPUNios2State *env)
                                  env->regs[7], env->regs[8], env->regs[9],
                                  0, 0);
 
-                if (env->regs[2] == 0) {    /* FIXME: syscall 0 workaround */
-                    ret = 0;
+                if (ret == -QEMU_ESIGRETURN) {
+                    /* rt_sigreturn has set all state. */
+                    break;
                 }
-
+                if (ret == -QEMU_ERESTARTSYS) {
+                    env->pc -= 4;
+                    break;
+                }
+                /*
+                 * See the code after translate_rc_and_ret: all negative
+                 * values are errors (aided by userspace restricted to 2G),
+                 * errno is returned positive in r2, and error indication
+                 * is a boolean in r7.
+                 */
                 env->regs[2] = abs(ret);
-                /* Return value is 0..4096 */
-                env->regs[7] = ret > 0xfffff000u;
-                env->regs[R_PC] += 4;
+                env->regs[7] = ret < 0;
                 break;
 
             case 1:
                 qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n");
-                force_sig_fault(TARGET_SIGUSR1, 0, env->regs[R_PC]);
+                force_sig_fault(TARGET_SIGUSR1, 0, env->pc);
                 break;
             case 2:
                 qemu_log_mask(CPU_LOG_INT, "\nTrap 2\n");
-                force_sig_fault(TARGET_SIGUSR2, 0, env->regs[R_PC]);
+                force_sig_fault(TARGET_SIGUSR2, 0, env->pc);
                 break;
             case 31:
                 qemu_log_mask(CPU_LOG_INT, "\nTrap 31\n");
-                force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->regs[R_PC]);
+                /* Match kernel's breakpoint_c(). */
+                env->pc -= 4;
+                force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
                 break;
             default:
                 qemu_log_mask(CPU_LOG_INT, "\nTrap %d\n", env->error_code);
-                force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
-                                env->regs[R_PC]);
+                force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP, env->pc);
                 break;
 
             case 16: /* QEMU specific, for __kuser_cmpxchg */
@@ -99,27 +131,13 @@ void cpu_loop(CPUNios2State *env)
                     o = env->regs[5];
                     n = env->regs[6];
                     env->regs[2] = qatomic_cmpxchg(h, o, n) - o;
-                    env->regs[R_PC] += 4;
                 }
                 break;
             }
             break;
 
         case EXCP_DEBUG:
-            info.si_signo = TARGET_SIGTRAP;
-            info.si_errno = 0;
-            info.si_code = TARGET_TRAP_BRKPT;
-            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
-            break;
-        case 0xaa:
-            {
-                info.si_signo = TARGET_SIGSEGV;
-                info.si_errno = 0;
-                /* TODO: check env->error_code */
-                info.si_code = TARGET_SEGV_MAPERR;
-                info._sifields._sigfault._addr = env->regs[R_PC];
-                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
-            }
+            force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
             break;
         default:
             EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
@@ -133,28 +151,6 @@ void cpu_loop(CPUNios2State *env)
 
 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
 {
-    env->regs[0] = 0;
-    env->regs[1] = regs->r1;
-    env->regs[2] = regs->r2;
-    env->regs[3] = regs->r3;
-    env->regs[4] = regs->r4;
-    env->regs[5] = regs->r5;
-    env->regs[6] = regs->r6;
-    env->regs[7] = regs->r7;
-    env->regs[8] = regs->r8;
-    env->regs[9] = regs->r9;
-    env->regs[10] = regs->r10;
-    env->regs[11] = regs->r11;
-    env->regs[12] = regs->r12;
-    env->regs[13] = regs->r13;
-    env->regs[14] = regs->r14;
-    env->regs[15] = regs->r15;
-    /* TODO: unsigned long  orig_r2; */
-    env->regs[R_RA] = regs->ra;
-    env->regs[R_FP] = regs->fp;
     env->regs[R_SP] = regs->sp;
-    env->regs[R_GP] = regs->gp;
-    env->regs[CR_ESTATUS] = regs->estatus;
-    env->regs[R_PC] = regs->ea;
-    /* TODO: unsigned long  orig_r7; */
+    env->pc = regs->ea;
 }