]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Merge remote-tracking branch 'remotes/xtensa/tags/20180316-xtensa' into staging
authorPeter Maydell <peter.maydell@linaro.org>
Sat, 17 Mar 2018 14:15:03 +0000 (14:15 +0000)
committerPeter Maydell <peter.maydell@linaro.org>
Sat, 17 Mar 2018 14:15:03 +0000 (14:15 +0000)
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 <filippov@cadence.com>"
# gpg:                 aka "Max Filippov <max.filippov@cogentembedded.com>"
# gpg:                 aka "Max Filippov <jcmvbkbc@gmail.com>"
# 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 <peter.maydell@linaro.org>
# Conflicts:
# linux-user/syscall.c

1  2 
MAINTAINERS
configure
linux-user/elfload.c
linux-user/main.c
linux-user/signal.c
linux-user/syscall.c
linux-user/syscall_defs.h

diff --cc MAINTAINERS
Simple merge
diff --cc configure
Simple merge
Simple merge
Simple merge
index 2461edf4639d10fbf717d9271e3bc04ca08545ec,24b6f38b42a5a59dc068f5d50170ce05720b71d8..2ea3e0321f4d042aa2427304681dc66aaffe4d4c
@@@ -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,
Simple merge
index e53583e921599eb0a6d144f5a3bf205df9ec4344,b034fa8d54f8e32b7e057a97e5eb901d3c00edef..13fe8402392faef2a867aec42dd2342fde428a96
  
  #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