Skip to content

Commit b993744

Browse files
committed
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
2 parents 9b04368 + bb85d20 commit b993744

13 files changed

Lines changed: 120 additions & 57 deletions

File tree

arch/loongarch/include/asm/loongarch.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@
9494
#define CPUCFG2_LSPW BIT(21)
9595
#define CPUCFG2_LAM BIT(22)
9696
#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)
97103

98104
#define LOONGARCH_CPUCFG3 0x3
99105
#define CPUCFG3_CCDMA BIT(0)
@@ -108,6 +114,7 @@
108114
#define CPUCFG3_SPW_HG_HF BIT(11)
109115
#define CPUCFG3_RVA BIT(12)
110116
#define CPUCFG3_RVAMAX GENMASK(16, 13)
117+
#define CPUCFG3_DBAR_HINTS BIT(17)
111118
#define CPUCFG3_ALDORDER_CAP BIT(18) /* All address load ordered, capability */
112119
#define CPUCFG3_ASTORDER_CAP BIT(19) /* All address store ordered, capability */
113120
#define CPUCFG3_ALDORDER_STA BIT(20) /* All address load ordered, status */

arch/loongarch/kernel/head.S

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize);
4242
.align 12
4343

4444
SYM_CODE_START(kernel_entry) # kernel entry point
45+
UNWIND_HINT_END_OF_STACK
4546

4647
SETUP_TWINS
4748
SETUP_MODES t0
@@ -113,6 +114,7 @@ SYM_CODE_END(kernel_entry)
113114
* function after setting up the stack and tp registers.
114115
*/
115116
SYM_CODE_START(smpboot_entry)
117+
UNWIND_HINT_END_OF_STACK
116118

117119
SETUP_TWINS
118120
SETUP_MODES t0
@@ -142,5 +144,3 @@ SYM_CODE_START(smpboot_entry)
142144
SYM_CODE_END(smpboot_entry)
143145

144146
#endif /* CONFIG_SMP */
145-
146-
SYM_ENTRY(kernel_entry_end, SYM_L_GLOBAL, SYM_A_NONE)

arch/loongarch/kernel/mcount_dyn.S

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
9494
* at the callsite, so there is no need to restore the T series regs.
9595
*/
9696
ftrace_common_return:
97-
PTR_L ra, sp, PT_R1
9897
PTR_L a0, sp, PT_R4
9998
PTR_L a1, sp, PT_R5
10099
PTR_L a2, sp, PT_R6
@@ -104,12 +103,17 @@ ftrace_common_return:
104103
PTR_L a6, sp, PT_R10
105104
PTR_L a7, sp, PT_R11
106105
PTR_L fp, sp, PT_R22
107-
PTR_L t0, sp, PT_ERA
108106
PTR_L t1, sp, PT_R13
109-
PTR_ADDI sp, sp, PT_SIZE
110107
bnez t1, .Ldirect
108+
109+
PTR_L ra, sp, PT_R1
110+
PTR_L t0, sp, PT_ERA
111+
PTR_ADDI sp, sp, PT_SIZE
111112
jr t0
112113
.Ldirect:
114+
PTR_L t0, sp, PT_R1
115+
PTR_L ra, sp, PT_ERA
116+
PTR_ADDI sp, sp, PT_SIZE
113117
jr t1
114118
SYM_CODE_END(ftrace_common)
115119

@@ -161,6 +165,8 @@ SYM_CODE_END(return_to_handler)
161165
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
162166
SYM_CODE_START(ftrace_stub_direct_tramp)
163167
UNWIND_HINT_UNDEFINED
164-
jr t0
168+
move t1, ra
169+
move ra, t0
170+
jr t1
165171
SYM_CODE_END(ftrace_stub_direct_tramp)
166172
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */

arch/loongarch/kernel/traps.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,10 +535,15 @@ asmlinkage void noinstr do_fpe(struct pt_regs *regs, unsigned long fcsr)
535535
asmlinkage void noinstr do_ade(struct pt_regs *regs)
536536
{
537537
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;
538542

539543
die_if_kernel("Kernel ade access", regs);
540544
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)regs->csr_badvaddr);
541545

546+
out:
542547
irqentry_exit(regs, state);
543548
}
544549

arch/loongarch/kernel/unwind_orc.c

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -348,24 +348,10 @@ void unwind_start(struct unwind_state *state, struct task_struct *task,
348348
}
349349
EXPORT_SYMBOL_GPL(unwind_start);
350350

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-
359351
static inline unsigned long bt_address(unsigned long ra)
360352
{
361353
extern unsigned long eentry;
362354

363-
if (__kernel_text_address(ra))
364-
return ra;
365-
366-
if (__module_text_address(ra))
367-
return ra;
368-
369355
if (ra >= eentry && ra < eentry + EXCCODE_INT_END * VECSIZE) {
370356
unsigned long func;
371357
unsigned long type = (ra - eentry) / VECSIZE;
@@ -383,10 +369,13 @@ static inline unsigned long bt_address(unsigned long ra)
383369
break;
384370
}
385371

386-
return func + offset;
372+
ra = func + offset;
387373
}
388374

