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

Pull LoongArch updates from Huacai Chen:

- Adjust build infrastructure for 32BIT/64BIT

- Add HIGHMEM (PKMAP and FIX_KMAP) support

- Show and handle CPU vulnerabilites correctly

- Batch the icache maintenance for jump_label

- Add more atomic instructions support for BPF JIT

- Add more features (e.g. fsession) support for BPF trampoline

- Some bug fixes and other small changes

* tag 'loongarch-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson: (21 commits)
selftests/bpf: Enable CAN_USE_LOAD_ACQ_STORE_REL for LoongArch
LoongArch: BPF: Add fsession support for trampolines
LoongArch: BPF: Introduce emit_store_stack_imm64() helper
LoongArch: BPF: Support up to 12 function arguments for trampoline
LoongArch: BPF: Support small struct arguments for trampoline
LoongArch: BPF: Open code and remove invoke_bpf_mod_ret()
LoongArch: BPF: Support load-acquire and store-release instructions
LoongArch: BPF: Support 8 and 16 bit read-modify-write instructions
LoongArch: BPF: Add the default case in emit_atomic() and rename it
LoongArch: Define instruction formats for AM{SWAP/ADD}.{B/H} and DBAR
LoongArch: Batch the icache maintenance for jump_label
LoongArch: Add flush_icache_all()/local_flush_icache_all()
LoongArch: Add spectre boundry for syscall dispatch table
LoongArch: Show CPU vulnerabilites correctly
LoongArch: Make arch_irq_work_has_interrupt() true only if IPI HW exist
LoongArch: Use get_random_canary() for stack canary init
LoongArch: Improve the logging of disabling KASLR
LoongArch: Align FPU register state to 32 bytes
LoongArch: Handle CONFIG_32BIT in syscall_get_arch()
LoongArch: Add HIGHMEM (PKMAP and FIX_KMAP) support
...

