All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/7] linux-user: nios2 fixes
@ 2021-12-21  2:50 Richard Henderson
  2021-12-21  2:50 ` [PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Richard Henderson @ 2021-12-21  2:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Fixes syscalls and signals for nios2.
Works with the docker cross-compile toolchain that has been committed.

r~

Richard Henderson (7):
  linux-user/nios2: Properly emulate EXCP_TRAP
  linux-user/nios2: Fixes for signal frame setup
  linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE
  linux-user/nios2: Map a real kuser page
  linux-user/nios2: Fix EA vs PC confusion
  linux-user/nios2: Fix sigmask in setup_rt_frame
  linux-user/nios2: Use set_sigmask in do_rt_sigreturn

 target/nios2/cpu.h          |  2 +-
 linux-user/elfload.c        | 66 ++++++++++++++++++++++----
 linux-user/nios2/cpu_loop.c | 93 +++++++++++++++++++------------------
 linux-user/nios2/signal.c   | 56 +++++++++-------------
 linux-user/signal.c         |  2 -
 target/nios2/translate.c    | 26 +++++++----
 6 files changed, 146 insertions(+), 99 deletions(-)

-- 
2.25.1



^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP
  2021-12-21  2:50 [PATCH v2 0/7] linux-user: nios2 fixes Richard Henderson
@ 2021-12-21  2:50 ` Richard Henderson
  2021-12-22 18:52   ` Laurent Vivier
  2022-01-05 10:23   ` Laurent Vivier
  2021-12-21  2:50 ` [PATCH v2 2/7] linux-user/nios2: Fixes for signal frame setup Richard Henderson
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 18+ messages in thread
From: Richard Henderson @ 2021-12-21  2:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alex Bennée, laurent

The real kernel has to load the instruction and extract
the imm5 field; for qemu, modify the translator to do this.

The use of R_AT for this in cpu_loop was a bug.  Handle
the other trap numbers as per the kernel's trap_table.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/nios2/cpu.h          |  2 +-
 linux-user/nios2/cpu_loop.c | 40 ++++++++++++++++++++-----------------
 target/nios2/translate.c    | 17 +++++++++++++++-
 3 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 1a69ed7a49..d2ba0c5bbd 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -160,9 +160,9 @@ struct CPUNios2State {
 
 #if !defined(CONFIG_USER_ONLY)
     Nios2MMU mmu;
-
     uint32_t irq_pending;
 #endif
+    int error_code;
 };
 
 /**
diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
index 34290fb3b5..5c3d01d22d 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);
-    Nios2CPU *cpu = NIOS2_CPU(cs);
     target_siginfo_t info;
     int trapnr, ret;
 
@@ -39,9 +38,10 @@ void cpu_loop(CPUNios2State *env)
         case EXCP_INTERRUPT:
             /* just indicate that signals should be handled asap */
             break;
+
         case EXCP_TRAP:
-            if (env->regs[R_AT] == 0) {
-                abi_long ret;
+            switch (env->error_code) {
+            case 0:
                 qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
 
                 ret = do_syscall(env, env->regs[2],
@@ -55,26 +55,30 @@ void cpu_loop(CPUNios2State *env)
 
                 env->regs[2] = abs(ret);
                 /* Return value is 0..4096 */
-                env->regs[7] = (ret > 0xfffffffffffff000ULL);
-                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
-                env->regs[CR_STATUS] &= ~0x3;
-                env->regs[R_EA] = env->regs[R_PC] + 4;
+                env->regs[7] = ret > 0xfffff000u;
                 env->regs[R_PC] += 4;
                 break;
-            } else {
-                qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
 
-                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
-                env->regs[CR_STATUS] &= ~0x3;
-                env->regs[R_EA] = env->regs[R_PC] + 4;
-                env->regs[R_PC] = cpu->exception_addr;
-
-                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);
+            case 1:
+                qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n");
+                force_sig_fault(TARGET_SIGUSR1, 0, env->regs[R_PC]);
+                break;
+            case 2:
+                qemu_log_mask(CPU_LOG_INT, "\nTrap 2\n");
+                force_sig_fault(TARGET_SIGUSR2, 0, env->regs[R_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]);
+                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]);
                 break;
             }
+            break;
+
         case EXCP_DEBUG:
             info.si_signo = TARGET_SIGTRAP;
             info.si_errno = 0;
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 08d7ac5398..a759877519 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -636,6 +636,21 @@ static void divu(DisasContext *dc, uint32_t code, uint32_t flags)
     tcg_temp_free(t0);
 }
 
+static void trap(DisasContext *dc, uint32_t code, uint32_t flags)
+{
+#ifdef CONFIG_USER_ONLY
+    /*
+     * The imm5 field is not stored anywhere on real hw; the kernel
+     * has to load the insn and extract the field.  But we can make
+     * things easier for cpu_loop if we pop this into env->error_code.
+     */
+    R_TYPE(instr, code);
+    tcg_gen_st_i32(tcg_constant_i32(instr.imm5), cpu_env,
+                   offsetof(CPUNios2State, error_code));
+#endif
+    t_gen_helper_raise_exception(dc, EXCP_TRAP);
+}
+
 static const Nios2Instruction r_type_instructions[] = {
     INSTRUCTION_ILLEGAL(),
     INSTRUCTION(eret),                                /* eret */
@@ -682,7 +697,7 @@ static const Nios2Instruction r_type_instructions[] = {
     INSTRUCTION_ILLEGAL(),
     INSTRUCTION_ILLEGAL(),
     INSTRUCTION_ILLEGAL(),
-    INSTRUCTION_FLG(gen_excp, EXCP_TRAP),             /* trap */
+    INSTRUCTION(trap),                                /* trap */
     INSTRUCTION(wrctl),                               /* wrctl */
     INSTRUCTION_ILLEGAL(),
     INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU),         /* cmpltu */
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 2/7] linux-user/nios2: Fixes for signal frame setup
  2021-12-21  2:50 [PATCH v2 0/7] linux-user: nios2 fixes Richard Henderson
  2021-12-21  2:50 ` [PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
@ 2021-12-21  2:50 ` Richard Henderson
  2022-01-05 10:23   ` Laurent Vivier
  2021-12-21  2:50 ` [PATCH v2 3/7] linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE Richard Henderson
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Richard Henderson @ 2021-12-21  2:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Alex Bennée, laurent

Do not confuse host and guest addresses.  Lock and unlock
the target_rt_sigframe structure in setup_rt_sigframe.

Since rt_setup_ucontext always returns 0, drop the return
value entirely.  This eliminates the only write to the err
variable in setup_rt_sigframe.

Always copy the siginfo structure.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/nios2/signal.c | 49 ++++++++++++++++-----------------------
 1 file changed, 20 insertions(+), 29 deletions(-)

diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
index a77e8a40f4..adbffe32e3 100644
--- a/linux-user/nios2/signal.c
+++ b/linux-user/nios2/signal.c
@@ -42,7 +42,7 @@ struct target_rt_sigframe {
     struct target_ucontext uc;
 };
 
-static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
+static void rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
 {
     unsigned long *gregs = uc->tuc_mcontext.gregs;
 
@@ -75,8 +75,6 @@ static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
     __put_user(env->regs[R_GP], &gregs[25]);
     __put_user(env->regs[R_EA], &gregs[27]);
     __put_user(env->regs[R_SP], &gregs[28]);
-
-    return 0;
 }
 
 static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
@@ -135,8 +133,8 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
     return 0;
 }
 
-static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
-                          size_t frame_size)
+static abi_ptr get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
+                            size_t frame_size)
 {
     unsigned long usp;
 
@@ -144,7 +142,7 @@ static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
     usp = target_sigsp(get_sp_from_cpustate(env), ka);
 
     /* Verify, is it 32 or 64 bit aligned */
-    return (void *)((usp - frame_size) & -8UL);
+    return (usp - frame_size) & -8;
 }
 
 void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -153,26 +151,25 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
                     CPUNios2State *env)
 {
     struct target_rt_sigframe *frame;
-    int i, err = 0;
+    abi_ptr frame_addr;
+    int i;
 
-    frame = get_sigframe(ka, env, sizeof(*frame));
-
-    if (ka->sa_flags & SA_SIGINFO) {
-        tswap_siginfo(&frame->info, info);
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        force_sigsegv(sig);
+        return;
     }
 
+    tswap_siginfo(&frame->info, info);
+
     /* Create the ucontext.  */
     __put_user(0, &frame->uc.tuc_flags);
     __put_user(0, &frame->uc.tuc_link);
     target_save_altstack(&frame->uc.tuc_stack, env);
-    err |= rt_setup_ucontext(&frame->uc, env);
+    rt_setup_ucontext(&frame->uc, env);
     for (i = 0; i < TARGET_NSIG_WORDS; i++) {
         __put_user((abi_ulong)set->sig[i],
-            (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
-    }
-
-    if (err) {
-        goto give_sigsegv;
+                   (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
     }
 
     /* Set up to return from userspace; jump to fixed address sigreturn
@@ -180,19 +177,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     env->regs[R_RA] = (unsigned long) (0x1044);
 
     /* Set up registers for signal handler */
-    env->regs[R_SP] = (unsigned long) frame;
-    env->regs[4] = (unsigned long) sig;
-    env->regs[5] = (unsigned long) &frame->info;
-    env->regs[6] = (unsigned long) &frame->uc;
-    env->regs[R_EA] = (unsigned long) ka->_sa_handler;
-    return;
+    env->regs[R_SP] = frame_addr;
+    env->regs[4] = sig;
+    env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info);
+    env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc);
+    env->regs[R_EA] = ka->_sa_handler;
 
-give_sigsegv:
-    if (sig == TARGET_SIGSEGV) {
-        ka->_sa_handler = TARGET_SIG_DFL;
-    }
-    force_sigsegv(sig);
-    return;
+    unlock_user_struct(frame, frame_addr, 1);
 }
 
 long do_sigreturn(CPUNios2State *env)
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 3/7] linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE
  2021-12-21  2:50 [PATCH v2 0/7] linux-user: nios2 fixes Richard Henderson
  2021-12-21  2:50 ` [PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
  2021-12-21  2:50 ` [PATCH v2 2/7] linux-user/nios2: Fixes for signal frame setup Richard Henderson
@ 2021-12-21  2:50 ` Richard Henderson
  2022-01-05 10:24   ` Laurent Vivier
  2021-12-21  2:50 ` [PATCH v2 4/7] linux-user/nios2: Map a real kuser page Richard Henderson
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Richard Henderson @ 2021-12-21  2:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Arm will no longer be the only target requiring a commpage,
but it will continue to be the only target placing the page
at the high end of the address space.

Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 767f54c76d..d34cd4fe43 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -390,11 +390,11 @@ enum {
 
 /* The commpage only exists for 32 bit kernels */
 
-#define ARM_COMMPAGE (intptr_t)0xffff0f00u
+#define HI_COMMPAGE (intptr_t)0xffff0f00u
 
 static bool init_guest_commpage(void)
 {
-    void *want = g2h_untagged(ARM_COMMPAGE & -qemu_host_page_size);
+    void *want = g2h_untagged(HI_COMMPAGE & -qemu_host_page_size);
     void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
                       MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
 
@@ -2160,8 +2160,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     return sp;
 }
 
-#ifndef ARM_COMMPAGE
-#define ARM_COMMPAGE 0
+#ifndef HI_COMMPAGE
+#define HI_COMMPAGE 0
 #define init_guest_commpage() true
 #endif
 
@@ -2361,7 +2361,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
     }
 
     loaddr &= -align;
-    if (ARM_COMMPAGE) {
+    if (HI_COMMPAGE) {
         /*
          * Extend the allocation to include the commpage.
          * For a 64-bit host, this is just 4GiB; for a 32-bit host we
@@ -2372,14 +2372,14 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
         if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) {
             hiaddr = (uintptr_t) 4 << 30;
         } else {
-            offset = -(ARM_COMMPAGE & -align);
+            offset = -(HI_COMMPAGE & -align);
         }
     }
 
     addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset);
     if (addr == -1) {
         /*
-         * If ARM_COMMPAGE, there *might* be a non-consecutive allocation
+         * If HI_COMMPAGE, there *might* be a non-consecutive allocation
          * that can satisfy both.  But as the normal arm32 link base address
          * is ~32k, and we extend down to include the commpage, making the
          * overhead only ~96k, this is unlikely.
@@ -2400,7 +2400,7 @@ static void pgb_dynamic(const char *image_name, long align)
      * All we need is a commpage that satisfies align.
      * If we do not need a commpage, leave guest_base == 0.
      */
-    if (ARM_COMMPAGE) {
+    if (HI_COMMPAGE) {
         uintptr_t addr, commpage;
 
         /* 64-bit hosts should have used reserved_va. */
@@ -2410,7 +2410,7 @@ static void pgb_dynamic(const char *image_name, long align)
          * By putting the commpage at the first hole, that puts guest_base
          * just above that, and maximises the positive guest addresses.
          */
-        commpage = ARM_COMMPAGE & -align;
+        commpage = HI_COMMPAGE & -align;
         addr = pgb_find_hole(commpage, -commpage, align, 0);
         assert(addr != -1);
         guest_base = addr;
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 4/7] linux-user/nios2: Map a real kuser page
  2021-12-21  2:50 [PATCH v2 0/7] linux-user: nios2 fixes Richard Henderson
                   ` (2 preceding siblings ...)
  2021-12-21  2:50 ` [PATCH v2 3/7] linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE Richard Henderson
@ 2021-12-21  2:50 ` Richard Henderson
  2021-12-22 20:18   ` Laurent Vivier
  2022-01-05 10:24   ` Laurent Vivier
  2021-12-21  2:50 ` [PATCH v2 5/7] linux-user/nios2: Fix EA vs PC confusion Richard Henderson
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 18+ messages in thread
From: Richard Henderson @ 2021-12-21  2:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

The first word of page1 is data, so the whole thing
can't be implemented with emulation of addresses.
Use init_guest_commpage for the allocation.

Hijack trap number 16 to implement cmpxchg.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c        | 50 ++++++++++++++++++++++++++++++++++++-
 linux-user/nios2/cpu_loop.c | 50 ++++++++++++++++++++-----------------
 target/nios2/translate.c    |  9 -------
 3 files changed, 76 insertions(+), 33 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index d34cd4fe43..329b2375ef 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1099,6 +1099,47 @@ static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
     regs->estatus = 0x3;
 }
 
+#define LO_COMMPAGE  TARGET_PAGE_SIZE
+
+static bool init_guest_commpage(void)
+{
+    static const uint8_t kuser_page[4 + 2 * 64] = {
+        /* __kuser_helper_version */
+        [0x00] = 0x02, 0x00, 0x00, 0x00,
+
+        /* __kuser_cmpxchg */
+        [0x04] = 0x3a, 0x6c, 0x3b, 0x00,  /* trap 16 */
+                 0x3a, 0x28, 0x00, 0xf8,  /* ret */
+
+        /* __kuser_sigtramp */
+        [0x44] = 0xc4, 0x22, 0x80, 0x00,  /* movi r2, __NR_rt_sigreturn */
+                 0x3a, 0x68, 0x3b, 0x00,  /* trap 0 */
+    };
+
+    void *want = g2h_untagged(LO_COMMPAGE & -qemu_host_page_size);
+    void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
+                      MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
+
+    if (addr == MAP_FAILED) {
+        perror("Allocating guest commpage");
+        exit(EXIT_FAILURE);
+    }
+    if (addr != want) {
+        return false;
+    }
+
+    memcpy(addr, kuser_page, sizeof(kuser_page));
+
+    if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
+        perror("Protecting guest commpage");
+        exit(EXIT_FAILURE);
+    }
+
+    page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE,
+                   PAGE_READ | PAGE_EXEC | PAGE_VALID);
+    return true;
+}
+
 #define ELF_EXEC_PAGESIZE        4096
 
 #define USE_ELF_CORE_DUMP
@@ -2160,8 +2201,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     return sp;
 }
 
-#ifndef HI_COMMPAGE
+#if defined(HI_COMMPAGE)
+#define LO_COMMPAGE 0
+#elif defined(LO_COMMPAGE)
 #define HI_COMMPAGE 0
+#else
+#define HI_COMMPAGE 0
+#define LO_COMMPAGE 0
 #define init_guest_commpage() true
 #endif
 
@@ -2374,6 +2420,8 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
         } else {
             offset = -(HI_COMMPAGE & -align);
         }
