Message ID | 1637302410-24632-20-git-send-email-gaosong@loongson.cn (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add LoongArch linux-user emulation support | expand |
On 11/19/21 7:13 AM, Song Gao wrote: > Signed-off-by: Song Gao <gaosong@loongson.cn> > Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn> > --- > linux-user/loongarch64/signal.c | 162 +++++++++++++++++++++++++++++++++ > linux-user/loongarch64/target_signal.h | 29 ++++++ > 2 files changed, 191 insertions(+) > create mode 100644 linux-user/loongarch64/signal.c > create mode 100644 linux-user/loongarch64/target_signal.h > > diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c > new file mode 100644 > index 0000000..8fbc827 > --- /dev/null > +++ b/linux-user/loongarch64/signal.c > @@ -0,0 +1,162 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * LoongArch emulation of Linux signals > + * > + * Copyright (c) 2021 Loongson Technology Corporation Limited > + */ > + > +#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; > +}; Does not match https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/sigcontext.h > + > +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; > +}; Does not match https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/ucontext.h > +static inline void setup_sigcontext(CPULoongArchState *env, > + struct target_sigcontext *sc) Drop all of the the inline markers. > +{ > + 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]); > + } > +} Missing fcsr and fcc. I'll note that the kernel is missing sets of vscr and scr[0-3]. IMO they should at least be zeroed in advance of supporting the vector extension. > +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]); > + } > +} Similarly. > + return (sp - frame_size) & ~7; include/asm/asm.h:#define ALMASK ~15 kernel/signal.c: return (void __user *)((sp - frame_size) & ALMASK); > + env->pc = env->gpr[20] = ka->_sa_handler; There is no set of gpr[20]. > +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 */ The comment is incorrect: "ori a7, zero, 0x8b", but the hex is right. > +/* 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 We should move these to generic/signal.h. r~
Hi Richard, On 2021/11/20 下午6:33, Richard Henderson wrote: > > Drop all of the the inline markers. > >> +{ >> + 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]); >> + } >> +} > > Missing fcsr and fcc. > > I'll note that the kernel is missing sets of vscr and scr[0-3]. IMO > they should at least be zeroed in advance of supporting the vector > extension. I see that vcsr set at [1]:178. [1] https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/kernel/signal.c and I also see that the kernel is missing sets of scr[0-3], Huacai is that right? Thanks Song Gao
Hi, all, On Mon, Nov 22, 2021 at 7:41 PM gaosong <gaosong@loongson.cn> wrote: > > Hi Richard, > > On 2021/11/20 下午6:33, Richard Henderson wrote: > > > Drop all of the the inline markers. > > +{ > + 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]); > + } > +} > > > Missing fcsr and fcc. > > I'll note that the kernel is missing sets of vscr and scr[0-3]. IMO they should at least be zeroed in advance of supporting the vector extension. > > I see that vcsr set at [1]:178. > [1] > https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/kernel/signal.c > > and I also see that the kernel is missing sets of scr[0-3], Huacai is that right? scr[0-3] is reserved for binary translation, it doesn't need to be set now. Huacai > > Thanks > Song Gao
On 11/22/21 12:41 PM, gaosong wrote: > Hi Richard, > > On 2021/11/20 下午6:33, Richard Henderson wrote: >> >> Drop all of the the inline markers. >> >>> +{ >>> + 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]); >>> + } >>> +} >> >> Missing fcsr and fcc. >> >> I'll note that the kernel is missing sets of vscr and scr[0-3]. IMO they should at least >> be zeroed in advance of supporting the vector extension. > > I see that vcsr set at [1]:178. > [1] > https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/kernel/signal.c That happens after line 171: if (likely(!err)) break; It seems most unlikely that there would be an error... There is a macro for sc_save_vcsr in fpu.S, but it isn't used. r~
Hi Richard, On 2021/11/20 下午6:33, Richard Henderson wrote: > On 11/19/21 7:13 AM, Song Gao wrote: >> >> + >> +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; >> +}; > > Does not match > https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/sigcontext.h > > #define FPU_REG_WIDTH 256 union fpureg { uint32_t val32[FPU_REG_WIDTH / 32]; uint64_t val64[FPU_REG_WIDTH / 64]; }; struct target_sigcontext { uint64_t sc_pc; uint64_t sc_regs[32]; uint32_t sc_flags; uint32_t sc_fcsr; uint32_t sc_vcsr; uint64_t sc_fcc; uint64_t scr[4]; union fpureg sc_fpregs[32] __attribute__((aligned(32))); uint32_t sc_reserved; }; Is this OK? >> + >> +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; >> +}; > > Does not match > https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/ucontext.h > > struct target_ucontext { target_ulong tuc_flags; target_ulong tuc_link; target_stack_t tuc_stack; target_sigset_t tuc_sigmask; target_ulong pad0; struct target_sigcontext tuc_mcontext; }; Is this OK? Thanks Song Gao
On 11/24/21 3:46 AM, gaosong wrote: > Hi Richard, > > On 2021/11/20 下午6:33, Richard Henderson wrote: >> On 11/19/21 7:13 AM, Song Gao wrote: >>> >>> + >>> +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; >>> +}; >> >> Does not match >> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/sigcontext.h >> >> > #define FPU_REG_WIDTH 256 > union fpureg { > uint32_t val32[FPU_REG_WIDTH / 32]; > uint64_t val64[FPU_REG_WIDTH / 64]; > }; > > struct target_sigcontext { > uint64_t sc_pc; > uint64_t sc_regs[32]; > uint32_t sc_flags; > > uint32_t sc_fcsr; > uint32_t sc_vcsr; > uint64_t sc_fcc; > uint64_t scr[4]; > union fpureg sc_fpregs[32] __attribute__((aligned(32))); > > uint32_t sc_reserved; > }; > > Is this OK? No, sc_reserved does not match. > >>> + >>> +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; >>> +}; >> >> Does not match >> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/ucontext.h >> >> > struct target_ucontext { > target_ulong tuc_flags; > target_ulong tuc_link; > target_stack_t tuc_stack; > target_sigset_t tuc_sigmask; > target_ulong pad0; > struct target_sigcontext tuc_mcontext; > }; > > Is this OK? No, pad0 does not match __unused. r~
Hi Richard, On 2021/11/24 下午3:27, Richard Henderson wrote: > On 11/24/21 3:46 AM, gaosong wrote: >> Hi Richard, >> >> On 2021/11/20 下午6:33, Richard Henderson wrote: >>> On 11/19/21 7:13 AM, Song Gao wrote: >>>> >>>> + >>>> +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; >>>> +}; >>> >>> Does not match >>> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/sigcontext.h >>> >>> >> #define FPU_REG_WIDTH 256 >> union fpureg { >> uint32_t val32[FPU_REG_WIDTH / 32]; >> uint64_t val64[FPU_REG_WIDTH / 64]; >> }; >> >> struct target_sigcontext { >> uint64_t sc_pc; >> uint64_t sc_regs[32]; >> uint32_t sc_flags; >> >> uint32_t sc_fcsr; >> uint32_t sc_vcsr; >> uint64_t sc_fcc; >> uint64_t scr[4]; >> union fpureg sc_fpregs[32] __attribute__((aligned(32))); >> >> uint32_t sc_reserved; >> }; >> >> Is this OK? > > No, sc_reserved does not match. > uint8 sc_reserved[4096] __attribute__((aligned(16))); BTW, should we set scr[0-3] as 0 ? >> >>>> + >>>> +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; >>>> +}; >>> >>> Does not match >>> https://github.com/loongson/linux/blob/loongarch-next/arch/loongarch/include/uapi/asm/ucontext.h >>> >>> >> struct target_ucontext { >> target_ulong tuc_flags; >> target_ulong tuc_link; >> target_stack_t tuc_stack; >> target_sigset_t tuc_sigmask; >> target_ulong pad0; >> struct target_sigcontext tuc_mcontext; >> }; >> >> Is this OK? > > No, pad0 does not match __unused. > uint8 unused[1024 / 8 - sizeof(target_sigset_t)]; Is this right? Thanks Song Gao > > r~
On 11/24/21 8:50 AM, gaosong wrote: >> No, sc_reserved does not match. >> > uint8 sc_reserved[4096] __attribute__((aligned(16))); Yes. > BTW, should we set scr[0-3] as 0 ? I think so. The LoongArch Reference Manual, Volume 3: Virtualization and Binary Translation Extensions, v1.00, is empty. But I do not imagine a world in which 0 is not a safe indication of "this field is empty/unused". >> No, pad0 does not match __unused. >> > uint8 unused[1024 / 8 - sizeof(target_sigset_t)]; > Is this right? Yes. r~
Hi Richard, On 2021/11/20 下午6:33, Richard Henderson wrote: >> +{ >> + 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]); >> + } >> +} > > Missing fcsr and fcc. I see that kernel define the fcc used type uint64_t, and used movgr2cf/movcf2gr save and restore the fcc0-fcc7. but qemu define fcc0-fcc7 as bool cf[8] at target/loongarch/cpu.h, how qemu can save/restore fcc, Do you have any idea? Does we can define the fcc as bool cf[8] at struct target_sigcontext? Thanks Song Gao
On 11/24/21 11:22 AM, gaosong wrote: > I see that kernel define the fcc used type uint64_t, and used movgr2cf/movcf2gr > save and restore the fcc0-fcc7. > but qemu define fcc0-fcc7 as bool cf[8] at target/loongarch/cpu.h, how qemu can > save/restore fcc, Do you have any idea? > Does we can define the fcc as bool cf[8] at struct target_sigcontext? No, you need to leave the declaration the same. To create the uint64_t, you do what the kernel does in sc_save_fcc: insert each bit into the first bit of each byte. static uint64_t read_all_fcc(CPULoongArchState *env) { uint64_t ret = 0; for (int i = 0; i < 8; ++i) { ret |= (uint64_t)env->cf[i] << (i * 8); } return ret; } And similarly from sc_restore_fcc: static void write_all_fcc(CPULoongArchState *env, uint64_t val) { for (int i = 0; i < 8; ++i) { env->cf[i] = (val >> (i * 8)) & 1; } } Remembering that movcf2gr copies the least significant bit. r~
Hi Richard, On 2021/11/20 下午6:33, Richard Henderson wrote: >> +/* 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 > > We should move these to generic/signal.h. Yes. I also see that TARGET_SIGSTKSZ is not used. I think we should delete it. Thanks Song Gao
On 11/25/21 4:03 AM, gaosong wrote:
> I also see that TARGET_SIGSTKSZ is not used. I think we should delete it.
Agreed. This constant will have been baked into the guest executable.
r~
diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c new file mode 100644 index 0000000..8fbc827 --- /dev/null +++ b/linux-user/loongarch64/signal.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * LoongArch emulation of Linux signals + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + */ + +#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/target_signal.h b/linux-user/loongarch64/target_signal.h new file mode 100644 index 0000000..c5f467b --- /dev/null +++ b/linux-user/loongarch64/target_signal.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + */ + +#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 */