Re: [Qemu-devel] [PATCH v8 10/23] RISC-V Linux User Emulation

2018-04-08 Thread Michael Clark
On Thu, Apr 5, 2018 at 12:44 AM, Laurent Vivier  wrote:

> Le 02/03/2018 à 14:51, Michael Clark a écrit :
> > Implementation of linux user emulation for RISC-V.
> >
> > Reviewed-by: Richard Henderson 
> > Signed-off-by: Sagar Karandikar 
> > Signed-off-by: Michael Clark 
> > ---
> >  linux-user/elfload.c  |  22 +++
> >  linux-user/main.c |  99 +
> >  linux-user/riscv/syscall_nr.h | 287 ++
> 
> >  linux-user/riscv/target_cpu.h |  18 +++
> >  linux-user/riscv/target_elf.h |  14 ++
> >  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   | 222 +
> >  linux-user/signal.c   | 203 ++-
> >  linux-user/syscall.c  |   2 +
> >  linux-user/syscall_defs.h |  13 +-
> >  target/riscv/cpu_user.h   |  13 ++
> >  13 files changed, 1012 insertions(+), 6 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_elf.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
> >
> ...
> > diff --git a/linux-user/signal.c b/linux-user/signal.c
> > index 9a380b9..4d3f244 100644
> > --- a/linux-user/signal.c
> > +++ b/linux-user/signal.c
> ...
> > +static abi_ulong get_sigframe(struct target_sigaction *ka,
> > +  CPURISCVState *regs, size_t framesize)
> > +{
> > +abi_ulong sp = regs->gpr[xSP];
> > +int onsigstack = on_sig_stack(sp);
> > +
> > +/* redzone */
> > +/* This is the X/Open sanctioned signal stack switching.  */
> > +if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
> > +sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_
> size;
> > +}
> > +
> > +sp -= framesize;
> > +sp &= ~3UL; /* align sp on 4-byte boundary */
>
> kernel aligns using 0xf. Why do you use a different alignment?


Thanks for reviewing this! This looks like a bug!

I'm raising this as an issue on the riscv-qemu tracker so that its easier
than searching through the mail archive:

- https://github.com/riscv/riscv-qemu/issues/129

> +
> > +/* If we are on the alternate signal stack and would overflow it,
> don't.
> > +   Return an always-bogus address instead so we will die with
> SIGSEGV. */
> > +if (onsigstack && !likely(on_sig_stack(sp))) {
> > +return -1L;
> > +}
> > +
> > +return sp;
> > +}
> Other question why don't you use the same logic as in kernel?
>
> 1- check for signal stack overflow
> 2- check for X/Open sanctioned signal stack switching
>
> static inline void __user *get_sigframe(struct ksignal *ksig,
> struct pt_regs *regs, size_t framesize)
> {
> unsigned long sp;
> /* Default to using normal stack */
> sp = regs->sp;
>
> /*
>  * If we are on the alternate signal stack and would overflow
> it, don't.
>  * Return an always-bogus address instead so we will die with
> SIGSEGV.
>  */
> if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
> return (void __user __force *)(-1UL);
>
> /* This is the X/Open sanctioned signal stack switching. */
> sp = sigsp(sp, ksig) - framesize;
>
> /* Align the stack frame. */
> sp &= ~0xfUL;
>
> return (void __user *)sp;
> }
>
> Thanks,
> Laurent
>


Re: [Qemu-devel] [PATCH v8 10/23] RISC-V Linux User Emulation

2018-04-04 Thread Laurent Vivier
Le 02/03/2018 à 14:51, Michael Clark a écrit :
> Implementation of linux user emulation for RISC-V.
> 
> Reviewed-by: Richard Henderson 
> Signed-off-by: Sagar Karandikar 
> Signed-off-by: Michael Clark 
> ---
>  linux-user/elfload.c  |  22 +++
>  linux-user/main.c |  99 +
>  linux-user/riscv/syscall_nr.h | 287 
> ++
>  linux-user/riscv/target_cpu.h |  18 +++
>  linux-user/riscv/target_elf.h |  14 ++
>  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   | 222 +
>  linux-user/signal.c   | 203 ++-
>  linux-user/syscall.c  |   2 +
>  linux-user/syscall_defs.h |  13 +-
>  target/riscv/cpu_user.h   |  13 ++
>  13 files changed, 1012 insertions(+), 6 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_elf.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
> 
...
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 9a380b9..4d3f244 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
...
> +static abi_ulong get_sigframe(struct target_sigaction *ka,
> +  CPURISCVState *regs, size_t framesize)
> +{
> +abi_ulong sp = regs->gpr[xSP];
> +int onsigstack = on_sig_stack(sp);
> +
> +/* redzone */
> +/* This is the X/Open sanctioned signal stack switching.  */
> +if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
> +sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
> +}
> +
> +sp -= framesize;
> +sp &= ~3UL; /* align sp on 4-byte boundary */