389-
return ra;
375+
if (__kernel_text_address(ra))
376+
return ra;
377+
378+
return 0;
390379
}
391380

392381
bool unwind_next_frame(struct unwind_state *state)
@@ -402,9 +391,6 @@ bool unwind_next_frame(struct unwind_state *state)
402391
/* Don't let modules unload while we're reading their ORC data. */
403392
guard(rcu)();
404393

405-
if (is_entry_func(state->pc))
406-
goto end;
407-
408394
orc = orc_find(state->pc);
409395
if (!orc) {
410396
/*
@@ -512,9 +498,6 @@ bool unwind_next_frame(struct unwind_state *state)
512498
goto err;
513499
}
514500

515-
if (!__kernel_text_address(state->pc))
516-
goto err;
517-
518501
return true;
519502

520503
err:

arch/loongarch/mm/cache.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ void cpu_cache_init(void)
160160

161161
static const pgprot_t protection_map[16] = {
162162
[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)),
165165
[VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID |
166166
_PAGE_USER | _PAGE_PRESENT |
167167
_PAGE_NO_EXEC),
@@ -180,8 +180,8 @@ static const pgprot_t protection_map[16] = {
180180
[VM_EXEC | VM_WRITE | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID |
181181
_PAGE_USER | _PAGE_PRESENT),
182182
[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)),
185185
[VM_SHARED | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID |
186186
_PAGE_USER | _PAGE_PRESENT |
187187
_PAGE_NO_EXEC),

arch/loongarch/net/bpf_jit.c

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ static void build_prologue(struct jit_ctx *ctx)
139139
stack_adjust = round_up(stack_adjust, 16);
140140
stack_adjust += bpf_stack_adjust;
141141

142+
move_reg(ctx, LOONGARCH_GPR_T0, LOONGARCH_GPR_RA);
142143
/* Reserve space for the move_imm + jirl instruction */
143144
for (i = 0; i < LOONGARCH_LONG_JUMP_NINSNS; i++)
144145
emit_insn(ctx, nop);
@@ -238,7 +239,7 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call)
238239
* Call the next bpf prog and skip the first instruction
239240
* of TCC initialization.
240241
*/
241-
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 6);
242+
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 7);
242243
}
243244
}
244245

@@ -280,6 +281,8 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
280281
* goto out;
281282
*/
282283
tc_ninsn = insn ? ctx->offset[insn+1] - ctx->offset[insn] : ctx->offset[0];
284+
emit_zext_32(ctx, a2, true);
285+
283286
off = offsetof(struct bpf_array, map.max_entries);
284287
emit_insn(ctx, ldwu, t1, a1, off);
285288
/* bgeu $a2, $t1, jmp_offset */
@@ -950,6 +953,22 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
950953
emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_SP, tcc_ptr_off);
951954
}
952955

956+
if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
957+
const struct btf_func_model *m;
958+
int i;
959+
960+
m = bpf_jit_find_kfunc_model(ctx->prog, insn);
961+
if (!m)
962+
return -EINVAL;
963+
964+
for (i = 0; i < m->nr_args; i++) {
965+
u8 reg = regmap[BPF_REG_1 + i];
966+
bool sign = m->arg_flags[i] & BTF_FMODEL_SIGNED_ARG;
967+
968+
emit_abi_ext(ctx, reg, m->arg_size[i], sign);
969+
}
970+
}
971+
953972
move_addr(ctx, t1, func_addr);
954973
emit_insn(ctx, jirl, LOONGARCH_GPR_RA, t1, 0);
955974

@@ -1265,7 +1284,7 @@ static int emit_jump_or_nops(void *target, void *ip, u32 *insns, bool is_call)
12651284
return 0;
12661285
}
12671286

1268-
return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_T0 : LOONGARCH_GPR_ZERO, (u64)target);
1287+
return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_RA : LOONGARCH_GPR_ZERO, (u64)target);
12691288
}
12701289