+727 -202
+86 -34
arch/loongarch/Kconfig
··· 20 20 select ARCH_HAS_FAST_MULTIPLIER 21 21 select ARCH_HAS_FORTIFY_SOURCE 22 22 select ARCH_HAS_KCOV 23 - select ARCH_HAS_KERNEL_FPU_SUPPORT if CPU_HAS_FPU 23 + select ARCH_HAS_KERNEL_FPU_SUPPORT if 64BIT && CPU_HAS_FPU 24 24 select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS 25 25 select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE 26 26 select ARCH_HAS_PREEMPT_LAZY 27 - select ARCH_HAS_PTE_SPECIAL 27 + select ARCH_HAS_PTE_SPECIAL if 64BIT 28 28 select ARCH_HAS_SET_MEMORY 29 29 select ARCH_HAS_SET_DIRECT_MAP 30 30 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST ··· 59 59 select ARCH_KEEP_MEMBLOCK 60 60 select ARCH_MIGHT_HAVE_PC_PARPORT 61 61 select ARCH_MIGHT_HAVE_PC_SERIO 62 - select ARCH_SPARSEMEM_ENABLE 63 62 select ARCH_STACKWALK 64 63 select ARCH_SUPPORTS_ACPI 65 64 select ARCH_SUPPORTS_ATOMIC_RMW 66 - select ARCH_SUPPORTS_HUGETLBFS 65 + select ARCH_SUPPORTS_HUGETLBFS if 64BIT 67 66 select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 68 67 select ARCH_SUPPORTS_LTO_CLANG 69 68 select ARCH_SUPPORTS_LTO_CLANG_THIN 70 69 select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS 71 - select ARCH_SUPPORTS_NUMA_BALANCING 70 + select ARCH_SUPPORTS_NUMA_BALANCING if NUMA 72 71 select ARCH_SUPPORTS_PER_VMA_LOCK 73 72 select ARCH_SUPPORTS_RT 74 73 select ARCH_SUPPORTS_SCHED_SMT if SMP ··· 77 78 select ARCH_USE_MEMTEST 78 79 select ARCH_USE_QUEUED_RWLOCKS 79 80 select ARCH_USE_QUEUED_SPINLOCKS 80 - select ARCH_WANT_DEFAULT_BPF_JIT 81 + select ARCH_WANT_DEFAULT_BPF_JIT if HAVE_EBPF_JIT 81 82 select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT 82 83 select ARCH_WANT_LD_ORPHAN_WARN 83 - select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP 84 + select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP if 64BIT 84 85 select ARCH_WANTS_NO_INSTR 85 86 select ARCH_WANTS_THP_SWAP if HAVE_ARCH_TRANSPARENT_HUGEPAGE 86 87 select BUILDTIME_TABLE_SORT ··· 88 89 select CPU_PM 89 90 select EDAC_SUPPORT 90 91 select EFI 92 + select GENERIC_ATOMIC64 if 32BIT 91 93 select GENERIC_CLOCKEVENTS 92 94 select GENERIC_CMOS_UPDATE 93 95 select GENERIC_CPU_AUTOPROBE 94 96 select GENERIC_CPU_DEVICES 95 97 select GENERIC_CPU_VULNERABILITIES 96 98 select GENERIC_ENTRY 97 - select GENERIC_GETTIMEOFDAY 99 + select GENERIC_GETTIMEOFDAY if 64BIT 98 100 select GENERIC_IOREMAP if !ARCH_IOREMAP 99 101 select GENERIC_IRQ_MATRIX_ALLOCATOR 100 102 select GENERIC_IRQ_MULTI_HANDLER ··· 110 110 select GENERIC_PCI_IOMAP 111 111 select GENERIC_SCHED_CLOCK 112 112 select GENERIC_SMP_IDLE_THREAD 113 - select GENERIC_TIME_VSYSCALL 113 + select GENERIC_TIME_VSYSCALL if GENERIC_GETTIMEOFDAY 114 114 select GPIOLIB 115 115 select HAS_IOPORT 116 - select HAVE_ALIGNED_STRUCT_PAGE 116 + select HAVE_ALIGNED_STRUCT_PAGE if 64BIT 117 117 select HAVE_ARCH_AUDITSYSCALL 118 - select HAVE_ARCH_BITREVERSE 118 + select HAVE_ARCH_BITREVERSE if 64BIT 119 119 select HAVE_ARCH_JUMP_LABEL 120 120 select HAVE_ARCH_JUMP_LABEL_RELATIVE 121 - select HAVE_ARCH_KASAN 122 - select HAVE_ARCH_KFENCE 121 + select HAVE_ARCH_KASAN if 64BIT 122 + select HAVE_ARCH_KFENCE if 64BIT 123 123 select HAVE_ARCH_KGDB if PERF_EVENTS 124 124 select HAVE_ARCH_KSTACK_ERASE 125 125 select HAVE_ARCH_MMAP_RND_BITS if MMU ··· 127 127 select HAVE_ARCH_SECCOMP 128 128 select HAVE_ARCH_SECCOMP_FILTER 129 129 select HAVE_ARCH_TRACEHOOK 130 - select HAVE_ARCH_TRANSPARENT_HUGEPAGE 131 - select HAVE_ARCH_USERFAULTFD_MINOR if USERFAULTFD 130 + select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT 131 + select HAVE_ARCH_USERFAULTFD_MINOR if 64BIT && USERFAULTFD 132 132 select HAVE_ASM_MODVERSIONS 133 133 select HAVE_CMPXCHG_DOUBLE 134 134 select HAVE_CMPXCHG_LOCAL ··· 142 142 select HAVE_FTRACE_REGS_HAVING_PT_REGS 143 143 select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 144 144 select HAVE_DYNAMIC_FTRACE_WITH_REGS 145 - select HAVE_EBPF_JIT 145 + select HAVE_EBPF_JIT if 64BIT 146 146 select HAVE_EFFICIENT_UNALIGNED_ACCESS if !ARCH_STRICT_ALIGN 147 147 select HAVE_EXIT_THREAD 148 148 select HAVE_GENERIC_TIF_BITS ··· 165 165 select HAVE_LIVEPATCH 166 166 select HAVE_MOD_ARCH_SPECIFIC 167 167 select HAVE_NMI 168 - select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS && AS_HAS_THIN_ADD_SUB 168 + select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS && AS_HAS_THIN_ADD_SUB && 64BIT 169 169 select HAVE_PCI 170 - select HAVE_PERF_EVENTS 170 + select HAVE_PERF_EVENTS if 64BIT 171 171 select HAVE_PERF_REGS 172 172 select HAVE_PERF_USER_STACK_DUMP 173 173 select HAVE_POSIX_CPU_TIMERS_TASK_WORK ··· 209 209 select SYSCTL_ARCH_UNALIGN_ALLOW 210 210 select SYSCTL_ARCH_UNALIGN_NO_WARN 211 211 select SYSCTL_EXCEPTION_TRACE 212 - select SWIOTLB 212 + select SWIOTLB if 64BIT 213 213 select TRACE_IRQFLAGS_SUPPORT 214 214 select USE_PERCPU_NUMA_NODE_ID 215 215 select USER_STACKTRACE_SUPPORT 216 216 select VDSO_GETRANDOM 217 - select ZONE_DMA32 217 + select ZONE_DMA32 if 64BIT 218 + 219 + menu "Kernel type and options" 220 + 221 + choice 222 + prompt "Kernel type" 218 223 219 224 config 32BIT 220 - bool 225 + bool "32-bit kernel" 226 + help 227 + Select this option if you want to build a 32-bit kernel. 221 228 222 229 config 64BIT 223 - def_bool y 230 + bool "64-bit kernel" 231 + help 232 + Select this option if you want to build a 64-bit kernel. 233 + 234 + endchoice 235 + 236 + if 32BIT 237 + 238 + choice 239 + prompt "32-bit kernel sub-type" 240 + 241 + config 32BIT_REDUCED 242 + bool "32-bit kernel for LA32R" 243 + help 244 + Select this option if you want to build a 32-bit kernel for 245 + LoongArch32 Reduced (LA32R). 246 + 247 + config 32BIT_STANDARD 248 + bool "32-bit kernel for LA32S" 249 + help 250 + Select this option if you want to build a 32-bit kernel for 251 + LoongArch32 Standard (LA32S). 252 + 253 + endchoice 254 + 255 + endif 224 256 225 257 config GENERIC_BUG 226 258 def_bool y ··· 345 313 depends on RUST 346 314 def_bool $(rustc-option,-Cllvm-args=--loongarch-annotate-tablejump) 347 315 348 - menu "Kernel type and options" 349 - 350 316 source "kernel/Kconfig.hz" 317 + 318 + config HIGHMEM 319 + bool "High Memory Support" 320 + depends on 32BIT 321 + select KMAP_LOCAL 351 322 352 323 choice 353 324 prompt "Page Table Layout" ··· 361 326 of page size and page table levels. The size of virtual memory 362 327 address space are determined by the page table layout. 363 328 329 + config 4KB_2LEVEL 330 + bool "4KB with 2 levels" 331 + select HAVE_PAGE_SIZE_4KB 332 + select PGTABLE_2LEVEL 333 + help 334 + This option selects 4KB page size with 2 level page tables, which 335 + support a maximum of 32 bits of application virtual memory. 336 + 364 337 config 4KB_3LEVEL 365 338 bool "4KB with 3 levels" 339 + depends on 64BIT 366 340 select HAVE_PAGE_SIZE_4KB 367 341 select PGTABLE_3LEVEL 368 342 help ··· 380 336 381 337 config 4KB_4LEVEL 382 338 bool "4KB with 4 levels" 339 + depends on 64BIT 383 340 select HAVE_PAGE_SIZE_4KB 384 341 select PGTABLE_4LEVEL 385 342 help ··· 397 352 398 353 config 16KB_3LEVEL 399 354 bool "16KB with 3 levels" 355 + depends on 64BIT 400 356 select HAVE_PAGE_SIZE_16KB 401 357 select PGTABLE_3LEVEL 402 358 help ··· 414 368 415 369 config 64KB_3LEVEL 416 370 bool "64KB with 3 levels" 371 + depends on 64BIT 417 372 select HAVE_PAGE_SIZE_64KB 418 373 select PGTABLE_3LEVEL 419 374 help ··· 512 465 513 466 config SMP 514 467 bool "Multi-Processing support" 468 + depends on 64BIT 515 469 help 516 470 This enables support for systems with more than one CPU. If you have 517 471 a system with only one CPU, say N. If you have a system with more ··· 551 503 config NUMA 552 504 bool "NUMA Support" 553 505 select SMP 506 + depends on 64BIT 554 507 help 555 508 Say Y to compile the kernel with NUMA (Non-Uniform Memory Access) 556 509 support. This option improves performance on systems with more ··· 634 585 635 586 config CPU_HAS_LSX 636 587 bool "Support for the Loongson SIMD Extension" 637 - depends on AS_HAS_LSX_EXTENSION 588 + depends on AS_HAS_LSX_EXTENSION && 64BIT 638 589 help 639 590 Loongson SIMD Extension (LSX) introduces 128 bit wide vector registers 640 591 and a set of SIMD instructions to operate on them. When this option ··· 649 600 config CPU_HAS_LASX 650 601 bool "Support for the Loongson Advanced SIMD Extension" 651 602 depends on CPU_HAS_LSX 652 - depends on AS_HAS_LASX_EXTENSION 603 + depends on AS_HAS_LASX_EXTENSION && 64BIT 653 604 help 654 605 Loongson Advanced SIMD Extension (LASX) introduces 256 bit wide vector 655 606 registers and a set of SIMD instructions to operate on them. When this ··· 663 614 664 615 config CPU_HAS_LBT 665 616 bool "Support for the Loongson Binary Translation Extension" 666 - depends on AS_HAS_LBT_EXTENSION 617 + depends on AS_HAS_LBT_EXTENSION && 64BIT 667 618 help 668 619 Loongson Binary Translation (LBT) introduces 4 scratch registers (SCR0 669 620 to SCR3), x86/ARM eflags (eflags) and x87 fpu stack pointer (ftop). ··· 691 642 select HAVE_IMA_KEXEC if IMA 692 643 693 644 config ARCH_SUPPORTS_CRASH_DUMP 694 - def_bool y 645 + def_bool 64BIT 695 646 696 647 config ARCH_DEFAULT_CRASH_DUMP 697 - def_bool y 648 + def_bool 64BIT 698 649 699 650 config ARCH_SELECTS_CRASH_DUMP 700 - def_bool y 651 + def_bool 64BIT 701 652 depends on CRASH_DUMP 702 653 select RELOCATABLE 703 654 ··· 706 657 707 658 config RELOCATABLE 708 659 bool "Relocatable kernel" 660 + depends on 64BIT 709 661 select ARCH_HAS_RELR 710 662 help 711 663 This builds the kernel as a Position Independent Executable (PIE), ··· 743 693 744 694 config PARAVIRT 745 695 bool "Enable paravirtualization code" 746 - depends on AS_HAS_LVZ_EXTENSION 696 + depends on AS_HAS_LVZ_EXTENSION && 64BIT 747 697 select HAVE_PV_STEAL_CLOCK_GEN 748 698 help 749 699 This changes the kernel so it can modify itself when it is run ··· 772 722 depends on !NUMA 773 723 774 724 config ARCH_SPARSEMEM_ENABLE 775 - def_bool y 725 + def_bool 64BIT 776 726 select SPARSEMEM_VMEMMAP_ENABLE 777 727 help 778 728 Say Y to support efficient handling of sparse physical memory, ··· 789 739 default y 790 740 791 741 config ARCH_MMAP_RND_BITS_MIN 792 - default 12 742 + default 10 if 32BIT 743 + default 12 if 64BIT 793 744 794 745 config ARCH_MMAP_RND_BITS_MAX 795 - default 18 746 + default 15 if 32BIT 747 + default 20 if 64BIT 796 748 797 749 config ARCH_SUPPORTS_UPROBES 798 750 def_bool y
+21 -2
arch/loongarch/Makefile
··· 25 25 # 26 26 # Select the object file format to substitute into the linker script. 27 27 # 28 + 32bit-tool-archpref = loongarch32 28 29 64bit-tool-archpref = loongarch64 29 30 32bit-bfd = elf32-loongarch 30 31 64bit-bfd = elf64-loongarch ··· 52 51 CC_FLAGS_FTRACE := -fpatchable-function-entry=2 53 52 endif 54 53 55 - ifdef CONFIG_64BIT 54 + ifdef CONFIG_32BIT 55 + tool-archpref = $(32bit-tool-archpref) 56 + UTS_MACHINE := loongarch32 57 + else 56 58 tool-archpref = $(64bit-tool-archpref) 57 59 UTS_MACHINE := loongarch64 58 60 endif ··· 66 62 endif 67 63 endif 68 64 65 + ifdef CONFIG_32BIT 66 + ifdef CONFIG_32BIT_STANDARD 67 + ld-emul = $(32bit-emul) 68 + cflags-y += -march=la32v1.0 -mabi=ilp32s -mcmodel=normal 69 + else # CONFIG_32BIT_REDUCED 70 + ld-emul = $(32bit-emul) 71 + cflags-y += -march=la32rv1.0 -mabi=ilp32s -mcmodel=normal 72 + endif 73 + endif 74 + 69 75 ifdef CONFIG_64BIT 70 76 ld-emul = $(64bit-emul) 71 - cflags-y += -mabi=lp64s -mcmodel=normal 77 + cflags-y += -march=loongarch64 -mabi=lp64s -mcmodel=normal 72 78 endif 73 79 74 80 cflags-y += -pipe $(CC_FLAGS_NO_FPU) ··· 154 140 cflags-y += -fno-builtin-memcpy -fno-builtin-memmove -fno-builtin-memset 155 141 endif 156 142 143 + ifdef CONFIG_32BIT 144 + load-y = 0xa0200000 145 + else 157 146 load-y = 0x9000000000200000 147 + endif 148 + 158 149 bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) 159 150 160 151 drivers-$(CONFIG_PCI) += arch/loongarch/pci/
+6
arch/loongarch/boot/Makefile
··· 20 20 $(call if_changed,objcopy) 21 21 22 22 EFI_ZBOOT_PAYLOAD := vmlinux.efi 23 + 24 + ifdef CONFIG_32BIT 25 + EFI_ZBOOT_BFD_TARGET := elf32-loongarch 26 + EFI_ZBOOT_MACH_TYPE := LOONGARCH32 27 + else 23 28 EFI_ZBOOT_BFD_TARGET := elf64-loongarch 24 29 EFI_ZBOOT_MACH_TYPE := LOONGARCH64 30 + endif 25 31 26 32 include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot
+15 -1
arch/loongarch/include/asm/cacheflush.h
··· 32 32 } 33 33 34 34 asmlinkage void __flush_cache_all(void); 35 - void local_flush_icache_range(unsigned long start, unsigned long end); 36 35 36 + /* 37 + * LoongArch maintains ICache/DCache coherency by hardware, 38 + * we just need "ibar" to avoid instruction hazard here. 39 + */ 40 + static inline void local_flush_icache_all(void) 41 + { 42 + asm volatile ("ibar\t0\n"::); 43 + } 44 + 45 + static inline void local_flush_icache_range(unsigned long start, unsigned long end) 46 + { 47 + asm volatile ("ibar\t0\n"::); 48 + } 49 + 50 + #define flush_icache_all local_flush_icache_all 37 51 #define flush_icache_range local_flush_icache_range 38 52 #define flush_icache_user_range local_flush_icache_range 39 53
+1
arch/loongarch/include/asm/cpu-features.h
··· 35 35 */ 36 36 #define cpu_has_cpucfg cpu_opt(LOONGARCH_CPU_CPUCFG) 37 37 #define cpu_has_lam cpu_opt(LOONGARCH_CPU_LAM) 38 + #define cpu_has_lam_bh cpu_opt(LOONGARCH_CPU_LAM_BH) 38 39 #define cpu_has_scq cpu_opt(LOONGARCH_CPU_SCQ) 39 40 #define cpu_has_ual cpu_opt(LOONGARCH_CPU_UAL) 40 41 #define cpu_has_fpu cpu_opt(LOONGARCH_CPU_FPU)
+33 -31
arch/loongarch/include/asm/cpu.h
··· 95 95 */ 96 96 #define CPU_FEATURE_CPUCFG 0 /* CPU has CPUCFG */ 97 97 #define CPU_FEATURE_LAM 1 /* CPU has Atomic instructions */ 98 - #define CPU_FEATURE_SCQ 2 /* CPU has SC.Q instruction */ 99 - #define CPU_FEATURE_UAL 3 /* CPU supports unaligned access */ 100 - #define CPU_FEATURE_FPU 4 /* CPU has FPU */ 101 - #define CPU_FEATURE_LSX 5 /* CPU has LSX (128-bit SIMD) */ 102 - #define CPU_FEATURE_LASX 6 /* CPU has LASX (256-bit SIMD) */ 103 - #define CPU_FEATURE_CRC32 7 /* CPU has CRC32 instructions */ 104 - #define CPU_FEATURE_COMPLEX 8 /* CPU has Complex instructions */ 105 - #define CPU_FEATURE_CRYPTO 9 /* CPU has Crypto instructions */ 106 - #define CPU_FEATURE_LVZ 10 /* CPU has Virtualization extension */ 107 - #define CPU_FEATURE_LBT_X86 11 /* CPU has X86 Binary Translation */ 108 - #define CPU_FEATURE_LBT_ARM 12 /* CPU has ARM Binary Translation */ 109 - #define CPU_FEATURE_LBT_MIPS 13 /* CPU has MIPS Binary Translation */ 110 - #define CPU_FEATURE_TLB 14 /* CPU has TLB */ 111 - #define CPU_FEATURE_CSR 15 /* CPU has CSR */ 112 - #define CPU_FEATURE_IOCSR 16 /* CPU has IOCSR */ 113 - #define CPU_FEATURE_WATCH 17 /* CPU has watchpoint registers */ 114 - #define CPU_FEATURE_VINT 18 /* CPU has vectored interrupts */ 115 - #define CPU_FEATURE_CSRIPI 19 /* CPU has CSR-IPI */ 116 - #define CPU_FEATURE_EXTIOI 20 /* CPU has EXT-IOI */ 117 - #define CPU_FEATURE_PREFETCH 21 /* CPU has prefetch instructions */ 118 - #define CPU_FEATURE_PMP 22 /* CPU has perfermance counter */ 119 - #define CPU_FEATURE_SCALEFREQ 23 /* CPU supports cpufreq scaling */ 120 - #define CPU_FEATURE_FLATMODE 24 /* CPU has flat mode */ 121 - #define CPU_FEATURE_EIODECODE 25 /* CPU has EXTIOI interrupt pin decode mode */ 122 - #define CPU_FEATURE_GUESTID 26 /* CPU has GuestID feature */ 123 - #define CPU_FEATURE_HYPERVISOR 27 /* CPU has hypervisor (running in VM) */ 124 - #define CPU_FEATURE_PTW 28 /* CPU has hardware page table walker */ 125 - #define CPU_FEATURE_LSPW 29 /* CPU has LSPW (lddir/ldpte instructions) */ 126 - #define CPU_FEATURE_MSGINT 30 /* CPU has MSG interrupt */ 127 - #define CPU_FEATURE_AVECINT 31 /* CPU has AVEC interrupt */ 128 - #define CPU_FEATURE_REDIRECTINT 32 /* CPU has interrupt remapping */ 98 + #define CPU_FEATURE_LAM_BH 2 /* CPU has AM{SWAP/ADD}[_DB].{B/H} instructions */ 99 + #define CPU_FEATURE_SCQ 3 /* CPU has SC.Q instruction */ 100 + #define CPU_FEATURE_UAL 4 /* CPU supports unaligned access */ 101 + #define CPU_FEATURE_FPU 5 /* CPU has FPU */ 102 + #define CPU_FEATURE_LSX 6 /* CPU has LSX (128-bit SIMD) */ 103 + #define CPU_FEATURE_LASX 7 /* CPU has LASX (256-bit SIMD) */ 104 + #define CPU_FEATURE_CRC32 8 /* CPU has CRC32 instructions */ 105 + #define CPU_FEATURE_COMPLEX 9 /* CPU has Complex instructions */ 106 + #define CPU_FEATURE_CRYPTO 10 /* CPU has Crypto instructions */ 107 + #define CPU_FEATURE_LVZ 11 /* CPU has Virtualization extension */ 108 + #define CPU_FEATURE_LBT_X86 12 /* CPU has X86 Binary Translation */ 109 + #define CPU_FEATURE_LBT_ARM 13 /* CPU has ARM Binary Translation */ 110 + #define CPU_FEATURE_LBT_MIPS 14 /* CPU has MIPS Binary Translation */ 111 + #define CPU_FEATURE_TLB 15 /* CPU has TLB */ 112 + #define CPU_FEATURE_CSR 16 /* CPU has CSR */ 113 + #define CPU_FEATURE_IOCSR 17 /* CPU has IOCSR */ 114 + #define CPU_FEATURE_WATCH 18 /* CPU has watchpoint registers */ 115 + #define CPU_FEATURE_VINT 19 /* CPU has vectored interrupts */ 116 + #define CPU_FEATURE_CSRIPI 20 /* CPU has CSR-IPI */ 117 + #define CPU_FEATURE_EXTIOI 21 /* CPU has EXT-IOI */ 118 + #define CPU_FEATURE_PREFETCH 22 /* CPU has prefetch instructions */ 119 + #define CPU_FEATURE_PMP 23 /* CPU has perfermance counter */ 120 + #define CPU_FEATURE_SCALEFREQ 24 /* CPU supports cpufreq scaling */ 121 + #define CPU_FEATURE_FLATMODE 25 /* CPU has flat mode */ 122 + #define CPU_FEATURE_EIODECODE 26 /* CPU has EXTIOI interrupt pin decode mode */ 123 + #define CPU_FEATURE_GUESTID 27 /* CPU has GuestID feature */ 124 + #define CPU_FEATURE_HYPERVISOR 28 /* CPU has hypervisor (running in VM) */ 125 + #define CPU_FEATURE_PTW 29 /* CPU has hardware page table walker */ 126 + #define CPU_FEATURE_LSPW 30 /* CPU has LSPW (lddir/ldpte instructions) */ 127 + #define CPU_FEATURE_MSGINT 31 /* CPU has MSG interrupt */ 128 + #define CPU_FEATURE_AVECINT 32 /* CPU has AVEC interrupt */ 129 + #define CPU_FEATURE_REDIRECTINT 33 /* CPU has interrupt remapping */ 129 130 130 131 #define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG) 131 132 #define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM) 133 + #define LOONGARCH_CPU_LAM_BH BIT_ULL(CPU_FEATURE_LAM_BH) 132 134 #define LOONGARCH_CPU_SCQ BIT_ULL(CPU_FEATURE_SCQ) 133 135 #define LOONGARCH_CPU_UAL BIT_ULL(CPU_FEATURE_UAL) 134 136 #define LOONGARCH_CPU_FPU BIT_ULL(CPU_FEATURE_FPU)
+14
arch/loongarch/include/asm/fixmap.h
··· 8 8 #ifndef _ASM_FIXMAP_H 9 9 #define _ASM_FIXMAP_H 10 10 11 + #ifdef CONFIG_HIGHMEM 12 + #include <linux/threads.h> 13 + #include <asm/kmap_size.h> 14 + #endif 15 + 11 16 #define NR_FIX_BTMAPS 64 12 17 13 18 enum fixed_addresses { 14 19 FIX_HOLE, 20 + #ifdef CONFIG_HIGHMEM 21 + FIX_KMAP_BEGIN, 22 + FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * NR_CPUS) - 1, 23 + #endif 15 24 FIX_EARLYCON_MEM_BASE, 16 25 __end_of_fixed_addresses 17 26 }; ··· 33 24 phys_addr_t phys, pgprot_t flags); 34 25 35 26 #include <asm-generic/fixmap.h> 27 + 28 + /* 29 + * Called from pagetable_init() 30 + */ 31 + extern void fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base); 36 32 37 33 #endif
+43
arch/loongarch/include/asm/highmem.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * highmem.h: virtual kernel memory mappings for high memory 4 + * 5 + * Used in CONFIG_HIGHMEM systems for memory pages which 6 + * are not addressable by direct kernel virtual addresses. 7 + * 8 + * Copyright (C) 2025 Loongson Technology Corporation Limited 9 + */ 10 + #ifndef _ASM_HIGHMEM_H 11 + #define _ASM_HIGHMEM_H 12 + 13 + #ifdef __KERNEL__ 14 + 15 + #include <asm/kmap_size.h> 16 + 17 + #ifndef __ASSEMBLER__ 18 + 19 + extern pte_t *pkmap_page_table; 20 + 21 + #define ARCH_HAS_KMAP_FLUSH_TLB 22 + void kmap_flush_tlb(unsigned long addr); 23 + 24 + #endif /* !__ASSEMBLER__ */ 25 + 26 + /* 27 + * Right now we initialize only a single pte table. It can be extended 28 + * easily, subsequent pte tables have to be allocated in one physical 29 + * chunk of RAM. 30 + */ 31 + #define LAST_PKMAP 1024 32 + #define LAST_PKMAP_MASK (LAST_PKMAP - 1) 33 + #define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT) 34 + #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) 35 + 36 + #define flush_cache_kmaps() do {} while (0) 37 + 38 + #define arch_kmap_local_post_map(vaddr, pteval) local_flush_tlb_one(vaddr) 39 + #define arch_kmap_local_post_unmap(vaddr) local_flush_tlb_one(vaddr) 40 + 41 + #endif /* __KERNEL__ */ 42 + 43 + #endif /* _ASM_HIGHMEM_H */
+10
arch/loongarch/include/asm/inst.h
··· 36 36 37 37 enum reg0i15_op { 38 38 break_op = 0x54, 39 + dbar_op = 0x70e4, 39 40 }; 40 41 41 42 enum reg0i26_op { ··· 195 194 fstxs_op = 0x7070, 196 195 fstxd_op = 0x7078, 197 196 scq_op = 0x70ae, 197 + amswapb_op = 0x70b8, 198 + amswaph_op = 0x70b9, 199 + amaddb_op = 0x70ba, 200 + amaddh_op = 0x70bb, 198 201 amswapw_op = 0x70c0, 199 202 amswapd_op = 0x70c1, 200 203 amaddw_op = 0x70c2, ··· 548 543 } 549 544 550 545 DEF_EMIT_REG0I15_FORMAT(break, break_op) 546 + DEF_EMIT_REG0I15_FORMAT(dbar, dbar_op) 551 547 552 548 /* like emit_break(imm) but returns a constant expression */ 553 549 #define __emit_break(imm) ((u32)((imm) | (break_op << 15))) ··· 769 763 DEF_EMIT_REG3_FORMAT(stxh, stxh_op) 770 764 DEF_EMIT_REG3_FORMAT(stxw, stxw_op) 771 765 DEF_EMIT_REG3_FORMAT(stxd, stxd_op) 766 + DEF_EMIT_REG3_FORMAT(amaddb, amaddb_op) 767 + DEF_EMIT_REG3_FORMAT(amaddh, amaddh_op) 772 768 DEF_EMIT_REG3_FORMAT(amaddw, amaddw_op) 773 769 DEF_EMIT_REG3_FORMAT(amaddd, amaddd_op) 774 770 DEF_EMIT_REG3_FORMAT(amandw, amandw_op) ··· 779 771 DEF_EMIT_REG3_FORMAT(amord, amord_op) 780 772 DEF_EMIT_REG3_FORMAT(amxorw, amxorw_op) 781 773 DEF_EMIT_REG3_FORMAT(amxord, amxord_op) 774 + DEF_EMIT_REG3_FORMAT(amswapb, amswapb_op) 775 + DEF_EMIT_REG3_FORMAT(amswaph, amswaph_op) 782 776 DEF_EMIT_REG3_FORMAT(amswapw, amswapw_op) 783 777 DEF_EMIT_REG3_FORMAT(amswapd, amswapd_op) 784 778
+1 -1
arch/loongarch/include/asm/irq_work.h
··· 4 4 5 5 static inline bool arch_irq_work_has_interrupt(void) 6 6 { 7 - return IS_ENABLED(CONFIG_SMP); 7 + return IS_ENABLED(CONFIG_SMP) && cpu_opt(LOONGARCH_CPU_CSRIPI); 8 8 } 9 9 10 10 #endif /* _ASM_LOONGARCH_IRQ_WORK_H */
+2
arch/loongarch/include/asm/jump_label.h
··· 13 13 #include <linux/stringify.h> 14 14 #include <asm/asm.h> 15 15 16 + #define HAVE_JUMP_LABEL_BATCH 17 + 16 18 #define JUMP_LABEL_NOP_SIZE 4 17 19 18 20 #ifdef CONFIG_32BIT
-4
arch/loongarch/include/asm/page.h
··· 36 36 37 37 struct page; 38 38 struct vm_area_struct; 39 - void copy_user_highpage(struct page *to, struct page *from, 40 - unsigned long vaddr, struct vm_area_struct *vma); 41 - 42 - #define __HAVE_ARCH_COPY_USER_HIGHPAGE 43 39 44 40 typedef struct { unsigned long pte; } pte_t; 45 41 #define pte_val(x) ((x).pte)
+12
arch/loongarch/include/asm/pgtable.h
··· 23 23 #include <asm-generic/pgtable-nop4d.h> 24 24 #endif 25 25 26 + #ifdef CONFIG_HIGHMEM 27 + #include <asm/highmem.h> 28 + #endif 29 + 26 30 #if CONFIG_PGTABLE_LEVELS == 2 27 31 #define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PTRLOG)) 28 32 #elif CONFIG_PGTABLE_LEVELS == 3 ··· 81 77 #ifdef CONFIG_32BIT 82 78 83 79 #define VMALLOC_START (vm_map_base + PCI_IOSIZE + (2 * PAGE_SIZE)) 80 + 81 + #ifdef CONFIG_HIGHMEM 82 + #define VMALLOC_END (PKMAP_BASE - (2 * PAGE_SIZE)) 83 + #else 84 84 #define VMALLOC_END (FIXADDR_START - (2 * PAGE_SIZE)) 85 + #endif 86 + 87 + #define PKMAP_BASE (PKMAP_END - (PAGE_SIZE * LAST_PKMAP)) 88 + #define PKMAP_END ((FIXADDR_START) & ~((LAST_PKMAP << PAGE_SHIFT)-1)) 85 89 86 90 #endif 87 91
+1 -1
arch/loongarch/include/asm/processor.h
··· 80 80 BUILD_FPR_ACCESS(64) 81 81 82 82 struct loongarch_fpu { 83 + union fpureg fpr[NUM_FPU_REGS]; 83 84 uint64_t fcc; /* 8x8 */ 84 85 uint32_t fcsr; 85 86 uint32_t ftop; 86 - union fpureg fpr[NUM_FPU_REGS]; 87 87 }; 88 88 89 89 struct loongarch_lbt {
+1 -8
arch/loongarch/include/asm/stackprotector.h
··· 12 12 #ifndef _ASM_STACKPROTECTOR_H 13 13 #define _ASM_STACKPROTECTOR_H 14 14 15 - #include <linux/random.h> 16 - #include <linux/version.h> 17 - 18 15 extern unsigned long __stack_chk_guard; 19 16 20 17 /* ··· 22 25 */ 23 26 static __always_inline void boot_init_stack_canary(void) 24 27 { 25 - unsigned long canary; 26 - 27 - /* Try to get a semi random initial value. */ 28 - get_random_bytes(&canary, sizeof(canary)); 29 - canary ^= LINUX_VERSION_CODE; 28 + unsigned long canary = get_random_canary(); 30 29 31 30 current->stack_canary = canary; 32 31 __stack_chk_guard = current->stack_canary;
+4
arch/loongarch/include/asm/syscall.h
··· 78 78 79 79 static inline int syscall_get_arch(struct task_struct *task) 80 80 { 81 + #ifdef CONFIG_32BIT 82 + return AUDIT_ARCH_LOONGARCH32; 83 + #else 81 84 return AUDIT_ARCH_LOONGARCH64; 85 + #endif 82 86 } 83 87 84 88 static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
+1
arch/loongarch/include/uapi/asm/hwcap.h
··· 19 19 #define HWCAP_LOONGARCH_PTW (1 << 13) 20 20 #define HWCAP_LOONGARCH_LSPW (1 << 14) 21 21 #define HWCAP_LOONGARCH_SCQ (1 << 15) 22 + #define HWCAP_LOONGARCH_LAM_BH (1 << 16) 22 23 23 24 #endif /* _UAPI_ASM_HWCAP_H */
+11
arch/loongarch/kernel/cpu-probe.c
··· 7 7 #include <linux/init.h> 8 8 #include <linux/kernel.h> 9 9 #include <linux/ptrace.h> 10 + #include <linux/cpu.h> 10 11 #include <linux/smp.h> 11 12 #include <linux/stddef.h> 12 13 #include <linux/export.h> ··· 177 176 if (config & CPUCFG2_LAM) { 178 177 c->options |= LOONGARCH_CPU_LAM; 179 178 elf_hwcap |= HWCAP_LOONGARCH_LAM; 179 + } 180 + if (config & CPUCFG2_LAM_BH) { 181 + c->options |= LOONGARCH_CPU_LAM_BH; 182 + elf_hwcap |= HWCAP_LOONGARCH_LAM_BH; 180 183 } 181 184 if (config & CPUCFG2_SCQ) { 182 185 c->options |= LOONGARCH_CPU_SCQ; ··· 406 401 #endif 407 402 408 403 cpu_report(); 404 + } 405 + 406 + ssize_t cpu_show_spectre_v1(struct device *dev, 407 + struct device_attribute *attr, char *buf) 408 + { 409 + return sysfs_emit(buf, "Mitigation: __user pointer sanitization\n"); 409 410 }
+6 -6
arch/loongarch/kernel/fpu.S
··· 97 97 .endm 98 98 99 99 #ifdef CONFIG_32BIT 100 - .macro sc_save_fcc thread tmp0 tmp1 100 + .macro sc_save_fcc base tmp0 tmp1 101 101 movcf2gr \tmp0, $fcc0 102 102 move \tmp1, \tmp0 103 103 movcf2gr \tmp0, $fcc1 ··· 106 106 bstrins.w \tmp1, \tmp0, 23, 16 107 107 movcf2gr \tmp0, $fcc3 108 108 bstrins.w \tmp1, \tmp0, 31, 24 109 - EX st.w \tmp1, \thread, THREAD_FCC 109 + EX st.w \tmp1, \base, 0 110 110 movcf2gr \tmp0, $fcc4 111 111 move \tmp1, \tmp0 112 112 movcf2gr \tmp0, $fcc5 ··· 115 115 bstrins.w \tmp1, \tmp0, 23, 16 116 116 movcf2gr \tmp0, $fcc7 117 117 bstrins.w \tmp1, \tmp0, 31, 24 118 - EX st.w \tmp1, \thread, (THREAD_FCC + 4) 118 + EX st.w \tmp1, \base, 4 119 119 .endm 120 120 121 - .macro sc_restore_fcc thread tmp0 tmp1 122 - EX ld.w \tmp0, \thread, THREAD_FCC 121 + .macro sc_restore_fcc base tmp0 tmp1 122 + EX ld.w \tmp0, \base, 0 123 123 bstrpick.w \tmp1, \tmp0, 7, 0 124 124 movgr2cf $fcc0, \tmp1 125 125 bstrpick.w \tmp1, \tmp0, 15, 8 ··· 128 128 movgr2cf $fcc2, \tmp1 129 129 bstrpick.w \tmp1, \tmp0, 31, 24 130 130 movgr2cf $fcc3, \tmp1 131 - EX ld.w \tmp0, \thread, (THREAD_FCC + 4) 131 + EX ld.w \tmp0, \base, 4 132 132 bstrpick.w \tmp1, \tmp0, 7, 0 133 133 movgr2cf $fcc4, \tmp1 134 134 bstrpick.w \tmp1, \tmp0, 15, 8
+3 -3
arch/loongarch/kernel/inst.c
··· 209 209 int ret; 210 210 unsigned long flags = 0; 211 211 212 + if ((unsigned long)addr & 3) 213 + return -EINVAL; 214 + 212 215 raw_spin_lock_irqsave(&patch_lock, flags); 213 216 ret = copy_to_kernel_nofault(addr, &insn, LOONGARCH_INSN_SIZE); 214 217 raw_spin_unlock_irqrestore(&patch_lock, flags); ··· 223 220 { 224 221 int ret; 225 222 u32 *tp = addr; 226 - 227 - if ((unsigned long)tp & 3) 228 - return -EINVAL; 229 223 230 224 ret = larch_insn_write(tp, insn); 231 225 if (!ret)
+10 -2
arch/loongarch/kernel/jump_label.c
··· 6 6 */ 7 7 #include <linux/kernel.h> 8 8 #include <linux/jump_label.h> 9 + #include <asm/cacheflush.h> 9 10 #include <asm/inst.h> 10 11 11 - void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type) 12 + bool arch_jump_label_transform_queue(struct jump_entry *entry, enum jump_label_type type) 12 13 { 13 14 u32 insn; 14 15 void *addr = (void *)jump_entry_code(entry); ··· 19 18 else 20 19 insn = larch_insn_gen_nop(); 21 20 22 - larch_insn_patch_text(addr, insn); 21 + larch_insn_write(addr, insn); 22 + 23 + return true; 24 + } 25 + 26 + void arch_jump_label_transform_apply(void) 27 + { 28 + flush_icache_all(); 23 29 }
+2
arch/loongarch/kernel/proc.c
··· 64 64 seq_puts(m, " cpucfg"); 65 65 if (cpu_has_lam) 66 66 seq_puts(m, " lam"); 67 + if (cpu_has_lam_bh) 68 + seq_puts(m, " lam_bh"); 67 69 if (cpu_has_scq) 68 70 seq_puts(m, " scq"); 69 71 if (cpu_has_ual)
+2
arch/loongarch/kernel/process.c
··· 136 136 return 0; 137 137 } 138 138 139 + dst->thread.fpu.fcsr = src->thread.fpu.fcsr; 140 + 139 141 if (!used_math()) 140 142 memcpy(dst, src, offsetof(struct task_struct, thread.fpu.fpr)); 141 143 else
+18 -8
arch/loongarch/kernel/relocate.c
··· 128 128 129 129 static int __init nokaslr(char *p) 130 130 { 131 - pr_info("KASLR is disabled.\n"); 132 - 133 - return 0; /* Print a notice and silence the boot warning */ 131 + return 0; /* Just silence the boot warning */ 134 132 } 135 133 early_param("nokaslr", nokaslr); 134 + 135 + #define KASLR_DISABLED_MESSAGE "KASLR is disabled by %s in %s cmdline.\n" 136 136 137 137 static inline __init bool kaslr_disabled(void) 138 138 { ··· 140 140 const char *builtin_cmdline = CONFIG_CMDLINE; 141 141 142 142 str = strstr(builtin_cmdline, "nokaslr"); 143 - if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) 143 + if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) { 144 + pr_info(KASLR_DISABLED_MESSAGE, "\'nokaslr\'", "built-in"); 144 145 return true; 146 + } 145 147 146 148 str = strstr(boot_command_line, "nokaslr"); 147 - if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) 149 + if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) { 150 + pr_info(KASLR_DISABLED_MESSAGE, "\'nokaslr\'", "bootloader"); 148 151 return true; 152 + } 149 153 150 154 #ifdef CONFIG_HIBERNATION 151 155 str = strstr(builtin_cmdline, "nohibernate"); ··· 169 165 return false; 170 166 171 167 str = strstr(builtin_cmdline, "resume="); 172 - if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) 168 + if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) { 169 + pr_info(KASLR_DISABLED_MESSAGE, "\'resume=\'", "built-in"); 173 170 return true; 171 + } 174 172 175 173 str = strstr(boot_command_line, "resume="); 176 - if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) 174 + if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) { 175 + pr_info(KASLR_DISABLED_MESSAGE, "\'resume=\'", "bootloader"); 177 176 return true; 177 + } 178 178 #endif 179 179 180 180 str = strstr(boot_command_line, "kexec_file"); 181 - if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) 181 + if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) { 182 + pr_info(KASLR_DISABLED_MESSAGE, "\'kexec_file\'", "bootloader"); 182 183 return true; 184 + } 183 185 184 186 return false; 185 187 }
+2 -1
arch/loongarch/kernel/syscall.c
··· 9 9 #include <linux/entry-common.h> 10 10 #include <linux/errno.h> 11 11 #include <linux/linkage.h> 12 + #include <linux/nospec.h> 12 13 #include <linux/objtool.h> 13 14 #include <linux/randomize_kstack.h> 14 15 #include <linux/syscalls.h> ··· 75 74 add_random_kstack_offset(); 76 75 77 76 if (nr < NR_syscalls) { 78 - syscall_fn = sys_call_table[nr]; 77 + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; 79 78 regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], 80 79 regs->regs[7], regs->regs[8], regs->regs[9]); 81 80 }
+6 -1
arch/loongarch/kernel/vmlinux.lds.S
··· 6 6 7 7 #define PAGE_SIZE _PAGE_SIZE 8 8 #define RO_EXCEPTION_TABLE_ALIGN 4 9 - #define PHYSADDR_MASK 0xffffffffffff /* 48-bit */ 9 + 10 + #ifdef CONFIG_32BIT 11 + #define PHYSADDR_MASK 0x1fffffff /* 29-bit */ 12 + #else 13 + #define PHYSADDR_MASK 0xffffffffffff /* 48-bit */ 14 + #endif 10 15 11 16 /* 12 17 * Put .bss..swapper_pg_dir as the first thing in .bss. This will
+1 -1
arch/loongarch/kvm/Kconfig
··· 19 19 20 20 config KVM 21 21 tristate "Kernel-based Virtual Machine (KVM) support" 22 - depends on AS_HAS_LVZ_EXTENSION 22 + depends on AS_HAS_LVZ_EXTENSION && 64BIT 23 23 select HAVE_KVM_DIRTY_RING_ACQ_REL 24 24 select HAVE_KVM_IRQ_ROUTING 25 25 select HAVE_KVM_IRQCHIP
+4 -2
arch/loongarch/lib/Makefile
··· 3 3 # Makefile for LoongArch-specific library files. 4 4 # 5 5 6 - lib-y += delay.o memset.o memcpy.o memmove.o \ 7 - clear_user.o copy_user.o csum.o dump_tlb.o unaligned.o 6 + lib-y += delay.o clear_user.o copy_user.o dump_tlb.o unaligned.o 7 + 8 + lib-$(CONFIG_32BIT) += bswapsi.o bswapdi.o 9 + lib-$(CONFIG_64BIT) += memset.o memcpy.o memmove.o csum.o 8 10 9 11 obj-$(CONFIG_ARCH_SUPPORTS_INT128) += tishift.o 10 12
+1
arch/loongarch/mm/Makefile
··· 7 7 fault.o ioremap.o maccess.o mmap.o pgtable.o \ 8 8 page.o pageattr.o 9 9 10 + obj-$(CONFIG_HIGHMEM) += highmem.o 10 11 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 11 12 obj-$(CONFIG_KASAN) += kasan_init.o 12 13
-10
arch/loongarch/mm/cache.c
··· 31 31 set_merr_handler(0x0, &except_vec_cex, 0x80); 32 32 } 33 33 34 - /* 35 - * LoongArch maintains ICache/DCache coherency by hardware, 36 - * we just need "ibar" to avoid instruction hazard here. 37 - */ 38 - void local_flush_icache_range(unsigned long start, unsigned long end) 39 - { 40 - asm volatile ("\tibar 0\n"::); 41 - } 42 - EXPORT_SYMBOL(local_flush_icache_range); 43 - 44 34 static void flush_cache_leaf(unsigned int leaf) 45 35 { 46 36 int i, j, nr_nodes;
+12
arch/loongarch/mm/highmem.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/init.h> 3 + #include <linux/export.h> 4 + #include <linux/highmem.h> 5 + #include <asm/fixmap.h> 6 + #include <asm/tlbflush.h> 7 + 8 + void kmap_flush_tlb(unsigned long addr) 9 + { 10 + flush_tlb_one(addr); 11 + } 12 + EXPORT_SYMBOL(kmap_flush_tlb);
+47 -14
arch/loongarch/mm/init.c
··· 36 36 #include <asm/pgalloc.h> 37 37 #include <asm/tlb.h> 38 38 39 - void copy_user_highpage(struct page *to, struct page *from, 40 - unsigned long vaddr, struct vm_area_struct *vma) 41 - { 42 - void *vfrom, *vto; 43 - 44 - vfrom = kmap_local_page(from); 45 - vto = kmap_local_page(to); 46 - copy_page(vto, vfrom); 47 - kunmap_local(vfrom); 48 - kunmap_local(vto); 49 - /* Make sure this page is cleared on other CPU's too before using it */ 50 - smp_wmb(); 51 - } 52 - 53 39 int __ref page_is_ram(unsigned long pfn) 54 40 { 55 41 unsigned long addr = PFN_PHYS(pfn); ··· 49 63 max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; 50 64 #endif 51 65 max_zone_pfns[ZONE_NORMAL] = max_low_pfn; 66 + #ifdef CONFIG_HIGHMEM 67 + max_zone_pfns[ZONE_HIGHMEM] = max_pfn; 68 + #endif 52 69 } 53 70 54 71 void __ref free_initmem(void) 55 72 { 56 73 free_initmem_default(POISON_FREE_INITMEM); 57 74 } 75 + 76 + #ifdef CONFIG_HIGHMEM 77 + 78 + void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) 79 + { 80 + pgd_t *pgd; 81 + pud_t *pud; 82 + pmd_t *pmd; 83 + pte_t *pte; 84 + int i, j, k; 85 + int ptrs_per_pgd; 86 + unsigned long vaddr; 87 + 88 + vaddr = start; 89 + i = pgd_index(vaddr); 90 + j = pud_index(vaddr); 91 + k = pmd_index(vaddr); 92 + pgd = pgd_base + i; 93 + ptrs_per_pgd = min((1 << (BITS_PER_LONG - PGDIR_SHIFT)), PTRS_PER_PGD); 94 + 95 + for ( ; (i < ptrs_per_pgd) && (vaddr < end); pgd++, i++) { 96 + pud = (pud_t *)pgd; 97 + for ( ; (j < PTRS_PER_PUD) && (vaddr < end); pud++, j++) { 98 + pmd = (pmd_t *)pud; 99 + for (; (k < PTRS_PER_PMD) && (vaddr < end); pmd++, k++) { 100 + if (pmd_none(*pmd)) { 101 + pte = (pte_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE); 102 + if (!pte) 103 + panic("%s: Failed to allocate %lu bytes align=%lx\n", 104 + __func__, PAGE_SIZE, PAGE_SIZE); 105 + 106 + kernel_pte_init(pte); 107 + set_pmd(pmd, __pmd((unsigned long)pte)); 108 + BUG_ON(pte != pte_offset_kernel(pmd, 0)); 109 + } 110 + vaddr += PMD_SIZE; 111 + } 112 + k = 0; 113 + } 114 + j = 0; 115 + } 116 + } 117 + 118 + #endif 58 119 59 120 #ifdef CONFIG_MEMORY_HOTPLUG 60 121 int arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *params)
+27
arch/loongarch/mm/pgtable.c
··· 5 5 #include <linux/init.h> 6 6 #include <linux/export.h> 7 7 #include <linux/mm.h> 8 + #include <asm/fixmap.h> 8 9 #include <asm/pgalloc.h> 9 10 #include <asm/pgtable.h> 10 11 #include <asm/tlbflush.h> ··· 145 144 146 145 void __init pagetable_init(void) 147 146 { 147 + #ifdef CONFIG_HIGHMEM 148 + unsigned long vaddr; 149 + pgd_t *pgd; 150 + p4d_t *p4d; 151 + pud_t *pud; 152 + pmd_t *pmd; 153 + pte_t *pte; 154 + #endif 155 + 148 156 /* Initialize the entire pgd. */ 149 157 pgd_init(swapper_pg_dir); 150 158 pgd_init(invalid_pg_dir); ··· 162 152 #endif 163 153 #ifndef __PAGETABLE_PMD_FOLDED 164 154 pmd_init(invalid_pmd_table); 155 + #endif 156 + 157 + #ifdef CONFIG_HIGHMEM 158 + /* Permanent kmaps */ 159 + vaddr = PKMAP_BASE; 160 + fixrange_init(vaddr & PMD_MASK, vaddr + PAGE_SIZE * LAST_PKMAP, swapper_pg_dir); 161 + 162 + pgd = swapper_pg_dir + pgd_index(vaddr); 163 + p4d = p4d_offset(pgd, vaddr); 164 + pud = pud_offset(p4d, vaddr); 165 + pmd = pmd_offset(pud, vaddr); 166 + pte = pte_offset_kernel(pmd, vaddr); 167 + pkmap_page_table = pte; 168 + 169 + /* Fixed mappings */ 170 + vaddr = __fix_to_virt(__end_of_fixed_addresses - 1); 171 + fixrange_init(vaddr & PMD_MASK, vaddr + FIXADDR_SIZE, swapper_pg_dir); 165 172 #endif 166 173 }
+317 -66
arch/loongarch/net/bpf_jit.c
··· 344 344 #undef jmp_offset 345 345 } 346 346 347 - static void emit_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx) 347 + static void emit_store_stack_imm64(struct jit_ctx *ctx, int reg, int stack_off, u64 imm64) 348 + { 349 + move_imm(ctx, reg, imm64, false); 350 + emit_insn(ctx, std, reg, LOONGARCH_GPR_FP, stack_off); 351 + } 352 + 353 + static int emit_atomic_rmw(const struct bpf_insn *insn, struct jit_ctx *ctx) 348 354 { 349 355 const u8 t1 = LOONGARCH_GPR_T1; 350 356 const u8 t2 = LOONGARCH_GPR_T2; ··· 369 363 switch (imm) { 370 364 /* lock *(size *)(dst + off) <op>= src */ 371 365 case BPF_ADD: 372 - if (isdw) 373 - emit_insn(ctx, amaddd, t2, t1, src); 374 - else 366 + switch (BPF_SIZE(insn->code)) { 367 + case BPF_B: 368 + if (!cpu_has_lam_bh) { 369 + pr_err_once("bpf-jit: amadd.b instruction is not supported\n"); 370 + return -EINVAL; 371 + } 372 + emit_insn(ctx, amaddb, t2, t1, src); 373 + break; 374 + case BPF_H: 375 + if (!cpu_has_lam_bh) { 376 + pr_err_once("bpf-jit: amadd.h instruction is not supported\n"); 377 + return -EINVAL; 378 + } 379 + emit_insn(ctx, amaddh, t2, t1, src); 380 + break; 381 + case BPF_W: 375 382 emit_insn(ctx, amaddw, t2, t1, src); 383 + break; 384 + case BPF_DW: 385 + emit_insn(ctx, amaddd, t2, t1, src); 386 + break; 387 + } 376 388 break; 377 389 case BPF_AND: 378 390 if (isdw) ··· 412 388 break; 413 389 /* src = atomic_fetch_<op>(dst + off, src) */ 414 390 case BPF_ADD | BPF_FETCH: 415 - if (isdw) { 416 - emit_insn(ctx, amaddd, src, t1, t3); 417 - } else { 391 + switch (BPF_SIZE(insn->code)) { 392 + case BPF_B: 393 + if (!cpu_has_lam_bh) { 394 + pr_err_once("bpf-jit: amadd.b instruction is not supported\n"); 395 + return -EINVAL; 396 + } 397 + emit_insn(ctx, amaddb, src, t1, t3); 398 + emit_zext_32(ctx, src, true); 399 + break; 400 + case BPF_H: 401 + if (!cpu_has_lam_bh) { 402 + pr_err_once("bpf-jit: amadd.h instruction is not supported\n"); 403 + return -EINVAL; 404 + } 405 + emit_insn(ctx, amaddh, src, t1, t3); 406 + emit_zext_32(ctx, src, true); 407 + break; 408 + case BPF_W: 418 409 emit_insn(ctx, amaddw, src, t1, t3); 419 410 emit_zext_32(ctx, src, true); 411 + break; 412 + case BPF_DW: 413 + emit_insn(ctx, amaddd, src, t1, t3); 414 + break; 420 415 } 421 416 break; 422 417 case BPF_AND | BPF_FETCH: ··· 464 421 break; 465 422 /* src = atomic_xchg(dst + off, src); */ 466 423 case BPF_XCHG: 467 - if (isdw) { 468 - emit_insn(ctx, amswapd, src, t1, t3); 469 - } else { 424 + switch (BPF_SIZE(insn->code)) { 425 + case BPF_B: 426 + if (!cpu_has_lam_bh) { 427 + pr_err_once("bpf-jit: amswap.b instruction is not supported\n"); 428 + return -EINVAL; 429 + } 430 + emit_insn(ctx, amswapb, src, t1, t3); 431 + emit_zext_32(ctx, src, true); 432 + break; 433 + case BPF_H: 434 + if (!cpu_has_lam_bh) { 435 + pr_err_once("bpf-jit: amswap.h instruction is not supported\n"); 436 + return -EINVAL; 437 + } 438 + emit_insn(ctx, amswaph, src, t1, t3); 439 + emit_zext_32(ctx, src, true); 440 + break; 441 + case BPF_W: 470 442 emit_insn(ctx, amswapw, src, t1, t3); 471 443 emit_zext_32(ctx, src, true); 444 + break; 445 + case BPF_DW: 446 + emit_insn(ctx, amswapd, src, t1, t3); 447 + break; 472 448 } 473 449 break; 474 450 /* r0 = atomic_cmpxchg(dst + off, r0, src); */ ··· 510 448 emit_zext_32(ctx, r0, true); 511 449 } 512 450 break; 451 + default: 452 + pr_err_once("bpf-jit: invalid atomic read-modify-write opcode %02x\n", imm); 453 + return -EINVAL; 513 454 } 455 + 456 + return 0; 457 + } 458 + 459 + static int emit_atomic_ld_st(const struct bpf_insn *insn, struct jit_ctx *ctx) 460 + { 461 + const u8 t1 = LOONGARCH_GPR_T1; 462 + const u8 src = regmap[insn->src_reg]; 463 + const u8 dst = regmap[insn->dst_reg]; 464 + const s16 off = insn->off; 465 + const s32 imm = insn->imm; 466 + 467 + switch (imm) { 468 + /* dst_reg = load_acquire(src_reg + off16) */ 469 + case BPF_LOAD_ACQ: 470 + switch (BPF_SIZE(insn->code)) { 471 + case BPF_B: 472 + if (is_signed_imm12(off)) { 473 + emit_insn(ctx, ldbu, dst, src, off); 474 + } else { 475 + move_imm(ctx, t1, off, false); 476 + emit_insn(ctx, ldxbu, dst, src, t1); 477 + } 478 + break; 479 + case BPF_H: 480 + if (is_signed_imm12(off)) { 481 + emit_insn(ctx, ldhu, dst, src, off); 482 + } else { 483 + move_imm(ctx, t1, off, false); 484 + emit_insn(ctx, ldxhu, dst, src, t1); 485 + } 486 + break; 487 + case BPF_W: 488 + if (is_signed_imm12(off)) { 489 + emit_insn(ctx, ldwu, dst, src, off); 490 + } else { 491 + move_imm(ctx, t1, off, false); 492 + emit_insn(ctx, ldxwu, dst, src, t1); 493 + } 494 + break; 495 + case BPF_DW: 496 + if (is_signed_imm12(off)) { 497 + emit_insn(ctx, ldd, dst, src, off); 498 + } else { 499 + move_imm(ctx, t1, off, false); 500 + emit_insn(ctx, ldxd, dst, src, t1); 501 + } 502 + break; 503 + } 504 + emit_insn(ctx, dbar, 0b10100); 505 + break; 506 + /* store_release(dst_reg + off16, src_reg) */ 507 + case BPF_STORE_REL: 508 + emit_insn(ctx, dbar, 0b10010); 509 + switch (BPF_SIZE(insn->code)) { 510 + case BPF_B: 511 + if (is_signed_imm12(off)) { 512 + emit_insn(ctx, stb, src, dst, off); 513 + } else { 514 + move_imm(ctx, t1, off, false); 515 + emit_insn(ctx, stxb, src, dst, t1); 516 + } 517 + break; 518 + case BPF_H: 519 + if (is_signed_imm12(off)) { 520 + emit_insn(ctx, sth, src, dst, off); 521 + } else { 522 + move_imm(ctx, t1, off, false); 523 + emit_insn(ctx, stxh, src, dst, t1); 524 + } 525 + break; 526 + case BPF_W: 527 + if (is_signed_imm12(off)) { 528 + emit_insn(ctx, stw, src, dst, off); 529 + } else { 530 + move_imm(ctx, t1, off, false); 531 + emit_insn(ctx, stxw, src, dst, t1); 532 + } 533 + break; 534 + case BPF_DW: 535 + if (is_signed_imm12(off)) { 536 + emit_insn(ctx, std, src, dst, off); 537 + } else { 538 + move_imm(ctx, t1, off, false); 539 + emit_insn(ctx, stxd, src, dst, t1); 540 + } 541 + break; 542 + } 543 + break; 544 + default: 545 + pr_err_once("bpf-jit: invalid atomic load/store opcode %02x\n", imm); 546 + return -EINVAL; 547 + } 548 + 549 + return 0; 514 550 } 515 551 516 552 static bool is_signed_bpf_cond(u8 cond) ··· 1414 1254 return ret; 1415 1255 break; 1416 1256 1257 + /* Atomics */ 1258 + case BPF_STX | BPF_ATOMIC | BPF_B: 1259 + case BPF_STX | BPF_ATOMIC | BPF_H: 1417 1260 case BPF_STX | BPF_ATOMIC | BPF_W: 1418 1261 case BPF_STX | BPF_ATOMIC | BPF_DW: 1419 - emit_atomic(insn, ctx); 1262 + if (!bpf_atomic_is_load_store(insn)) 1263 + ret = emit_atomic_rmw(insn, ctx); 1264 + else 1265 + ret = emit_atomic_ld_st(insn, ctx); 1266 + if (ret) 1267 + return ret; 1420 1268 break; 1421 1269 1422 1270 /* Speculation barrier */ ··· 1634 1466 return ret; 1635 1467 } 1636 1468 1637 - static void store_args(struct jit_ctx *ctx, int nargs, int args_off) 1469 + static void store_args(struct jit_ctx *ctx, int nr_arg_slots, int args_off) 1638 1470 { 1639 1471 int i; 1640 1472 1641 - for (i = 0; i < nargs; i++) { 1642 - emit_insn(ctx, std, LOONGARCH_GPR_A0 + i, LOONGARCH_GPR_FP, -args_off); 1473 + for (i = 0; i < nr_arg_slots; i++) { 1474 + if (i < LOONGARCH_MAX_REG_ARGS) 1475 + emit_insn(ctx, std, LOONGARCH_GPR_A0 + i, LOONGARCH_GPR_FP, -args_off); 1476 + else { 1477 + /* Skip slots for T0 and FP of traced function */ 1478 + emit_insn(ctx, ldd, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, 1479 + 16 + (i - LOONGARCH_MAX_REG_ARGS) * 8); 1480 + emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -args_off); 1481 + } 1643 1482 args_off -= 8; 1644 1483 } 1645 1484 } 1646 1485 1647 - static void restore_args(struct jit_ctx *ctx, int nargs, int args_off) 1486 + static void restore_args(struct jit_ctx *ctx, int nr_reg_args, int args_off) 1648 1487 { 1649 1488 int i; 1650 1489 1651 - for (i = 0; i < nargs; i++) { 1490 + for (i = 0; i < nr_reg_args; i++) { 1652 1491 emit_insn(ctx, ldd, LOONGARCH_GPR_A0 + i, LOONGARCH_GPR_FP, -args_off); 1653 1492 args_off -= 8; 1493 + } 1494 + } 1495 + 1496 + static void restore_stk_args(struct jit_ctx *ctx, int nr_stk_args, int args_off, int stk_args_off) 1497 + { 1498 + int i; 1499 + 1500 + for (i = 0; i < nr_stk_args; i++) { 1501 + emit_insn(ctx, ldd, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, 1502 + -(args_off - LOONGARCH_MAX_REG_ARGS * 8)); 1503 + emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -stk_args_off); 1504 + args_off -= 8; 1505 + stk_args_off -= 8; 1654 1506 } 1655 1507 } 1656 1508 ··· 1682 1494 struct bpf_prog *p = l->link.prog; 1683 1495 int cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie); 1684 1496 1685 - if (l->cookie) { 1686 - move_imm(ctx, LOONGARCH_GPR_T1, l->cookie, false); 1687 - emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -run_ctx_off + cookie_off); 1688 - } else { 1497 + if (l->cookie) 1498 + emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, 1499 + -run_ctx_off + cookie_off, l->cookie); 1500 + else 1689 1501 emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -run_ctx_off + cookie_off); 1690 - } 1691 1502 1692 1503 /* arg1: prog */ 1693 1504 move_imm(ctx, LOONGARCH_GPR_A0, (const s64)p, false); ··· 1737 1550 return ret; 1738 1551 } 1739 1552 1740 - static void invoke_bpf_mod_ret(struct jit_ctx *ctx, struct bpf_tramp_links *tl, 1741 - int args_off, int retval_off, int run_ctx_off, u32 **branches) 1553 + static int invoke_bpf(struct jit_ctx *ctx, struct bpf_tramp_links *tl, 1554 + int args_off, int retval_off, int run_ctx_off, 1555 + int func_meta_off, bool save_ret, u64 func_meta, int cookie_off) 1742 1556 { 1743 - int i; 1557 + int i, cur_cookie = (cookie_off - args_off) / 8; 1744 1558 1745 - emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -retval_off); 1746 1559 for (i = 0; i < tl->nr_links; i++) { 1747 - invoke_bpf_prog(ctx, tl->links[i], args_off, retval_off, run_ctx_off, true); 1748 - emit_insn(ctx, ldd, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -retval_off); 1749 - branches[i] = (u32 *)ctx->image + ctx->idx; 1750 - emit_insn(ctx, nop); 1560 + int err; 1561 + 1562 + if (bpf_prog_calls_session_cookie(tl->links[i])) { 1563 + u64 meta = func_meta | ((u64)cur_cookie << BPF_TRAMP_COOKIE_INDEX_SHIFT); 1564 + 1565 + emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -func_meta_off, meta); 1566 + cur_cookie--; 1567 + } 1568 + err = invoke_bpf_prog(ctx, tl->links[i], args_off, retval_off, run_ctx_off, save_ret); 1569 + if (err) 1570 + return err; 1751 1571 } 1572 + 1573 + return 0; 1752 1574 } 1753 1575 1754 1576 void *arch_alloc_bpf_trampoline(unsigned int size) ··· 1811 1615 void *func_addr, u32 flags) 1812 1616 { 1813 1617 int i, ret, save_ret; 1814 - int stack_size, nargs; 1815 - int retval_off, args_off, nargs_off, ip_off, run_ctx_off, sreg_off, tcc_ptr_off; 1618 + int cookie_cnt, cookie_off; 1619 + int stack_size, args_off, stk_args_off, nr_arg_slots = 0; 1620 + int retval_off, func_meta_off, ip_off, run_ctx_off, sreg_off, tcc_ptr_off; 1621 + unsigned long long func_meta; 1816 1622 bool is_struct_ops = flags & BPF_TRAMP_F_INDIRECT; 1817 1623 void *orig_call = func_addr; 1818 1624 struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY]; ··· 1832 1634 * FP - 16 [ FP of traced func ] frame pointer of traced 1833 1635 * function 1834 1636 * 1835 - * FP - retval_off [ return value ] BPF_TRAMP_F_CALL_ORIG or 1836 - * BPF_TRAMP_F_RET_FENTRY_RET 1837 - * [ argN ] 1838 - * [ ... ] 1839 - * FP - args_off [ arg1 ] 1637 + * FP - retval_off [ return value ] BPF_TRAMP_F_CALL_ORIG or 1638 + * BPF_TRAMP_F_RET_FENTRY_RET 1639 + * [ arg regN ] 1640 + * [ ... ] 1641 + * FP - args_off [ arg reg1 ] 1840 1642 * 1841 - * FP - nargs_off [ regs count ] 1643 + * FP - func_meta_off [ regs count, etc ] 1842 1644 * 1843 - * FP - ip_off [ traced func ] BPF_TRAMP_F_IP_ARG 1645 + * FP - ip_off [ traced func ] BPF_TRAMP_F_IP_ARG 1844 1646 * 1845 - * FP - run_ctx_off [ bpf_tramp_run_ctx ] 1647 + * [ stack cookie N ] 1648 + * [ ... ] 1649 + * FP - cookie_off [ stack cookie 1 ] 1846 1650 * 1847 - * FP - sreg_off [ callee saved reg ] 1651 + * FP - run_ctx_off [ bpf_tramp_run_ctx ] 1848 1652 * 1849 - * FP - tcc_ptr_off [ tail_call_cnt_ptr ] 1653 + * FP - sreg_off [ callee saved reg ] 1654 + * 1655 + * FP - tcc_ptr_off [ tail_call_cnt_ptr ] 1656 + * 1657 + * [ stack_argN ] 1658 + * [ ... ] 1659 + * FP - stk_args_off [ stack_arg1 ] BPF_TRAMP_F_CALL_ORIG 1850 1660 */ 1851 1661 1852 - if (m->nr_args > LOONGARCH_MAX_REG_ARGS) 1662 + if (m->nr_args > MAX_BPF_FUNC_ARGS) 1853 1663 return -ENOTSUPP; 1854 1664 1855 - /* FIXME: No support of struct argument */ 1665 + /* Extra registers for struct arguments */ 1856 1666 for (i = 0; i < m->nr_args; i++) { 1857 - if (m->arg_flags[i] & BTF_FMODEL_STRUCT_ARG) 1858 - return -ENOTSUPP; 1667 + /* 1668 + * The struct argument size is at most 16 bytes, 1669 + * enforced by the verifier. The struct argument 1670 + * may be passed in a pair of registers if its 1671 + * size is more than 8 bytes and no more than 16 1672 + * bytes. 1673 + */ 1674 + nr_arg_slots += round_up(m->arg_size[i], 8) / 8; 1859 1675 } 1860 1676 1861 1677 if (flags & (BPF_TRAMP_F_ORIG_STACK | BPF_TRAMP_F_SHARE_IPMODIFY)) ··· 1885 1673 retval_off = stack_size; 1886 1674 1887 1675 /* Room of trampoline frame to store args */ 1888 - nargs = m->nr_args; 1889 - stack_size += nargs * 8; 1676 + stack_size += nr_arg_slots * 8; 1890 1677 args_off = stack_size; 1891 1678 1892 - /* Room of trampoline frame to store args number */ 1679 + /* Room of function metadata, such as regs count */ 1893 1680 stack_size += 8; 1894 - nargs_off = stack_size; 1681 + func_meta_off = stack_size; 1895 1682 1896 1683 /* Room of trampoline frame to store ip address */ 1897 1684 if (flags & BPF_TRAMP_F_IP_ARG) { 1898 1685 stack_size += 8; 1899 1686 ip_off = stack_size; 1900 1687 } 1688 + 1689 + cookie_cnt = bpf_fsession_cookie_cnt(tlinks); 1690 + 1691 + /* Room for session cookies */ 1692 + stack_size += cookie_cnt * 8; 1693 + cookie_off = stack_size; 1901 1694 1902 1695 /* Room of trampoline frame to store struct bpf_tramp_run_ctx */ 1903 1696 stack_size += round_up(sizeof(struct bpf_tramp_run_ctx), 8); ··· 1917 1700 tcc_ptr_off = stack_size; 1918 1701 } 1919 1702 1703 + if ((flags & BPF_TRAMP_F_CALL_ORIG) && (nr_arg_slots - LOONGARCH_MAX_REG_ARGS > 0)) 1704 + stack_size += (nr_arg_slots - LOONGARCH_MAX_REG_ARGS) * 8; 1705 + 1920 1706 stack_size = round_up(stack_size, 16); 1707 + 1708 + /* Room for args on stack must be at the top of stack */ 1709 + stk_args_off = stack_size; 1921 1710 1922 1711 if (is_struct_ops) { 1923 1712 /* ··· 1960 1737 emit_insn(ctx, std, LOONGARCH_GPR_S1, LOONGARCH_GPR_FP, -sreg_off); 1961 1738 1962 1739 /* store ip address of the traced function */ 1963 - if (flags & BPF_TRAMP_F_IP_ARG) { 1964 - move_imm(ctx, LOONGARCH_GPR_T1, (const s64)func_addr, false); 1965 - emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -ip_off); 1740 + if (flags & BPF_TRAMP_F_IP_ARG) 1741 + emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -ip_off, (u64)func_addr); 1742 + 1743 + /* store arg regs count */ 1744 + func_meta = nr_arg_slots; 1745 + emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -func_meta_off, func_meta); 1746 + 1747 + store_args(ctx, nr_arg_slots, args_off); 1748 + 1749 + if (bpf_fsession_cnt(tlinks)) { 1750 + /* clear all session cookies' value */ 1751 + for (i = 0; i < cookie_cnt; i++) 1752 + emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -cookie_off + 8 * i); 1753 + 1754 + /* clear return value to make sure fentry always get 0 */ 1755 + emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -retval_off); 1966 1756 } 1967 - 1968 - /* store nargs number */ 1969 - move_imm(ctx, LOONGARCH_GPR_T1, nargs, false); 1970 - emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -nargs_off); 1971 - 1972 - store_args(ctx, nargs, args_off); 1973 1757 1974 1758 /* To traced function */ 1975 1759 /* Ftrace jump skips 2 NOP instructions */ ··· 1994 1764 return ret; 1995 1765 } 1996 1766 1997 - for (i = 0; i < fentry->nr_links; i++) { 1998 - ret = invoke_bpf_prog(ctx, fentry->links[i], args_off, retval_off, 1999 - run_ctx_off, flags & BPF_TRAMP_F_RET_FENTRY_RET); 1767 + if (fentry->nr_links) { 1768 + ret = invoke_bpf(ctx, fentry, args_off, retval_off, run_ctx_off, func_meta_off, 1769 + flags & BPF_TRAMP_F_RET_FENTRY_RET, func_meta, cookie_off); 2000 1770 if (ret) 2001 1771 return ret; 2002 1772 } ··· 2005 1775 if (!branches) 2006 1776 return -ENOMEM; 2007 1777 2008 - invoke_bpf_mod_ret(ctx, fmod_ret, args_off, retval_off, run_ctx_off, branches); 1778 + emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -retval_off); 1779 + for (i = 0; i < fmod_ret->nr_links; i++) { 1780 + ret = invoke_bpf_prog(ctx, fmod_ret->links[i], 1781 + args_off, retval_off, run_ctx_off, true); 1782 + if (ret) 1783 + goto out; 1784 + emit_insn(ctx, ldd, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -retval_off); 1785 + branches[i] = (u32 *)ctx->image + ctx->idx; 1786 + emit_insn(ctx, nop); 1787 + } 2009 1788 } 2010 1789 2011 1790 if (flags & BPF_TRAMP_F_CALL_ORIG) { 2012 - restore_args(ctx, m->nr_args, args_off); 1791 + restore_args(ctx, min_t(int, nr_arg_slots, LOONGARCH_MAX_REG_ARGS), args_off); 1792 + restore_stk_args(ctx, nr_arg_slots - LOONGARCH_MAX_REG_ARGS, args_off, stk_args_off); 2013 1793 2014 1794 if (flags & BPF_TRAMP_F_TAIL_CALL_CTX) 2015 1795 emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_FP, -tcc_ptr_off); ··· 2040 1800 *branches[i] = larch_insn_gen_bne(LOONGARCH_GPR_T1, LOONGARCH_GPR_ZERO, offset); 2041 1801 } 2042 1802 2043 - for (i = 0; i < fexit->nr_links; i++) { 2044 - ret = invoke_bpf_prog(ctx, fexit->links[i], args_off, retval_off, run_ctx_off, false); 1803 + /* Set "is_return" flag for fsession */ 1804 + func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT); 1805 + if (bpf_fsession_cnt(tlinks)) 1806 + emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -func_meta_off, func_meta); 1807 + 1808 + if (fexit->nr_links) { 1809 + ret = invoke_bpf(ctx, fexit, args_off, retval_off, run_ctx_off, 1810 + func_meta_off, false, func_meta, cookie_off); 2045 1811 if (ret) 2046 1812 goto out; 2047 1813 } ··· 2061 1815 } 2062 1816 2063 1817 if (flags & BPF_TRAMP_F_RESTORE_REGS) 2064 - restore_args(ctx, m->nr_args, args_off); 1818 + restore_args(ctx, min_t(int, nr_arg_slots, LOONGARCH_MAX_REG_ARGS), args_off); 2065 1819 2066 1820 if (save_ret) { 2067 1821 emit_insn(ctx, ldd, regmap[BPF_REG_0], LOONGARCH_GPR_FP, -(retval_off - 8)); ··· 2353 2107 } 2354 2108 2355 2109 bool bpf_jit_supports_arena(void) 2110 + { 2111 + return true; 2112 + } 2113 + 2114 + bool bpf_jit_supports_fsession(void) 2356 2115 { 2357 2116 return true; 2358 2117 }
+1
drivers/firmware/efi/libstub/Makefile
··· 96 96 CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd 97 97 98 98 zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o 99 + zboot-obj-$(CONFIG_LOONGARCH) += lib-clz_ctz.o lib-ashldi3.o 99 100 lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y) 100 101 101 102 lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o
+1 -1
drivers/pci/controller/Kconfig
··· 187 187 188 188 config PCI_LOONGSON 189 189 bool "LOONGSON PCIe controller" 190 - depends on MACH_LOONGSON64 || COMPILE_TEST 190 + depends on MACH_LOONGSON32 || MACH_LOONGSON64 || COMPILE_TEST 191 191 depends on OF || ACPI 192 192 depends on PCI_QUIRKS 193 193 default MACH_LOONGSON64
+1 -1
lib/crc/Kconfig
··· 65 65 depends on CRC32 && CRC_OPTIMIZATIONS 66 66 default y if ARM && KERNEL_MODE_NEON 67 67 default y if ARM64 68 - default y if LOONGARCH 68 + default y if LOONGARCH && 64BIT 69 69 default y if MIPS && CPU_MIPSR6 70 70 default y if PPC64 && ALTIVEC 71 71 default y if RISCV && RISCV_ISA_ZBC
+2 -2
tools/testing/selftests/bpf/progs/bpf_misc.h
··· 263 263 264 264 #if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \ 265 265 (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 266 - (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) || \ 267 - (defined(__TARGET_ARCH_powerpc)) 266 + (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 267 + defined(__TARGET_ARCH_powerpc) || defined(__TARGET_ARCH_loongarch)) 268 268 #define CAN_USE_LOAD_ACQ_STORE_REL 269 269 #endif 270 270
+2 -2
tools/testing/selftests/bpf/progs/verifier_precision.c
··· 75 75 76 76 #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 77 77 (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 78 - defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \ 79 - __clang_major__ >= 18 78 + defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390) || \ 79 + defined(__TARGET_ARCH_loongarch)) && __clang_major__ >= 18 80 80 81 81 SEC("?raw_tp") 82 82 __success __log_level(2)