+    } else if (LO_COMMPAGE) {
+        loaddr = MIN(loaddr, LO_COMMPAGE & -align);
     }
 
     addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset);
diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
index 5c3d01d22d..de0fc63e21 100644
--- a/linux-user/nios2/cpu_loop.c
+++ b/linux-user/nios2/cpu_loop.c
@@ -76,6 +76,32 @@ void cpu_loop(CPUNios2State *env)
                 force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
                                 env->regs[R_PC]);
                 break;
+
+            case 16: /* QEMU specific, for __kuser_cmpxchg */
+                {
+                    abi_ptr g = env->regs[4];
+                    uint32_t *h, n, o;
+
+                    if (g & 0x3) {
+                        force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, g);
+                        break;
+                    }
+                    ret = page_get_flags(g);
+                    if (!(ret & PAGE_VALID)) {
+                        force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, g);
+                        break;
+                    }
+                    if (!(ret & PAGE_READ) || !(ret & PAGE_WRITE)) {
+                        force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_ACCERR, g);
+                        break;
+                    }
+                    h = g2h(cs, g);
+                    o = env->regs[5];
+                    n = env->regs[6];
+                    env->regs[2] = qatomic_cmpxchg(h, o, n) - o;
+                    env->regs[R_PC] += 4;
+                }
+                break;
             }
             break;
 
