From: Peter Maydell Date: Sat, 17 Mar 2018 14:15:03 +0000 (+0000) Subject: Merge remote-tracking branch 'remotes/xtensa/tags/20180316-xtensa' into staging X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=e1e44a9916b4318e943aecd669e096222cb3eaeb;p=qemu.git Merge remote-tracking branch 'remotes/xtensa/tags/20180316-xtensa' into staging target/xtensa linux-user support. - small cleanup for xtensa registers dumping (-d cpu); - add support for debugging linux-user process with xtensa-linux-gdb (as opposed to xtensa-elf-gdb), which can only access unprivileged registers; - enable MTTCG for target/xtensa; - cleanup in linux-user/mmap area making sure that it works correctly with limited 30-bit-wide user address space; - import xtensa-specific definitions from the linux kernel, conditionalize user-only/softmmu-only code and add handlers for signals, exceptions, process/thread creation and core registers dumping. # gpg: Signature made Fri 16 Mar 2018 16:46:19 GMT # gpg: using RSA key 51F9CC91F83FA044 # gpg: Good signature from "Max Filippov " # gpg: aka "Max Filippov " # gpg: aka "Max Filippov " # Primary key fingerprint: 2B67 854B 98E5 327D CDEB 17D8 51F9 CC91 F83F A044 * remotes/xtensa/tags/20180316-xtensa: MAINTAINERS: fix W: address for xtensa qemu-binfmt-conf.sh: add qemu-xtensa target/xtensa: add linux-user support linux-user: drop unused target_msync function linux-user: fix target_mprotect/target_munmap error return values linux-user: fix assertion in shmdt linux-user: fix mmap/munmap/mprotect/mremap/shmat target/xtensa: support MTTCG target/xtensa: use correct number of registers in gdbstub target/xtensa: mark register windows in the dump target/xtensa: dump correct physical registers Signed-off-by: Peter Maydell # Conflicts: # linux-user/syscall.c --- e1e44a9916b4318e943aecd669e096222cb3eaeb diff --cc linux-user/signal.c index 2461edf463,24b6f38b42..2ea3e0321f --- a/linux-user/signal.c +++ b/linux-user/signal.c @@@ -7048,8 -7051,287 +7048,262 @@@ long do_rt_sigreturn(CPUArchState *env return -TARGET_QEMU_ESIGRETURN; } + #elif defined(TARGET_XTENSA) + + struct target_sigcontext { + abi_ulong sc_pc; + abi_ulong sc_ps; + abi_ulong sc_lbeg; + abi_ulong sc_lend; + abi_ulong sc_lcount; + abi_ulong sc_sar; + abi_ulong sc_acclo; + abi_ulong sc_acchi; + abi_ulong sc_a[16]; + abi_ulong sc_xtregs; + }; + + struct target_ucontext { + abi_ulong tuc_flags; + abi_ulong tuc_link; + target_stack_t tuc_stack; + struct target_sigcontext tuc_mcontext; + target_sigset_t tuc_sigmask; + }; + + struct target_rt_sigframe { + target_siginfo_t info; + struct target_ucontext uc; + /* TODO: xtregs */ + uint8_t retcode[6]; + abi_ulong window[4]; + }; + + static abi_ulong get_sigframe(struct target_sigaction *sa, + CPUXtensaState *env, + unsigned long framesize) + { + abi_ulong sp = env->regs[1]; + + /* This is the X/Open sanctioned signal stack switching. */ + if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) { + sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; + } + return (sp - framesize) & -16; + } + + static int flush_window_regs(CPUXtensaState *env) + { + const uint32_t nareg_mask = env->config->nareg - 1; + uint32_t wb = env->sregs[WINDOW_BASE]; + uint32_t ws = (xtensa_replicate_windowstart(env) >> (wb + 1)) & + ((1 << env->config->nareg / 4) - 1); + uint32_t d = ctz32(ws) + 1; + uint32_t sp; + abi_long ret = 0; + + wb += d; + ws >>= d; + + xtensa_sync_phys_from_window(env); + sp = env->phys_regs[(wb * 4 + 1) & nareg_mask]; + + while (ws && ret == 0) { + int d; + int i; + int idx; + + if (ws & 0x1) { + ws >>= 1; + d = 1; + } else if (ws & 0x2) { + ws >>= 2; + d = 2; + for (i = 0; i < 4; ++i) { + idx = (wb * 4 + 4 + i) & nareg_mask; + ret |= put_user_ual(env->phys_regs[idx], sp + (i - 12) * 4); + } + } else if (ws & 0x4) { + ws >>= 3; + d = 3; + for (i = 0; i < 8; ++i) { + idx = (wb * 4 + 4 + i) & nareg_mask; + ret |= put_user_ual(env->phys_regs[idx], sp + (i - 16) * 4); + } + } else { + g_assert_not_reached(); + } + sp = env->phys_regs[((wb + d) * 4 + 1) & nareg_mask]; + for (i = 0; i < 4; ++i) { + idx = (wb * 4 + i) & nareg_mask; + ret |= put_user_ual(env->phys_regs[idx], sp + (i - 4) * 4); + } + wb += d; + } + return ret == 0; + } + + static int setup_sigcontext(struct target_rt_sigframe *frame, + CPUXtensaState *env) + { + struct target_sigcontext *sc = &frame->uc.tuc_mcontext; + int i; + + __put_user(env->pc, &sc->sc_pc); + __put_user(env->sregs[PS], &sc->sc_ps); + __put_user(env->sregs[LBEG], &sc->sc_lbeg); + __put_user(env->sregs[LEND], &sc->sc_lend); + __put_user(env->sregs[LCOUNT], &sc->sc_lcount); + if (!flush_window_regs(env)) { + return 0; + } + for (i = 0; i < 16; ++i) { + __put_user(env->regs[i], sc->sc_a + i); + } + __put_user(0, &sc->sc_xtregs); + /* TODO: xtregs */ + return 1; + } + + static void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPUXtensaState *env) + { + abi_ulong frame_addr; + struct target_rt_sigframe *frame; + uint32_t ra; + int i; + + frame_addr = get_sigframe(ka, env, sizeof(*frame)); + trace_user_setup_rt_frame(env, frame_addr); + + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { + goto give_sigsegv; + } + + if (ka->sa_flags & SA_SIGINFO) { + tswap_siginfo(&frame->info, info); + } + + __put_user(0, &frame->uc.tuc_flags); + __put_user(0, &frame->uc.tuc_link); + __put_user(target_sigaltstack_used.ss_sp, + &frame->uc.tuc_stack.ss_sp); + __put_user(sas_ss_flags(env->regs[1]), + &frame->uc.tuc_stack.ss_flags); + __put_user(target_sigaltstack_used.ss_size, + &frame->uc.tuc_stack.ss_size); + if (!setup_sigcontext(frame, env)) { + unlock_user_struct(frame, frame_addr, 0); + goto give_sigsegv; + } + for (i = 0; i < TARGET_NSIG_WORDS; ++i) { + __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); + } + + if (ka->sa_flags & TARGET_SA_RESTORER) { + ra = ka->sa_restorer; + } else { + ra = frame_addr + offsetof(struct target_rt_sigframe, retcode); + #ifdef TARGET_WORDS_BIGENDIAN + /* Generate instruction: MOVI a2, __NR_rt_sigreturn */ + __put_user(0x22, &frame->retcode[0]); + __put_user(0x0a, &frame->retcode[1]); + __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]); + /* Generate instruction: SYSCALL */ + __put_user(0x00, &frame->retcode[3]); + __put_user(0x05, &frame->retcode[4]); + __put_user(0x00, &frame->retcode[5]); + #else + /* Generate instruction: MOVI a2, __NR_rt_sigreturn */ + __put_user(0x22, &frame->retcode[0]); + __put_user(0xa0, &frame->retcode[1]); + __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]); + /* Generate instruction: SYSCALL */ + __put_user(0x00, &frame->retcode[3]); + __put_user(0x50, &frame->retcode[4]); + __put_user(0x00, &frame->retcode[5]); + #endif + } + env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT); + if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER)) { + env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT); + } + memset(env->regs, 0, sizeof(env->regs)); + env->pc = ka->_sa_handler; + env->regs[1] = frame_addr; + env->sregs[WINDOW_BASE] = 0; + env->sregs[WINDOW_START] = 1; + + env->regs[4] = (ra & 0x3fffffff) | 0x40000000; + env->regs[6] = sig; + env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, info); + env->regs[8] = frame_addr + offsetof(struct target_rt_sigframe, uc); + unlock_user_struct(frame, frame_addr, 1); + return; + + give_sigsegv: + force_sigsegv(sig); + return; + } + + static void restore_sigcontext(CPUXtensaState *env, + struct target_rt_sigframe *frame) + { + struct target_sigcontext *sc = &frame->uc.tuc_mcontext; + uint32_t ps; + int i; + + __get_user(env->pc, &sc->sc_pc); + __get_user(ps, &sc->sc_ps); + __get_user(env->sregs[LBEG], &sc->sc_lbeg); + __get_user(env->sregs[LEND], &sc->sc_lend); + __get_user(env->sregs[LCOUNT], &sc->sc_lcount); + + env->sregs[WINDOW_BASE] = 0; + env->sregs[WINDOW_START] = 1; + env->sregs[PS] = deposit32(env->sregs[PS], + PS_CALLINC_SHIFT, + PS_CALLINC_LEN, + extract32(ps, PS_CALLINC_SHIFT, + PS_CALLINC_LEN)); + for (i = 0; i < 16; ++i) { + __get_user(env->regs[i], sc->sc_a + i); + } + /* TODO: xtregs */ + } + + long do_rt_sigreturn(CPUXtensaState *env) + { + abi_ulong frame_addr = env->regs[1]; + struct target_rt_sigframe *frame; + sigset_t set; + + trace_user_do_rt_sigreturn(env, frame_addr); + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { + goto badframe; + } + target_to_host_sigset(&set, &frame->uc.tuc_sigmask); + set_sigmask(&set); + + restore_sigcontext(env, frame); + + if (do_sigaltstack(frame_addr + + offsetof(struct target_rt_sigframe, uc.tuc_stack), + 0, get_sp_from_cpustate(env)) == -TARGET_EFAULT) { + goto badframe; + } + unlock_user_struct(frame, frame_addr, 0); + return -TARGET_QEMU_ESIGRETURN; + + badframe: + unlock_user_struct(frame, frame_addr, 0); + force_sig(TARGET_SIGSEGV); + return -TARGET_QEMU_ESIGRETURN; + } + #else - -static void setup_frame(int sig, struct target_sigaction *ka, - target_sigset_t *set, CPUArchState *env) -{ - fprintf(stderr, "setup_frame: not implemented\n"); -} - -static void setup_rt_frame(int sig, struct target_sigaction *ka, - target_siginfo_t *info, - target_sigset_t *set, CPUArchState *env) -{ - fprintf(stderr, "setup_rt_frame: not implemented\n"); -} - -long do_sigreturn(CPUArchState *env) -{ - fprintf(stderr, "do_sigreturn: not implemented\n"); - return -TARGET_ENOSYS; -} - -long do_rt_sigreturn(CPUArchState *env) -{ - fprintf(stderr, "do_rt_sigreturn: not implemented\n"); - return -TARGET_ENOSYS; -} - +#error Target needs to add support for signal handling #endif static void handle_pending_signal(CPUArchState *cpu_env, int sig, diff --cc linux-user/syscall_defs.h index e53583e921,b034fa8d54..13fe840239 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@@ -69,9 -69,10 +69,10 @@@ #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \ || defined(TARGET_M68K) || defined(TARGET_CRIS) \ - || defined(TARGET_UNICORE32) || defined(TARGET_S390X) \ + || defined(TARGET_S390X) \ || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \ - || defined(TARGET_NIOS2) || defined(TARGET_RISCV) + || defined(TARGET_NIOS2) || defined(TARGET_RISCV) \ + || defined(TARGET_XTENSA) #define TARGET_IOC_SIZEBITS 14 #define TARGET_IOC_DIRBITS 2 @@@ -420,10 -434,10 +421,10 @@@ int do_sigaction(int sig, const struct #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \ || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined(TARGET_SH4) \ || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) \ - || defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32) \ + || defined(TARGET_MICROBLAZE) \ || defined(TARGET_S390X) || defined(TARGET_OPENRISC) \ || defined(TARGET_TILEGX) || defined(TARGET_HPPA) || defined(TARGET_NIOS2) \ - || defined(TARGET_RISCV) + || defined(TARGET_RISCV) || defined(TARGET_XTENSA) #if defined(TARGET_SPARC) #define TARGET_SA_NOCLDSTOP 8u