Skip to content

Commit 656f9ae

Browse files
committed
LoongArch: Ensure FP/SIMD registers in the core dump file is up to date
This is a port of commit 379eb01 ("riscv: Ensure the value of FP registers in the core dump file is up to date"). The values of FP/SIMD registers in the core dump file come from the thread.fpu. However, kernel saves the FP/SIMD registers only before scheduling out the process. If no process switch happens during the exception handling, kernel will not have a chance to save the latest values of FP/SIMD registers. So it may cause their values in the core dump file incorrect. To solve this problem, force fpr_get()/simd_get() to save the FP/SIMD registers into the thread.fpu if the target task equals the current task. Cc: stable@vger.kernel.org Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent c337c84 commit 656f9ae

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

arch/loongarch/include/asm/fpu.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,16 +173,30 @@ static inline void restore_fp(struct task_struct *tsk)
173173
_restore_fp(&tsk->thread.fpu);
174174
}
175175

176-
static inline union fpureg *get_fpu_regs(struct task_struct *tsk)
176+
static inline void save_fpu_regs(struct task_struct *tsk)
177177
{
178+
unsigned int euen;
179+
178180
if (tsk == current) {
179181
preempt_disable();
180-
if (is_fpu_owner())
182+
183+
euen = csr_read32(LOONGARCH_CSR_EUEN);
184+
185+
#ifdef CONFIG_CPU_HAS_LASX
186+
if (euen & CSR_EUEN_LASXEN)
187+
_save_lasx(&current->thread.fpu);
188+
else
189+
#endif
190+
#ifdef CONFIG_CPU_HAS_LSX
191+
if (euen & CSR_EUEN_LSXEN)
192+
_save_lsx(&current->thread.fpu);
193+
else
194+
#endif
195+
if (euen & CSR_EUEN_FPEN)
181196
_save_fp(&current->thread.fpu);
197+
182198
preempt_enable();
183199
}
184-
185-
return tsk->thread.fpu.fpr;
186200
}
187201

188202
static inline int is_simd_owner(void)

arch/loongarch/kernel/ptrace.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ static int fpr_get(struct task_struct *target,
147147
{
148148
int r;
149149

150+
save_fpu_regs(target);
151+
150152
if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
151153
r = gfpr_get(target, &to);
152154
else
@@ -278,6 +280,8 @@ static int simd_get(struct task_struct *target,
278280
{
279281
const unsigned int wr_size = NUM_FPU_REGS * regset->size;
280282

283+
save_fpu_regs(target);
284+
281285
if (!tsk_used_math(target)) {
282286
/* The task hasn't used FP or LSX, fill with 0xff */
283287
copy_pad_fprs(target, regset, &to, 0);

0 commit comments

Comments
 (0)