@@ -86,29 +112,7 @@ void cpu_loop(CPUNios2State *env)
             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
             break;
         case 0xaa:
-            switch (env->regs[R_PC]) {
-            /*case 0x1000:*/  /* TODO:__kuser_helper_version */
-            case 0x1004:      /* __kuser_cmpxchg */
-                start_exclusive();
-                if (env->regs[4] & 0x3) {
-                    goto kuser_fail;
-                }
-                ret = get_user_u32(env->regs[2], env->regs[4]);
-                if (ret) {
-                    end_exclusive();
-                    goto kuser_fail;
-                }
-                env->regs[2] -= env->regs[5];
-                if (env->regs[2] == 0) {
-                    put_user_u32(env->regs[6], env->regs[4]);
-                }
-                end_exclusive();
-                env->regs[R_PC] = env->regs[R_RA];
-                break;
-            /*case 0x1040:*/  /* TODO:__kuser_sigtramp */
-            default:
-                ;
-kuser_fail:
+            {
                 info.si_signo = TARGET_SIGSEGV;
                 info.si_errno = 0;
                 /* TODO: check env->error_code */
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index a759877519..f9abc2fdd2 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -795,15 +795,6 @@ static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
     dc->base.pc_next = pc + 4;
 
     /* Decode an instruction */
-
-#if defined(CONFIG_USER_ONLY)
-    /* FIXME: Is this needed ? */
-    if (pc >= 0x1000 && pc < 0x2000) {
-        t_gen_helper_raise_exception(dc, 0xaa);
-        return;
-    }
-#endif
-
     code = cpu_ldl_code(env, pc);
     op = get_opcode(code);
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 5/7] linux-user/nios2: Fix EA vs PC confusion
  2021-12-21  2:50 [PATCH v2 0/7] linux-user: nios2 fixes Richard Henderson
                   ` (3 preceding siblings ...)
  2021-12-21  2:50 ` [PATCH v2 4/7] linux-user/nios2: Map a real kuser page Richard Henderson
@ 2021-12-21  2:50 ` Richard Henderson
  2021-12-22 20:20   ` Laurent Vivier
  2022-01-05 10:24   ` Laurent Vivier
  2021-12-21  2:50 ` [PATCH v2 6/7] linux-user/nios2: Fix sigmask in setup_rt_frame Richard Henderson
  2021-12-21  2:50 ` [PATCH v2 7/7] linux-user/nios2: Use set_sigmask in do_rt_sigreturn Richard Henderson
  6 siblings, 2 replies; 18+ messages in thread
From: Richard Henderson @ 2021-12-21  2:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

The real kernel will talk about the user PC as EA,
because that's where the hardware will have copied it,
and where it expects to put it to then use ERET.
But qemu does not emulate all of the exception stuff
while emulating user-only.  Manipulate PC directly.

This fixes signal entry and return, and eliminates
some slight confusion from target_cpu_copy_regs.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/nios2/cpu_loop.c | 5 +----
 linux-user/nios2/signal.c   | 6 +++---
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
index de0fc63e21..1e93ef34e6 100644
--- a/linux-user/nios2/cpu_loop.c
+++ b/linux-user/nios2/cpu_loop.c
@@ -155,9 +155,6 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
     env->regs[R_SP] = regs->sp;
     env->regs[R_GP] = regs->gp;
     env->regs[CR_ESTATUS] = regs->estatus;
-    env->regs[R_EA] = regs->ea;
-    /* TODO: unsigned long  orig_r7; */
-
-    /* Emulate eret when starting thread. */
     env->regs[R_PC] = regs->ea;
+    /* TODO: unsigned long  orig_r7; */
 }
diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
index adbffe32e3..20b65aa06e 100644
--- a/linux-user/nios2/signal.c
+++ b/linux-user/nios2/signal.c
@@ -73,7 +73,7 @@ static void rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
     __put_user(env->regs[R_RA], &gregs[23]);
     __put_user(env->regs[R_FP], &gregs[24]);
     __put_user(env->regs[R_GP], &gregs[25]);
-    __put_user(env->regs[R_EA], &gregs[27]);
+    __put_user(env->regs[R_PC], &gregs[27]);
     __put_user(env->regs[R_SP], &gregs[28]);
 }
 
@@ -122,7 +122,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
     __get_user(env->regs[R_GP], &gregs[25]);
     /* Not really necessary no user settable bits */
     __get_user(temp, &gregs[26]);
-    __get_user(env->regs[R_EA], &gregs[27]);
+    __get_user(env->regs[R_PC], &gregs[27]);
 
     __get_user(env->regs[R_RA], &gregs[23]);
     __get_user(env->regs[R_SP], &gregs[28]);
@@ -181,7 +181,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     env->regs[4] = sig;
     env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info);
     env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc);
-    env->regs[R_EA] = ka->_sa_handler;
+    env->regs[R_PC] = ka->_sa_handler;
 
     unlock_user_struct(frame, frame_addr, 1);
 }
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 6/7] linux-user/nios2: Fix sigmask in setup_rt_frame
  2021-12-21  2:50 [PATCH v2 0/7] linux-user: nios2 fixes Richard Henderson
                   ` (4 preceding siblings ...)
  2021-12-21  2:50 ` [PATCH v2 5/7] linux-user/nios2: Fix EA vs PC confusion Richard Henderson
@ 2021-12-21  2:50 ` Richard Henderson
  2022-01-05 10:24   ` Laurent Vivier
  2021-12-21  2:50 ` [PATCH v2 7/7] linux-user/nios2: Use set_sigmask in do_rt_sigreturn Richard Henderson
  6 siblings, 1 reply; 18+ messages in thread
From: Richard Henderson @ 2021-12-21  2:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Do not cast the signal mask elements; trust __put_user.

Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/nios2/signal.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
index 20b65aa06e..80e3d42fc9 100644
--- a/linux-user/nios2/signal.c
+++ b/linux-user/nios2/signal.c
@@ -168,8 +168,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     target_save_altstack(&frame->uc.tuc_stack, env);
     rt_setup_ucontext(&frame->uc, env);
     for (i = 0; i < TARGET_NSIG_WORDS; i++) {
-        __put_user((abi_ulong)set->sig[i],
-                   (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
+        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
     }
 
     /* Set up to return from userspace; jump to fixed address sigreturn
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 7/7] linux-user/nios2: Use set_sigmask in do_rt_sigreturn
  2021-12-21  2:50 [PATCH v2 0/7] linux-user: nios2 fixes Richard Henderson
                   ` (5 preceding siblings ...)
  2021-12-21  2:50 ` [PATCH v2 6/7] linux-user/nios2: Fix sigmask in setup_rt_frame Richard Henderson
@ 2021-12-21  2:50 ` Richard Henderson
  2022-01-05 10:24   ` Laurent Vivier
  6 siblings, 1 reply; 18+ messages in thread
From: Richard Henderson @ 2021-12-21  2:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Using do_sigprocmask directly was incorrect, as it will
leave the signal blocked by the outer layers of linux-user.

Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/nios2/signal.c | 2 +-
 linux-user/signal.c       | 2 --
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
index 80e3d42fc9..517cd39270 100644
--- a/linux-user/nios2/signal.c
+++ b/linux-user/nios2/signal.c
@@ -205,7 +205,7 @@ long do_rt_sigreturn(CPUNios2State *env)
     }
 
     target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
-    do_sigprocmask(SIG_SETMASK, &set, NULL);
+    set_sigmask(&set);
 
     if (rt_restore_ucontext(env, &frame->uc, &rval)) {
         goto badframe;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 6d5e5b698c..8cb33a351c 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -258,7 +258,6 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
     return 0;
 }
 
-#if !defined(TARGET_NIOS2)
 /* Just set the guest's signal mask to the specified value; the
  * caller is assumed to have called block_signals() already.
  */
@@ -268,7 +267,6 @@ void set_sigmask(const sigset_t *set)
 
     ts->signal_mask = *set;
 }
-#endif
 
 /* sigaltstack management */
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP
  2021-12-21  2:50 ` [PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
@ 2021-12-22 18:52   ` Laurent Vivier
  2022-01-05 10:23   ` Laurent Vivier
  1 sibling, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2021-12-22 18:52 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: Alex Bennée

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> The real kernel has to load the instruction and extract
> the imm5 field; for qemu, modify the translator to do this.
> 
> The use of R_AT for this in cpu_loop was a bug.  Handle
> the other trap numbers as per the kernel's trap_table.
> 
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/nios2/cpu.h          |  2 +-
>   linux-user/nios2/cpu_loop.c | 40 ++++++++++++++++++++-----------------
>   target/nios2/translate.c    | 17 +++++++++++++++-
>   3 files changed, 39 insertions(+), 20 deletions(-)
> 
> diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
> index 1a69ed7a49..d2ba0c5bbd 100644
> --- a/target/nios2/cpu.h
> +++ b/target/nios2/cpu.h
> @@ -160,9 +160,9 @@ struct CPUNios2State {
>   
>   #if !defined(CONFIG_USER_ONLY)
>       Nios2MMU mmu;
> -
>       uint32_t irq_pending;
>   #endif
> +    int error_code;
>   };
>   
>   /**
> diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
> index 34290fb3b5..5c3d01d22d 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);
> -    Nios2CPU *cpu = NIOS2_CPU(cs);
>       target_siginfo_t info;
>       int trapnr, ret;
>   
> @@ -39,9 +38,10 @@ void cpu_loop(CPUNios2State *env)
>           case EXCP_INTERRUPT:
>               /* just indicate that signals should be handled asap */
>               break;
> +
>           case EXCP_TRAP:
> -            if (env->regs[R_AT] == 0) {
> -                abi_long ret;
> +            switch (env->error_code) {
> +            case 0:
>                   qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
>   
>                   ret = do_syscall(env, env->regs[2],
> @@ -55,26 +55,30 @@ void cpu_loop(CPUNios2State *env)
>   
>                   env->regs[2] = abs(ret);
>                   /* Return value is 0..4096 */
> -                env->regs[7] = (ret > 0xfffffffffffff000ULL);
> -                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
> -                env->regs[CR_STATUS] &= ~0x3;
> -                env->regs[R_EA] = env->regs[R_PC] + 4;

I think this change above deserves more explanation.

I guess CR_ESTATUS is never used in linux-user mode and R_EA is set by nios2_cpu_do_interrupt().

Moreover It doesn't seem supervisor-only instructiond like eret (that uses CR_ESTATUS) generates an 
exception in linux-user mode.

Anyway, it looks good:

Reviewed-by: Laurent Vivier <laurent@vivier.eu>

> +                env->regs[7] = ret > 0xfffff000u;
>                   env->regs[R_PC] += 4;
>                   break;
> -            } else {
> -                qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
>   
> -                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
> -                env->regs[CR_STATUS] &= ~0x3;
> -                env->regs[R_EA] = env->regs[R_PC] + 4;
> -                env->regs[R_PC] = cpu->exception_addr;
> -
> -                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);
> +            case 1:
> +                qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n");
> +                force_sig_fault(TARGET_SIGUSR1, 0, env->regs[R_PC]);
> +                break;
> +            case 2:
> +                qemu_log_mask(CPU_LOG_INT, "\nTrap 2\n");
> +                force_sig_fault(TARGET_SIGUSR2, 0, env->regs[R_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]);
> +                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]);
>                   break;
>               }
> +            break;
> +
>           case EXCP_DEBUG:
>               info.si_signo = TARGET_SIGTRAP;
>               info.si_errno = 0;
> diff --git a/target/nios2/translate.c b/target/nios2/translate.c
> index 08d7ac5398..a759877519 100644
> --- a/target/nios2/translate.c
> +++ b/target/nios2/translate.c
> @@ -636,6 +636,21 @@ static void divu(DisasContext *dc, uint32_t code, uint32_t flags)
>       tcg_temp_free(t0);
>   }
>   
> +static void trap(DisasContext *dc, uint32_t code, uint32_t flags)
> +{
> +#ifdef CONFIG_USER_ONLY
> +    /*
> +     * The imm5 field is not stored anywhere on real hw; the kernel
> +     * has to load the insn and extract the field.  But we can make
> +     * things easier for cpu_loop if we pop this into env->error_code.
> +     */
> +    R_TYPE(instr, code);
> +    tcg_gen_st_i32(tcg_constant_i32(instr.imm5), cpu_env,
> +                   offsetof(CPUNios2State, error_code));
> +#endif
> +    t_gen_helper_raise_exception(dc, EXCP_TRAP);
> +}
> +
>   static const Nios2Instruction r_type_instructions[] = {
>       INSTRUCTION_ILLEGAL(),
>       INSTRUCTION(eret),                                /* eret */
> @@ -682,7 +697,7 @@ static const Nios2Instruction r_type_instructions[] = {
>       INSTRUCTION_ILLEGAL(),
>       INSTRUCTION_ILLEGAL(),
>       INSTRUCTION_ILLEGAL(),
> -    INSTRUCTION_FLG(gen_excp, EXCP_TRAP),             /* trap */
> +    INSTRUCTION(trap),                                /* trap */
>       INSTRUCTION(wrctl),                               /* wrctl */
>       INSTRUCTION_ILLEGAL(),
>       INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU),         /* cmpltu */

Thanks,
Laurent


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 4/7] linux-user/nios2: Map a real kuser page
  2021-12-21  2:50 ` [PATCH v2 4/7] linux-user/nios2: Map a real kuser page Richard Henderson
@ 2021-12-22 20:18   ` Laurent Vivier
  2022-01-05 10:24   ` Laurent Vivier
  1 sibling, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2021-12-22 20:18 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> The first word of page1 is data, so the whole thing
> can't be implemented with emulation of addresses.
> Use init_guest_commpage for the allocation.
> 
> Hijack trap number 16 to implement cmpxchg.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/elfload.c        | 50 ++++++++++++++++++++++++++++++++++++-
>   linux-user/nios2/cpu_loop.c | 50 ++++++++++++++++++++-----------------
>   target/nios2/translate.c    |  9 -------
>   3 files changed, 76 insertions(+), 33 deletions(-)
> 

Reviewed-by: Laurent Vivier <laurent@vivier.eu>



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/7] linux-user/nios2: Fix EA vs PC confusion
  2021-12-21  2:50 ` [PATCH v2 5/7] linux-user/nios2: Fix EA vs PC confusion Richard Henderson
@ 2021-12-22 20:20   ` Laurent Vivier
  2022-01-05 10:24   ` Laurent Vivier
  1 sibling, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2021-12-22 20:20 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> The real kernel will talk about the user PC as EA,
> because that's where the hardware will have copied it,
> and where it expects to put it to then use ERET.
> But qemu does not emulate all of the exception stuff
> while emulating user-only.  Manipulate PC directly.
> 
> This fixes signal entry and return, and eliminates
> some slight confusion from target_cpu_copy_regs.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/nios2/cpu_loop.c | 5 +----
>   linux-user/nios2/signal.c   | 6 +++---
>   2 files changed, 4 insertions(+), 7 deletions(-)
> 

Reviewed-by: Laurent Vivier <laurent@vivier.eu>



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP
  2021-12-21  2:50 ` [PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
  2021-12-22 18:52   ` Laurent Vivier
@ 2022-01-05 10:23   ` Laurent Vivier
  1 sibling, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2022-01-05 10:23 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: Alex Bennée

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> The real kernel has to load the instruction and extract
> the imm5 field; for qemu, modify the translator to do this.
> 
> The use of R_AT for this in cpu_loop was a bug.  Handle
> the other trap numbers as per the kernel's trap_table.
> 
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/nios2/cpu.h          |  2 +-
>   linux-user/nios2/cpu_loop.c | 40 ++++++++++++++++++++-----------------
>   target/nios2/translate.c    | 17 +++++++++++++++-
>   3 files changed, 39 insertions(+), 20 deletions(-)
> 
> diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
> index 1a69ed7a49..d2ba0c5bbd 100644
> --- a/target/nios2/cpu.h
> +++ b/target/nios2/cpu.h
> @@ -160,9 +160,9 @@ struct CPUNios2State {
>   
>   #if !defined(CONFIG_USER_ONLY)
>       Nios2MMU mmu;
> -
>       uint32_t irq_pending;
>   #endif
> +    int error_code;
>   };
>   
>   /**
> diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
> index 34290fb3b5..5c3d01d22d 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);
> -    Nios2CPU *cpu = NIOS2_CPU(cs);
>       target_siginfo_t info;
>       int trapnr, ret;
>   
> @@ -39,9 +38,10 @@ void cpu_loop(CPUNios2State *env)
>           case EXCP_INTERRUPT:
>               /* just indicate that signals should be handled asap */
>               break;
> +
>           case EXCP_TRAP:
> -            if (env->regs[R_AT] == 0) {
> -                abi_long ret;
> +            switch (env->error_code) {
> +            case 0:
>                   qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
>   
>                   ret = do_syscall(env, env->regs[2],
> @@ -55,26 +55,30 @@ void cpu_loop(CPUNios2State *env)
>   
>                   env->regs[2] = abs(ret);
>                   /* Return value is 0..4096 */
> -                env->regs[7] = (ret > 0xfffffffffffff000ULL);
> -                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
> -                env->regs[CR_STATUS] &= ~0x3;
> -                env->regs[R_EA] = env->regs[R_PC] + 4;
> +                env->regs[7] = ret > 0xfffff000u;
>                   env->regs[R_PC] += 4;
>                   break;
> -            } else {
> -                qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
>   
> -                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
> -                env->regs[CR_STATUS] &= ~0x3;
> -                env->regs[R_EA] = env->regs[R_PC] + 4;
> -                env->regs[R_PC] = cpu->exception_addr;
> -
> -                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);
> +            case 1:
> +                qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n");
> +                force_sig_fault(TARGET_SIGUSR1, 0, env->regs[R_PC]);
> +                break;
> +            case 2:
> +                qemu_log_mask(CPU_LOG_INT, "\nTrap 2\n");
> +                force_sig_fault(TARGET_SIGUSR2, 0, env->regs[R_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]);
> +                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]);
>                   break;
>               }
> +            break;
> +
>           case EXCP_DEBUG:
>               info.si_signo = TARGET_SIGTRAP;
>               info.si_errno = 0;
> diff --git a/target/nios2/translate.c b/target/nios2/translate.c
> index 08d7ac5398..a759877519 100644
> --- a/target/nios2/translate.c
> +++ b/target/nios2/translate.c
> @@ -636,6 +636,21 @@ static void divu(DisasContext *dc, uint32_t code, uint32_t flags)
>       tcg_temp_free(t0);
>   }
>   
> +static void trap(DisasContext *dc, uint32_t code, uint32_t flags)
> +{
> +#ifdef CONFIG_USER_ONLY
> +    /*
> +     * The imm5 field is not stored anywhere on real hw; the kernel
> +     * has to load the insn and extract the field.  But we can make
> +     * things easier for cpu_loop if we pop this into env->error_code.
> +     */
> +    R_TYPE(instr, code);
> +    tcg_gen_st_i32(tcg_constant_i32(instr.imm5), cpu_env,
> +                   offsetof(CPUNios2State, error_code));
> +#endif
> +    t_gen_helper_raise_exception(dc, EXCP_TRAP);
> +}
> +
>   static const Nios2Instruction r_type_instructions[] = {
>       INSTRUCTION_ILLEGAL(),
>       INSTRUCTION(eret),                                /* eret */
> @@ -682,7 +697,7 @@ static const Nios2Instruction r_type_instructions[] = {
>       INSTRUCTION_ILLEGAL(),
>       INSTRUCTION_ILLEGAL(),
>       INSTRUCTION_ILLEGAL(),
> -    INSTRUCTION_FLG(gen_excp, EXCP_TRAP),             /* trap */
> +    INSTRUCTION(trap),                                /* trap */
>       INSTRUCTION(wrctl),                               /* wrctl */
>       INSTRUCTION_ILLEGAL(),
>       INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU),         /* cmpltu */

Applied to my linux-user-for-7.0 branch.

Thanks,
Laurent


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 2/7] linux-user/nios2: Fixes for signal frame setup
  2021-12-21  2:50 ` [PATCH v2 2/7] linux-user/nios2: Fixes for signal frame setup Richard Henderson
@ 2022-01-05 10:23   ` Laurent Vivier
  0 siblings, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2022-01-05 10:23 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: Peter Maydell, Alex Bennée

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> Do not confuse host and guest addresses.  Lock and unlock
> the target_rt_sigframe structure in setup_rt_sigframe.
> 
> Since rt_setup_ucontext always returns 0, drop the return
> value entirely.  This eliminates the only write to the err
> variable in setup_rt_sigframe.
> 
> Always copy the siginfo structure.
> 
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/nios2/signal.c | 49 ++++++++++++++++-----------------------
>   1 file changed, 20 insertions(+), 29 deletions(-)
> 
> diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
> index a77e8a40f4..adbffe32e3 100644
> --- a/linux-user/nios2/signal.c
> +++ b/linux-user/nios2/signal.c
> @@ -42,7 +42,7 @@ struct target_rt_sigframe {
>       struct target_ucontext uc;
>   };
>   
> -static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
> +static void rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
>   {
>       unsigned long *gregs = uc->tuc_mcontext.gregs;
>   
> @@ -75,8 +75,6 @@ static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
>       __put_user(env->regs[R_GP], &gregs[25]);
>       __put_user(env->regs[R_EA], &gregs[27]);
>       __put_user(env->regs[R_SP], &gregs[28]);
> -
> -    return 0;
>   }
>   
>   static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
> @@ -135,8 +133,8 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
>       return 0;
>   }
>   
> -static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
> -                          size_t frame_size)
> +static abi_ptr get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
> +                            size_t frame_size)
>   {
>       unsigned long usp;
>   
> @@ -144,7 +142,7 @@ static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
>       usp = target_sigsp(get_sp_from_cpustate(env), ka);
>   
>       /* Verify, is it 32 or 64 bit aligned */
> -    return (void *)((usp - frame_size) & -8UL);
> +    return (usp - frame_size) & -8;
>   }
>   
>   void setup_rt_frame(int sig, struct target_sigaction *ka,
> @@ -153,26 +151,25 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
>                       CPUNios2State *env)
>   {
>       struct target_rt_sigframe *frame;
> -    int i, err = 0;
> +    abi_ptr frame_addr;
> +    int i;
>   
> -    frame = get_sigframe(ka, env, sizeof(*frame));
> -
> -    if (ka->sa_flags & SA_SIGINFO) {
> -        tswap_siginfo(&frame->info, info);
> +    frame_addr = get_sigframe(ka, env, sizeof(*frame));
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        force_sigsegv(sig);
> +        return;
>       }
>   
> +    tswap_siginfo(&frame->info, info);
> +
>       /* Create the ucontext.  */
>       __put_user(0, &frame->uc.tuc_flags);
>       __put_user(0, &frame->uc.tuc_link);
>       target_save_altstack(&frame->uc.tuc_stack, env);
> -    err |= rt_setup_ucontext(&frame->uc, env);
> +    rt_setup_ucontext(&frame->uc, env);
>       for (i = 0; i < TARGET_NSIG_WORDS; i++) {
>           __put_user((abi_ulong)set->sig[i],
> -            (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
> -    }
> -
> -    if (err) {
> -        goto give_sigsegv;
> +                   (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
>       }
>   
>       /* Set up to return from userspace; jump to fixed address sigreturn
> @@ -180,19 +177,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
>       env->regs[R_RA] = (unsigned long) (0x1044);
>   
>       /* Set up registers for signal handler */
> -    env->regs[R_SP] = (unsigned long) frame;
> -    env->regs[4] = (unsigned long) sig;
> -    env->regs[5] = (unsigned long) &frame->info;
> -    env->regs[6] = (unsigned long) &frame->uc;
> -    env->regs[R_EA] = (unsigned long) ka->_sa_handler;
> -    return;
> +    env->regs[R_SP] = frame_addr;
> +    env->regs[4] = sig;
> +    env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info);
> +    env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc);
> +    env->regs[R_EA] = ka->_sa_handler;
>   
> -give_sigsegv:
> -    if (sig == TARGET_SIGSEGV) {
> -        ka->_sa_handler = TARGET_SIG_DFL;
> -    }
> -    force_sigsegv(sig);
> -    return;
> +    unlock_user_struct(frame, frame_addr, 1);
>   }
>   
>   long do_sigreturn(CPUNios2State *env)


Applied to my linux-user-for-7.0 branch.

Thanks,
Laurent


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 3/7] linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE
  2021-12-21  2:50 ` [PATCH v2 3/7] linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE Richard Henderson
@ 2022-01-05 10:24   ` Laurent Vivier
  0 siblings, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2022-01-05 10:24 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> Arm will no longer be the only target requiring a commpage,
