Re: [PULL 20/27] linux-user/nios2: Map a real kuser page

2022-01-10 Thread Peter Maydell
On Thu, 6 Jan 2022 at 11:01, Laurent Vivier  wrote:
>
> From: Richard Henderson 
>
> 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 
> Reviewed-by: Laurent Vivier 
> Message-Id: <20211221025012.1057923-5-richard.hender...@linaro.org>
> Signed-off-by: Laurent Vivier 
> ---
>  linux-user/elfload.c| 50 -
>  linux-user/nios2/cpu_loop.c | 50 -
>  target/nios2/translate.c|  9 ---
>  3 files changed, 76 insertions(+), 33 deletions(-)

Hi; on my local Linux box clang complains about this code:

> @@ -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);

../../linux-user/elfload.c:2423:16: error: converting the result of
'<<' to a boolean always evaluates to true
[-Werror,-Wtautological-constant-compare]
} else if (LO_COMMPAGE) {
   ^
../../linux-user/elfload.c:1102:22: note: expanded from macro 'LO_COMMPAGE'
#define LO_COMMPAGE  TARGET_PAGE_SIZE
 ^
/mnt/nvmedisk/linaro/qemu-for-merges/include/exec/cpu-all.h:231:31:
note: expanded from macro 'TARGET_PAGE_SIZE'
#define TARGET_PAGE_SIZE   (1 << TARGET_PAGE_BITS)
  ^
1 error generated.

Using "if (LO_COMMPAGE != 0)" shuts the compiler up.

This is with clang version 10.0.0-4ubuntu1.

-- PMM



[PULL 20/27] linux-user/nios2: Map a real kuser page

2022-01-06 Thread Laurent Vivier
From: Richard Henderson 

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 
Reviewed-by: Laurent Vivier 
Message-Id: <20211221025012.1057923-5-richard.hender...@linaro.org>
Signed-off-by: Laurent Vivier 
---
 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 d34cd4fe43fb..329b2375ef15 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_PAGESIZE4096
 
 #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 5c3d01d22dd7..de0fc63e2196 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, );
 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;
-}
-