From: Greg Kroah-Hartman Date: Mon, 22 Jan 2024 19:50:01 +0000 (-0800) Subject: 6.1-stable patches X-Git-Tag: v4.19.306~55 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f4fd844c6febe51093934a1aab00c729ea7fbf74;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: loongarch-fix-and-simplify-fcsr-initialization-on-execve.patch --- diff --git a/queue-6.1/loongarch-fix-and-simplify-fcsr-initialization-on-execve.patch b/queue-6.1/loongarch-fix-and-simplify-fcsr-initialization-on-execve.patch new file mode 100644 index 00000000000..0583017ecf2 --- /dev/null +++ b/queue-6.1/loongarch-fix-and-simplify-fcsr-initialization-on-execve.patch @@ -0,0 +1,117 @@ +From c2396651309eba291c15e32db8fbe44c738b5921 Mon Sep 17 00:00:00 2001 +From: Xi Ruoyao +Date: Wed, 17 Jan 2024 12:43:08 +0800 +Subject: LoongArch: Fix and simplify fcsr initialization on execve() + +From: Xi Ruoyao + +commit c2396651309eba291c15e32db8fbe44c738b5921 upstream. + +There has been a lingering bug in LoongArch Linux systems causing some +GCC tests to intermittently fail (see Closes link). I've made a minimal +reproducer: + + zsh% cat measure.s + .align 4 + .globl _start + _start: + movfcsr2gr $a0, $fcsr0 + bstrpick.w $a0, $a0, 16, 16 + beqz $a0, .ok + break 0 + .ok: + li.w $a7, 93 + syscall 0 + zsh% cc mesaure.s -o measure -nostdlib + zsh% echo $((1.0/3)) + 0.33333333333333331 + zsh% while ./measure; do ; done + +This while loop should not stop as POSIX is clear that execve must set +fenv to the default, where FCSR should be zero. But in fact it will +just stop after running for a while (normally less than 30 seconds). +Note that "$((1.0/3))" is needed to reproduce this issue because it +raises FE_INVALID and makes fcsr0 non-zero. + +The problem is we are currently relying on SET_PERSONALITY2() to reset +current->thread.fpu.fcsr. But SET_PERSONALITY2() is executed before +start_thread which calls lose_fpu(0). We can see if kernel preempt is +enabled, we may switch to another thread after SET_PERSONALITY2() but +before lose_fpu(0). Then bad thing happens: during the thread switch +the value of the fcsr0 register is stored into current->thread.fpu.fcsr, +making it dirty again. + +The issue can be fixed by setting current->thread.fpu.fcsr after +lose_fpu(0) because lose_fpu() clears TIF_USEDFPU, then the thread +switch won't touch current->thread.fpu.fcsr. + +The only other architecture setting FCSR in SET_PERSONALITY2() is MIPS. +I've ran a similar test on MIPS with mainline kernel and it turns out +MIPS is buggy, too. Anyway MIPS do this for supporting different FP +flavors (NaN encodings, etc.) which do not exist on LoongArch. So for +LoongArch, we can simply remove the current->thread.fpu.fcsr setting +from SET_PERSONALITY2() and do it in start_thread(), after lose_fpu(0). + +The while loop failing with the mainline kernel has survived one hour +after this change on LoongArch. + +Fixes: 803b0fc5c3f2baa ("LoongArch: Add process management") +Closes: https://github.com/loongson-community/discussions/issues/7 +Link: https://lore.kernel.org/linux-mips/7a6aa1bbdbbe2e63ae96ff163fab0349f58f1b9e.camel@xry111.site/ +Cc: stable@vger.kernel.org +Signed-off-by: Xi Ruoyao +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/include/asm/elf.h | 5 ----- + arch/loongarch/kernel/elf.c | 5 ----- + arch/loongarch/kernel/process.c | 1 + + 3 files changed, 1 insertion(+), 10 deletions(-) + +--- a/arch/loongarch/include/asm/elf.h ++++ b/arch/loongarch/include/asm/elf.h +@@ -241,8 +241,6 @@ void loongarch_dump_regs64(u64 *uregs, c + do { \ + current->thread.vdso = &vdso_info; \ + \ +- loongarch_set_personality_fcsr(state); \ +- \ + if (personality(current->personality) != PER_LINUX) \ + set_personality(PER_LINUX); \ + } while (0) +@@ -259,7 +257,6 @@ do { \ + clear_thread_flag(TIF_32BIT_ADDR); \ + \ + current->thread.vdso = &vdso_info; \ +- loongarch_set_personality_fcsr(state); \ + \ + p = personality(current->personality); \ + if (p != PER_LINUX32 && p != PER_LINUX) \ +@@ -340,6 +337,4 @@ extern int arch_elf_pt_proc(void *ehdr, + extern int arch_check_elf(void *ehdr, bool has_interpreter, void *interp_ehdr, + struct arch_elf_state *state); + +-extern void loongarch_set_personality_fcsr(struct arch_elf_state *state); +- + #endif /* _ASM_ELF_H */ +--- a/arch/loongarch/kernel/elf.c ++++ b/arch/loongarch/kernel/elf.c +@@ -23,8 +23,3 @@ int arch_check_elf(void *_ehdr, bool has + { + return 0; + } +- +-void loongarch_set_personality_fcsr(struct arch_elf_state *state) +-{ +- current->thread.fpu.fcsr = boot_cpu_data.fpu_csr0; +-} +--- a/arch/loongarch/kernel/process.c ++++ b/arch/loongarch/kernel/process.c +@@ -82,6 +82,7 @@ void start_thread(struct pt_regs *regs, + euen = regs->csr_euen & ~(CSR_EUEN_FPEN); + regs->csr_euen = euen; + lose_fpu(0); ++ current->thread.fpu.fcsr = boot_cpu_data.fpu_csr0; + + clear_thread_flag(TIF_LSX_CTX_LIVE); + clear_thread_flag(TIF_LASX_CTX_LIVE); diff --git a/queue-6.1/series b/queue-6.1/series index 6a76ea8a22e..04d37bbbb8f 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -301,3 +301,4 @@ md-raid1-use-blk_opf_t-for-read-and-write-operations.patch rootfs-fix-support-for-rootfstype-when-root-is-given.patch bluetooth-fix-atomicity-violation-in-min-max-_key_size_set.patch bpf-fix-re-attachment-branch-in-bpf_tracing_prog_attach.patch +loongarch-fix-and-simplify-fcsr-initialization-on-execve.patch