kernel aligns using 0xf. Why do you use a different alignment?

> +
> +/* If we are on the alternate signal stack and would overflow it, don't.
> +   Return an always-bogus address instead so we will die with SIGSEGV. */
> +if (onsigstack && !likely(on_sig_stack(sp))) {
> +return -1L;
> +}
> +
> +return sp;
> +}
Other question why don't you use the same logic as in kernel?

1- check for signal stack overflow
2- check for X/Open sanctioned signal stack switching

static inline void __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs, size_t framesize)
{
unsigned long sp;
/* Default to using normal stack */
sp = regs->sp;

/*
 * If we are on the alternate signal stack and would overflow
it, don't.
 * Return an always-bogus address instead so we will die with
SIGSEGV.
 */
if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
return (void __user __force *)(-1UL);

/* This is the X/Open sanctioned signal stack switching. */
sp = sigsp(sp, ksig) - framesize;

/* Align the stack frame. */
sp &= ~0xfUL;

return (void __user *)sp;
}

Thanks,
Laurent



[Qemu-devel] [PATCH v8 10/23] RISC-V Linux User Emulation

2018-03-02 Thread Michael Clark
Implementation of linux user emulation for RISC-V.

Reviewed-by: Richard Henderson 
Signed-off-by: Sagar Karandikar 
Signed-off-by: Michael Clark 
---
 linux-user/elfload.c  |  22 +++
 linux-user/main.c |  99 +
 linux-user/riscv/syscall_nr.h | 287 ++
 linux-user/riscv/target_cpu.h |  18 +++
 linux-user/riscv/target_elf.h |  14 ++
 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   | 222 +
 linux-user/signal.c   | 203 ++-
 linux-user/syscall.c  |   2 +
 linux-user/syscall_defs.h |  13 +-
 target/riscv/cpu_user.h   |  13 ++
 13 files changed, 1012 insertions(+), 6 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_elf.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

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 6689089..838f1c4 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1293,6 +1293,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 bbeb78f..7bc9bc7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3653,6 +3653,100 @@ 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);
+process_queued_cpu_work(cs);
+
+signum = 0;
+sigcode = 0;
+sigaddr = 0;
+
+switch (trapnr) {
+case EXCP_INTERRUPT:
+/* just indicate that signals should be handled asap */
+break;
+case EXCP_ATOMIC:
+cpu_exec_step_atomic(cs);
+break;
+case RISCV_EXCP_U_ECALL:
+env->pc += 4;
+if (env->gpr[xA7] == TARGET_NR_arch_specific_syscall + 15) {
+/* riscv_flush_icache_syscall is a no-op in QEMU as
+   self-modifying code is automatically detected */
+ret = 0;
+} else {
+ret = do_syscall(env,
+ env->gpr[xA7],
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+ env->gpr[xA3],
+ env->gpr[xA4],
+ env->gpr[xA5],
+ 0, 0);
+}
+if (ret == -TARGET_ERESTARTSYS) {
+env->pc -= 4;
+} else if (ret != -TARGET_QEMU_ESIGRETURN) {
+env->gpr[xA0] = ret;
+}
+if (cs->singlestep_enabled) {
+goto gdbstep;
+}
+break;
+case RISCV_EXCP_ILLEGAL_INST:
+signum = TARGET_SIGILL;
+sigcode = TARGET_ILL_ILLOPC;
+break;
+case RISCV_EXCP_BREAKPOINT:
+signum = TARGET_SIGTRAP;
+sigcode = TARGET_TRAP_BRKPT;
+sigaddr = env->pc;
+break;
+case RISCV_EXCP_INST_PAGE_FAULT:
+case RISCV_EXCP_LOAD_PAGE_FAULT:
+case RISCV_EXCP_STORE_PAGE_FAULT:
+signum = TARGET_SIGSEGV;
+sigcode = TARGET_SEGV_MAPERR;
+break;
+case EXCP_DEBUG:
+gdbstep:
+signum = gdb_handlesig(cs, TARGET_SIGTRAP);
+sigcode = TARGET_TRAP_BRKPT;
+break;
+default:
+EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
+ trapnr);
+exit(EXIT_FAILURE);
+}
+
+if (signum) {
+target_siginfo_t info = {
+.si_signo = signum,
+