> but it will continue to be the only target placing the page
> at the high end of the address space.
> 
> Reviewed-by: Laurent Vivier <laurent@vivier.eu>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/elfload.c | 18 +++++++++---------
>   1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 767f54c76d..d34cd4fe43 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -390,11 +390,11 @@ enum {
>   
>   /* The commpage only exists for 32 bit kernels */
>   
> -#define ARM_COMMPAGE (intptr_t)0xffff0f00u
> +#define HI_COMMPAGE (intptr_t)0xffff0f00u
>   
>   static bool init_guest_commpage(void)
>   {
> -    void *want = g2h_untagged(ARM_COMMPAGE & -qemu_host_page_size);
> +    void *want = g2h_untagged(HI_COMMPAGE & -qemu_host_page_size);
>       void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
>                         MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
>   
> @@ -2160,8 +2160,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
>       return sp;
>   }
>   
> -#ifndef ARM_COMMPAGE
> -#define ARM_COMMPAGE 0
> +#ifndef HI_COMMPAGE
> +#define HI_COMMPAGE 0
>   #define init_guest_commpage() true
>   #endif
>   
> @@ -2361,7 +2361,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
>       }
>   
>       loaddr &= -align;
> -    if (ARM_COMMPAGE) {
> +    if (HI_COMMPAGE) {
>           /*
>            * Extend the allocation to include the commpage.
>            * For a 64-bit host, this is just 4GiB; for a 32-bit host we
> @@ -2372,14 +2372,14 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
>           if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) {
>               hiaddr = (uintptr_t) 4 << 30;
>           } else {
> -            offset = -(ARM_COMMPAGE & -align);
> +            offset = -(HI_COMMPAGE & -align);
>           }
>       }
>   
>       addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset);
>       if (addr == -1) {
>           /*
> -         * If ARM_COMMPAGE, there *might* be a non-consecutive allocation
> +         * If HI_COMMPAGE, there *might* be a non-consecutive allocation
>            * that can satisfy both.  But as the normal arm32 link base address
>            * is ~32k, and we extend down to include the commpage, making the
>            * overhead only ~96k, this is unlikely.
> @@ -2400,7 +2400,7 @@ static void pgb_dynamic(const char *image_name, long align)
>        * All we need is a commpage that satisfies align.
>        * If we do not need a commpage, leave guest_base == 0.
>        */
> -    if (ARM_COMMPAGE) {
> +    if (HI_COMMPAGE) {
>           uintptr_t addr, commpage;
>   
>           /* 64-bit hosts should have used reserved_va. */
> @@ -2410,7 +2410,7 @@ static void pgb_dynamic(const char *image_name, long align)
>            * By putting the commpage at the first hole, that puts guest_base
>            * just above that, and maximises the positive guest addresses.
>            */
> -        commpage = ARM_COMMPAGE & -align;
> +        commpage = HI_COMMPAGE & -align;
>           addr = pgb_find_hole(commpage, -commpage, align, 0);
>           assert(addr != -1);
>           guest_base = addr;

Applied to my linux-user-for-7.0 branch.

Thanks,
Laurent



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 4/7] linux-user/nios2: Map a real kuser page
  2021-12-21  2:50 ` [PATCH v2 4/7] linux-user/nios2: Map a real kuser page Richard Henderson
  2021-12-22 20:18   ` Laurent Vivier
@ 2022-01-05 10:24   ` Laurent Vivier
  1 sibling, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2022-01-05 10:24 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> The first word of page1 is data, so the whole thing
> can't be implemented with emulation of addresses.
> Use init_guest_commpage for the allocation.
> 
> Hijack trap number 16 to implement cmpxchg.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/elfload.c        | 50 ++++++++++++++++++++++++++++++++++++-
>   linux-user/nios2/cpu_loop.c | 50 ++++++++++++++++++++-----------------
>   target/nios2/translate.c    |  9 -------
>   3 files changed, 76 insertions(+), 33 deletions(-)
> 
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index d34cd4fe43..329b2375ef 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -1099,6 +1099,47 @@ static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
>       regs->estatus = 0x3;
>   }
>   
> +#define LO_COMMPAGE  TARGET_PAGE_SIZE
> +
> +static bool init_guest_commpage(void)
> +{
> +    static const uint8_t kuser_page[4 + 2 * 64] = {
> +        /* __kuser_helper_version */
> +        [0x00] = 0x02, 0x00, 0x00, 0x00,
> +
> +        /* __kuser_cmpxchg */
> +        [0x04] = 0x3a, 0x6c, 0x3b, 0x00,  /* trap 16 */
> +                 0x3a, 0x28, 0x00, 0xf8,  /* ret */
> +
> +        /* __kuser_sigtramp */
> +        [0x44] = 0xc4, 0x22, 0x80, 0x00,  /* movi r2, __NR_rt_sigreturn */
> +                 0x3a, 0x68, 0x3b, 0x00,  /* trap 0 */
> +    };
> +
> +    void *want = g2h_untagged(LO_COMMPAGE & -qemu_host_page_size);
> +    void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
> +                      MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
> +
> +    if (addr == MAP_FAILED) {
> +        perror("Allocating guest commpage");
> +        exit(EXIT_FAILURE);
> +    }
> +    if (addr != want) {
> +        return false;
> +    }
> +
> +    memcpy(addr, kuser_page, sizeof(kuser_page));
> +
> +    if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
> +        perror("Protecting guest commpage");
> +        exit(EXIT_FAILURE);
> +    }
> +
> +    page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE,
> +                   PAGE_READ | PAGE_EXEC | PAGE_VALID);
> +    return true;
> +}
> +
>   #define ELF_EXEC_PAGESIZE        4096
>   
>   #define USE_ELF_CORE_DUMP
> @@ -2160,8 +2201,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
>       return sp;
>   }
>   
> -#ifndef HI_COMMPAGE
> +#if defined(HI_COMMPAGE)
> +#define LO_COMMPAGE 0
> +#elif defined(LO_COMMPAGE)
>   #define HI_COMMPAGE 0
> +#else
> +#define HI_COMMPAGE 0
> +#define LO_COMMPAGE 0
>   #define init_guest_commpage() true
>   #endif
>   
> @@ -2374,6 +2420,8 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
>           } else {
>               offset = -(HI_COMMPAGE & -align);
>           }
> +    } else if (LO_COMMPAGE) {
> +        loaddr = MIN(loaddr, LO_COMMPAGE & -align);
>       }
>   
>       addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset);
> diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
> index 5c3d01d22d..de0fc63e21 100644
> --- a/linux-user/nios2/cpu_loop.c
> +++ b/linux-user/nios2/cpu_loop.c
> @@ -76,6 +76,32 @@ void cpu_loop(CPUNios2State *env)
>                   force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
>                                   env->regs[R_PC]);
>                   break;
> +
> +            case 16: /* QEMU specific, for __kuser_cmpxchg */
> +                {
> +                    abi_ptr g = env->regs[4];
> +                    uint32_t *h, n, o;
> +
> +                    if (g & 0x3) {
> +                        force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, g);
> +                        break;
> +                    }
> +                    ret = page_get_flags(g);
> +                    if (!(ret & PAGE_VALID)) {
> +                        force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, g);
> +                        break;
> +                    }
> +                    if (!(ret & PAGE_READ) || !(ret & PAGE_WRITE)) {
> +                        force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_ACCERR, g);
> +                        break;
> +                    }
> +                    h = g2h(cs, g);
> +                    o = env->regs[5];
> +                    n = env->regs[6];
> +                    env->regs[2] = qatomic_cmpxchg(h, o, n) - o;
> +                    env->regs[R_PC] += 4;
> +                }
> +                break;
>               }
>               break;
>   
> @@ -86,29 +112,7 @@ void cpu_loop(CPUNios2State *env)
>               queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
>               break;
>           case 0xaa:
> -            switch (env->regs[R_PC]) {
> -            /*case 0x1000:*/  /* TODO:__kuser_helper_version */
> -            case 0x1004:      /* __kuser_cmpxchg */
> -                start_exclusive();
> -                if (env->regs[4] & 0x3) {
> -                    goto kuser_fail;
> -                }
> -                ret = get_user_u32(env->regs[2], env->regs[4]);
> -                if (ret) {
> -                    end_exclusive();
> -                    goto kuser_fail;
> -                }
> -                env->regs[2] -= env->regs[5];
> -                if (env->regs[2] == 0) {
> -                    put_user_u32(env->regs[6], env->regs[4]);
> -                }
> -                end_exclusive();
> -                env->regs[R_PC] = env->regs[R_RA];
> -                break;
> -            /*case 0x1040:*/  /* TODO:__kuser_sigtramp */
> -            default:
> -                ;
> -kuser_fail:
> +            {
>                   info.si_signo = TARGET_SIGSEGV;
>                   info.si_errno = 0;
>                   /* TODO: check env->error_code */
> diff --git a/target/nios2/translate.c b/target/nios2/translate.c
> index a759877519..f9abc2fdd2 100644
> --- a/target/nios2/translate.c
> +++ b/target/nios2/translate.c
> @@ -795,15 +795,6 @@ static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
>       dc->base.pc_next = pc + 4;
>   
>       /* Decode an instruction */
> -
> -#if defined(CONFIG_USER_ONLY)
> -    /* FIXME: Is this needed ? */
> -    if (pc >= 0x1000 && pc < 0x2000) {
> -        t_gen_helper_raise_exception(dc, 0xaa);
> -        return;
> -    }
> -#endif
> -
>       code = cpu_ldl_code(env, pc);
>       op = get_opcode(code);
>   

Applied to my linux-user-for-7.0 branch.

Thanks,
Laurent



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/7] linux-user/nios2: Fix EA vs PC confusion
  2021-12-21  2:50 ` [PATCH v2 5/7] linux-user/nios2: Fix EA vs PC confusion Richard Henderson
  2021-12-22 20:20   ` Laurent Vivier
@ 2022-01-05 10:24   ` Laurent Vivier
  1 sibling, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2022-01-05 10:24 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> The real kernel will talk about the user PC as EA,
> because that's where the hardware will have copied it,
> and where it expects to put it to then use ERET.
> But qemu does not emulate all of the exception stuff
> while emulating user-only.  Manipulate PC directly.
> 
> This fixes signal entry and return, and eliminates
> some slight confusion from target_cpu_copy_regs.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/nios2/cpu_loop.c | 5 +----
>   linux-user/nios2/signal.c   | 6 +++---
>   2 files changed, 4 insertions(+), 7 deletions(-)
> 
> diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
> index de0fc63e21..1e93ef34e6 100644
> --- a/linux-user/nios2/cpu_loop.c
> +++ b/linux-user/nios2/cpu_loop.c
> @@ -155,9 +155,6 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
>       env->regs[R_SP] = regs->sp;
>       env->regs[R_GP] = regs->gp;
>       env->regs[CR_ESTATUS] = regs->estatus;
> -    env->regs[R_EA] = regs->ea;
> -    /* TODO: unsigned long  orig_r7; */
> -
> -    /* Emulate eret when starting thread. */
>       env->regs[R_PC] = regs->ea;
> +    /* TODO: unsigned long  orig_r7; */
>   }
> diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
> index adbffe32e3..20b65aa06e 100644
> --- a/linux-user/nios2/signal.c
> +++ b/linux-user/nios2/signal.c
> @@ -73,7 +73,7 @@ static void rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
>       __put_user(env->regs[R_RA], &gregs[23]);
>       __put_user(env->regs[R_FP], &gregs[24]);
>       __put_user(env->regs[R_GP], &gregs[25]);
> -    __put_user(env->regs[R_EA], &gregs[27]);
> +    __put_user(env->regs[R_PC], &gregs[27]);
>       __put_user(env->regs[R_SP], &gregs[28]);
>   }
>   
> @@ -122,7 +122,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
>       __get_user(env->regs[R_GP], &gregs[25]);
>       /* Not really necessary no user settable bits */
>       __get_user(temp, &gregs[26]);
> -    __get_user(env->regs[R_EA], &gregs[27]);
> +    __get_user(env->regs[R_PC], &gregs[27]);
>   
>       __get_user(env->regs[R_RA], &gregs[23]);
>       __get_user(env->regs[R_SP], &gregs[28]);
> @@ -181,7 +181,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
>       env->regs[4] = sig;
>       env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info);
>       env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc);
> -    env->regs[R_EA] = ka->_sa_handler;
> +    env->regs[R_PC] = ka->_sa_handler;
>   
>       unlock_user_struct(frame, frame_addr, 1);
>   }

