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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'loongarch-fixes-6.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson

Pull LoongArch fixes from Huacai Chen:
"Complete CPUCFG registers definition, set correct protection_map[] for
VM_NONE/VM_SHARED, fix some bugs in the orc stack unwinder, ftrace and
BPF JIT"

* tag 'loongarch-fixes-6.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
samples/ftrace: Adjust LoongArch register restore order in direct calls
LoongArch: BPF: Enhance the bpf_arch_text_poke() function
LoongArch: BPF: Enable trampoline-based tracing for module functions
LoongArch: BPF: Adjust the jump offset of tail calls
LoongArch: BPF: Save return address register ra to t0 before trampoline
LoongArch: BPF: Zero-extend bpf_tail_call() index
LoongArch: BPF: Sign extend kfunc call arguments
LoongArch: Refactor register restoration in ftrace_common_return
LoongArch: Enable exception fixup for specific ADE subcode
LoongArch: Remove unnecessary checks for ORC unwinder
LoongArch: Remove is_entry_func() and kernel_entry_end
LoongArch: Use UNWIND_HINT_END_OF_STACK for entry points
LoongArch: Set correct protection_map[] for VM_NONE/VM_SHARED
LoongArch: Complete CPUCFG registers definition

+120 -57
+7
arch/loongarch/include/asm/loongarch.h
··· 94 94 #define CPUCFG2_LSPW BIT(21) 95 95 #define CPUCFG2_LAM BIT(22) 96 96 #define CPUCFG2_PTW BIT(24) 97 + #define CPUCFG2_FRECIPE BIT(25) 98 + #define CPUCFG2_DIV32 BIT(26) 99 + #define CPUCFG2_LAM_BH BIT(27) 100 + #define CPUCFG2_LAMCAS BIT(28) 101 + #define CPUCFG2_LLACQ_SCREL BIT(29) 102 + #define CPUCFG2_SCQ BIT(30) 97 103 98 104 #define LOONGARCH_CPUCFG3 0x3 99 105 #define CPUCFG3_CCDMA BIT(0) ··· 114 108 #define CPUCFG3_SPW_HG_HF BIT(11) 115 109 #define CPUCFG3_RVA BIT(12) 116 110 #define CPUCFG3_RVAMAX GENMASK(16, 13) 111 + #define CPUCFG3_DBAR_HINTS BIT(17) 117 112 #define CPUCFG3_ALDORDER_CAP BIT(18) /* All address load ordered, capability */ 118 113 #define CPUCFG3_ASTORDER_CAP BIT(19) /* All address store ordered, capability */ 119 114 #define CPUCFG3_ALDORDER_STA BIT(20) /* All address load ordered, status */
+2 -2
arch/loongarch/kernel/head.S
··· 42 42 .align 12 43 43 44 44 SYM_CODE_START(kernel_entry) # kernel entry point 45 + UNWIND_HINT_END_OF_STACK 45 46 46 47 SETUP_TWINS 47 48 SETUP_MODES t0 ··· 114 113 * function after setting up the stack and tp registers. 115 114 */ 116 115 SYM_CODE_START(smpboot_entry) 116 + UNWIND_HINT_END_OF_STACK 117 117 118 118 SETUP_TWINS 119 119 SETUP_MODES t0 ··· 144 142 SYM_CODE_END(smpboot_entry) 145 143 146 144 #endif /* CONFIG_SMP */ 147 - 148 - SYM_ENTRY(kernel_entry_end, SYM_L_GLOBAL, SYM_A_NONE)
+10 -4
arch/loongarch/kernel/mcount_dyn.S
··· 94 94 * at the callsite, so there is no need to restore the T series regs. 95 95 */ 96 96 ftrace_common_return: 97 - PTR_L ra, sp, PT_R1 98 97 PTR_L a0, sp, PT_R4 99 98 PTR_L a1, sp, PT_R5 100 99 PTR_L a2, sp, PT_R6 ··· 103 104 PTR_L a6, sp, PT_R10 104 105 PTR_L a7, sp, PT_R11 105 106 PTR_L fp, sp, PT_R22 106 - PTR_L t0, sp, PT_ERA 107 107 PTR_L t1, sp, PT_R13 108 - PTR_ADDI sp, sp, PT_SIZE 109 108 bnez t1, .Ldirect 109 + 110 + PTR_L ra, sp, PT_R1 111 + PTR_L t0, sp, PT_ERA 112 + PTR_ADDI sp, sp, PT_SIZE 110 113 jr t0 111 114 .Ldirect: 115 + PTR_L t0, sp, PT_R1 116 + PTR_L ra, sp, PT_ERA 117 + PTR_ADDI sp, sp, PT_SIZE 112 118 jr t1 113 119 SYM_CODE_END(ftrace_common) 114 120 ··· 165 161 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 166 162 SYM_CODE_START(ftrace_stub_direct_tramp) 167 163 UNWIND_HINT_UNDEFINED 168 - jr t0 164 + move t1, ra 165 + move ra, t0 166 + jr t1 169 167 SYM_CODE_END(ftrace_stub_direct_tramp) 170 168 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
+5
arch/loongarch/kernel/traps.c
··· 535 535 asmlinkage void noinstr do_ade(struct pt_regs *regs) 536 536 { 537 537 irqentry_state_t state = irqentry_enter(regs); 538 + unsigned int esubcode = FIELD_GET(CSR_ESTAT_ESUBCODE, regs->csr_estat); 539 + 540 + if ((esubcode == EXSUBCODE_ADEM) && fixup_exception(regs)) 541 + goto out; 538 542 539 543 die_if_kernel("Kernel ade access", regs); 540 544 force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)regs->csr_badvaddr); 541 545 546 + out: 542 547 irqentry_exit(regs, state); 543 548 } 544 549
+5 -22
arch/loongarch/kernel/unwind_orc.c
··· 348 348 } 349 349 EXPORT_SYMBOL_GPL(unwind_start); 350 350 351 - static bool is_entry_func(unsigned long addr) 352 - { 353 - extern u32 kernel_entry; 354 - extern u32 kernel_entry_end; 355 - 356 - return addr >= (unsigned long)&kernel_entry && addr < (unsigned long)&kernel_entry_end; 357 - } 358 - 359 351 static inline unsigned long bt_address(unsigned long ra) 360 352 { 361 353 extern unsigned long eentry; 362 - 363 - if (__kernel_text_address(ra)) 364 - return ra; 365 - 366 - if (__module_text_address(ra)) 367 - return ra; 368 354 369 355 if (ra >= eentry && ra < eentry + EXCCODE_INT_END * VECSIZE) { 370 356 unsigned long func; ··· 369 383 break; 370 384 } 371 385 372 - return func + offset; 386 + ra = func + offset; 373 387 } 374 388 375 - return ra; 389 + if (__kernel_text_address(ra)) 390 + return ra; 391 + 392 + return 0; 376 393 } 377 394 378 395 bool unwind_next_frame(struct unwind_state *state) ··· 390 401 391 402 /* Don't let modules unload while we're reading their ORC data. */ 392 403 guard(rcu)(); 393 - 394 - if (is_entry_func(state->pc)) 395 - goto end; 396 404 397 405 orc = orc_find(state->pc); 398 406 if (!orc) { ··· 497 511 pr_err("cannot find unwind pc at %p\n", (void *)pc); 498 512 goto err; 499 513 } 500 - 501 - if (!__kernel_text_address(state->pc)) 502 - goto err; 503 514 504 515 return true; 505 516
+4 -4
arch/loongarch/mm/cache.c
··· 160 160 161 161 static const pgprot_t protection_map[16] = { 162 162 [VM_NONE] = __pgprot(_CACHE_CC | _PAGE_USER | 163 - _PAGE_PROTNONE | _PAGE_NO_EXEC | 164 - _PAGE_NO_READ), 163 + _PAGE_NO_EXEC | _PAGE_NO_READ | 164 + (_PAGE_PROTNONE ? : _PAGE_PRESENT)), 165 165 [VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID | 166 166 _PAGE_USER | _PAGE_PRESENT | 167 167 _PAGE_NO_EXEC), ··· 180 180 [VM_EXEC | VM_WRITE | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID | 181 181 _PAGE_USER | _PAGE_PRESENT), 182 182 [VM_SHARED] = __pgprot(_CACHE_CC | _PAGE_USER | 183 - _PAGE_PROTNONE | _PAGE_NO_EXEC | 184 - _PAGE_NO_READ), 183 + _PAGE_NO_EXEC | _PAGE_NO_READ | 184 + (_PAGE_PROTNONE ? : _PAGE_PRESENT)), 185 185 [VM_SHARED | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID | 186 186 _PAGE_USER | _PAGE_PRESENT | 187 187 _PAGE_NO_EXEC),
+47 -11
arch/loongarch/net/bpf_jit.c
··· 139 139 stack_adjust = round_up(stack_adjust, 16); 140 140 stack_adjust += bpf_stack_adjust; 141 141 142 + move_reg(ctx, LOONGARCH_GPR_T0, LOONGARCH_GPR_RA); 142 143 /* Reserve space for the move_imm + jirl instruction */ 143 144 for (i = 0; i < LOONGARCH_LONG_JUMP_NINSNS; i++) 144 145 emit_insn(ctx, nop); ··· 239 238 * Call the next bpf prog and skip the first instruction 240 239 * of TCC initialization. 241 240 */ 242 - emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 6); 241 + emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 7); 243 242 } 244 243 } 245 244 ··· 281 280 * goto out; 282 281 */ 283 282 tc_ninsn = insn ? ctx->offset[insn+1] - ctx->offset[insn] : ctx->offset[0]; 283 + emit_zext_32(ctx, a2, true); 284 + 284 285 off = offsetof(struct bpf_array, map.max_entries); 285 286 emit_insn(ctx, ldwu, t1, a1, off); 286 287 /* bgeu $a2, $t1, jmp_offset */ ··· 953 950 emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_SP, tcc_ptr_off); 954 951 } 955 952 953 + if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) { 954 + const struct btf_func_model *m; 955 + int i; 956 + 957 + m = bpf_jit_find_kfunc_model(ctx->prog, insn); 958 + if (!m) 959 + return -EINVAL; 960 + 961 + for (i = 0; i < m->nr_args; i++) { 962 + u8 reg = regmap[BPF_REG_1 + i]; 963 + bool sign = m->arg_flags[i] & BTF_FMODEL_SIGNED_ARG; 964 + 965 + emit_abi_ext(ctx, reg, m->arg_size[i], sign); 966 + } 967 + } 968 + 956 969 move_addr(ctx, t1, func_addr); 957 970 emit_insn(ctx, jirl, LOONGARCH_GPR_RA, t1, 0); 958 971 ··· 1284 1265 return 0; 1285 1266 } 1286 1267 1287 - return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_T0 : LOONGARCH_GPR_ZERO, (u64)target); 1268 + return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_RA : LOONGARCH_GPR_ZERO, (u64)target); 1288 1269 } 1289 1270 1290 1271 static int emit_call(struct jit_ctx *ctx, u64 addr) ··· 1309 1290 { 1310 1291 int ret; 1311 1292 bool is_call; 1293 + unsigned long size = 0; 1294 + unsigned long offset = 0; 1295 + void *image = NULL; 1296 + char namebuf[KSYM_NAME_LEN]; 1312 1297 u32 old_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP}; 1313 1298 u32 new_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP}; 1314 1299 1315 1300 /* Only poking bpf text is supported. Since kernel function entry 1316 1301 * is set up by ftrace, we rely on ftrace to poke kernel functions. 1317 1302 */ 1318 - if (!is_bpf_text_address((unsigned long)ip)) 1303 + if (!__bpf_address_lookup((unsigned long)ip, &size, &offset, namebuf)) 1319 1304 return -ENOTSUPP; 1305 + 1306 + image = ip - offset; 1307 + 1308 + /* zero offset means we're poking bpf prog entry */ 1309 + if (offset == 0) { 1310 + /* skip to the nop instruction in bpf prog entry: 1311 + * move t0, ra 1312 + * nop 1313 + */ 1314 + ip = image + LOONGARCH_INSN_SIZE; 1315 + } 1320 1316 1321 1317 is_call = old_t == BPF_MOD_CALL; 1322 1318 ret = emit_jump_or_nops(old_addr, ip, old_insns, is_call); ··· 1656 1622 1657 1623 /* To traced function */ 1658 1624 /* Ftrace jump skips 2 NOP instructions */ 1659 - if (is_kernel_text((unsigned long)orig_call)) 1625 + if (is_kernel_text((unsigned long)orig_call) || 1626 + is_module_text_address((unsigned long)orig_call)) 1660 1627 orig_call += LOONGARCH_FENTRY_NBYTES; 1661 1628 /* Direct jump skips 5 NOP instructions */ 1662 1629 else if (is_bpf_text_address((unsigned long)orig_call)) 1663 1630 orig_call += LOONGARCH_BPF_FENTRY_NBYTES; 1664 - /* Module tracing not supported - cause kernel lockups */ 1665 - else if (is_module_text_address((unsigned long)orig_call)) 1666 - return -ENOTSUPP; 1667 1631 1668 1632 if (flags & BPF_TRAMP_F_CALL_ORIG) { 1669 1633 move_addr(ctx, LOONGARCH_GPR_A0, (const u64)im); ··· 1754 1722 emit_insn(ctx, ldd, LOONGARCH_GPR_FP, LOONGARCH_GPR_SP, 0); 1755 1723 emit_insn(ctx, addid, LOONGARCH_GPR_SP, LOONGARCH_GPR_SP, 16); 1756 1724 1757 - if (flags & BPF_TRAMP_F_SKIP_FRAME) 1725 + if (flags & BPF_TRAMP_F_SKIP_FRAME) { 1758 1726 /* return to parent function */ 1759 - emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0); 1760 - else 1761 - /* return to traced function */ 1727 + move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0); 1762 1728 emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T0, 0); 1729 + } else { 1730 + /* return to traced function */ 1731 + move_reg(ctx, LOONGARCH_GPR_T1, LOONGARCH_GPR_RA); 1732 + move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0); 1733 + emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T1, 0); 1734 + } 1763 1735 } 1764 1736 1765 1737 ret = ctx->idx;
+26
arch/loongarch/net/bpf_jit.h
··· 88 88 emit_insn(ctx, addiw, reg, reg, 0); 89 89 } 90 90 91 + /* Emit proper extension according to ABI requirements. 92 + * Note that it requires a value of size `size` already resides in register `reg`. 93 + */ 94 + static inline void emit_abi_ext(struct jit_ctx *ctx, int reg, u8 size, bool sign) 95 + { 96 + /* ABI requires unsigned char/short to be zero-extended */ 97 + if (!sign && (size == 1 || size == 2)) 98 + return; 99 + 100 + switch (size) { 101 + case 1: 102 + emit_insn(ctx, extwb, reg, reg); 103 + break; 104 + case 2: 105 + emit_insn(ctx, extwh, reg, reg); 106 + break; 107 + case 4: 108 + emit_insn(ctx, addiw, reg, reg, 0); 109 + break; 110 + case 8: 111 + break; 112 + default: 113 + pr_warn("bpf_jit: invalid size %d for extension\n", size); 114 + } 115 + } 116 + 91 117 static inline void move_addr(struct jit_ctx *ctx, enum loongarch_gpr rd, u64 addr) 92 118 { 93 119 u64 imm_11_0, imm_31_12, imm_51_32, imm_63_52;
+4 -4
samples/ftrace/ftrace-direct-modify.c
··· 176 176 " st.d $t0, $sp, 0\n" 177 177 " st.d $ra, $sp, 8\n" 178 178 " bl my_direct_func1\n" 179 - " ld.d $t0, $sp, 0\n" 180 - " ld.d $ra, $sp, 8\n" 179 + " ld.d $ra, $sp, 0\n" 180 + " ld.d $t0, $sp, 8\n" 181 181 " addi.d $sp, $sp, 16\n" 182 182 " jr $t0\n" 183 183 " .size my_tramp1, .-my_tramp1\n" ··· 189 189 " st.d $t0, $sp, 0\n" 190 190 " st.d $ra, $sp, 8\n" 191 191 " bl my_direct_func2\n" 192 - " ld.d $t0, $sp, 0\n" 193 - " ld.d $ra, $sp, 8\n" 192 + " ld.d $ra, $sp, 0\n" 193 + " ld.d $t0, $sp, 8\n" 194 194 " addi.d $sp, $sp, 16\n" 195 195 " jr $t0\n" 196 196 " .size my_tramp2, .-my_tramp2\n"
+4 -4
samples/ftrace/ftrace-direct-multi-modify.c
··· 199 199 " move $a0, $t0\n" 200 200 " bl my_direct_func1\n" 201 201 " ld.d $a0, $sp, 0\n" 202 - " ld.d $t0, $sp, 8\n" 203 - " ld.d $ra, $sp, 16\n" 202 + " ld.d $ra, $sp, 8\n" 203 + " ld.d $t0, $sp, 16\n" 204 204 " addi.d $sp, $sp, 32\n" 205 205 " jr $t0\n" 206 206 " .size my_tramp1, .-my_tramp1\n" ··· 215 215 " move $a0, $t0\n" 216 216 " bl my_direct_func2\n" 217 217 " ld.d $a0, $sp, 0\n" 218 - " ld.d $t0, $sp, 8\n" 219 - " ld.d $ra, $sp, 16\n" 218 + " ld.d $ra, $sp, 8\n" 219 + " ld.d $t0, $sp, 16\n" 220 220 " addi.d $sp, $sp, 32\n" 221 221 " jr $t0\n" 222 222 " .size my_tramp2, .-my_tramp2\n"
+2 -2
samples/ftrace/ftrace-direct-multi.c
··· 131 131 " move $a0, $t0\n" 132 132 " bl my_direct_func\n" 133 133 " ld.d $a0, $sp, 0\n" 134 - " ld.d $t0, $sp, 8\n" 135 - " ld.d $ra, $sp, 16\n" 134 + " ld.d $ra, $sp, 8\n" 135 + " ld.d $t0, $sp, 16\n" 136 136 " addi.d $sp, $sp, 32\n" 137 137 " jr $t0\n" 138 138 " .size my_tramp, .-my_tramp\n"
+2 -2
samples/ftrace/ftrace-direct-too.c
··· 143 143 " ld.d $a0, $sp, 0\n" 144 144 " ld.d $a1, $sp, 8\n" 145 145 " ld.d $a2, $sp, 16\n" 146 - " ld.d $t0, $sp, 24\n" 147 - " ld.d $ra, $sp, 32\n" 146 + " ld.d $ra, $sp, 24\n" 147 + " ld.d $t0, $sp, 32\n" 148 148 " addi.d $sp, $sp, 48\n" 149 149 " jr $t0\n" 150 150 " .size my_tramp, .-my_tramp\n"
+2 -2
samples/ftrace/ftrace-direct.c
··· 124 124 " st.d $ra, $sp, 16\n" 125 125 " bl my_direct_func\n" 126 126 " ld.d $a0, $sp, 0\n" 127 - " ld.d $t0, $sp, 8\n" 128 - " ld.d $ra, $sp, 16\n" 127 + " ld.d $ra, $sp, 8\n" 128 + " ld.d $t0, $sp, 16\n" 129 129 " addi.d $sp, $sp, 32\n" 130 130 " jr $t0\n" 131 131 " .size my_tramp, .-my_tramp\n"