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;
+};
+
+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 */
--
1.8.3.1
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: >> +{ >> + 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~
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: > > 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 -- Huacai Chen
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~
© 2016 - 2024 Red Hat, Inc.