Applied to my linux-user-for-7.0 branch.

Thanks,
Laurent



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 6/7] linux-user/nios2: Fix sigmask in setup_rt_frame
  2021-12-21  2:50 ` [PATCH v2 6/7] linux-user/nios2: Fix sigmask in setup_rt_frame Richard Henderson
@ 2022-01-05 10:24   ` Laurent Vivier
  0 siblings, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2022-01-05 10:24 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> Do not cast the signal mask elements; trust __put_user.
> 
> Reviewed-by: Laurent Vivier <laurent@vivier.eu>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/nios2/signal.c | 3 +--
>   1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
> index 20b65aa06e..80e3d42fc9 100644
> --- a/linux-user/nios2/signal.c
> +++ b/linux-user/nios2/signal.c
> @@ -168,8 +168,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
>       target_save_altstack(&frame->uc.tuc_stack, env);
>       rt_setup_ucontext(&frame->uc, env);
>       for (i = 0; i < TARGET_NSIG_WORDS; i++) {
> -        __put_user((abi_ulong)set->sig[i],
> -                   (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
> +        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
>       }
>   
>       /* Set up to return from userspace; jump to fixed address sigreturn


Applied to my linux-user-for-7.0 branch.

Thanks,
Laurent


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 7/7] linux-user/nios2: Use set_sigmask in do_rt_sigreturn
  2021-12-21  2:50 ` [PATCH v2 7/7] linux-user/nios2: Use set_sigmask in do_rt_sigreturn Richard Henderson
@ 2022-01-05 10:24   ` Laurent Vivier
  0 siblings, 0 replies; 18+ messages in thread
From: Laurent Vivier @ 2022-01-05 10:24 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

Le 21/12/2021 à 03:50, Richard Henderson a écrit :
> Using do_sigprocmask directly was incorrect, as it will
> leave the signal blocked by the outer layers of linux-user.
> 
> Reviewed-by: Laurent Vivier <laurent@vivier.eu>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/nios2/signal.c | 2 +-
>   linux-user/signal.c       | 2 --
>   2 files changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
> index 80e3d42fc9..517cd39270 100644
> --- a/linux-user/nios2/signal.c
> +++ b/linux-user/nios2/signal.c
> @@ -205,7 +205,7 @@ long do_rt_sigreturn(CPUNios2State *env)
>       }
>   
>       target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
> -    do_sigprocmask(SIG_SETMASK, &set, NULL);
> +    set_sigmask(&set);
>   
>       if (rt_restore_ucontext(env, &frame->uc, &rval)) {
>           goto badframe;
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 6d5e5b698c..8cb33a351c 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -258,7 +258,6 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
>       return 0;
>   }
>   
> -#if !defined(TARGET_NIOS2)
>   /* Just set the guest's signal mask to the specified value; the
>    * caller is assumed to have called block_signals() already.
>    */
> @@ -268,7 +267,6 @@ void set_sigmask(const sigset_t *set)
>   
>       ts->signal_mask = *set;
>   }
> -#endif
>   
>   /* sigaltstack management */
>   


Applied to my linux-user-for-7.0 branch.

Thanks,
Laurent


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2022-01-05 10:44 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-21  2:50 [PATCH v2 0/7] linux-user: nios2 fixes Richard Henderson
2021-12-21  2:50 ` [PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
2021-12-22 18:52   ` Laurent Vivier
2022-01-05 10:23   ` Laurent Vivier
2021-12-21  2:50 ` [PATCH v2 2/7] linux-user/nios2: Fixes for signal frame setup Richard Henderson
2022-01-05 10:23   ` Laurent Vivier
2021-12-21  2:50 ` [PATCH v2 3/7] linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE Richard Henderson
2022-01-05 10:24   ` Laurent Vivier
2021-12-21  2:50 ` [PATCH v2 4/7] linux-user/nios2: Map a real kuser page Richard Henderson
2021-12-22 20:18   ` Laurent Vivier
2022-01-05 10:24   ` Laurent Vivier
2021-12-21  2:50 ` [PATCH v2 5/7] linux-user/nios2: Fix EA vs PC confusion Richard Henderson
2021-12-22 20:20   ` Laurent Vivier
2022-01-05 10:24   ` Laurent Vivier
2021-12-21  2:50 ` [PATCH v2 6/7] linux-user/nios2: Fix sigmask in setup_rt_frame Richard Henderson
2022-01-05 10:24   ` Laurent Vivier
2021-12-21  2:50 ` [PATCH v2 7/7] linux-user/nios2: Use set_sigmask in do_rt_sigreturn Richard Henderson
2022-01-05 10:24   ` Laurent Vivier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.