12711290
static int emit_call(struct jit_ctx *ctx, u64 addr)
@@ -1290,15 +1309,30 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
12901309
{
12911310
int ret;
12921311
bool is_call;
1312+
unsigned long size = 0;
1313+
unsigned long offset = 0;
1314+
void *image = NULL;
1315+
char namebuf[KSYM_NAME_LEN];
12931316
u32 old_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
12941317
u32 new_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
12951318

12961319
/* Only poking bpf text is supported. Since kernel function entry
12971320
* is set up by ftrace, we rely on ftrace to poke kernel functions.
12981321
*/
1299-
if (!is_bpf_text_address((unsigned long)ip))
1322+
if (!__bpf_address_lookup((unsigned long)ip, &size, &offset, namebuf))
13001323
return -ENOTSUPP;
13011324

1325+
image = ip - offset;
1326+
1327+
/* zero offset means we're poking bpf prog entry */
1328+
if (offset == 0) {
1329+
/* skip to the nop instruction in bpf prog entry:
1330+
* move t0, ra
1331+
* nop
1332+
*/
1333+
ip = image + LOONGARCH_INSN_SIZE;
1334+
}
1335+
13021336
is_call = old_t == BPF_MOD_CALL;
13031337
ret = emit_jump_or_nops(old_addr, ip, old_insns, is_call);
13041338
if (ret)
@@ -1622,14 +1656,12 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
16221656

16231657
/* To traced function */
16241658
/* Ftrace jump skips 2 NOP instructions */
1625-
if (is_kernel_text((unsigned long)orig_call))
1659+
if (is_kernel_text((unsigned long)orig_call) ||
1660+
is_module_text_address((unsigned long)orig_call))
16261661
orig_call += LOONGARCH_FENTRY_NBYTES;
16271662
/* Direct jump skips 5 NOP instructions */
16281663
else if (is_bpf_text_address((unsigned long)orig_call))
16291664
orig_call += LOONGARCH_BPF_FENTRY_NBYTES;
1630-
/* Module tracing not supported - cause kernel lockups */
1631-
else if (is_module_text_address((unsigned long)orig_call))
1632-
return -ENOTSUPP;
16331665

16341666
if (flags & BPF_TRAMP_F_CALL_ORIG) {
16351667
move_addr(ctx, LOONGARCH_GPR_A0, (const u64)im);
@@ -1722,12 +1754,16 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
17221754
emit_insn(ctx, ldd, LOONGARCH_GPR_FP, LOONGARCH_GPR_SP, 0);
17231755
emit_insn(ctx, addid, LOONGARCH_GPR_SP, LOONGARCH_GPR_SP, 16);
17241756

1725-
if (flags & BPF_TRAMP_F_SKIP_FRAME)
1757+
if (flags & BPF_TRAMP_F_SKIP_FRAME) {
17261758
/* return to parent function */
1727-
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0);
1728-
else
1729-
/* return to traced function */
1759+
move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0);
17301760
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T0, 0);
1761+
} else {
1762+
/* return to traced function */
1763+
move_reg(ctx, LOONGARCH_GPR_T1, LOONGARCH_GPR_RA);
1764+
move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0);
1765+
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T1, 0);
1766+
}
17311767
}
17321768

17331769
ret = ctx->idx;

arch/loongarch/net/bpf_jit.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,32 @@ static inline void emit_sext_32(struct jit_ctx *ctx, enum loongarch_gpr reg, boo
8888
emit_insn(ctx, addiw, reg, reg, 0);
8989
}
9090

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+
91117
static inline void move_addr(struct jit_ctx *ctx, enum loongarch_gpr rd, u64 addr)
92118
{
93119
u64 imm_11_0, imm_31_12, imm_51_32, imm_63_52;

samples/ftrace/ftrace-direct-modify.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ asm (
176176
" st.d $t0, $sp, 0\n"
177177
" st.d $ra, $sp, 8\n"
178178
" 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"
181181
" addi.d $sp, $sp, 16\n"
182182
" jr $t0\n"
183183
" .size my_tramp1, .-my_tramp1\n"
@@ -189,8 +189,8 @@ asm (
189189
" st.d $t0, $sp, 0\n"
190190
" st.d $ra, $sp, 8\n"
191191
" 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"
194194
" addi.d $sp, $sp, 16\n"
195195
" jr $t0\n"
196196
" .size my_tramp2, .-my_tramp2\n"

samples/ftrace/ftrace-direct-multi-modify.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ asm (
199199
" move $a0, $t0\n"
200200
" bl my_direct_func1\n"
201201
" 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"
204204
" addi.d $sp, $sp, 32\n"
205205
" jr $t0\n"
206206
" .size my_tramp1, .-my_tramp1\n"
@@ -215,8 +215,8 @@ asm (
215215
" move $a0, $t0\n"
216216
" bl my_direct_func2\n"
217217
" 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"
220220
" addi.d $sp, $sp, 32\n"
221221
" jr $t0\n"
222222
" .size my_tramp2, .-my_tramp2\n"

0 commit comments

Comments
 (0)