Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

LoongArch: Adjust process management for 32BIT/64BIT

Adjust process management for both 32BIT and 64BIT, including: CPU
context switching, FPU loading/restoring, process dumping and process
tracing routines.

Q: Why modify switch.S?
A: LoongArch32 has no ldptr.d/stptr.d instructions, and asm offsets of
thead_struct members are too large to be filled in the 12b immediate
field of ld.w/st.w.

Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

+187 -16
+31
arch/loongarch/include/asm/elf.h
··· 120 120 #define R_LARCH_ADD_ULEB128 107 121 121 #define R_LARCH_SUB_ULEB128 108 122 122 #define R_LARCH_64_PCREL 109 123 + #define R_LARCH_CALL36 110 124 + #define R_LARCH_TLS_DESC_PC_HI20 111 125 + #define R_LARCH_TLS_DESC_PC_LO12 112 126 + #define R_LARCH_TLS_DESC64_PC_LO20 113 127 + #define R_LARCH_TLS_DESC64_PC_HI12 114 128 + #define R_LARCH_TLS_DESC_HI20 115 129 + #define R_LARCH_TLS_DESC_LO12 116 130 + #define R_LARCH_TLS_DESC64_LO20 117 131 + #define R_LARCH_TLS_DESC64_HI12 118 132 + #define R_LARCH_TLS_DESC_LD 119 133 + #define R_LARCH_TLS_DESC_CALL 120 134 + #define R_LARCH_TLS_LE_HI20_R 121 135 + #define R_LARCH_TLS_LE_ADD_R 122 136 + #define R_LARCH_TLS_LE_LO12_R 123 137 + #define R_LARCH_TLS_LD_PCREL20_S2 124 138 + #define R_LARCH_TLS_GD_PCREL20_S2 125 139 + #define R_LARCH_TLS_DESC_PCREL20_S2 126 140 + #define R_LARCH_CALL30 127 141 + #define R_LARCH_PCADD_HI20 128 142 + #define R_LARCH_PCADD_LO12 129 143 + #define R_LARCH_GOT_PCADD_HI20 130 144 + #define R_LARCH_GOT_PCADD_LO12 131 145 + #define R_LARCH_TLS_IE_PCADD_HI20 132 146 + #define R_LARCH_TLS_IE_PCADD_LO12 133 147 + #define R_LARCH_TLS_LD_PCADD_HI20 134 148 + #define R_LARCH_TLS_LD_PCADD_LO12 135 149 + #define R_LARCH_TLS_GD_PCADD_HI20 136 150 + #define R_LARCH_TLS_GD_PCADD_LO12 137 151 + #define R_LARCH_TLS_DESC_PCADD_HI20 138 152 + #define R_LARCH_TLS_DESC_PCADD_LO12 139 123 153 124 154 #ifndef ELF_ARCH 125 155 ··· 186 156 typedef double elf_fpreg_t; 187 157 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; 188 158 159 + void loongarch_dump_regs32(u32 *uregs, const struct pt_regs *regs); 189 160 void loongarch_dump_regs64(u64 *uregs, const struct pt_regs *regs); 190 161 191 162 #ifdef CONFIG_32BIT
+8 -4
arch/loongarch/include/asm/inst.h
··· 438 438 439 439 static inline bool is_ra_save_ins(union loongarch_instruction *ip) 440 440 { 441 - /* st.d $ra, $sp, offset */ 442 - return ip->reg2i12_format.opcode == std_op && 441 + const u32 opcode = IS_ENABLED(CONFIG_32BIT) ? stw_op : std_op; 442 + 443 + /* st.w / st.d $ra, $sp, offset */ 444 + return ip->reg2i12_format.opcode == opcode && 443 445 ip->reg2i12_format.rj == LOONGARCH_GPR_SP && 444 446 ip->reg2i12_format.rd == LOONGARCH_GPR_RA && 445 447 !is_imm12_negative(ip->reg2i12_format.immediate); ··· 449 447 450 448 static inline bool is_stack_alloc_ins(union loongarch_instruction *ip) 451 449 { 452 - /* addi.d $sp, $sp, -imm */ 453 - return ip->reg2i12_format.opcode == addid_op && 450 + const u32 opcode = IS_ENABLED(CONFIG_32BIT) ? addiw_op : addid_op; 451 + 452 + /* addi.w / addi.d $sp, $sp, -imm */ 453 + return ip->reg2i12_format.opcode == opcode && 454 454 ip->reg2i12_format.rj == LOONGARCH_GPR_SP && 455 455 ip->reg2i12_format.rd == LOONGARCH_GPR_SP && 456 456 is_imm12_negative(ip->reg2i12_format.immediate);
+10
arch/loongarch/include/uapi/asm/ptrace.h
··· 61 61 struct user_watch_state { 62 62 __u64 dbg_info; 63 63 struct { 64 + #if __BITS_PER_LONG == 32 65 + __u32 addr; 66 + __u32 mask; 67 + #else 64 68 __u64 addr; 65 69 __u64 mask; 70 + #endif 66 71 __u32 ctrl; 67 72 __u32 pad; 68 73 } dbg_regs[8]; ··· 76 71 struct user_watch_state_v2 { 77 72 __u64 dbg_info; 78 73 struct { 74 + #if __BITS_PER_LONG == 32 75 + __u32 addr; 76 + __u32 mask; 77 + #else 79 78 __u64 addr; 80 79 __u64 mask; 80 + #endif 81 81 __u32 ctrl; 82 82 __u32 pad; 83 83 } dbg_regs[14];
+111
arch/loongarch/kernel/fpu.S
··· 96 96 EX fld.d $f31, \base, (31 * FPU_REG_WIDTH) 97 97 .endm 98 98 99 + #ifdef CONFIG_32BIT 100 + .macro sc_save_fcc thread tmp0 tmp1 101 + movcf2gr \tmp0, $fcc0 102 + move \tmp1, \tmp0 103 + movcf2gr \tmp0, $fcc1 104 + bstrins.w \tmp1, \tmp0, 15, 8 105 + movcf2gr \tmp0, $fcc2 106 + bstrins.w \tmp1, \tmp0, 23, 16 107 + movcf2gr \tmp0, $fcc3 108 + bstrins.w \tmp1, \tmp0, 31, 24 109 + EX st.w \tmp1, \thread, THREAD_FCC 110 + movcf2gr \tmp0, $fcc4 111 + move \tmp1, \tmp0 112 + movcf2gr \tmp0, $fcc5 113 + bstrins.w \tmp1, \tmp0, 15, 8 114 + movcf2gr \tmp0, $fcc6 115 + bstrins.w \tmp1, \tmp0, 23, 16 116 + movcf2gr \tmp0, $fcc7 117 + bstrins.w \tmp1, \tmp0, 31, 24 118 + EX st.w \tmp1, \thread, (THREAD_FCC + 4) 119 + .endm 120 + 121 + .macro sc_restore_fcc thread tmp0 tmp1 122 + EX ld.w \tmp0, \thread, THREAD_FCC 123 + bstrpick.w \tmp1, \tmp0, 7, 0 124 + movgr2cf $fcc0, \tmp1 125 + bstrpick.w \tmp1, \tmp0, 15, 8 126 + movgr2cf $fcc1, \tmp1 127 + bstrpick.w \tmp1, \tmp0, 23, 16 128 + movgr2cf $fcc2, \tmp1 129 + bstrpick.w \tmp1, \tmp0, 31, 24 130 + movgr2cf $fcc3, \tmp1 131 + EX ld.w \tmp0, \thread, (THREAD_FCC + 4) 132 + bstrpick.w \tmp1, \tmp0, 7, 0 133 + movgr2cf $fcc4, \tmp1 134 + bstrpick.w \tmp1, \tmp0, 15, 8 135 + movgr2cf $fcc5, \tmp1 136 + bstrpick.w \tmp1, \tmp0, 23, 16 137 + movgr2cf $fcc6, \tmp1 138 + bstrpick.w \tmp1, \tmp0, 31, 24 139 + movgr2cf $fcc7, \tmp1 140 + .endm 141 + #else 99 142 .macro sc_save_fcc base, tmp0, tmp1 100 143 movcf2gr \tmp0, $fcc0 101 144 move \tmp1, \tmp0 ··· 178 135 bstrpick.d \tmp1, \tmp0, 63, 56 179 136 movgr2cf $fcc7, \tmp1 180 137 .endm 138 + #endif 181 139 182 140 .macro sc_save_fcsr base, tmp0 183 141 movfcsr2gr \tmp0, fcsr0 ··· 454 410 455 411 li.w t1, -1 # SNaN 456 412 413 + #ifdef CONFIG_32BIT 414 + movgr2fr.w $f0, t1 415 + movgr2frh.w $f0, t1 416 + movgr2fr.w $f1, t1 417 + movgr2frh.w $f1, t1 418 + movgr2fr.w $f2, t1 419 + movgr2frh.w $f2, t1 420 + movgr2fr.w $f3, t1 421 + movgr2frh.w $f3, t1 422 + movgr2fr.w $f4, t1 423 + movgr2frh.w $f4, t1 424 + movgr2fr.w $f5, t1 425 + movgr2frh.w $f5, t1 426 + movgr2fr.w $f6, t1 427 + movgr2frh.w $f6, t1 428 + movgr2fr.w $f7, t1 429 + movgr2frh.w $f7, t1 430 + movgr2fr.w $f8, t1 431 + movgr2frh.w $f8, t1 432 + movgr2fr.w $f9, t1 433 + movgr2frh.w $f9, t1 434 + movgr2fr.w $f10, t1 435 + movgr2frh.w $f10, t1 436 + movgr2fr.w $f11, t1 437 + movgr2frh.w $f11, t1 438 + movgr2fr.w $f12, t1 439 + movgr2frh.w $f12, t1 440 + movgr2fr.w $f13, t1 441 + movgr2frh.w $f13, t1 442 + movgr2fr.w $f14, t1 443 + movgr2frh.w $f14, t1 444 + movgr2fr.w $f15, t1 445 + movgr2frh.w $f15, t1 446 + movgr2fr.w $f16, t1 447 + movgr2frh.w $f16, t1 448 + movgr2fr.w $f17, t1 449 + movgr2frh.w $f17, t1 450 + movgr2fr.w $f18, t1 451 + movgr2frh.w $f18, t1 452 + movgr2fr.w $f19, t1 453 + movgr2frh.w $f19, t1 454 + movgr2fr.w $f20, t1 455 + movgr2frh.w $f20, t1 456 + movgr2fr.w $f21, t1 457 + movgr2frh.w $f21, t1 458 + movgr2fr.w $f22, t1 459 + movgr2frh.w $f22, t1 460 + movgr2fr.w $f23, t1 461 + movgr2frh.w $f23, t1 462 + movgr2fr.w $f24, t1 463 + movgr2frh.w $f24, t1 464 + movgr2fr.w $f25, t1 465 + movgr2frh.w $f25, t1 466 + movgr2fr.w $f26, t1 467 + movgr2frh.w $f26, t1 468 + movgr2fr.w $f27, t1 469 + movgr2frh.w $f27, t1 470 + movgr2fr.w $f28, t1 471 + movgr2frh.w $f28, t1 472 + movgr2fr.w $f29, t1 473 + movgr2frh.w $f29, t1 474 + movgr2fr.w $f30, t1 475 + movgr2frh.w $f30, t1 476 + movgr2fr.w $f31, t1 477 + movgr2frh.w $f31, t1 478 + #else 457 479 movgr2fr.d $f0, t1 458 480 movgr2fr.d $f1, t1 459 481 movgr2fr.d $f2, t1 ··· 552 442 movgr2fr.d $f29, t1 553 443 movgr2fr.d $f30, t1 554 444 movgr2fr.d $f31, t1 445 + #endif 555 446 556 447 jr ra 557 448 SYM_FUNC_END(_init_fpu)
+4 -2
arch/loongarch/kernel/process.c
··· 382 382 nmi_trigger_cpumask_backtrace(mask, exclude_cpu, raise_backtrace); 383 383 } 384 384 385 - #ifdef CONFIG_64BIT 385 + #ifdef CONFIG_32BIT 386 + void loongarch_dump_regs32(u32 *uregs, const struct pt_regs *regs) 387 + #else 386 388 void loongarch_dump_regs64(u64 *uregs, const struct pt_regs *regs) 389 + #endif 387 390 { 388 391 unsigned int i; 389 392 ··· 403 400 uregs[LOONGARCH_EF_CSR_ECFG] = regs->csr_ecfg; 404 401 uregs[LOONGARCH_EF_CSR_ESTAT] = regs->csr_estat; 405 402 } 406 - #endif /* CONFIG_64BIT */
+5
arch/loongarch/kernel/ptrace.c
··· 650 650 struct perf_event_attr attr; 651 651 652 652 /* Kernel-space address cannot be monitored by user-space */ 653 + #ifdef CONFIG_32BIT 654 + if ((unsigned long)addr >= KPRANGE0) 655 + return -EINVAL; 656 + #else 653 657 if ((unsigned long)addr >= XKPRANGE) 654 658 return -EINVAL; 659 + #endif 655 660 656 661 bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); 657 662 if (IS_ERR(bp))
+18 -10
arch/loongarch/kernel/switch.S
··· 16 16 */ 17 17 .align 5 18 18 SYM_FUNC_START(__switch_to) 19 - csrrd t1, LOONGARCH_CSR_PRMD 20 - stptr.d t1, a0, THREAD_CSRPRMD 19 + #ifdef CONFIG_32BIT 20 + PTR_ADDI a0, a0, TASK_STRUCT_OFFSET 21 + PTR_ADDI a1, a1, TASK_STRUCT_OFFSET 22 + #endif 23 + csrrd t1, LOONGARCH_CSR_PRMD 24 + LONG_SPTR t1, a0, (THREAD_CSRPRMD - TASK_STRUCT_OFFSET) 21 25 22 26 cpu_save_nonscratch a0 23 - stptr.d ra, a0, THREAD_REG01 24 - stptr.d a3, a0, THREAD_SCHED_RA 25 - stptr.d a4, a0, THREAD_SCHED_CFA 27 + LONG_SPTR a3, a0, (THREAD_SCHED_RA - TASK_STRUCT_OFFSET) 28 + LONG_SPTR a4, a0, (THREAD_SCHED_CFA - TASK_STRUCT_OFFSET) 29 + 26 30 #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP) 27 - la t7, __stack_chk_guard 28 - ldptr.d t8, a1, TASK_STACK_CANARY 29 - stptr.d t8, t7, 0 31 + la t7, __stack_chk_guard 32 + LONG_LPTR t8, a1, (TASK_STACK_CANARY - TASK_STRUCT_OFFSET) 33 + LONG_SPTR t8, t7, 0 30 34 #endif 35 + 31 36 move tp, a2 32 37 cpu_restore_nonscratch a1 33 38 ··· 40 35 PTR_ADD t0, t0, tp 41 36 set_saved_sp t0, t1, t2 42 37 43 - ldptr.d t1, a1, THREAD_CSRPRMD 44 - csrwr t1, LOONGARCH_CSR_PRMD 38 + LONG_LPTR t1, a1, (THREAD_CSRPRMD - TASK_STRUCT_OFFSET) 39 + csrwr t1, LOONGARCH_CSR_PRMD 45 40 41 + #ifdef CONFIG_32BIT 42 + PTR_ADDI a0, a0, -TASK_STRUCT_OFFSET 43 + #endif 46 44 jr ra 47 45 SYM_FUNC_END(__switch_to)