Message ID | 1634561247-25499-18-git-send-email-gaosong@loongson.cn (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add LoongArch linux-user emulation support | expand |
Hi Song, Sorry for the late review; I only became aware of this work and subscribed to qemu-devel after you sent v6, so I wasn't able to reply to that thread I didn't receive earlier. On 10/18/21 20:47, Song Gao wrote: > Implementation of linux user emulation for LoongArch. > > Signed-off-by: Song Gao <gaosong@loongson.cn> > Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn> > --- > accel/tcg/user-exec.c | 15 ++ > configure | 5 + > include/elf.h | 2 + > linux-user/elfload.c | 58 ++++++ > linux-user/host/loongarch/hostdep.h | 11 + > linux-user/loongarch64/cpu_loop.c | 98 +++++++++ > linux-user/loongarch64/signal.c | 163 +++++++++++++++ > linux-user/loongarch64/sockbits.h | 1 + > linux-user/loongarch64/syscall_nr.h | 312 +++++++++++++++++++++++++++++ > linux-user/loongarch64/target_cpu.h | 35 ++++ > linux-user/loongarch64/target_elf.h | 14 ++ > linux-user/loongarch64/target_errno_defs.h | 7 + > linux-user/loongarch64/target_fcntl.h | 12 ++ > linux-user/loongarch64/target_signal.h | 30 +++ > linux-user/loongarch64/target_structs.h | 49 +++++ > linux-user/loongarch64/target_syscall.h | 46 +++++ > linux-user/loongarch64/termbits.h | 1 + > linux-user/syscall_defs.h | 10 +- > scripts/gensyscalls.sh | 1 + > 19 files changed, 866 insertions(+), 4 deletions(-) > create mode 100644 linux-user/host/loongarch/hostdep.h > create mode 100644 linux-user/loongarch64/cpu_loop.c > create mode 100644 linux-user/loongarch64/signal.c > create mode 100644 linux-user/loongarch64/sockbits.h > create mode 100644 linux-user/loongarch64/syscall_nr.h > create mode 100644 linux-user/loongarch64/target_cpu.h > create mode 100644 linux-user/loongarch64/target_elf.h > create mode 100644 linux-user/loongarch64/target_errno_defs.h > create mode 100644 linux-user/loongarch64/target_fcntl.h > create mode 100644 linux-user/loongarch64/target_signal.h > create mode 100644 linux-user/loongarch64/target_structs.h > create mode 100644 linux-user/loongarch64/target_syscall.h > create mode 100644 linux-user/loongarch64/termbits.h Overall I think this patch could use some further splitting. For example (1) splitting out the header additions except the syscall bits, (2) adding to gensyscalls.sh, (3) add the generated syscall_nr.h, and finally the other wiring-ups. This way the commit message could be more descriptive too. > > diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c > index e6bb29b..714eeb4 100644 > --- a/accel/tcg/user-exec.c > +++ b/accel/tcg/user-exec.c > @@ -803,6 +803,21 @@ int cpu_signal_handler(int host_signum, void *pinfo, > return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); > } > > +#elif defined(__loongarch__) > + > +int cpu_signal_handler(int host_signum, void *pinfo, > + void *puc) > +{ > + siginfo_t *info = pinfo; > + ucontext_t *uc = puc; > + greg_t pc = uc->uc_mcontext.__pc; > + int is_write; > + > + /* XXX: compute is_write */ > + is_write = 0; FYI this part is already covered by my patch [1], you may base your series on mine to avoid conflicts. [1]: https://patchew.org/QEMU/20210925173032.2434906-1-git@xen0n.name/20210925173032.2434906-30-git@xen0n.name/ > + return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); > +} > + > #elif defined(__riscv) > > int cpu_signal_handler(int host_signum, void *pinfo, > diff --git a/configure b/configure > index 039467c..8d3cd59 100755 > --- a/configure > +++ b/configure > @@ -579,6 +579,8 @@ elif check_define __arm__ ; then > cpu="arm" > elif check_define __aarch64__ ; then > cpu="aarch64" > +elif check_define __loongarch__ ; then > + cpu="loongarch" > else > cpu=$(uname -m) > fi > @@ -610,6 +612,9 @@ case "$cpu" in > sparc|sun4[cdmuv]) > cpu="sparc" > ;; > + loongarch) > + cpu="loongarch" > + ;; And this [2]... [2]: https://patchew.org/QEMU/20210925173032.2434906-1-git@xen0n.name/20210925173032.2434906-31-git@xen0n.name/ > *) > # This will result in either an error or falling back to TCI later > ARCH=unknown > diff --git a/include/elf.h b/include/elf.h > index 811bf4a..3a4bcb6 100644 > --- a/include/elf.h > +++ b/include/elf.h > @@ -182,6 +182,8 @@ typedef struct mips_elf_abiflags_v0 { > > #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ > > +#define EM_LOONGARCH 258 /* LoongArch */ > + And this [3]. [3]: https://patchew.org/QEMU/20210925173032.2434906-1-git@xen0n.name/20210925173032.2434906-2-git@xen0n.name/ > /* > * This is an interim value that we will use until the committee comes > * up with a final number. > diff --git a/linux-user/elfload.c b/linux-user/elfload.c > index 2404d48..9036f0a 100644 > --- a/linux-user/elfload.c > +++ b/linux-user/elfload.c > @@ -914,6 +914,64 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en > > #endif > > +#ifdef TARGET_LOONGARCH64 > + > +#define ELF_START_MMAP 0x80000000 > + > +#define ELF_CLASS ELFCLASS64 > +#define ELF_ARCH EM_LOONGARCH > + > +#define elf_check_arch(x) ((x) == EM_LOONGARCH) > +static inline void init_thread(struct target_pt_regs *regs, > + struct image_info *infop) > +{ > + regs->csr_crmd = 2 << 3; > + regs->csr_era = infop->entry; > + regs->regs[3] = infop->start_stack; > +} > + > +/* See linux kernel: arch/loongarch/include/asm/elf.h. */ > +#define ELF_NREG 45 > +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; > + > +/* See linux kernel: arch/loongarch/include/asm/reg.h. */ > +enum { > + TARGET_EF_R0 = 0, > + TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32, > + TARGET_EF_CSR_BADVADDR = TARGET_EF_R0 + 33, > +}; > + > +/* See linux kernel: arch/loongarch/kernel/process.c:loongarch_dump_regs64. */ > +static void elf_core_copy_regs(target_elf_gregset_t *regs, > + const CPULoongArchState *env) > +{ > + int i; > + > + for (i = 0; i < TARGET_EF_R0; i++) { > + (*regs)[i] = 0; > + } > + (*regs)[TARGET_EF_R0] = 0; > + > + for (i = 1; i < ARRAY_SIZE(env->gpr); i++) { > + (*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]); > + } > + > + (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc); > + (*regs)[TARGET_EF_CSR_BADVADDR] = tswapreg(env->badaddr); > +} > + > +#define USE_ELF_CORE_DUMP > +#define ELF_EXEC_PAGESIZE 4096 > + > +#define ELF_HWCAP get_elf_hwcap() > + > +static uint32_t get_elf_hwcap(void) > +{ > + return 0; > +} > + > +#endif /* TARGET_LOONGARCH64 */ > + > #ifdef TARGET_MIPS > > #define ELF_START_MMAP 0x80000000 > diff --git a/linux-user/host/loongarch/hostdep.h b/linux-user/host/loongarch/hostdep.h > new file mode 100644 > index 0000000..c1b1537 > --- /dev/null > +++ b/linux-user/host/loongarch/hostdep.h > @@ -0,0 +1,11 @@ > +/* > + * hostdep.h : things which are dependent on the host architecture > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or later. > + * See the COPYING file in the top-level directory. > + */ > + > +#ifndef LOONGARCH_HOSTDEP_H > +#define LOONGARCH_HOSTDEP_H > + > +#endif And this file [4]. [4]: https://patchew.org/QEMU/20210925173032.2434906-1-git@xen0n.name/20210925173032.2434906-29-git@xen0n.name/ > diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c > new file mode 100644 > index 0000000..6fba2ec > --- /dev/null > +++ b/linux-user/loongarch64/cpu_loop.c > @@ -0,0 +1,98 @@ > +/* > + * QEMU LoongArch user cpu loop. > + * > + * Copyright (c) 2021 Loongson Technology Corporation Limited > + * > + * SPDX-License-Identifier: LGPL-2.1+ > + */ > + > +#include "qemu/osdep.h" > +#include "qemu.h" > +#include "qemu-common.h" > +#include "user-internals.h" > +#include "cpu_loop-common.h" > +#include "signal-common.h" > + > +void cpu_loop(CPULoongArchState *env) > +{ > + CPUState *cs = env_cpu(env); > + int trapnr, si_code; > + abi_long ret; > + > + for (;;) { > + cpu_exec_start(cs); > + trapnr = cpu_exec(cs); > + cpu_exec_end(cs); > + process_queued_cpu_work(cs); > + > + switch (trapnr) { > + case EXCP_INTERRUPT: > + /* just indicate that signals should be handled asap */ > + break; > + case EXCP_SYSCALL: > + env->pc += 4; > + ret = do_syscall(env, env->gpr[11], > + env->gpr[4], env->gpr[5], > + env->gpr[6], env->gpr[7], > + env->gpr[8], env->gpr[9], > + -1, -1); > + if (ret == -TARGET_ERESTARTSYS) { > + env->pc -= 4; > + break; > + } > + if (ret == -TARGET_QEMU_ESIGRETURN) { > + /* > + * Returning from a successful sigreturn syscall. > + * Avoid clobbering register state. > + */ > + break; > + } > + env->gpr[4] = ret; > + break; > + case EXCP_ADE: > + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->badaddr); > + break; > + case EXCP_INE: > + force_sig_fault(TARGET_SIGILL, 0, env->pc); > + break; > + case EXCP_FPE: > + si_code = TARGET_FPE_FLTUNK; > + if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) { > + si_code = TARGET_FPE_FLTINV; > + } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) { > + si_code = TARGET_FPE_FLTDIV; > + } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) { > + si_code = TARGET_FPE_FLTOVF; > + } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) { > + si_code = TARGET_FPE_FLTUND; > + } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) { > + si_code = TARGET_FPE_FLTRES; > + } > + force_sig_fault(TARGET_SIGFPE, si_code, env->pc); > + break; > + case EXCP_DEBUG: > + case EXCP_BREAK: > + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); > + break; > + case EXCP_ATOMIC: > + cpu_exec_step_atomic(cs); > + break; > + default: > + EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", > + trapnr); > + exit(EXIT_FAILURE); > + } > + process_pending_signals(env); > + } > +} > + > +void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) > +{ > + int i; > + > + for (i = 0; i < 32; i++) { > + env->gpr[i] = regs->regs[i]; > + } > + env->pc = regs->csr_era; > + > +} > diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c > new file mode 100644 > index 0000000..f3d61de > --- /dev/null > +++ b/linux-user/loongarch64/signal.c > @@ -0,0 +1,163 @@ > +/* > + * LoongArch emulation of Linux signals > + * > + * Copyright (c) 2021 Loongson Technology Corporation Limited > + * > + * SPDX-License-Identifier: LGPL-2.1+ > + */ > + > +#include "qemu/osdep.h" > +#include "qemu.h" > +#include "signal-common.h" > +#include "user-internals.h" > +#include "linux-user/trace.h" > + > +struct target_sigcontext { > + uint64_t sc_pc; > + uint64_t sc_gpr[32]; > + uint64_t sc_fpr[32]; > + uint64_t sc_fcc; > + uint32_t sc_fcsr; > + uint32_t sc_flags; > +}; > + > +struct target_ucontext { > + target_ulong tuc_flags; > + target_ulong tuc_link; > + target_stack_t tuc_stack; > + target_ulong pad0; > + struct target_sigcontext tuc_mcontext; > + target_sigset_t tuc_sigmask; > +}; > + > +struct target_rt_sigframe { > + struct target_siginfo rs_info; > + struct target_ucontext rs_uc; > +}; > + > +static inline void setup_sigcontext(CPULoongArchState *env, > + struct target_sigcontext *sc) > +{ > + int i; > + > + __put_user(env->pc, &sc->sc_pc); > + > + __put_user(0, &sc->sc_gpr[0]); > + for (i = 1; i < 32; ++i) { > + __put_user(env->gpr[i], &sc->sc_gpr[i]); > + } > + > + for (i = 0; i < 32; ++i) { > + __put_user(env->fpr[i], &sc->sc_fpr[i]); > + } > +} > + > +static inline void > +restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc) > +{ > + int i; > + > + __get_user(env->pc, &sc->sc_pc); > + > + for (i = 1; i < 32; ++i) { > + __get_user(env->gpr[i], &sc->sc_gpr[i]); > + } > + > + for (i = 0; i < 32; ++i) { > + __get_user(env->fpr[i], &sc->sc_fpr[i]); > + } > +} > + > +/* > + * Determine which stack to use.. > + */ > +static inline abi_ulong > +get_sigframe(struct target_sigaction *ka, CPULoongArchState *env, > + size_t frame_size) > +{ > + unsigned long sp; > + > + sp = target_sigsp(get_sp_from_cpustate(env) - 32, ka); > + > + return (sp - frame_size) & ~7; > +} > + > +void setup_rt_frame(int sig, struct target_sigaction *ka, > + target_siginfo_t *info, > + target_sigset_t *set, CPULoongArchState *env) > +{ > + struct target_rt_sigframe *frame; > + abi_ulong frame_addr; > + 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; > + } > + > + tswap_siginfo(&frame->rs_info, info); > + > + __put_user(0, &frame->rs_uc.tuc_flags); > + __put_user(0, &frame->rs_uc.tuc_link); > + target_save_altstack(&frame->rs_uc.tuc_stack, env); > + > + setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); > + > + for (i = 0; i < TARGET_NSIG_WORDS; i++) { > + __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); > + } > + > + env->gpr[4] = sig; > + env->gpr[5] = frame_addr + offsetof(struct target_rt_sigframe, rs_info); > + env->gpr[6] = frame_addr + offsetof(struct target_rt_sigframe, rs_uc); > + env->gpr[3] = frame_addr; > + env->gpr[1] = default_rt_sigreturn; > + > + env->pc = env->gpr[20] = ka->_sa_handler; > + unlock_user_struct(frame, frame_addr, 1); > + return; > + > +give_sigsegv: > + unlock_user_struct(frame, frame_addr, 1); > + force_sigsegv(sig); > +} > + > +long do_rt_sigreturn(CPULoongArchState *env) > +{ > + struct target_rt_sigframe *frame; > + abi_ulong frame_addr; > + sigset_t blocked; > + > + frame_addr = env->gpr[3]; > + trace_user_do_rt_sigreturn(env, frame_addr); > + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { > + goto badframe; > + } > + > + target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); > + set_sigmask(&blocked); > + > + restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); > + target_restore_altstack(&frame->rs_uc.tuc_stack, env); > + > + 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; > +} > + > +void setup_sigtramp(abi_ulong sigtramp_page) > +{ > + uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0); > + assert(tramp != NULL); > + > + __put_user(0x03822c0b, tramp + 0); /* ori a7, a7, 0x8b */ Nit: two spaces after "ori" which is neither alignment to "syscall" below, nor ordinary 1-space separation. > + __put_user(0x002b0000, tramp + 1); /* syscall 0 */ > + > + default_rt_sigreturn = sigtramp_page; > + unlock_user(tramp, sigtramp_page, 8); > +} > diff --git a/linux-user/loongarch64/sockbits.h b/linux-user/loongarch64/sockbits.h > new file mode 100644 > index 0000000..0e4c8f0 > --- /dev/null > +++ b/linux-user/loongarch64/sockbits.h > @@ -0,0 +1 @@ > +#include "../generic/sockbits.h" > diff --git a/linux-user/loongarch64/syscall_nr.h b/linux-user/loongarch64/syscall_nr.h > new file mode 100644 > index 0000000..8fbf287 > --- /dev/null > +++ b/linux-user/loongarch64/syscall_nr.h > @@ -0,0 +1,312 @@ > +/* > + * This file contains the system call numbers. > + * Do not modify. > + * This file is generated by scripts/gensyscalls.sh > + */ > +#ifndef LINUX_USER_LOONGARCH_SYSCALL_NR_H > +#define LINUX_USER_LOONGARCH_SYSCALL_NR_H > + > +#define TARGET_NR_io_setup 0 > +#define TARGET_NR_io_destroy 1 > +#define TARGET_NR_io_submit 2 > +#define TARGET_NR_io_cancel 3 > +#define TARGET_NR_io_getevents 4 > +#define TARGET_NR_setxattr 5 > +#define TARGET_NR_lsetxattr 6 > +#define TARGET_NR_fsetxattr 7 > +#define TARGET_NR_getxattr 8 > +#define TARGET_NR_lgetxattr 9 > +#define TARGET_NR_fgetxattr 10 > +#define TARGET_NR_listxattr 11 > +#define TARGET_NR_llistxattr 12 > +#define TARGET_NR_flistxattr 13 > +#define TARGET_NR_removexattr 14 > +#define TARGET_NR_lremovexattr 15 > +#define TARGET_NR_fremovexattr 16 > +#define TARGET_NR_getcwd 17 > +#define TARGET_NR_lookup_dcookie 18 > +#define TARGET_NR_eventfd2 19 > +#define TARGET_NR_epoll_create1 20 > +#define TARGET_NR_epoll_ctl 21 > +#define TARGET_NR_epoll_pwait 22 > +#define TARGET_NR_dup 23 > +#define TARGET_NR_dup3 24 > +#define TARGET_NR_fcntl 25 > +#define TARGET_NR_inotify_init1 26 > +#define TARGET_NR_inotify_add_watch 27 > +#define TARGET_NR_inotify_rm_watch 28 > +#define TARGET_NR_ioctl 29 > +#define TARGET_NR_ioprio_set 30 > +#define TARGET_NR_ioprio_get 31 > +#define TARGET_NR_flock 32 > +#define TARGET_NR_mknodat 33 > +#define TARGET_NR_mkdirat 34 > +#define TARGET_NR_unlinkat 35 > +#define TARGET_NR_symlinkat 36 > +#define TARGET_NR_linkat 37 > +#define TARGET_NR_umount2 39 > +#define TARGET_NR_mount 40 > +#define TARGET_NR_pivot_root 41 > +#define TARGET_NR_nfsservctl 42 > +#define TARGET_NR_statfs 43 > +#define TARGET_NR_fstatfs 44 > +#define TARGET_NR_truncate 45 > +#define TARGET_NR_ftruncate 46 > +#define TARGET_NR_fallocate 47 > +#define TARGET_NR_faccessat 48 > +#define TARGET_NR_chdir 49 > +#define TARGET_NR_fchdir 50 > +#define TARGET_NR_chroot 51 > +#define TARGET_NR_fchmod 52 > +#define TARGET_NR_fchmodat 53 > +#define TARGET_NR_fchownat 54 > +#define TARGET_NR_fchown 55 > +#define TARGET_NR_openat 56 > +#define TARGET_NR_close 57 > +#define TARGET_NR_vhangup 58 > +#define TARGET_NR_pipe2 59 > +#define TARGET_NR_quotactl 60 > +#define TARGET_NR_getdents64 61 > +#define TARGET_NR_lseek 62 > +#define TARGET_NR_read 63 > +#define TARGET_NR_write 64 > +#define TARGET_NR_readv 65 > +#define TARGET_NR_writev 66 > +#define TARGET_NR_pread64 67 > +#define TARGET_NR_pwrite64 68 > +#define TARGET_NR_preadv 69 > +#define TARGET_NR_pwritev 70 > +#define TARGET_NR_sendfile 71 > +#define TARGET_NR_pselect6 72 > +#define TARGET_NR_ppoll 73 > +#define TARGET_NR_signalfd4 74 > +#define TARGET_NR_vmsplice 75 > +#define TARGET_NR_splice 76 > +#define TARGET_NR_tee 77 > +#define TARGET_NR_readlinkat 78 > +#define TARGET_NR_newfstatat 79 > +#define TARGET_NR_fstat 80 > +#define TARGET_NR_sync 81 > +#define TARGET_NR_fsync 82 > +#define TARGET_NR_fdatasync 83 > +#define TARGET_NR_sync_file_range 84 > +#define TARGET_NR_timerfd_create 85 > +#define TARGET_NR_timerfd_settime 86 > +#define TARGET_NR_timerfd_gettime 87 > +#define TARGET_NR_utimensat 88 > +#define TARGET_NR_acct 89 > +#define TARGET_NR_capget 90 > +#define TARGET_NR_capset 91 > +#define TARGET_NR_personality 92 > +#define TARGET_NR_exit 93 > +#define TARGET_NR_exit_group 94 > +#define TARGET_NR_waitid 95 > +#define TARGET_NR_set_tid_address 96 > +#define TARGET_NR_unshare 97 > +#define TARGET_NR_futex 98 > +#define TARGET_NR_set_robust_list 99 > +#define TARGET_NR_get_robust_list 100 > +#define TARGET_NR_nanosleep 101 > +#define TARGET_NR_getitimer 102 > +#define TARGET_NR_setitimer 103 > +#define TARGET_NR_kexec_load 104 > +#define TARGET_NR_init_module 105 > +#define TARGET_NR_delete_module 106 > +#define TARGET_NR_timer_create 107 > +#define TARGET_NR_timer_gettime 108 > +#define TARGET_NR_timer_getoverrun 109 > +#define TARGET_NR_timer_settime 110 > +#define TARGET_NR_timer_delete 111 > +#define TARGET_NR_clock_settime 112 > +#define TARGET_NR_clock_gettime 113 > +#define TARGET_NR_clock_getres 114 > +#define TARGET_NR_clock_nanosleep 115 > +#define TARGET_NR_syslog 116 > +#define TARGET_NR_ptrace 117 > +#define TARGET_NR_sched_setparam 118 > +#define TARGET_NR_sched_setscheduler 119 > +#define TARGET_NR_sched_getscheduler 120 > +#define TARGET_NR_sched_getparam 121 > +#define TARGET_NR_sched_setaffinity 122 > +#define TARGET_NR_sched_getaffinity 123 > +#define TARGET_NR_sched_yield 124 > +#define TARGET_NR_sched_get_priority_max 125 > +#define TARGET_NR_sched_get_priority_min 126 > +#define TARGET_NR_sched_rr_get_interval 127 > +#define TARGET_NR_restart_syscall 128 > +#define TARGET_NR_kill 129 > +#define TARGET_NR_tkill 130 > +#define TARGET_NR_tgkill 131 > +#define TARGET_NR_sigaltstack 132 > +#define TARGET_NR_rt_sigsuspend 133 > +#define TARGET_NR_rt_sigaction 134 > +#define TARGET_NR_rt_sigprocmask 135 > +#define TARGET_NR_rt_sigpending 136 > +#define TARGET_NR_rt_sigtimedwait 137 > +#define TARGET_NR_rt_sigqueueinfo 138 > +#define TARGET_NR_rt_sigreturn 139 > +#define TARGET_NR_setpriority 140 > +#define TARGET_NR_getpriority 141 > +#define TARGET_NR_reboot 142 > +#define TARGET_NR_setregid 143 > +#define TARGET_NR_setgid 144 > +#define TARGET_NR_setreuid 145 > +#define TARGET_NR_setuid 146 > +#define TARGET_NR_setresuid 147 > +#define TARGET_NR_getresuid 148 > +#define TARGET_NR_setresgid 149 > +#define TARGET_NR_getresgid 150 > +#define TARGET_NR_setfsuid 151 > +#define TARGET_NR_setfsgid 152 > +#define TARGET_NR_times 153 > +#define TARGET_NR_setpgid 154 > +#define TARGET_NR_getpgid 155 > +#define TARGET_NR_getsid 156 > +#define TARGET_NR_setsid 157 > +#define TARGET_NR_getgroups 158 > +#define TARGET_NR_setgroups 159 > +#define TARGET_NR_uname 160 > +#define TARGET_NR_sethostname 161 > +#define TARGET_NR_setdomainname 162 > +#define TARGET_NR_getrusage 165 > +#define TARGET_NR_umask 166 > +#define TARGET_NR_prctl 167 > +#define TARGET_NR_getcpu 168 > +#define TARGET_NR_gettimeofday 169 > +#define TARGET_NR_settimeofday 170 > +#define TARGET_NR_adjtimex 171 > +#define TARGET_NR_getpid 172 > +#define TARGET_NR_getppid 173 > +#define TARGET_NR_getuid 174 > +#define TARGET_NR_geteuid 175 > +#define TARGET_NR_getgid 176 > +#define TARGET_NR_getegid 177 > +#define TARGET_NR_gettid 178 > +#define TARGET_NR_sysinfo 179 > +#define TARGET_NR_mq_open 180 > +#define TARGET_NR_mq_unlink 181 > +#define TARGET_NR_mq_timedsend 182 > +#define TARGET_NR_mq_timedreceive 183 > +#define TARGET_NR_mq_notify 184 > +#define TARGET_NR_mq_getsetattr 185 > +#define TARGET_NR_msgget 186 > +#define TARGET_NR_msgctl 187 > +#define TARGET_NR_msgrcv 188 > +#define TARGET_NR_msgsnd 189 > +#define TARGET_NR_semget 190 > +#define TARGET_NR_semctl 191 > +#define TARGET_NR_semtimedop 192 > +#define TARGET_NR_semop 193 > +#define TARGET_NR_shmget 194 > +#define TARGET_NR_shmctl 195 > +#define TARGET_NR_shmat 196 > +#define TARGET_NR_shmdt 197 > +#define TARGET_NR_socket 198 > +#define TARGET_NR_socketpair 199 > +#define TARGET_NR_bind 200 > +#define TARGET_NR_listen 201 > +#define TARGET_NR_accept 202 > +#define TARGET_NR_connect 203 > +#define TARGET_NR_getsockname 204 > +#define TARGET_NR_getpeername 205 > +#define TARGET_NR_sendto 206 > +#define TARGET_NR_recvfrom 207 > +#define TARGET_NR_setsockopt 208 > +#define TARGET_NR_getsockopt 209 > +#define TARGET_NR_shutdown 210 > +#define TARGET_NR_sendmsg 211 > +#define TARGET_NR_recvmsg 212 > +#define TARGET_NR_readahead 213 > +#define TARGET_NR_brk 214 > +#define TARGET_NR_munmap 215 > +#define TARGET_NR_mremap 216 > +#define TARGET_NR_add_key 217 > +#define TARGET_NR_request_key 218 > +#define TARGET_NR_keyctl 219 > +#define TARGET_NR_clone 220 > +#define TARGET_NR_execve 221 > +#define TARGET_NR_mmap 222 > +#define TARGET_NR_fadvise64 223 > +#define TARGET_NR_swapon 224 > +#define TARGET_NR_swapoff 225 > +#define TARGET_NR_mprotect 226 > +#define TARGET_NR_msync 227 > +#define TARGET_NR_mlock 228 > +#define TARGET_NR_munlock 229 > +#define TARGET_NR_mlockall 230 > +#define TARGET_NR_munlockall 231 > +#define TARGET_NR_mincore 232 > +#define TARGET_NR_madvise 233 > +#define TARGET_NR_remap_file_pages 234 > +#define TARGET_NR_mbind 235 > +#define TARGET_NR_get_mempolicy 236 > +#define TARGET_NR_set_mempolicy 237 > +#define TARGET_NR_migrate_pages 238 > +#define TARGET_NR_move_pages 239 > +#define TARGET_NR_rt_tgsigqueueinfo 240 > +#define TARGET_NR_perf_event_open 241 > +#define TARGET_NR_accept4 242 > +#define TARGET_NR_recvmmsg 243 > +#define TARGET_NR_arch_specific_syscall 244 > +#define TARGET_NR_wait4 260 > +#define TARGET_NR_prlimit64 261 > +#define TARGET_NR_fanotify_init 262 > +#define TARGET_NR_fanotify_mark 263 > +#define TARGET_NR_name_to_handle_at 264 > +#define TARGET_NR_open_by_handle_at 265 > +#define TARGET_NR_clock_adjtime 266 > +#define TARGET_NR_syncfs 267 > +#define TARGET_NR_setns 268 > +#define TARGET_NR_sendmmsg 269 > +#define TARGET_NR_process_vm_readv 270 > +#define TARGET_NR_process_vm_writev 271 > +#define TARGET_NR_kcmp 272 > +#define TARGET_NR_finit_module 273 > +#define TARGET_NR_sched_setattr 274 > +#define TARGET_NR_sched_getattr 275 > +#define TARGET_NR_renameat2 276 > +#define TARGET_NR_seccomp 277 > +#define TARGET_NR_getrandom 278 > +#define TARGET_NR_memfd_create 279 > +#define TARGET_NR_bpf 280 > +#define TARGET_NR_execveat 281 > +#define TARGET_NR_userfaultfd 282 > +#define TARGET_NR_membarrier 283 > +#define TARGET_NR_mlock2 284 > +#define TARGET_NR_copy_file_range 285 > +#define TARGET_NR_preadv2 286 > +#define TARGET_NR_pwritev2 287 > +#define TARGET_NR_pkey_mprotect 288 > +#define TARGET_NR_pkey_alloc 289 > +#define TARGET_NR_pkey_free 290 > +#define TARGET_NR_statx 291 > +#define TARGET_NR_io_pgetevents 292 > +#define TARGET_NR_rseq 293 > +#define TARGET_NR_kexec_file_load 294 > +#define TARGET_NR_pidfd_send_signal 424 > +#define TARGET_NR_io_uring_setup 425 > +#define TARGET_NR_io_uring_enter 426 > +#define TARGET_NR_io_uring_register 427 > +#define TARGET_NR_open_tree 428 > +#define TARGET_NR_move_mount 429 > +#define TARGET_NR_fsopen 430 > +#define TARGET_NR_fsconfig 431 > +#define TARGET_NR_fsmount 432 > +#define TARGET_NR_fspick 433 > +#define TARGET_NR_pidfd_open 434 > +#define TARGET_NR_clone3 435 > +#define TARGET_NR_close_range 436 > +#define TARGET_NR_openat2 437 > +#define TARGET_NR_pidfd_getfd 438 > +#define TARGET_NR_faccessat2 439 > +#define TARGET_NR_process_madvise 440 > +#define TARGET_NR_epoll_pwait2 441 > +#define TARGET_NR_mount_setattr 442 > +#define TARGET_NR_quotactl_fd 443 > +#define TARGET_NR_landlock_create_ruleset 444 > +#define TARGET_NR_landlock_add_rule 445 > +#define TARGET_NR_landlock_restrict_self 446 > +#define TARGET_NR_process_mrelease 448 > +#define TARGET_NR_syscalls 449 > + > +#endif /* LINUX_USER_LOONGARCH_SYSCALL_NR_H */ > diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h > new file mode 100644 > index 0000000..5bd13a7 > --- /dev/null > +++ b/linux-user/loongarch64/target_cpu.h > @@ -0,0 +1,35 @@ > +/* > + * LoongArch specific CPU ABI and functions for linux-user > + * > + * Copyright (c) 2021 Loongson Technology Corporation Limited > + * > + * SPDX-License-Identifier: LGPL-2.1+ > + */ > + > +#ifndef LOONGARCH_TARGET_CPU_H > +#define LOONGARCH_TARGET_CPU_H > + > +static inline void cpu_clone_regs_child(CPULoongArchState *env, > + target_ulong newsp, unsigned flags) > +{ > + if (newsp) { > + env->gpr[3] = newsp; > + } > + env->gpr[4] = 0; > +} > + > +static inline void cpu_clone_regs_parent(CPULoongArchState *env, > + unsigned flags) > +{ > +} > + > +static inline void cpu_set_tls(CPULoongArchState *env, target_ulong newtls) > +{ > + env->gpr[2] = newtls; > +} > + > +static inline abi_ulong get_sp_from_cpustate(CPULoongArchState *state) > +{ > + return state->gpr[3]; > +} > +#endif > diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h > new file mode 100644 > index 0000000..7c88394 > --- /dev/null > +++ b/linux-user/loongarch64/target_elf.h > @@ -0,0 +1,14 @@ > +/* > + * Copyright (c) 2021 Loongson Technology Corporation Limited > + * > + * SPDX-License-Identifier: LGPL-2.1+ > + */ > + > + > +#ifndef LOONGARCH_TARGET_ELF_H > +#define LOONGARCH_TARGET_ELF_H > +static inline const char *cpu_get_model(uint32_t eflags) > +{ > + return "Loongson-3A5000"; > +} > +#endif > diff --git a/linux-user/loongarch64/target_errno_defs.h b/linux-user/loongarch64/target_errno_defs.h > new file mode 100644 > index 0000000..17165c1 > --- /dev/null > +++ b/linux-user/loongarch64/target_errno_defs.h > @@ -0,0 +1,7 @@ > +#ifndef LOONGARCH_TARGET_ERRNO_DEFS_H > +#define LOONGARCH_TARGET_ERRNO_DEFS_H > + > +/* Target uses generic errno */ > +#include "../generic/target_errno_defs.h" > + > +#endif > diff --git a/linux-user/loongarch64/target_fcntl.h b/linux-user/loongarch64/target_fcntl.h > new file mode 100644 > index 0000000..b810293 > --- /dev/null > +++ b/linux-user/loongarch64/target_fcntl.h > @@ -0,0 +1,12 @@ > +/* > + * Copyright (c) 2021 Loongson Technology Corporation Limited > + * > + * SPDX-License-Identifier: LGPL-2.1+ > + */ > + > +#ifndef LOONGARCH_TARGET_FCNTL_H > +#define LOONGARCH_TARGET_FCNTL_H > + > +#include "../generic/fcntl.h" > + > +#endif /* LOONGARCH_TARGET_FCNTL_H */ > diff --git a/linux-user/loongarch64/target_signal.h b/linux-user/loongarch64/target_signal.h > new file mode 100644 > index 0000000..2deb88c > --- /dev/null > +++ b/linux-user/loongarch64/target_signal.h > @@ -0,0 +1,30 @@ > +/* > + * Copyright (c) 2021 Loongson Technology Corporation Limited > + * > + * SPDX-License-Identifier: LGPL-2.1+ > + */ > + > +#ifndef LOONGARCH_TARGET_SIGNAL_H > +#define LOONGARCH_TARGET_SIGNAL_H > + > +/* this struct defines a stack used during syscall handling */ > +typedef struct target_sigaltstack { > + abi_long ss_sp; > + abi_int ss_flags; > + abi_ulong ss_size; > +} target_stack_t; > + > +/* > + * sigaltstack controls > + */ > +#define TARGET_SS_ONSTACK 1 > +#define TARGET_SS_DISABLE 2 > + > +#define TARGET_MINSIGSTKSZ 2048 > +#define TARGET_SIGSTKSZ 8192 > + > +#include "../generic/signal.h" > + > +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 > + > +#endif /* LOONGARCH_TARGET_SIGNAL_H */ > diff --git a/linux-user/loongarch64/target_structs.h b/linux-user/loongarch64/target_structs.h > new file mode 100644 > index 0000000..818e8d6 > --- /dev/null > +++ b/linux-user/loongarch64/target_structs.h > @@ -0,0 +1,49 @@ > +/* > + * LoongArch specific structures for linux-user > + * > + * Copyright (c) 2021 Loongson Technology Corporation Limited > + * > + * SPDX-License-Identifier: LGPL-2.1+ > + */ > + > +#ifndef LOONGARCH_TARGET_STRUCTS_H > +#define LOONGARCH_TARGET_STRUCTS_H > + > +struct target_ipc_perm { > + abi_int __key; /* Key. */ > + abi_uint uid; /* Owner's user ID. */ > + abi_uint gid; /* Owner's group ID. */ > + abi_uint cuid; /* Creator's user ID. */ > + abi_uint cgid; /* Creator's group ID. */ > + abi_uint mode; /* Read/write permission. */ > + abi_ushort __seq; /* Sequence number. */ > + abi_ushort __pad1; > + abi_ulong __unused1; > + abi_ulong __unused2; > +}; > + > +struct target_shmid_ds { > + struct target_ipc_perm shm_perm; /* operation permission struct */ > + abi_long shm_segsz; /* size of segment in bytes */ > + abi_ulong shm_atime; /* time of last shmat() */ > + abi_ulong shm_dtime; /* time of last shmdt() */ > + abi_ulong shm_ctime; /* time of last change by shmctl() */ > + abi_int shm_cpid; /* pid of creator */ > + abi_int shm_lpid; /* pid of last shmop */ > + abi_ulong shm_nattch; /* number of current attaches */ > + abi_ulong __unused1; > + abi_ulong __unused2; > +}; > + > +#define TARGET_SEMID64_DS > + > +struct target_semid64_ds { > + struct target_ipc_perm sem_perm; > + abi_ulong sem_otime; > + abi_ulong sem_ctime; > + abi_ulong sem_nsems; > + abi_ulong __unused1; > + abi_ulong __unused2; > +}; > + > +#endif > diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h > new file mode 100644 > index 0000000..393160d > --- /dev/null > +++ b/linux-user/loongarch64/target_syscall.h > @@ -0,0 +1,46 @@ > +/* > + * Copyright (c) 2021 Loongson Technology Corporation Limited > + * > + * SPDX-License-Identifier: LGPL-2.1+ > + */ > + > +#ifndef LOONGARCH_TARGET_SYSCALL_H > +#define LOONGARCH_TARGET_SYSCALL_H > + > +/* > + * this struct defines the way the registers are stored on the > + * stack during a system call. > + */ > + > +struct target_pt_regs { > + /* Saved main processor registers. */ > + target_ulong regs[32]; > + > + /* Saved special registers. */ > + target_ulong csr_crmd; > + target_ulong csr_prmd; > + target_ulong csr_euen; > + target_ulong csr_ecfg; > + target_ulong csr_estat; > + target_ulong csr_era; > + target_ulong csr_badvaddr; > + target_ulong orig_a0; > + target_ulong __last[0]; > +}; > + > +#define UNAME_MACHINE "loongarch64" > +#define UNAME_MINIMUM_RELEASE "4.19.0" The 4.19.x LoongArch kernel is not upstreamed, is not upstreamable, and AFAIK not even open-source (GPL violation, anyone?). In addition to this, the kernel being upstreamed has NSIG=64 like almost every other architecture except MIPS, while AFAIK the shipped 4.19.x kernel blobs all have NSIG=128 like MIPS, so binaries compiled for that old kernel version are ABI-incompatible with this series. They are nearly impossible to work, since signal handling is present/required for nearly every non-trivial app. So I'd suggest bumping this to at least the upcoming Linux version which is 5.16 at the moment; I personally think even this would need re-visiting because it seems not likely to have LoongArch accepted before end of 2021. > + > +#define TARGET_MINSIGSTKSZ 2048 > +#define TARGET_MCL_CURRENT 1 > +#define TARGET_MCL_FUTURE 2 > +#define TARGET_MCL_ONFAULT 4 > + > +#define TARGET_FORCE_SHMLBA > + > +static inline abi_ulong target_shmlba(CPULoongArchState *env) > +{ > + return 0x40000; > +} > + > +#endif > diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h > new file mode 100644 > index 0000000..b1d4f4f > --- /dev/null > +++ b/linux-user/loongarch64/termbits.h > @@ -0,0 +1 @@ > +#include "../generic/termbits.h" > diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h > index a5ce487..bec125f 100644 > --- a/linux-user/syscall_defs.h > +++ b/linux-user/syscall_defs.h > @@ -74,7 +74,7 @@ > || defined(TARGET_M68K) || defined(TARGET_CRIS) \ > || defined(TARGET_S390X) || defined(TARGET_OPENRISC) \ > || defined(TARGET_NIOS2) || defined(TARGET_RISCV) \ > - || defined(TARGET_XTENSA) > + || defined(TARGET_XTENSA) || defined(TARGET_LOONGARCH64) > > #define TARGET_IOC_SIZEBITS 14 > #define TARGET_IOC_DIRBITS 2 > @@ -2129,7 +2129,8 @@ struct target_stat64 { > abi_ulong __unused5; > }; > > -#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV) > +#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || \ > + defined(TARGET_RISCV) || defined(TARGET_LOONGARCH64) > > /* These are the asm-generic versions of the stat and stat64 structures */ > > @@ -2157,7 +2158,7 @@ struct target_stat { > unsigned int __unused5; > }; > > -#if !defined(TARGET_RISCV64) > +#if !defined(TARGET_RISCV64) && !defined(TARGET_LOONGARCH64) > #define TARGET_HAS_STRUCT_STAT64 > struct target_stat64 { > uint64_t st_dev; > @@ -2327,7 +2328,8 @@ struct target_statfs64 { > }; > #elif (defined(TARGET_PPC64) || defined(TARGET_X86_64) || \ > defined(TARGET_SPARC64) || defined(TARGET_AARCH64) || \ > - defined(TARGET_RISCV)) && !defined(TARGET_ABI32) > + defined(TARGET_RISCV) || defined(TARGET_LOONGARCH64)) && \ > + !defined(TARGET_ABI32) > struct target_statfs { > abi_long f_type; > abi_long f_bsize; > diff --git a/scripts/gensyscalls.sh b/scripts/gensyscalls.sh > index 8fb450e..b69e193 100755 > --- a/scripts/gensyscalls.sh > +++ b/scripts/gensyscalls.sh > @@ -99,4 +99,5 @@ generate_syscall_nr openrisc 32 "$output/linux-user/openrisc/syscall_nr.h" > generate_syscall_nr riscv 32 "$output/linux-user/riscv/syscall32_nr.h" > generate_syscall_nr riscv 64 "$output/linux-user/riscv/syscall64_nr.h" > generate_syscall_nr hexagon 32 "$output/linux-user/hexagon/syscall_nr.h" > +generate_syscall_nr loongarch 64 "$output/linux-user/loongarch64/syscall_nr.h" > rm -fr "$TMP"
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index e6bb29b..714eeb4 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -803,6 +803,21 @@ int cpu_signal_handler(int host_signum, void *pinfo, return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); } +#elif defined(__loongarch__) + +int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) +{ + siginfo_t *info = pinfo; + ucontext_t *uc = puc; + greg_t pc = uc->uc_mcontext.__pc; + int is_write; + + /* XXX: compute is_write */ + is_write = 0; + return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); +} + #elif defined(__riscv) int cpu_signal_handler(int host_signum, void *pinfo, diff --git a/configure b/configure index 039467c..8d3cd59 100755 --- a/configure +++ b/configure @@ -579,6 +579,8 @@ elif check_define __arm__ ; then cpu="arm" elif check_define __aarch64__ ; then cpu="aarch64" +elif check_define __loongarch__ ; then + cpu="loongarch" else cpu=$(uname -m) fi @@ -610,6 +612,9 @@ case "$cpu" in sparc|sun4[cdmuv]) cpu="sparc" ;; + loongarch) + cpu="loongarch" + ;; *) # This will result in either an error or falling back to TCI later ARCH=unknown diff --git a/include/elf.h b/include/elf.h index 811bf4a..3a4bcb6 100644 --- a/include/elf.h +++ b/include/elf.h @@ -182,6 +182,8 @@ typedef struct mips_elf_abiflags_v0 { #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ +#define EM_LOONGARCH 258 /* LoongArch */ + /* * This is an interim value that we will use until the committee comes * up with a final number. diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 2404d48..9036f0a 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -914,6 +914,64 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en #endif +#ifdef TARGET_LOONGARCH64 + +#define ELF_START_MMAP 0x80000000 + +#define ELF_CLASS ELFCLASS64 +#define ELF_ARCH EM_LOONGARCH + +#define elf_check_arch(x) ((x) == EM_LOONGARCH) +static inline void init_thread(struct target_pt_regs *regs, + struct image_info *infop) +{ + regs->csr_crmd = 2 << 3; + regs->csr_era = infop->entry; + regs->regs[3] = infop->start_stack; +} + +/* See linux kernel: arch/loongarch/include/asm/elf.h. */ +#define ELF_NREG 45 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +/* See linux kernel: arch/loongarch/include/asm/reg.h. */ +enum { + TARGET_EF_R0 = 0, + TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32, + TARGET_EF_CSR_BADVADDR = TARGET_EF_R0 + 33, +}; + +/* See linux kernel: arch/loongarch/kernel/process.c:loongarch_dump_regs64. */ +static void elf_core_copy_regs(target_elf_gregset_t *regs, + const CPULoongArchState *env) +{ + int i; + + for (i = 0; i < TARGET_EF_R0; i++) { + (*regs)[i] = 0; + } + (*regs)[TARGET_EF_R0] = 0; + + for (i = 1; i < ARRAY_SIZE(env->gpr); i++) { + (*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]); + } + + (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc); + (*regs)[TARGET_EF_CSR_BADVADDR] = tswapreg(env->badaddr); +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ + return 0; +} + +#endif /* TARGET_LOONGARCH64 */ + #ifdef TARGET_MIPS #define ELF_START_MMAP 0x80000000 diff --git a/linux-user/host/loongarch/hostdep.h b/linux-user/host/loongarch/hostdep.h new file mode 100644 index 0000000..c1b1537 --- /dev/null +++ b/linux-user/host/loongarch/hostdep.h @@ -0,0 +1,11 @@ +/* + * hostdep.h : things which are dependent on the host architecture + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef LOONGARCH_HOSTDEP_H +#define LOONGARCH_HOSTDEP_H + +#endif diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c new file mode 100644 index 0000000..6fba2ec --- /dev/null +++ b/linux-user/loongarch64/cpu_loop.c @@ -0,0 +1,98 @@ +/* + * QEMU LoongArch user cpu loop. + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu.h" +#include "qemu-common.h" +#include "user-internals.h" +#include "cpu_loop-common.h" +#include "signal-common.h" + +void cpu_loop(CPULoongArchState *env) +{ + CPUState *cs = env_cpu(env); + int trapnr, si_code; + abi_long ret; + + for (;;) { + cpu_exec_start(cs); + trapnr = cpu_exec(cs); + cpu_exec_end(cs); + process_queued_cpu_work(cs); + + switch (trapnr) { + case EXCP_INTERRUPT: + /* just indicate that signals should be handled asap */ + break; + case EXCP_SYSCALL: + env->pc += 4; + ret = do_syscall(env, env->gpr[11], + env->gpr[4], env->gpr[5], + env->gpr[6], env->gpr[7], + env->gpr[8], env->gpr[9], + -1, -1); + if (ret == -TARGET_ERESTARTSYS) { + env->pc -= 4; + break; + } + if (ret == -TARGET_QEMU_ESIGRETURN) { + /* + * Returning from a successful sigreturn syscall. + * Avoid clobbering register state. + */ + break; + } + env->gpr[4] = ret; + break; + case EXCP_ADE: + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->badaddr); + break; + case EXCP_INE: + force_sig_fault(TARGET_SIGILL, 0, env->pc); + break; + case EXCP_FPE: + si_code = TARGET_FPE_FLTUNK; + if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) { + si_code = TARGET_FPE_FLTINV; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) { + si_code = TARGET_FPE_FLTDIV; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) { + si_code = TARGET_FPE_FLTOVF; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) { + si_code = TARGET_FPE_FLTUND; + } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) { + si_code = TARGET_FPE_FLTRES; + } + force_sig_fault(TARGET_SIGFPE, si_code, env->pc); + break; + case EXCP_DEBUG: + case EXCP_BREAK: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); + break; + case EXCP_ATOMIC: + cpu_exec_step_atomic(cs); + break; + default: + EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", + trapnr); + exit(EXIT_FAILURE); + } + process_pending_signals(env); + } +} + +void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) +{ + int i; + + for (i = 0; i < 32; i++) { + env->gpr[i] = regs->regs[i]; + } + env->pc = regs->csr_era; + +} diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c new file mode 100644 index 0000000..f3d61de --- /dev/null +++ b/linux-user/loongarch64/signal.c @@ -0,0 +1,163 @@ +/* + * LoongArch emulation of Linux signals + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu.h" +#include "signal-common.h" +#include "user-internals.h" +#include "linux-user/trace.h" + +struct target_sigcontext { + uint64_t sc_pc; + uint64_t sc_gpr[32]; + uint64_t sc_fpr[32]; + uint64_t sc_fcc; + uint32_t sc_fcsr; + uint32_t sc_flags; +}; + +struct target_ucontext { + target_ulong tuc_flags; + target_ulong tuc_link; + target_stack_t tuc_stack; + target_ulong pad0; + struct target_sigcontext tuc_mcontext; + target_sigset_t tuc_sigmask; +}; + +struct target_rt_sigframe { + struct target_siginfo rs_info; + struct target_ucontext rs_uc; +}; + +static inline void setup_sigcontext(CPULoongArchState *env, + struct target_sigcontext *sc) +{ + int i; + + __put_user(env->pc, &sc->sc_pc); + + __put_user(0, &sc->sc_gpr[0]); + for (i = 1; i < 32; ++i) { + __put_user(env->gpr[i], &sc->sc_gpr[i]); + } + + for (i = 0; i < 32; ++i) { + __put_user(env->fpr[i], &sc->sc_fpr[i]); + } +} + +static inline void +restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc) +{ + int i; + + __get_user(env->pc, &sc->sc_pc); + + for (i = 1; i < 32; ++i) { + __get_user(env->gpr[i], &sc->sc_gpr[i]); + } + + for (i = 0; i < 32; ++i) { + __get_user(env->fpr[i], &sc->sc_fpr[i]); + } +} + +/* + * Determine which stack to use.. + */ +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPULoongArchState *env, + size_t frame_size) +{ + unsigned long sp; + + sp = target_sigsp(get_sp_from_cpustate(env) - 32, ka); + + return (sp - frame_size) & ~7; +} + +void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPULoongArchState *env) +{ + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + 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; + } + + tswap_siginfo(&frame->rs_info, info); + + __put_user(0, &frame->rs_uc.tuc_flags); + __put_user(0, &frame->rs_uc.tuc_link); + target_save_altstack(&frame->rs_uc.tuc_stack, env); + + setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); + + for (i = 0; i < TARGET_NSIG_WORDS; i++) { + __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); + } + + env->gpr[4] = sig; + env->gpr[5] = frame_addr + offsetof(struct target_rt_sigframe, rs_info); + env->gpr[6] = frame_addr + offsetof(struct target_rt_sigframe, rs_uc); + env->gpr[3] = frame_addr; + env->gpr[1] = default_rt_sigreturn; + + env->pc = env->gpr[20] = ka->_sa_handler; + unlock_user_struct(frame, frame_addr, 1); + return; + +give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); + force_sigsegv(sig); +} + +long do_rt_sigreturn(CPULoongArchState *env) +{ + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + sigset_t blocked; + + frame_addr = env->gpr[3]; + trace_user_do_rt_sigreturn(env, frame_addr); + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { + goto badframe; + } + + target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); + set_sigmask(&blocked); + + restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); + target_restore_altstack(&frame->rs_uc.tuc_stack, env); + + 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; +} + +void setup_sigtramp(abi_ulong sigtramp_page) +{ + uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0); + assert(tramp != NULL); + + __put_user(0x03822c0b, tramp + 0); /* ori a7, a7, 0x8b */ + __put_user(0x002b0000, tramp + 1); /* syscall 0 */ + + default_rt_sigreturn = sigtramp_page; + unlock_user(tramp, sigtramp_page, 8); +} diff --git a/linux-user/loongarch64/sockbits.h b/linux-user/loongarch64/sockbits.h new file mode 100644 index 0000000..0e4c8f0 --- /dev/null +++ b/linux-user/loongarch64/sockbits.h @@ -0,0 +1 @@ +#include "../generic/sockbits.h" diff --git a/linux-user/loongarch64/syscall_nr.h b/linux-user/loongarch64/syscall_nr.h new file mode 100644 index 0000000..8fbf287 --- /dev/null +++ b/linux-user/loongarch64/syscall_nr.h @@ -0,0 +1,312 @@ +/* + * This file contains the system call numbers. + * Do not modify. + * This file is generated by scripts/gensyscalls.sh + */ +#ifndef LINUX_USER_LOONGARCH_SYSCALL_NR_H +#define LINUX_USER_LOONGARCH_SYSCALL_NR_H + +#define TARGET_NR_io_setup 0 +#define TARGET_NR_io_destroy 1 +#define TARGET_NR_io_submit 2 +#define TARGET_NR_io_cancel 3 +#define TARGET_NR_io_getevents 4 +#define TARGET_NR_setxattr 5 +#define TARGET_NR_lsetxattr 6 +#define TARGET_NR_fsetxattr 7 +#define TARGET_NR_getxattr 8 +#define TARGET_NR_lgetxattr 9 +#define TARGET_NR_fgetxattr 10 +#define TARGET_NR_listxattr 11 +#define TARGET_NR_llistxattr 12 +#define TARGET_NR_flistxattr 13 +#define TARGET_NR_removexattr 14 +#define TARGET_NR_lremovexattr 15 +#define TARGET_NR_fremovexattr 16 +#define TARGET_NR_getcwd 17 +#define TARGET_NR_lookup_dcookie 18 +#define TARGET_NR_eventfd2 19 +#define TARGET_NR_epoll_create1 20 +#define TARGET_NR_epoll_ctl 21 +#define TARGET_NR_epoll_pwait 22 +#define TARGET_NR_dup 23 +#define TARGET_NR_dup3 24 +#define TARGET_NR_fcntl 25 +#define TARGET_NR_inotify_init1 26 +#define TARGET_NR_inotify_add_watch 27 +#define TARGET_NR_inotify_rm_watch 28 +#define TARGET_NR_ioctl 29 +#define TARGET_NR_ioprio_set 30 +#define TARGET_NR_ioprio_get 31 +#define TARGET_NR_flock 32 +#define TARGET_NR_mknodat 33 +#define TARGET_NR_mkdirat 34 +#define TARGET_NR_unlinkat 35 +#define TARGET_NR_symlinkat 36 +#define TARGET_NR_linkat 37 +#define TARGET_NR_umount2 39 +#define TARGET_NR_mount 40 +#define TARGET_NR_pivot_root 41 +#define TARGET_NR_nfsservctl 42 +#define TARGET_NR_statfs 43 +#define TARGET_NR_fstatfs 44 +#define TARGET_NR_truncate 45 +#define TARGET_NR_ftruncate 46 +#define TARGET_NR_fallocate 47 +#define TARGET_NR_faccessat 48 +#define TARGET_NR_chdir 49 +#define TARGET_NR_fchdir 50 +#define TARGET_NR_chroot 51 +#define TARGET_NR_fchmod 52 +#define TARGET_NR_fchmodat 53 +#define TARGET_NR_fchownat 54 +#define TARGET_NR_fchown 55 +#define TARGET_NR_openat 56 +#define TARGET_NR_close 57 +#define TARGET_NR_vhangup 58 +#define TARGET_NR_pipe2 59 +#define TARGET_NR_quotactl 60 +#define TARGET_NR_getdents64 61 +#define TARGET_NR_lseek 62 +#define TARGET_NR_read 63 +#define TARGET_NR_write 64 +#define TARGET_NR_readv 65 +#define TARGET_NR_writev 66 +#define TARGET_NR_pread64 67 +#define TARGET_NR_pwrite64 68 +#define TARGET_NR_preadv 69 +#define TARGET_NR_pwritev 70 +#define TARGET_NR_sendfile 71 +#define TARGET_NR_pselect6 72 +#define TARGET_NR_ppoll 73 +#define TARGET_NR_signalfd4 74 +#define TARGET_NR_vmsplice 75 +#define TARGET_NR_splice 76 +#define TARGET_NR_tee 77 +#define TARGET_NR_readlinkat 78 +#define TARGET_NR_newfstatat 79 +#define TARGET_NR_fstat 80 +#define TARGET_NR_sync 81 +#define TARGET_NR_fsync 82 +#define TARGET_NR_fdatasync 83 +#define TARGET_NR_sync_file_range 84 +#define TARGET_NR_timerfd_create 85 +#define TARGET_NR_timerfd_settime 86 +#define TARGET_NR_timerfd_gettime 87 +#define TARGET_NR_utimensat 88 +#define TARGET_NR_acct 89 +#define TARGET_NR_capget 90 +#define TARGET_NR_capset 91 +#define TARGET_NR_personality 92 +#define TARGET_NR_exit 93 +#define TARGET_NR_exit_group 94 +#define TARGET_NR_waitid 95 +#define TARGET_NR_set_tid_address 96 +#define TARGET_NR_unshare 97 +#define TARGET_NR_futex 98 +#define TARGET_NR_set_robust_list 99 +#define TARGET_NR_get_robust_list 100 +#define TARGET_NR_nanosleep 101 +#define TARGET_NR_getitimer 102 +#define TARGET_NR_setitimer 103 +#define TARGET_NR_kexec_load 104 +#define TARGET_NR_init_module 105 +#define TARGET_NR_delete_module 106 +#define TARGET_NR_timer_create 107 +#define TARGET_NR_timer_gettime 108 +#define TARGET_NR_timer_getoverrun 109 +#define TARGET_NR_timer_settime 110 +#define TARGET_NR_timer_delete 111 +#define TARGET_NR_clock_settime 112 +#define TARGET_NR_clock_gettime 113 +#define TARGET_NR_clock_getres 114 +#define TARGET_NR_clock_nanosleep 115 +#define TARGET_NR_syslog 116 +#define TARGET_NR_ptrace 117 +#define TARGET_NR_sched_setparam 118 +#define TARGET_NR_sched_setscheduler 119 +#define TARGET_NR_sched_getscheduler 120 +#define TARGET_NR_sched_getparam 121 +#define TARGET_NR_sched_setaffinity 122 +#define TARGET_NR_sched_getaffinity 123 +#define TARGET_NR_sched_yield 124 +#define TARGET_NR_sched_get_priority_max 125 +#define TARGET_NR_sched_get_priority_min 126 +#define TARGET_NR_sched_rr_get_interval 127 +#define TARGET_NR_restart_syscall 128 +#define TARGET_NR_kill 129 +#define TARGET_NR_tkill 130 +#define TARGET_NR_tgkill 131 +#define TARGET_NR_sigaltstack 132 +#define TARGET_NR_rt_sigsuspend 133 +#define TARGET_NR_rt_sigaction 134 +#define TARGET_NR_rt_sigprocmask 135 +#define TARGET_NR_rt_sigpending 136 +#define TARGET_NR_rt_sigtimedwait 137 +#define TARGET_NR_rt_sigqueueinfo 138 +#define TARGET_NR_rt_sigreturn 139 +#define TARGET_NR_setpriority 140 +#define TARGET_NR_getpriority 141 +#define TARGET_NR_reboot 142 +#define TARGET_NR_setregid 143 +#define TARGET_NR_setgid 144 +#define TARGET_NR_setreuid 145 +#define TARGET_NR_setuid 146 +#define TARGET_NR_setresuid 147 +#define TARGET_NR_getresuid 148 +#define TARGET_NR_setresgid 149 +#define TARGET_NR_getresgid 150 +#define TARGET_NR_setfsuid 151 +#define TARGET_NR_setfsgid 152 +#define TARGET_NR_times 153 +#define TARGET_NR_setpgid 154 +#define TARGET_NR_getpgid 155 +#define TARGET_NR_getsid 156 +#define TARGET_NR_setsid 157 +#define TARGET_NR_getgroups 158 +#define TARGET_NR_setgroups 159 +#define TARGET_NR_uname 160 +#define TARGET_NR_sethostname 161 +#define TARGET_NR_setdomainname 162 +#define TARGET_NR_getrusage 165 +#define TARGET_NR_umask 166 +#define TARGET_NR_prctl 167 +#define TARGET_NR_getcpu 168 +#define TARGET_NR_gettimeofday 169 +#define TARGET_NR_settimeofday 170 +#define TARGET_NR_adjtimex 171 +#define TARGET_NR_getpid 172 +#define TARGET_NR_getppid 173 +#define TARGET_NR_getuid 174 +#define TARGET_NR_geteuid 175 +#define TARGET_NR_getgid 176 +#define TARGET_NR_getegid 177 +#define TARGET_NR_gettid 178 +#define TARGET_NR_sysinfo 179 +#define TARGET_NR_mq_open 180 +#define TARGET_NR_mq_unlink 181 +#define TARGET_NR_mq_timedsend 182 +#define TARGET_NR_mq_timedreceive 183 +#define TARGET_NR_mq_notify 184 +#define TARGET_NR_mq_getsetattr 185 +#define TARGET_NR_msgget 186 +#define TARGET_NR_msgctl 187 +#define TARGET_NR_msgrcv 188 +#define TARGET_NR_msgsnd 189 +#define TARGET_NR_semget 190 +#define TARGET_NR_semctl 191 +#define TARGET_NR_semtimedop 192 +#define TARGET_NR_semop 193 +#define TARGET_NR_shmget 194 +#define TARGET_NR_shmctl 195 +#define TARGET_NR_shmat 196 +#define TARGET_NR_shmdt 197 +#define TARGET_NR_socket 198 +#define TARGET_NR_socketpair 199 +#define TARGET_NR_bind 200 +#define TARGET_NR_listen 201 +#define TARGET_NR_accept 202 +#define TARGET_NR_connect 203 +#define TARGET_NR_getsockname 204 +#define TARGET_NR_getpeername 205 +#define TARGET_NR_sendto 206 +#define TARGET_NR_recvfrom 207 +#define TARGET_NR_setsockopt 208 +#define TARGET_NR_getsockopt 209 +#define TARGET_NR_shutdown 210 +#define TARGET_NR_sendmsg 211 +#define TARGET_NR_recvmsg 212 +#define TARGET_NR_readahead 213 +#define TARGET_NR_brk 214 +#define TARGET_NR_munmap 215 +#define TARGET_NR_mremap 216 +#define TARGET_NR_add_key 217 +#define TARGET_NR_request_key 218 +#define TARGET_NR_keyctl 219 +#define TARGET_NR_clone 220 +#define TARGET_NR_execve 221 +#define TARGET_NR_mmap 222 +#define TARGET_NR_fadvise64 223 +#define TARGET_NR_swapon 224 +#define TARGET_NR_swapoff 225 +#define TARGET_NR_mprotect 226 +#define TARGET_NR_msync 227 +#define TARGET_NR_mlock 228 +#define TARGET_NR_munlock 229 +#define TARGET_NR_mlockall 230 +#define TARGET_NR_munlockall 231 +#define TARGET_NR_mincore 232 +#define TARGET_NR_madvise 233 +#define TARGET_NR_remap_file_pages 234 +#define TARGET_NR_mbind 235 +#define TARGET_NR_get_mempolicy 236 +#define TARGET_NR_set_mempolicy 237 +#define TARGET_NR_migrate_pages 238 +#define TARGET_NR_move_pages 239 +#define TARGET_NR_rt_tgsigqueueinfo 240 +#define TARGET_NR_perf_event_open 241 +#define TARGET_NR_accept4 242 +#define TARGET_NR_recvmmsg 243 +#define TARGET_NR_arch_specific_syscall 244 +#define TARGET_NR_wait4 260 +#define TARGET_NR_prlimit64 261 +#define TARGET_NR_fanotify_init 262 +#define TARGET_NR_fanotify_mark 263 +#define TARGET_NR_name_to_handle_at 264 +#define TARGET_NR_open_by_handle_at 265 +#define TARGET_NR_clock_adjtime 266 +#define TARGET_NR_syncfs 267 +#define TARGET_NR_setns 268 +#define TARGET_NR_sendmmsg 269 +#define TARGET_NR_process_vm_readv 270 +#define TARGET_NR_process_vm_writev 271 +#define TARGET_NR_kcmp 272 +#define TARGET_NR_finit_module 273 +#define TARGET_NR_sched_setattr 274 +#define TARGET_NR_sched_getattr 275 +#define TARGET_NR_renameat2 276 +#define TARGET_NR_seccomp 277 +#define TARGET_NR_getrandom 278 +#define TARGET_NR_memfd_create 279 +#define TARGET_NR_bpf 280 +#define TARGET_NR_execveat 281 +#define TARGET_NR_userfaultfd 282 +#define TARGET_NR_membarrier 283 +#define TARGET_NR_mlock2 284 +#define TARGET_NR_copy_file_range 285 +#define TARGET_NR_preadv2 286 +#define TARGET_NR_pwritev2 287 +#define TARGET_NR_pkey_mprotect 288 +#define TARGET_NR_pkey_alloc 289 +#define TARGET_NR_pkey_free 290 +#define TARGET_NR_statx 291 +#define TARGET_NR_io_pgetevents 292 +#define TARGET_NR_rseq 293 +#define TARGET_NR_kexec_file_load 294 +#define TARGET_NR_pidfd_send_signal 424 +#define TARGET_NR_io_uring_setup 425 +#define TARGET_NR_io_uring_enter 426 +#define TARGET_NR_io_uring_register 427 +#define TARGET_NR_open_tree 428 +#define TARGET_NR_move_mount 429 +#define TARGET_NR_fsopen 430 +#define TARGET_NR_fsconfig 431 +#define TARGET_NR_fsmount 432 +#define TARGET_NR_fspick 433 +#define TARGET_NR_pidfd_open 434 +#define TARGET_NR_clone3 435 +#define TARGET_NR_close_range 436 +#define TARGET_NR_openat2 437 +#define TARGET_NR_pidfd_getfd 438 +#define TARGET_NR_faccessat2 439 +#define TARGET_NR_process_madvise 440 +#define TARGET_NR_epoll_pwait2 441 +#define TARGET_NR_mount_setattr 442 +#define TARGET_NR_quotactl_fd 443 +#define TARGET_NR_landlock_create_ruleset 444 +#define TARGET_NR_landlock_add_rule 445 +#define TARGET_NR_landlock_restrict_self 446 +#define TARGET_NR_process_mrelease 448 +#define TARGET_NR_syscalls 449 + +#endif /* LINUX_USER_LOONGARCH_SYSCALL_NR_H */ diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h new file mode 100644 index 0000000..5bd13a7 --- /dev/null +++ b/linux-user/loongarch64/target_cpu.h @@ -0,0 +1,35 @@ +/* + * LoongArch specific CPU ABI and functions for linux-user + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_CPU_H +#define LOONGARCH_TARGET_CPU_H + +static inline void cpu_clone_regs_child(CPULoongArchState *env, + target_ulong newsp, unsigned flags) +{ + if (newsp) { + env->gpr[3] = newsp; + } + env->gpr[4] = 0; +} + +static inline void cpu_clone_regs_parent(CPULoongArchState *env, + unsigned flags) +{ +} + +static inline void cpu_set_tls(CPULoongArchState *env, target_ulong newtls) +{ + env->gpr[2] = newtls; +} + +static inline abi_ulong get_sp_from_cpustate(CPULoongArchState *state) +{ + return state->gpr[3]; +} +#endif diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h new file mode 100644 index 0000000..7c88394 --- /dev/null +++ b/linux-user/loongarch64/target_elf.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + + +#ifndef LOONGARCH_TARGET_ELF_H +#define LOONGARCH_TARGET_ELF_H +static inline const char *cpu_get_model(uint32_t eflags) +{ + return "Loongson-3A5000"; +} +#endif diff --git a/linux-user/loongarch64/target_errno_defs.h b/linux-user/loongarch64/target_errno_defs.h new file mode 100644 index 0000000..17165c1 --- /dev/null +++ b/linux-user/loongarch64/target_errno_defs.h @@ -0,0 +1,7 @@ +#ifndef LOONGARCH_TARGET_ERRNO_DEFS_H +#define LOONGARCH_TARGET_ERRNO_DEFS_H + +/* Target uses generic errno */ +#include "../generic/target_errno_defs.h" + +#endif diff --git a/linux-user/loongarch64/target_fcntl.h b/linux-user/loongarch64/target_fcntl.h new file mode 100644 index 0000000..b810293 --- /dev/null +++ b/linux-user/loongarch64/target_fcntl.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_FCNTL_H +#define LOONGARCH_TARGET_FCNTL_H + +#include "../generic/fcntl.h" + +#endif /* LOONGARCH_TARGET_FCNTL_H */ diff --git a/linux-user/loongarch64/target_signal.h b/linux-user/loongarch64/target_signal.h new file mode 100644 index 0000000..2deb88c --- /dev/null +++ b/linux-user/loongarch64/target_signal.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_SIGNAL_H +#define LOONGARCH_TARGET_SIGNAL_H + +/* this struct defines a stack used during syscall handling */ +typedef struct target_sigaltstack { + abi_long ss_sp; + abi_int ss_flags; + abi_ulong ss_size; +} target_stack_t; + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK 1 +#define TARGET_SS_DISABLE 2 + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_SIGSTKSZ 8192 + +#include "../generic/signal.h" + +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 + +#endif /* LOONGARCH_TARGET_SIGNAL_H */ diff --git a/linux-user/loongarch64/target_structs.h b/linux-user/loongarch64/target_structs.h new file mode 100644 index 0000000..818e8d6 --- /dev/null +++ b/linux-user/loongarch64/target_structs.h @@ -0,0 +1,49 @@ +/* + * LoongArch specific structures for linux-user + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_STRUCTS_H +#define LOONGARCH_TARGET_STRUCTS_H + +struct target_ipc_perm { + abi_int __key; /* Key. */ + abi_uint uid; /* Owner's user ID. */ + abi_uint gid; /* Owner's group ID. */ + abi_uint cuid; /* Creator's user ID. */ + abi_uint cgid; /* Creator's group ID. */ + abi_uint mode; /* Read/write permission. */ + abi_ushort __seq; /* Sequence number. */ + abi_ushort __pad1; + abi_ulong __unused1; + abi_ulong __unused2; +}; + +struct target_shmid_ds { + struct target_ipc_perm shm_perm; /* operation permission struct */ + abi_long shm_segsz; /* size of segment in bytes */ + abi_ulong shm_atime; /* time of last shmat() */ + abi_ulong shm_dtime; /* time of last shmdt() */ + abi_ulong shm_ctime; /* time of last change by shmctl() */ + abi_int shm_cpid; /* pid of creator */ + abi_int shm_lpid; /* pid of last shmop */ + abi_ulong shm_nattch; /* number of current attaches */ + abi_ulong __unused1; + abi_ulong __unused2; +}; + +#define TARGET_SEMID64_DS + +struct target_semid64_ds { + struct target_ipc_perm sem_perm; + abi_ulong sem_otime; + abi_ulong sem_ctime; + abi_ulong sem_nsems; + abi_ulong __unused1; + abi_ulong __unused2; +}; + +#endif diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h new file mode 100644 index 0000000..393160d --- /dev/null +++ b/linux-user/loongarch64/target_syscall.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_SYSCALL_H +#define LOONGARCH_TARGET_SYSCALL_H + +/* + * this struct defines the way the registers are stored on the + * stack during a system call. + */ + +struct target_pt_regs { + /* Saved main processor registers. */ + target_ulong regs[32]; + + /* Saved special registers. */ + target_ulong csr_crmd; + target_ulong csr_prmd; + target_ulong csr_euen; + target_ulong csr_ecfg; + target_ulong csr_estat; + target_ulong csr_era; + target_ulong csr_badvaddr; + target_ulong orig_a0; + target_ulong __last[0]; +}; + +#define UNAME_MACHINE "loongarch64" +#define UNAME_MINIMUM_RELEASE "4.19.0" + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MCL_CURRENT 1 +#define TARGET_MCL_FUTURE 2 +#define TARGET_MCL_ONFAULT 4 + +#define TARGET_FORCE_SHMLBA + +static inline abi_ulong target_shmlba(CPULoongArchState *env) +{ + return 0x40000; +} + +#endif diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h new file mode 100644 index 0000000..b1d4f4f --- /dev/null +++ b/linux-user/loongarch64/termbits.h @@ -0,0 +1 @@ +#include "../generic/termbits.h" diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index a5ce487..bec125f 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -74,7 +74,7 @@ || defined(TARGET_M68K) || defined(TARGET_CRIS) \ || defined(TARGET_S390X) || defined(TARGET_OPENRISC) \ || defined(TARGET_NIOS2) || defined(TARGET_RISCV) \ - || defined(TARGET_XTENSA) + || defined(TARGET_XTENSA) || defined(TARGET_LOONGARCH64) #define TARGET_IOC_SIZEBITS 14 #define TARGET_IOC_DIRBITS 2 @@ -2129,7 +2129,8 @@ struct target_stat64 { abi_ulong __unused5; }; -#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV) +#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || \ + defined(TARGET_RISCV) || defined(TARGET_LOONGARCH64) /* These are the asm-generic versions of the stat and stat64 structures */ @@ -2157,7 +2158,7 @@ struct target_stat { unsigned int __unused5; }; -#if !defined(TARGET_RISCV64) +#if !defined(TARGET_RISCV64) && !defined(TARGET_LOONGARCH64) #define TARGET_HAS_STRUCT_STAT64 struct target_stat64 { uint64_t st_dev; @@ -2327,7 +2328,8 @@ struct target_statfs64 { }; #elif (defined(TARGET_PPC64) || defined(TARGET_X86_64) || \ defined(TARGET_SPARC64) || defined(TARGET_AARCH64) || \ - defined(TARGET_RISCV)) && !defined(TARGET_ABI32) + defined(TARGET_RISCV) || defined(TARGET_LOONGARCH64)) && \ + !defined(TARGET_ABI32) struct target_statfs { abi_long f_type; abi_long f_bsize; diff --git a/scripts/gensyscalls.sh b/scripts/gensyscalls.sh index 8fb450e..b69e193 100755 --- a/scripts/gensyscalls.sh +++ b/scripts/gensyscalls.sh @@ -99,4 +99,5 @@ generate_syscall_nr openrisc 32 "$output/linux-user/openrisc/syscall_nr.h" generate_syscall_nr riscv 32 "$output/linux-user/riscv/syscall32_nr.h" generate_syscall_nr riscv 64 "$output/linux-user/riscv/syscall64_nr.h" generate_syscall_nr hexagon 32 "$output/linux-user/hexagon/syscall_nr.h" +generate_syscall_nr loongarch 64 "$output/linux-user/loongarch64/syscall_nr.h" rm -fr "$TMP"