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-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson

Pull LoongArch updates from Huacai Chen:

- support PREEMPT_DYNAMIC with static keys

- relax memory ordering for atomic operations

- support BPF CPU v4 instructions for LoongArch

- some build and runtime warning fixes

* tag 'loongarch-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
selftests/bpf: Enable cpu v4 tests for LoongArch
LoongArch: BPF: Support signed mod instructions
LoongArch: BPF: Support signed div instructions
LoongArch: BPF: Support 32-bit offset jmp instructions
LoongArch: BPF: Support unconditional bswap instructions
LoongArch: BPF: Support sign-extension mov instructions
LoongArch: BPF: Support sign-extension load instructions
LoongArch: Add more instruction opcodes and emit_* helpers
LoongArch/smp: Call rcutree_report_cpu_starting() earlier
LoongArch: Relax memory ordering for atomic operations
LoongArch: Mark __percpu functions as always inline
LoongArch: Disable module from accessing external data directly
LoongArch: Support PREEMPT_DYNAMIC with static keys

+215 -63
+1
arch/loongarch/Kconfig
··· 136 136 select HAVE_PERF_EVENTS 137 137 select HAVE_PERF_REGS 138 138 select HAVE_PERF_USER_STACK_DUMP 139 + select HAVE_PREEMPT_DYNAMIC_KEY 139 140 select HAVE_REGS_AND_STACK_ACCESS_API 140 141 select HAVE_RETHOOK 141 142 select HAVE_RSEQ
+2
arch/loongarch/Makefile
··· 68 68 ifdef CONFIG_AS_HAS_EXPLICIT_RELOCS 69 69 cflags-y += $(call cc-option,-mexplicit-relocs) 70 70 KBUILD_CFLAGS_KERNEL += $(call cc-option,-mdirect-extern-access) 71 + KBUILD_AFLAGS_MODULE += $(call cc-option,-fno-direct-access-external-data) 72 + KBUILD_CFLAGS_MODULE += $(call cc-option,-fno-direct-access-external-data) 71 73 KBUILD_AFLAGS_MODULE += $(call cc-option,-mno-relax) $(call cc-option,-Wa$(comma)-mno-relax) 72 74 KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) $(call cc-option,-Wa$(comma)-mno-relax) 73 75 else
+68 -20
arch/loongarch/include/asm/atomic.h
··· 36 36 static inline void arch_atomic_##op(int i, atomic_t *v) \ 37 37 { \ 38 38 __asm__ __volatile__( \ 39 - "am"#asm_op"_db.w" " $zero, %1, %0 \n" \ 39 + "am"#asm_op".w" " $zero, %1, %0 \n" \ 40 40 : "+ZB" (v->counter) \ 41 41 : "r" (I) \ 42 42 : "memory"); \ 43 43 } 44 44 45 - #define ATOMIC_OP_RETURN(op, I, asm_op, c_op) \ 46 - static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \ 45 + #define ATOMIC_OP_RETURN(op, I, asm_op, c_op, mb, suffix) \ 46 + static inline int arch_atomic_##op##_return##suffix(int i, atomic_t *v) \ 47 47 { \ 48 48 int result; \ 49 49 \ 50 50 __asm__ __volatile__( \ 51 - "am"#asm_op"_db.w" " %1, %2, %0 \n" \ 51 + "am"#asm_op#mb".w" " %1, %2, %0 \n" \ 52 52 : "+ZB" (v->counter), "=&r" (result) \ 53 53 : "r" (I) \ 54 54 : "memory"); \ ··· 56 56 return result c_op I; \ 57 57 } 58 58 59 - #define ATOMIC_FETCH_OP(op, I, asm_op) \ 60 - static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v) \ 59 + #define ATOMIC_FETCH_OP(op, I, asm_op, mb, suffix) \ 60 + static inline int arch_atomic_fetch_##op##suffix(int i, atomic_t *v) \ 61 61 { \ 62 62 int result; \ 63 63 \ 64 64 __asm__ __volatile__( \ 65 - "am"#asm_op"_db.w" " %1, %2, %0 \n" \ 65 + "am"#asm_op#mb".w" " %1, %2, %0 \n" \ 66 66 : "+ZB" (v->counter), "=&r" (result) \ 67 67 : "r" (I) \ 68 68 : "memory"); \ ··· 72 72 73 73 #define ATOMIC_OPS(op, I, asm_op, c_op) \ 74 74 ATOMIC_OP(op, I, asm_op) \ 75 - ATOMIC_OP_RETURN(op, I, asm_op, c_op) \ 76 - ATOMIC_FETCH_OP(op, I, asm_op) 75 + ATOMIC_OP_RETURN(op, I, asm_op, c_op, _db, ) \ 76 + ATOMIC_OP_RETURN(op, I, asm_op, c_op, , _relaxed) \ 77 + ATOMIC_FETCH_OP(op, I, asm_op, _db, ) \ 78 + ATOMIC_FETCH_OP(op, I, asm_op, , _relaxed) 77 79 78 80 ATOMIC_OPS(add, i, add, +) 79 81 ATOMIC_OPS(sub, -i, add, +) 80 82 83 + #define arch_atomic_add_return arch_atomic_add_return 84 + #define arch_atomic_add_return_acquire arch_atomic_add_return 85 + #define arch_atomic_add_return_release arch_atomic_add_return 81 86 #define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed 87 + #define arch_atomic_sub_return arch_atomic_sub_return 88 + #define arch_atomic_sub_return_acquire arch_atomic_sub_return 89 + #define arch_atomic_sub_return_release arch_atomic_sub_return 82 90 #define arch_atomic_sub_return_relaxed arch_atomic_sub_return_relaxed 91 + #define arch_atomic_fetch_add arch_atomic_fetch_add 92 + #define arch_atomic_fetch_add_acquire arch_atomic_fetch_add 93 + #define arch_atomic_fetch_add_release arch_atomic_fetch_add 83 94 #define arch_atomic_fetch_add_relaxed arch_atomic_fetch_add_relaxed 95 + #define arch_atomic_fetch_sub arch_atomic_fetch_sub 96 + #define arch_atomic_fetch_sub_acquire arch_atomic_fetch_sub 97 + #define arch_atomic_fetch_sub_release arch_atomic_fetch_sub 84 98 #define arch_atomic_fetch_sub_relaxed arch_atomic_fetch_sub_relaxed 85 99 86 100 #undef ATOMIC_OPS 87 101 88 102 #define ATOMIC_OPS(op, I, asm_op) \ 89 103 ATOMIC_OP(op, I, asm_op) \ 90 - ATOMIC_FETCH_OP(op, I, asm_op) 104 + ATOMIC_FETCH_OP(op, I, asm_op, _db, ) \ 105 + ATOMIC_FETCH_OP(op, I, asm_op, , _relaxed) 91 106 92 107 ATOMIC_OPS(and, i, and) 93 108 ATOMIC_OPS(or, i, or) 94 109 ATOMIC_OPS(xor, i, xor) 95 110 111 + #define arch_atomic_fetch_and arch_atomic_fetch_and 112 + #define arch_atomic_fetch_and_acquire arch_atomic_fetch_and 113 + #define arch_atomic_fetch_and_release arch_atomic_fetch_and 96 114 #define arch_atomic_fetch_and_relaxed arch_atomic_fetch_and_relaxed 115 + #define arch_atomic_fetch_or arch_atomic_fetch_or 116 + #define arch_atomic_fetch_or_acquire arch_atomic_fetch_or 117 + #define arch_atomic_fetch_or_release arch_atomic_fetch_or 97 118 #define arch_atomic_fetch_or_relaxed arch_atomic_fetch_or_relaxed 119 + #define arch_atomic_fetch_xor arch_atomic_fetch_xor 120 + #define arch_atomic_fetch_xor_acquire arch_atomic_fetch_xor 121 + #define arch_atomic_fetch_xor_release arch_atomic_fetch_xor 98 122 #define arch_atomic_fetch_xor_relaxed arch_atomic_fetch_xor_relaxed 99 123 100 124 #undef ATOMIC_OPS ··· 196 172 static inline void arch_atomic64_##op(long i, atomic64_t *v) \ 197 173 { \ 198 174 __asm__ __volatile__( \ 199 - "am"#asm_op"_db.d " " $zero, %1, %0 \n" \ 175 + "am"#asm_op".d " " $zero, %1, %0 \n" \ 200 176 : "+ZB" (v->counter) \ 201 177 : "r" (I) \ 202 178 : "memory"); \ 203 179 } 204 180 205 - #define ATOMIC64_OP_RETURN(op, I, asm_op, c_op) \ 206 - static inline long arch_atomic64_##op##_return_relaxed(long i, atomic64_t *v) \ 181 + #define ATOMIC64_OP_RETURN(op, I, asm_op, c_op, mb, suffix) \ 182 + static inline long arch_atomic64_##op##_return##suffix(long i, atomic64_t *v) \ 207 183 { \ 208 184 long result; \ 209 185 __asm__ __volatile__( \ 210 - "am"#asm_op"_db.d " " %1, %2, %0 \n" \ 186 + "am"#asm_op#mb".d " " %1, %2, %0 \n" \ 211 187 : "+ZB" (v->counter), "=&r" (result) \ 212 188 : "r" (I) \ 213 189 : "memory"); \ ··· 215 191 return result c_op I; \ 216 192 } 217 193 218 - #define ATOMIC64_FETCH_OP(op, I, asm_op) \ 219 - static inline long arch_atomic64_fetch_##op##_relaxed(long i, atomic64_t *v) \ 194 + #define ATOMIC64_FETCH_OP(op, I, asm_op, mb, suffix) \ 195 + static inline long arch_atomic64_fetch_##op##suffix(long i, atomic64_t *v) \ 220 196 { \ 221 197 long result; \ 222 198 \ 223 199 __asm__ __volatile__( \ 224 - "am"#asm_op"_db.d " " %1, %2, %0 \n" \ 200 + "am"#asm_op#mb".d " " %1, %2, %0 \n" \ 225 201 : "+ZB" (v->counter), "=&r" (result) \ 226 202 : "r" (I) \ 227 203 : "memory"); \ ··· 231 207 232 208 #define ATOMIC64_OPS(op, I, asm_op, c_op) \ 233 209 ATOMIC64_OP(op, I, asm_op) \ 234 - ATOMIC64_OP_RETURN(op, I, asm_op, c_op) \ 235 - ATOMIC64_FETCH_OP(op, I, asm_op) 210 + ATOMIC64_OP_RETURN(op, I, asm_op, c_op, _db, ) \ 211 + ATOMIC64_OP_RETURN(op, I, asm_op, c_op, , _relaxed) \ 212 + ATOMIC64_FETCH_OP(op, I, asm_op, _db, ) \ 213 + ATOMIC64_FETCH_OP(op, I, asm_op, , _relaxed) 236 214 237 215 ATOMIC64_OPS(add, i, add, +) 238 216 ATOMIC64_OPS(sub, -i, add, +) 239 217 218 + #define arch_atomic64_add_return arch_atomic64_add_return 219 + #define arch_atomic64_add_return_acquire arch_atomic64_add_return 220 + #define arch_atomic64_add_return_release arch_atomic64_add_return 240 221 #define arch_atomic64_add_return_relaxed arch_atomic64_add_return_relaxed 222 + #define arch_atomic64_sub_return arch_atomic64_sub_return 223 + #define arch_atomic64_sub_return_acquire arch_atomic64_sub_return 224 + #define arch_atomic64_sub_return_release arch_atomic64_sub_return 241 225 #define arch_atomic64_sub_return_relaxed arch_atomic64_sub_return_relaxed 226 + #define arch_atomic64_fetch_add arch_atomic64_fetch_add 227 + #define arch_atomic64_fetch_add_acquire arch_atomic64_fetch_add 228 + #define arch_atomic64_fetch_add_release arch_atomic64_fetch_add 242 229 #define arch_atomic64_fetch_add_relaxed arch_atomic64_fetch_add_relaxed 230 + #define arch_atomic64_fetch_sub arch_atomic64_fetch_sub 231 + #define arch_atomic64_fetch_sub_acquire arch_atomic64_fetch_sub 232 + #define arch_atomic64_fetch_sub_release arch_atomic64_fetch_sub 243 233 #define arch_atomic64_fetch_sub_relaxed arch_atomic64_fetch_sub_relaxed 244 234 245 235 #undef ATOMIC64_OPS 246 236 247 237 #define ATOMIC64_OPS(op, I, asm_op) \ 248 238 ATOMIC64_OP(op, I, asm_op) \ 249 - ATOMIC64_FETCH_OP(op, I, asm_op) 239 + ATOMIC64_FETCH_OP(op, I, asm_op, _db, ) \ 240 + ATOMIC64_FETCH_OP(op, I, asm_op, , _relaxed) 250 241 251 242 ATOMIC64_OPS(and, i, and) 252 243 ATOMIC64_OPS(or, i, or) 253 244 ATOMIC64_OPS(xor, i, xor) 254 245 246 + #define arch_atomic64_fetch_and arch_atomic64_fetch_and 247 + #define arch_atomic64_fetch_and_acquire arch_atomic64_fetch_and 248 + #define arch_atomic64_fetch_and_release arch_atomic64_fetch_and 255 249 #define arch_atomic64_fetch_and_relaxed arch_atomic64_fetch_and_relaxed 250 + #define arch_atomic64_fetch_or arch_atomic64_fetch_or 251 + #define arch_atomic64_fetch_or_acquire arch_atomic64_fetch_or 252 + #define arch_atomic64_fetch_or_release arch_atomic64_fetch_or 256 253 #define arch_atomic64_fetch_or_relaxed arch_atomic64_fetch_or_relaxed 254 + #define arch_atomic64_fetch_xor arch_atomic64_fetch_xor 255 + #define arch_atomic64_fetch_xor_acquire arch_atomic64_fetch_xor 256 + #define arch_atomic64_fetch_xor_release arch_atomic64_fetch_xor 257 257 #define arch_atomic64_fetch_xor_relaxed arch_atomic64_fetch_xor_relaxed 258 258 259 259 #undef ATOMIC64_OPS
+13
arch/loongarch/include/asm/inst.h
··· 65 65 revbd_op = 0x0f, 66 66 revh2w_op = 0x10, 67 67 revhd_op = 0x11, 68 + extwh_op = 0x16, 69 + extwb_op = 0x17, 68 70 iocsrrdb_op = 0x19200, 69 71 iocsrrdh_op = 0x19201, 70 72 iocsrrdw_op = 0x19202, ··· 574 572 DEF_EMIT_REG2_FORMAT(revb2h, revb2h_op) 575 573 DEF_EMIT_REG2_FORMAT(revb2w, revb2w_op) 576 574 DEF_EMIT_REG2_FORMAT(revbd, revbd_op) 575 + DEF_EMIT_REG2_FORMAT(extwh, extwh_op) 576 + DEF_EMIT_REG2_FORMAT(extwb, extwb_op) 577 577 578 578 #define DEF_EMIT_REG2I5_FORMAT(NAME, OP) \ 579 579 static inline void emit_##NAME(union loongarch_instruction *insn, \ ··· 627 623 DEF_EMIT_REG2I12_FORMAT(andi, andi_op) 628 624 DEF_EMIT_REG2I12_FORMAT(ori, ori_op) 629 625 DEF_EMIT_REG2I12_FORMAT(xori, xori_op) 626 + DEF_EMIT_REG2I12_FORMAT(ldb, ldb_op) 627 + DEF_EMIT_REG2I12_FORMAT(ldh, ldh_op) 628 + DEF_EMIT_REG2I12_FORMAT(ldw, ldw_op) 630 629 DEF_EMIT_REG2I12_FORMAT(ldbu, ldbu_op) 631 630 DEF_EMIT_REG2I12_FORMAT(ldhu, ldhu_op) 632 631 DEF_EMIT_REG2I12_FORMAT(ldwu, ldwu_op) ··· 708 701 insn->reg3_format.rk = rk; \ 709 702 } 710 703 704 + DEF_EMIT_REG3_FORMAT(addw, addw_op) 711 705 DEF_EMIT_REG3_FORMAT(addd, addd_op) 712 706 DEF_EMIT_REG3_FORMAT(subd, subd_op) 713 707 DEF_EMIT_REG3_FORMAT(muld, muld_op) 708 + DEF_EMIT_REG3_FORMAT(divd, divd_op) 709 + DEF_EMIT_REG3_FORMAT(modd, modd_op) 714 710 DEF_EMIT_REG3_FORMAT(divdu, divdu_op) 715 711 DEF_EMIT_REG3_FORMAT(moddu, moddu_op) 716 712 DEF_EMIT_REG3_FORMAT(and, and_op) ··· 725 715 DEF_EMIT_REG3_FORMAT(srld, srld_op) 726 716 DEF_EMIT_REG3_FORMAT(sraw, sraw_op) 727 717 DEF_EMIT_REG3_FORMAT(srad, srad_op) 718 + DEF_EMIT_REG3_FORMAT(ldxb, ldxb_op) 719 + DEF_EMIT_REG3_FORMAT(ldxh, ldxh_op) 720 + DEF_EMIT_REG3_FORMAT(ldxw, ldxw_op) 728 721 DEF_EMIT_REG3_FORMAT(ldxbu, ldxbu_op) 729 722 DEF_EMIT_REG3_FORMAT(ldxhu, ldxhu_op) 730 723 DEF_EMIT_REG3_FORMAT(ldxwu, ldxwu_op)
+5 -5
arch/loongarch/include/asm/percpu.h
··· 32 32 #define __my_cpu_offset __my_cpu_offset 33 33 34 34 #define PERCPU_OP(op, asm_op, c_op) \ 35 - static inline unsigned long __percpu_##op(void *ptr, \ 35 + static __always_inline unsigned long __percpu_##op(void *ptr, \ 36 36 unsigned long val, int size) \ 37 37 { \ 38 38 unsigned long ret; \ ··· 63 63 PERCPU_OP(or, or, |) 64 64 #undef PERCPU_OP 65 65 66 - static inline unsigned long __percpu_read(void *ptr, int size) 66 + static __always_inline unsigned long __percpu_read(void *ptr, int size) 67 67 { 68 68 unsigned long ret; 69 69 ··· 100 100 return ret; 101 101 } 102 102 103 - static inline void __percpu_write(void *ptr, unsigned long val, int size) 103 + static __always_inline void __percpu_write(void *ptr, unsigned long val, int size) 104 104 { 105 105 switch (size) { 106 106 case 1: ··· 132 132 } 133 133 } 134 134 135 - static inline unsigned long __percpu_xchg(void *ptr, unsigned long val, 136 - int size) 135 + static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val, 136 + int size) 137 137 { 138 138 switch (size) { 139 139 case 1:
+2 -1
arch/loongarch/kernel/smp.c
··· 504 504 unsigned int cpu; 505 505 506 506 sync_counter(); 507 - cpu = smp_processor_id(); 507 + cpu = raw_smp_processor_id(); 508 508 set_my_cpu_offset(per_cpu_offset(cpu)); 509 + rcutree_report_cpu_starting(cpu); 509 510 510 511 cpu_probe(); 511 512 constant_clockevent_init();
+112 -31
arch/loongarch/net/bpf_jit.c
··· 411 411 off_t offset; 412 412 struct exception_table_entry *ex; 413 413 414 - if (!ctx->image || !ctx->prog->aux->extable || BPF_MODE(insn->code) != BPF_PROBE_MEM) 414 + if (!ctx->image || !ctx->prog->aux->extable) 415 + return 0; 416 + 417 + if (BPF_MODE(insn->code) != BPF_PROBE_MEM && 418 + BPF_MODE(insn->code) != BPF_PROBE_MEMSX) 415 419 return 0; 416 420 417 421 if (WARN_ON_ONCE(ctx->num_exentries >= ctx->prog->aux->num_exentries)) ··· 454 450 { 455 451 u8 tm = -1; 456 452 u64 func_addr; 457 - bool func_addr_fixed; 453 + bool func_addr_fixed, sign_extend; 458 454 int i = insn - ctx->prog->insnsi; 459 455 int ret, jmp_offset; 460 456 const u8 code = insn->code; ··· 472 468 /* dst = src */ 473 469 case BPF_ALU | BPF_MOV | BPF_X: 474 470 case BPF_ALU64 | BPF_MOV | BPF_X: 475 - move_reg(ctx, dst, src); 476 - emit_zext_32(ctx, dst, is32); 471 + switch (off) { 472 + case 0: 473 + move_reg(ctx, dst, src); 474 + emit_zext_32(ctx, dst, is32); 475 + break; 476 + case 8: 477 + move_reg(ctx, t1, src); 478 + emit_insn(ctx, extwb, dst, t1); 479 + break; 480 + case 16: 481 + move_reg(ctx, t1, src); 482 + emit_insn(ctx, extwh, dst, t1); 483 + break; 484 + case 32: 485 + emit_insn(ctx, addw, dst, src, LOONGARCH_GPR_ZERO); 486 + break; 487 + } 477 488 break; 478 489 479 490 /* dst = imm */ ··· 553 534 /* dst = dst / src */ 554 535 case BPF_ALU | BPF_DIV | BPF_X: 555 536 case BPF_ALU64 | BPF_DIV | BPF_X: 556 - emit_zext_32(ctx, dst, is32); 557 - move_reg(ctx, t1, src); 558 - emit_zext_32(ctx, t1, is32); 559 - emit_insn(ctx, divdu, dst, dst, t1); 560 - emit_zext_32(ctx, dst, is32); 537 + if (!off) { 538 + emit_zext_32(ctx, dst, is32); 539 + move_reg(ctx, t1, src); 540 + emit_zext_32(ctx, t1, is32); 541 + emit_insn(ctx, divdu, dst, dst, t1); 542 + emit_zext_32(ctx, dst, is32); 543 + } else { 544 + emit_sext_32(ctx, dst, is32); 545 + move_reg(ctx, t1, src); 546 + emit_sext_32(ctx, t1, is32); 547 + emit_insn(ctx, divd, dst, dst, t1); 548 + emit_sext_32(ctx, dst, is32); 549 + } 561 550 break; 562 551 563 552 /* dst = dst / imm */ 564 553 case BPF_ALU | BPF_DIV | BPF_K: 565 554 case BPF_ALU64 | BPF_DIV | BPF_K: 566 - move_imm(ctx, t1, imm, is32); 567 - emit_zext_32(ctx, dst, is32); 568 - emit_insn(ctx, divdu, dst, dst, t1); 569 - emit_zext_32(ctx, dst, is32); 555 + if (!off) { 556 + move_imm(ctx, t1, imm, is32); 557 + emit_zext_32(ctx, dst, is32); 558 + emit_insn(ctx, divdu, dst, dst, t1); 559 + emit_zext_32(ctx, dst, is32); 560 + } else { 561 + move_imm(ctx, t1, imm, false); 562 + emit_sext_32(ctx, t1, is32); 563 + emit_sext_32(ctx, dst, is32); 564 + emit_insn(ctx, divd, dst, dst, t1); 565 + emit_sext_32(ctx, dst, is32); 566 + } 570 567 break; 571 568 572 569 /* dst = dst % src */ 573 570 case BPF_ALU | BPF_MOD | BPF_X: 574 571 case BPF_ALU64 | BPF_MOD | BPF_X: 575 - emit_zext_32(ctx, dst, is32); 576 - move_reg(ctx, t1, src); 577 - emit_zext_32(ctx, t1, is32); 578 - emit_insn(ctx, moddu, dst, dst, t1); 579 - emit_zext_32(ctx, dst, is32); 572 + if (!off) { 573 + emit_zext_32(ctx, dst, is32); 574 + move_reg(ctx, t1, src); 575 + emit_zext_32(ctx, t1, is32); 576 + emit_insn(ctx, moddu, dst, dst, t1); 577 + emit_zext_32(ctx, dst, is32); 578 + } else { 579 + emit_sext_32(ctx, dst, is32); 580 + move_reg(ctx, t1, src); 581 + emit_sext_32(ctx, t1, is32); 582 + emit_insn(ctx, modd, dst, dst, t1); 583 + emit_sext_32(ctx, dst, is32); 584 + } 580 585 break; 581 586 582 587 /* dst = dst % imm */ 583 588 case BPF_ALU | BPF_MOD | BPF_K: 584 589 case BPF_ALU64 | BPF_MOD | BPF_K: 585 - move_imm(ctx, t1, imm, is32); 586 - emit_zext_32(ctx, dst, is32); 587 - emit_insn(ctx, moddu, dst, dst, t1); 588 - emit_zext_32(ctx, dst, is32); 590 + if (!off) { 591 + move_imm(ctx, t1, imm, is32); 592 + emit_zext_32(ctx, dst, is32); 593 + emit_insn(ctx, moddu, dst, dst, t1); 594 + emit_zext_32(ctx, dst, is32); 595 + } else { 596 + move_imm(ctx, t1, imm, false); 597 + emit_sext_32(ctx, t1, is32); 598 + emit_sext_32(ctx, dst, is32); 599 + emit_insn(ctx, modd, dst, dst, t1); 600 + emit_sext_32(ctx, dst, is32); 601 + } 589 602 break; 590 603 591 604 /* dst = -dst */ ··· 763 712 break; 764 713 765 714 case BPF_ALU | BPF_END | BPF_FROM_BE: 715 + case BPF_ALU64 | BPF_END | BPF_FROM_LE: 766 716 switch (imm) { 767 717 case 16: 768 718 emit_insn(ctx, revb2h, dst, dst); ··· 880 828 881 829 /* PC += off */ 882 830 case BPF_JMP | BPF_JA: 883 - jmp_offset = bpf2la_offset(i, off, ctx); 831 + case BPF_JMP32 | BPF_JA: 832 + if (BPF_CLASS(code) == BPF_JMP) 833 + jmp_offset = bpf2la_offset(i, off, ctx); 834 + else 835 + jmp_offset = bpf2la_offset(i, imm, ctx); 884 836 if (emit_uncond_jmp(ctx, jmp_offset) < 0) 885 837 goto toofar; 886 838 break; ··· 935 879 case BPF_LDX | BPF_PROBE_MEM | BPF_W: 936 880 case BPF_LDX | BPF_PROBE_MEM | BPF_H: 937 881 case BPF_LDX | BPF_PROBE_MEM | BPF_B: 882 + /* dst_reg = (s64)*(signed size *)(src_reg + off) */ 883 + case BPF_LDX | BPF_MEMSX | BPF_B: 884 + case BPF_LDX | BPF_MEMSX | BPF_H: 885 + case BPF_LDX | BPF_MEMSX | BPF_W: 886 + case BPF_LDX | BPF_PROBE_MEMSX | BPF_B: 887 + case BPF_LDX | BPF_PROBE_MEMSX | BPF_H: 888 + case BPF_LDX | BPF_PROBE_MEMSX | BPF_W: 889 + sign_extend = BPF_MODE(insn->code) == BPF_MEMSX || 890 + BPF_MODE(insn->code) == BPF_PROBE_MEMSX; 938 891 switch (BPF_SIZE(code)) { 939 892 case BPF_B: 940 893 if (is_signed_imm12(off)) { 941 - emit_insn(ctx, ldbu, dst, src, off); 894 + if (sign_extend) 895 + emit_insn(ctx, ldb, dst, src, off); 896 + else 897 + emit_insn(ctx, ldbu, dst, src, off); 942 898 } else { 943 899 move_imm(ctx, t1, off, is32); 944 - emit_insn(ctx, ldxbu, dst, src, t1); 900 + if (sign_extend) 901 + emit_insn(ctx, ldxb, dst, src, t1); 902 + else 903 + emit_insn(ctx, ldxbu, dst, src, t1); 945 904 } 946 905 break; 947 906 case BPF_H: 948 907 if (is_signed_imm12(off)) { 949 - emit_insn(ctx, ldhu, dst, src, off); 908 + if (sign_extend) 909 + emit_insn(ctx, ldh, dst, src, off); 910 + else 911 + emit_insn(ctx, ldhu, dst, src, off); 950 912 } else { 951 913 move_imm(ctx, t1, off, is32); 952 - emit_insn(ctx, ldxhu, dst, src, t1); 914 + if (sign_extend) 915 + emit_insn(ctx, ldxh, dst, src, t1); 916 + else 917 + emit_insn(ctx, ldxhu, dst, src, t1); 953 918 } 954 919 break; 955 920 case BPF_W: 956 921 if (is_signed_imm12(off)) { 957 - emit_insn(ctx, ldwu, dst, src, off); 958 - } else if (is_signed_imm14(off)) { 959 - emit_insn(ctx, ldptrw, dst, src, off); 922 + if (sign_extend) 923 + emit_insn(ctx, ldw, dst, src, off); 924 + else 925 + emit_insn(ctx, ldwu, dst, src, off); 960 926 } else { 961 927 move_imm(ctx, t1, off, is32); 962 - emit_insn(ctx, ldxwu, dst, src, t1); 928 + if (sign_extend) 929 + emit_insn(ctx, ldxw, dst, src, t1); 930 + else 931 + emit_insn(ctx, ldxwu, dst, src, t1); 963 932 } 964 933 break; 965 934 case BPF_DW:
+2 -1
tools/testing/selftests/bpf/progs/test_ldsx_insn.c
··· 7 7 8 8 #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 9 9 (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 10 - defined(__TARGET_ARCH_s390)) && __clang_major__ >= 18 10 + defined(__TARGET_ARCH_s390) || defined(__TARGET_ARCH_loongarch)) && \ 11 + __clang_major__ >= 18 11 12 const volatile int skip = 0; 12 13 #else 13 14 const volatile int skip = 1;
+2 -1
tools/testing/selftests/bpf/progs/verifier_bswap.c
··· 6 6 7 7 #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 8 8 (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 9 - defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \ 9 + defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390) || \ 10 + defined(__TARGET_ARCH_loongarch)) && \ 10 11 __clang_major__ >= 18 11 12 12 13 SEC("socket")
+2 -1
tools/testing/selftests/bpf/progs/verifier_gotol.c
··· 6 6 7 7 #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 8 8 (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 9 - defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \ 9 + defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390) || \ 10 + defined(__TARGET_ARCH_loongarch)) && \ 10 11 __clang_major__ >= 18 11 12 12 13 SEC("socket")
+2 -1
tools/testing/selftests/bpf/progs/verifier_ldsx.c
··· 6 6 7 7 #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 8 8 (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 9 - defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \ 9 + defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390) || \ 10 + defined(__TARGET_ARCH_loongarch)) && \ 10 11 __clang_major__ >= 18 11 12 12 13 SEC("socket")
+2 -1
tools/testing/selftests/bpf/progs/verifier_movsx.c
··· 6 6 7 7 #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 8 8 (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 9 - defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \ 9 + defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390) || \ 10 + defined(__TARGET_ARCH_loongarch)) && \ 10 11 __clang_major__ >= 18 11 12 12 13 SEC("socket")
+2 -1
tools/testing/selftests/bpf/progs/verifier_sdiv.c
··· 6 6 7 7 #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 8 8 (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 9 - defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \ 9 + defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390) || \ 10 + defined(__TARGET_ARCH_loongarch)) && \ 10 11 __clang_major__ >= 18 11 12 12 13 SEC("socket")