LoongArch changes for v7.1

1, Adjust build infrastructure for 32BIT/64BIT;
 2, Add HIGHMEM (PKMAP and FIX_KMAP) support;
 3, Show and handle CPU vulnerabilites correctly;
 4, Batch the icache maintenance for jump_label;
 5, Add more atomic instructions support for BPF JIT;
 6, Add more features (e.g. fsession) support for BPF trampoline;
 7, Some bug fixes and other small changes.
 -----BEGIN PGP SIGNATURE-----
 
 iQJKBAABCAA0FiEEzOlt8mkP+tbeiYy5AoYrw/LiJnoFAmnpwWgWHGNoZW5odWFj
 YWlAa2VybmVsLm9yZwAKCRAChivD8uImeiAXD/0RSRhj2y8LYGhVSPStMgN4uwMl
 1ylbkRg0biTvV0g8sD1R3MQ58/tKBZY5wTeLjwT50rl+JgOqVdrN6OMAxjwOKzJ6
 7C0rgpxBG5/YHI93paFVIYszsiWhRQaB5qfZCUOr230ZDJzvnfF1aH6JLybeHoMp
 HvERNURQsRbZo9yc69YxhrmHETEbum37u9hsrY5mJSEs5Fh+QxvTSYjE36z3Dtal
 YFqopTCaBgAhVw6BldVAcyvGvVK+d6iQEA035jObNLKKReNkwsQixxgnJhDSkbbG
 Z3md+hWp+YQQElGIP5q6+rj1rJZGrs/XL3HAnTQfXN+8bXIUO9AOf2/l5f9fZx7o
 2Vtt8n2/vVdzsVnKiHXGtsZ5uXrw4/kLiMZSCrUMZCtEOxJV9mmrVskPeie0iq0/
 nDG9uCgRldL8Xpg7d5NM9coECui3J+ztNkv06tL/JLm02bJPuqNwt3FeA1T/aH1c
 l2Hpw3Xuzl7lYuAYoa5CMm4X6yD/RA6w44pW1NKnb6j6llIOk6V6NwcwggWUnqht
 oB5VIqPKMOYjZ+fLurI2o9VWqWokJxDdzyrHhXyaG0JRK9Vak06C8UI5BQuosu88
 9WBoxK77PyNa60m56C32OZ5tu4UoPT8PgZWXDQDwn82SWzuYKWRruS2ng5A/JF7r
 H2Ez4iBjs2/P7vTQHA==
 =FiFl
 -----END PGP SIGNATURE-----

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
  ...
master
Linus Torvalds 2026-04-24 09:54:45 -07:00
commit ff57d59200
39 changed files with 727 additions and 202 deletions

View File

@ -20,11 +20,11 @@ config LOONGARCH
select ARCH_HAS_FAST_MULTIPLIER select ARCH_HAS_FAST_MULTIPLIER
select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_KCOV select ARCH_HAS_KCOV
select ARCH_HAS_KERNEL_FPU_SUPPORT if CPU_HAS_FPU select ARCH_HAS_KERNEL_FPU_SUPPORT if 64BIT && CPU_HAS_FPU
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
select ARCH_HAS_PREEMPT_LAZY select ARCH_HAS_PREEMPT_LAZY
select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_PTE_SPECIAL if 64BIT
select ARCH_HAS_SET_MEMORY select ARCH_HAS_SET_MEMORY
select ARCH_HAS_SET_DIRECT_MAP select ARCH_HAS_SET_DIRECT_MAP
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
@ -59,16 +59,15 @@ config LOONGARCH
select ARCH_KEEP_MEMBLOCK select ARCH_KEEP_MEMBLOCK
select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO select ARCH_MIGHT_HAVE_PC_SERIO
select ARCH_SPARSEMEM_ENABLE
select ARCH_STACKWALK select ARCH_STACKWALK
select ARCH_SUPPORTS_ACPI select ARCH_SUPPORTS_ACPI
select ARCH_SUPPORTS_ATOMIC_RMW select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_HUGETLBFS select ARCH_SUPPORTS_HUGETLBFS if 64BIT
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
select ARCH_SUPPORTS_LTO_CLANG select ARCH_SUPPORTS_LTO_CLANG
select ARCH_SUPPORTS_LTO_CLANG_THIN select ARCH_SUPPORTS_LTO_CLANG_THIN
select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS
select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_SUPPORTS_NUMA_BALANCING if NUMA
select ARCH_SUPPORTS_PER_VMA_LOCK select ARCH_SUPPORTS_PER_VMA_LOCK
select ARCH_SUPPORTS_RT select ARCH_SUPPORTS_RT
select ARCH_SUPPORTS_SCHED_SMT if SMP select ARCH_SUPPORTS_SCHED_SMT if SMP
@ -78,10 +77,10 @@ config LOONGARCH
select ARCH_USE_MEMTEST select ARCH_USE_MEMTEST
select ARCH_USE_QUEUED_RWLOCKS select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_WANT_DEFAULT_BPF_JIT select ARCH_WANT_DEFAULT_BPF_JIT if HAVE_EBPF_JIT
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
select ARCH_WANT_LD_ORPHAN_WARN select ARCH_WANT_LD_ORPHAN_WARN
select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP if 64BIT
select ARCH_WANTS_NO_INSTR select ARCH_WANTS_NO_INSTR
select ARCH_WANTS_THP_SWAP if HAVE_ARCH_TRANSPARENT_HUGEPAGE select ARCH_WANTS_THP_SWAP if HAVE_ARCH_TRANSPARENT_HUGEPAGE
select BUILDTIME_TABLE_SORT select BUILDTIME_TABLE_SORT
@ -89,13 +88,14 @@ config LOONGARCH
select CPU_PM select CPU_PM
select EDAC_SUPPORT select EDAC_SUPPORT
select EFI select EFI
select GENERIC_ATOMIC64 if 32BIT
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GENERIC_CMOS_UPDATE select GENERIC_CMOS_UPDATE
select GENERIC_CPU_AUTOPROBE select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_DEVICES select GENERIC_CPU_DEVICES
select GENERIC_CPU_VULNERABILITIES select GENERIC_CPU_VULNERABILITIES
select GENERIC_ENTRY select GENERIC_ENTRY
select GENERIC_GETTIMEOFDAY select GENERIC_GETTIMEOFDAY if 64BIT
select GENERIC_IOREMAP if !ARCH_IOREMAP select GENERIC_IOREMAP if !ARCH_IOREMAP
select GENERIC_IRQ_MATRIX_ALLOCATOR select GENERIC_IRQ_MATRIX_ALLOCATOR
select GENERIC_IRQ_MULTI_HANDLER select GENERIC_IRQ_MULTI_HANDLER
@ -110,16 +110,16 @@ config LOONGARCH
select GENERIC_PCI_IOMAP select GENERIC_PCI_IOMAP
select GENERIC_SCHED_CLOCK select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL select GENERIC_TIME_VSYSCALL if GENERIC_GETTIMEOFDAY
select GPIOLIB select GPIOLIB
select HAS_IOPORT select HAS_IOPORT
select HAVE_ALIGNED_STRUCT_PAGE select HAVE_ALIGNED_STRUCT_PAGE if 64BIT
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_BITREVERSE select HAVE_ARCH_BITREVERSE if 64BIT
select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN select HAVE_ARCH_KASAN if 64BIT
select HAVE_ARCH_KFENCE select HAVE_ARCH_KFENCE if 64BIT
select HAVE_ARCH_KGDB if PERF_EVENTS select HAVE_ARCH_KGDB if PERF_EVENTS
select HAVE_ARCH_KSTACK_ERASE select HAVE_ARCH_KSTACK_ERASE
select HAVE_ARCH_MMAP_RND_BITS if MMU select HAVE_ARCH_MMAP_RND_BITS if MMU
@ -127,8 +127,8 @@ config LOONGARCH
select HAVE_ARCH_SECCOMP select HAVE_ARCH_SECCOMP
select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT
select HAVE_ARCH_USERFAULTFD_MINOR if USERFAULTFD select HAVE_ARCH_USERFAULTFD_MINOR if 64BIT && USERFAULTFD
select HAVE_ASM_MODVERSIONS select HAVE_ASM_MODVERSIONS
select HAVE_CMPXCHG_DOUBLE select HAVE_CMPXCHG_DOUBLE
select HAVE_CMPXCHG_LOCAL select HAVE_CMPXCHG_LOCAL
@ -142,7 +142,7 @@ config LOONGARCH
select HAVE_FTRACE_REGS_HAVING_PT_REGS select HAVE_FTRACE_REGS_HAVING_PT_REGS
select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
select HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_DYNAMIC_FTRACE_WITH_REGS
select HAVE_EBPF_JIT select HAVE_EBPF_JIT if 64BIT
select HAVE_EFFICIENT_UNALIGNED_ACCESS if !ARCH_STRICT_ALIGN select HAVE_EFFICIENT_UNALIGNED_ACCESS if !ARCH_STRICT_ALIGN
select HAVE_EXIT_THREAD select HAVE_EXIT_THREAD
select HAVE_GENERIC_TIF_BITS select HAVE_GENERIC_TIF_BITS
@ -165,9 +165,9 @@ config LOONGARCH
select HAVE_LIVEPATCH select HAVE_LIVEPATCH
select HAVE_MOD_ARCH_SPECIFIC select HAVE_MOD_ARCH_SPECIFIC
select HAVE_NMI select HAVE_NMI
select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS && AS_HAS_THIN_ADD_SUB select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS && AS_HAS_THIN_ADD_SUB && 64BIT
select HAVE_PCI select HAVE_PCI
select HAVE_PERF_EVENTS select HAVE_PERF_EVENTS if 64BIT
select HAVE_PERF_REGS select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP select HAVE_PERF_USER_STACK_DUMP
select HAVE_POSIX_CPU_TIMERS_TASK_WORK select HAVE_POSIX_CPU_TIMERS_TASK_WORK
@ -209,18 +209,50 @@ config LOONGARCH
select SYSCTL_ARCH_UNALIGN_ALLOW select SYSCTL_ARCH_UNALIGN_ALLOW
select SYSCTL_ARCH_UNALIGN_NO_WARN select SYSCTL_ARCH_UNALIGN_NO_WARN
select SYSCTL_EXCEPTION_TRACE select SYSCTL_EXCEPTION_TRACE
select SWIOTLB select SWIOTLB if 64BIT
select TRACE_IRQFLAGS_SUPPORT select TRACE_IRQFLAGS_SUPPORT
select USE_PERCPU_NUMA_NODE_ID select USE_PERCPU_NUMA_NODE_ID
select USER_STACKTRACE_SUPPORT select USER_STACKTRACE_SUPPORT
select VDSO_GETRANDOM select VDSO_GETRANDOM
select ZONE_DMA32 select ZONE_DMA32 if 64BIT
menu "Kernel type and options"
choice
prompt "Kernel type"
config 32BIT config 32BIT
bool bool "32-bit kernel"
help
Select this option if you want to build a 32-bit kernel.
config 64BIT config 64BIT
def_bool y bool "64-bit kernel"
help
Select this option if you want to build a 64-bit kernel.
endchoice
if 32BIT
choice
prompt "32-bit kernel sub-type"
config 32BIT_REDUCED
bool "32-bit kernel for LA32R"
help
Select this option if you want to build a 32-bit kernel for
LoongArch32 Reduced (LA32R).
config 32BIT_STANDARD
bool "32-bit kernel for LA32S"
help
Select this option if you want to build a 32-bit kernel for
LoongArch32 Standard (LA32S).
endchoice
endif
config GENERIC_BUG config GENERIC_BUG
def_bool y def_bool y
@ -313,10 +345,13 @@ config RUSTC_HAS_ANNOTATE_TABLEJUMP
depends on RUST depends on RUST
def_bool $(rustc-option,-Cllvm-args=--loongarch-annotate-tablejump) def_bool $(rustc-option,-Cllvm-args=--loongarch-annotate-tablejump)
menu "Kernel type and options"
source "kernel/Kconfig.hz" source "kernel/Kconfig.hz"
config HIGHMEM
bool "High Memory Support"
depends on 32BIT
select KMAP_LOCAL
choice choice
prompt "Page Table Layout" prompt "Page Table Layout"
default 16KB_2LEVEL if 32BIT default 16KB_2LEVEL if 32BIT
@ -326,8 +361,17 @@ choice
of page size and page table levels. The size of virtual memory of page size and page table levels. The size of virtual memory
address space are determined by the page table layout. address space are determined by the page table layout.
config 4KB_2LEVEL
bool "4KB with 2 levels"
select HAVE_PAGE_SIZE_4KB
select PGTABLE_2LEVEL
help
This option selects 4KB page size with 2 level page tables, which
support a maximum of 32 bits of application virtual memory.
config 4KB_3LEVEL config 4KB_3LEVEL
bool "4KB with 3 levels" bool "4KB with 3 levels"
depends on 64BIT
select HAVE_PAGE_SIZE_4KB select HAVE_PAGE_SIZE_4KB
select PGTABLE_3LEVEL select PGTABLE_3LEVEL
help help
@ -336,6 +380,7 @@ config 4KB_3LEVEL
config 4KB_4LEVEL config 4KB_4LEVEL
bool "4KB with 4 levels" bool "4KB with 4 levels"
depends on 64BIT
select HAVE_PAGE_SIZE_4KB select HAVE_PAGE_SIZE_4KB
select PGTABLE_4LEVEL select PGTABLE_4LEVEL
help help
@ -352,6 +397,7 @@ config 16KB_2LEVEL
config 16KB_3LEVEL config 16KB_3LEVEL
bool "16KB with 3 levels" bool "16KB with 3 levels"
depends on 64BIT
select HAVE_PAGE_SIZE_16KB select HAVE_PAGE_SIZE_16KB
select PGTABLE_3LEVEL select PGTABLE_3LEVEL
help help
@ -368,6 +414,7 @@ config 64KB_2LEVEL
config 64KB_3LEVEL config 64KB_3LEVEL
bool "64KB with 3 levels" bool "64KB with 3 levels"
depends on 64BIT
select HAVE_PAGE_SIZE_64KB select HAVE_PAGE_SIZE_64KB
select PGTABLE_3LEVEL select PGTABLE_3LEVEL
help help
@ -465,6 +512,7 @@ config EFI_STUB
config SMP config SMP
bool "Multi-Processing support" bool "Multi-Processing support"
depends on 64BIT
help help
This enables support for systems with more than one CPU. If you have This enables support for systems with more than one CPU. If you have
a system with only one CPU, say N. If you have a system with more a system with only one CPU, say N. If you have a system with more
@ -503,6 +551,7 @@ config NR_CPUS
config NUMA config NUMA
bool "NUMA Support" bool "NUMA Support"
select SMP select SMP
depends on 64BIT
help help
Say Y to compile the kernel with NUMA (Non-Uniform Memory Access) Say Y to compile the kernel with NUMA (Non-Uniform Memory Access)
support. This option improves performance on systems with more support. This option improves performance on systems with more
@ -585,7 +634,7 @@ config CPU_HAS_FPU
config CPU_HAS_LSX config CPU_HAS_LSX
bool "Support for the Loongson SIMD Extension" bool "Support for the Loongson SIMD Extension"
depends on AS_HAS_LSX_EXTENSION depends on AS_HAS_LSX_EXTENSION && 64BIT
help help
Loongson SIMD Extension (LSX) introduces 128 bit wide vector registers Loongson SIMD Extension (LSX) introduces 128 bit wide vector registers
and a set of SIMD instructions to operate on them. When this option and a set of SIMD instructions to operate on them. When this option
@ -600,7 +649,7 @@ config CPU_HAS_LSX
config CPU_HAS_LASX config CPU_HAS_LASX
bool "Support for the Loongson Advanced SIMD Extension" bool "Support for the Loongson Advanced SIMD Extension"
depends on CPU_HAS_LSX depends on CPU_HAS_LSX
depends on AS_HAS_LASX_EXTENSION depends on AS_HAS_LASX_EXTENSION && 64BIT
help help
Loongson Advanced SIMD Extension (LASX) introduces 256 bit wide vector Loongson Advanced SIMD Extension (LASX) introduces 256 bit wide vector
registers and a set of SIMD instructions to operate on them. When this registers and a set of SIMD instructions to operate on them. When this
@ -614,7 +663,7 @@ config CPU_HAS_LASX
config CPU_HAS_LBT config CPU_HAS_LBT
bool "Support for the Loongson Binary Translation Extension" bool "Support for the Loongson Binary Translation Extension"
depends on AS_HAS_LBT_EXTENSION depends on AS_HAS_LBT_EXTENSION && 64BIT
help help
Loongson Binary Translation (LBT) introduces 4 scratch registers (SCR0 Loongson Binary Translation (LBT) introduces 4 scratch registers (SCR0
to SCR3), x86/ARM eflags (eflags) and x87 fpu stack pointer (ftop). to SCR3), x86/ARM eflags (eflags) and x87 fpu stack pointer (ftop).
@ -642,13 +691,13 @@ config ARCH_SELECTS_KEXEC_FILE
select HAVE_IMA_KEXEC if IMA select HAVE_IMA_KEXEC if IMA
config ARCH_SUPPORTS_CRASH_DUMP config ARCH_SUPPORTS_CRASH_DUMP
def_bool y def_bool 64BIT
config ARCH_DEFAULT_CRASH_DUMP config ARCH_DEFAULT_CRASH_DUMP
def_bool y def_bool 64BIT
config ARCH_SELECTS_CRASH_DUMP config ARCH_SELECTS_CRASH_DUMP
def_bool y def_bool 64BIT
depends on CRASH_DUMP depends on CRASH_DUMP
select RELOCATABLE select RELOCATABLE
@ -657,6 +706,7 @@ config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
config RELOCATABLE config RELOCATABLE
bool "Relocatable kernel" bool "Relocatable kernel"
depends on 64BIT
select ARCH_HAS_RELR select ARCH_HAS_RELR
help help
This builds the kernel as a Position Independent Executable (PIE), This builds the kernel as a Position Independent Executable (PIE),
@ -693,7 +743,7 @@ source "kernel/livepatch/Kconfig"
config PARAVIRT config PARAVIRT
bool "Enable paravirtualization code" bool "Enable paravirtualization code"
depends on AS_HAS_LVZ_EXTENSION depends on AS_HAS_LVZ_EXTENSION && 64BIT
select HAVE_PV_STEAL_CLOCK_GEN select HAVE_PV_STEAL_CLOCK_GEN
help help
This changes the kernel so it can modify itself when it is run This changes the kernel so it can modify itself when it is run
@ -722,7 +772,7 @@ config ARCH_FLATMEM_ENABLE
depends on !NUMA depends on !NUMA
config ARCH_SPARSEMEM_ENABLE config ARCH_SPARSEMEM_ENABLE
def_bool y def_bool 64BIT
select SPARSEMEM_VMEMMAP_ENABLE select SPARSEMEM_VMEMMAP_ENABLE
help help
Say Y to support efficient handling of sparse physical memory, Say Y to support efficient handling of sparse physical memory,
@ -739,10 +789,12 @@ config MMU
default y default y
config ARCH_MMAP_RND_BITS_MIN config ARCH_MMAP_RND_BITS_MIN
default 12 default 10 if 32BIT
default 12 if 64BIT
config ARCH_MMAP_RND_BITS_MAX config ARCH_MMAP_RND_BITS_MAX
default 18 default 15 if 32BIT
default 20 if 64BIT
config ARCH_SUPPORTS_UPROBES config ARCH_SUPPORTS_UPROBES
def_bool y def_bool y

View File

@ -25,6 +25,7 @@ endif
# #
# Select the object file format to substitute into the linker script. # Select the object file format to substitute into the linker script.
# #
32bit-tool-archpref = loongarch32
64bit-tool-archpref = loongarch64 64bit-tool-archpref = loongarch64
32bit-bfd = elf32-loongarch 32bit-bfd = elf32-loongarch
64bit-bfd = elf64-loongarch 64bit-bfd = elf64-loongarch
@ -51,7 +52,10 @@ KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
CC_FLAGS_FTRACE := -fpatchable-function-entry=2 CC_FLAGS_FTRACE := -fpatchable-function-entry=2
endif endif
ifdef CONFIG_64BIT ifdef CONFIG_32BIT
tool-archpref = $(32bit-tool-archpref)
UTS_MACHINE := loongarch32
else
tool-archpref = $(64bit-tool-archpref) tool-archpref = $(64bit-tool-archpref)
UTS_MACHINE := loongarch64 UTS_MACHINE := loongarch64
endif endif
@ -62,9 +66,19 @@ ifneq ($(SUBARCH),$(ARCH))
endif endif
endif endif
ifdef CONFIG_32BIT
ifdef CONFIG_32BIT_STANDARD
ld-emul = $(32bit-emul)
cflags-y += -march=la32v1.0 -mabi=ilp32s -mcmodel=normal
else # CONFIG_32BIT_REDUCED
ld-emul = $(32bit-emul)
cflags-y += -march=la32rv1.0 -mabi=ilp32s -mcmodel=normal
endif
endif
ifdef CONFIG_64BIT ifdef CONFIG_64BIT
ld-emul = $(64bit-emul) ld-emul = $(64bit-emul)
cflags-y += -mabi=lp64s -mcmodel=normal cflags-y += -march=loongarch64 -mabi=lp64s -mcmodel=normal
endif endif
cflags-y += -pipe $(CC_FLAGS_NO_FPU) cflags-y += -pipe $(CC_FLAGS_NO_FPU)
@ -140,7 +154,12 @@ ifndef CONFIG_KASAN
cflags-y += -fno-builtin-memcpy -fno-builtin-memmove -fno-builtin-memset cflags-y += -fno-builtin-memcpy -fno-builtin-memmove -fno-builtin-memset
endif endif
ifdef CONFIG_32BIT
load-y = 0xa0200000
else
load-y = 0x9000000000200000 load-y = 0x9000000000200000
endif
bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y)
drivers-$(CONFIG_PCI) += arch/loongarch/pci/ drivers-$(CONFIG_PCI) += arch/loongarch/pci/

View File

@ -20,7 +20,13 @@ $(obj)/vmlinux.efi: vmlinux FORCE
$(call if_changed,objcopy) $(call if_changed,objcopy)
EFI_ZBOOT_PAYLOAD := vmlinux.efi EFI_ZBOOT_PAYLOAD := vmlinux.efi
ifdef CONFIG_32BIT
EFI_ZBOOT_BFD_TARGET := elf32-loongarch
EFI_ZBOOT_MACH_TYPE := LOONGARCH32
else
EFI_ZBOOT_BFD_TARGET := elf64-loongarch EFI_ZBOOT_BFD_TARGET := elf64-loongarch
EFI_ZBOOT_MACH_TYPE := LOONGARCH64 EFI_ZBOOT_MACH_TYPE := LOONGARCH64
endif
include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot

View File

@ -32,8 +32,22 @@ static inline unsigned int cpu_last_level_cache_line_size(void)
} }
asmlinkage void __flush_cache_all(void); asmlinkage void __flush_cache_all(void);
void local_flush_icache_range(unsigned long start, unsigned long end);
/*
* LoongArch maintains ICache/DCache coherency by hardware,
* we just need "ibar" to avoid instruction hazard here.
*/
static inline void local_flush_icache_all(void)
{
asm volatile ("ibar\t0\n"::);
}
static inline void local_flush_icache_range(unsigned long start, unsigned long end)
{
asm volatile ("ibar\t0\n"::);
}
#define flush_icache_all local_flush_icache_all
#define flush_icache_range local_flush_icache_range #define flush_icache_range local_flush_icache_range
#define flush_icache_user_range local_flush_icache_range #define flush_icache_user_range local_flush_icache_range

View File

@ -35,6 +35,7 @@
*/ */
#define cpu_has_cpucfg cpu_opt(LOONGARCH_CPU_CPUCFG) #define cpu_has_cpucfg cpu_opt(LOONGARCH_CPU_CPUCFG)
#define cpu_has_lam cpu_opt(LOONGARCH_CPU_LAM) #define cpu_has_lam cpu_opt(LOONGARCH_CPU_LAM)
#define cpu_has_lam_bh cpu_opt(LOONGARCH_CPU_LAM_BH)
#define cpu_has_scq cpu_opt(LOONGARCH_CPU_SCQ) #define cpu_has_scq cpu_opt(LOONGARCH_CPU_SCQ)
#define cpu_has_ual cpu_opt(LOONGARCH_CPU_UAL) #define cpu_has_ual cpu_opt(LOONGARCH_CPU_UAL)
#define cpu_has_fpu cpu_opt(LOONGARCH_CPU_FPU) #define cpu_has_fpu cpu_opt(LOONGARCH_CPU_FPU)

View File

@ -95,40 +95,42 @@ static inline char *id_to_core_name(unsigned int id)
*/ */
#define CPU_FEATURE_CPUCFG 0 /* CPU has CPUCFG */ #define CPU_FEATURE_CPUCFG 0 /* CPU has CPUCFG */
#define CPU_FEATURE_LAM 1 /* CPU has Atomic instructions */ #define CPU_FEATURE_LAM 1 /* CPU has Atomic instructions */
#define CPU_FEATURE_SCQ 2 /* CPU has SC.Q instruction */ #define CPU_FEATURE_LAM_BH 2 /* CPU has AM{SWAP/ADD}[_DB].{B/H} instructions */
#define CPU_FEATURE_UAL 3 /* CPU supports unaligned access */ #define CPU_FEATURE_SCQ 3 /* CPU has SC.Q instruction */
#define CPU_FEATURE_FPU 4 /* CPU has FPU */ #define CPU_FEATURE_UAL 4 /* CPU supports unaligned access */
#define CPU_FEATURE_LSX 5 /* CPU has LSX (128-bit SIMD) */ #define CPU_FEATURE_FPU 5 /* CPU has FPU */
#define CPU_FEATURE_LASX 6 /* CPU has LASX (256-bit SIMD) */ #define CPU_FEATURE_LSX 6 /* CPU has LSX (128-bit SIMD) */
#define CPU_FEATURE_CRC32 7 /* CPU has CRC32 instructions */ #define CPU_FEATURE_LASX 7 /* CPU has LASX (256-bit SIMD) */
#define CPU_FEATURE_COMPLEX 8 /* CPU has Complex instructions */ #define CPU_FEATURE_CRC32 8 /* CPU has CRC32 instructions */
#define CPU_FEATURE_CRYPTO 9 /* CPU has Crypto instructions */ #define CPU_FEATURE_COMPLEX 9 /* CPU has Complex instructions */
#define CPU_FEATURE_LVZ 10 /* CPU has Virtualization extension */ #define CPU_FEATURE_CRYPTO 10 /* CPU has Crypto instructions */
#define CPU_FEATURE_LBT_X86 11 /* CPU has X86 Binary Translation */ #define CPU_FEATURE_LVZ 11 /* CPU has Virtualization extension */
#define CPU_FEATURE_LBT_ARM 12 /* CPU has ARM Binary Translation */ #define CPU_FEATURE_LBT_X86 12 /* CPU has X86 Binary Translation */
#define CPU_FEATURE_LBT_MIPS 13 /* CPU has MIPS Binary Translation */ #define CPU_FEATURE_LBT_ARM 13 /* CPU has ARM Binary Translation */
#define CPU_FEATURE_TLB 14 /* CPU has TLB */ #define CPU_FEATURE_LBT_MIPS 14 /* CPU has MIPS Binary Translation */
#define CPU_FEATURE_CSR 15 /* CPU has CSR */ #define CPU_FEATURE_TLB 15 /* CPU has TLB */
#define CPU_FEATURE_IOCSR 16 /* CPU has IOCSR */ #define CPU_FEATURE_CSR 16 /* CPU has CSR */
#define CPU_FEATURE_WATCH 17 /* CPU has watchpoint registers */ #define CPU_FEATURE_IOCSR 17 /* CPU has IOCSR */
#define CPU_FEATURE_VINT 18 /* CPU has vectored interrupts */ #define CPU_FEATURE_WATCH 18 /* CPU has watchpoint registers */
#define CPU_FEATURE_CSRIPI 19 /* CPU has CSR-IPI */ #define CPU_FEATURE_VINT 19 /* CPU has vectored interrupts */
#define CPU_FEATURE_EXTIOI 20 /* CPU has EXT-IOI */ #define CPU_FEATURE_CSRIPI 20 /* CPU has CSR-IPI */
#define CPU_FEATURE_PREFETCH 21 /* CPU has prefetch instructions */ #define CPU_FEATURE_EXTIOI 21 /* CPU has EXT-IOI */
#define CPU_FEATURE_PMP 22 /* CPU has perfermance counter */ #define CPU_FEATURE_PREFETCH 22 /* CPU has prefetch instructions */
#define CPU_FEATURE_SCALEFREQ 23 /* CPU supports cpufreq scaling */ #define CPU_FEATURE_PMP 23 /* CPU has perfermance counter */
#define CPU_FEATURE_FLATMODE 24 /* CPU has flat mode */ #define CPU_FEATURE_SCALEFREQ 24 /* CPU supports cpufreq scaling */
#define CPU_FEATURE_EIODECODE 25 /* CPU has EXTIOI interrupt pin decode mode */ #define CPU_FEATURE_FLATMODE 25 /* CPU has flat mode */
#define CPU_FEATURE_GUESTID 26 /* CPU has GuestID feature */ #define CPU_FEATURE_EIODECODE 26 /* CPU has EXTIOI interrupt pin decode mode */
#define CPU_FEATURE_HYPERVISOR 27 /* CPU has hypervisor (running in VM) */ #define CPU_FEATURE_GUESTID 27 /* CPU has GuestID feature */
#define CPU_FEATURE_PTW 28 /* CPU has hardware page table walker */ #define CPU_FEATURE_HYPERVISOR 28 /* CPU has hypervisor (running in VM) */
#define CPU_FEATURE_LSPW 29 /* CPU has LSPW (lddir/ldpte instructions) */ #define CPU_FEATURE_PTW 29 /* CPU has hardware page table walker */
#define CPU_FEATURE_MSGINT 30 /* CPU has MSG interrupt */ #define CPU_FEATURE_LSPW 30 /* CPU has LSPW (lddir/ldpte instructions) */
#define CPU_FEATURE_AVECINT 31 /* CPU has AVEC interrupt */ #define CPU_FEATURE_MSGINT 31 /* CPU has MSG interrupt */
#define CPU_FEATURE_REDIRECTINT 32 /* CPU has interrupt remapping */ #define CPU_FEATURE_AVECINT 32 /* CPU has AVEC interrupt */
#define CPU_FEATURE_REDIRECTINT 33 /* CPU has interrupt remapping */
#define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG) #define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG)
#define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM) #define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM)
#define LOONGARCH_CPU_LAM_BH BIT_ULL(CPU_FEATURE_LAM_BH)
#define LOONGARCH_CPU_SCQ BIT_ULL(CPU_FEATURE_SCQ) #define LOONGARCH_CPU_SCQ BIT_ULL(CPU_FEATURE_SCQ)
#define LOONGARCH_CPU_UAL BIT_ULL(CPU_FEATURE_UAL) #define LOONGARCH_CPU_UAL BIT_ULL(CPU_FEATURE_UAL)
#define LOONGARCH_CPU_FPU BIT_ULL(CPU_FEATURE_FPU) #define LOONGARCH_CPU_FPU BIT_ULL(CPU_FEATURE_FPU)

View File

@ -8,10 +8,19 @@
#ifndef _ASM_FIXMAP_H #ifndef _ASM_FIXMAP_H
#define _ASM_FIXMAP_H #define _ASM_FIXMAP_H
#ifdef CONFIG_HIGHMEM
#include <linux/threads.h>
#include <asm/kmap_size.h>
#endif
#define NR_FIX_BTMAPS 64 #define NR_FIX_BTMAPS 64
enum fixed_addresses { enum fixed_addresses {
FIX_HOLE, FIX_HOLE,
#ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN,
FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_MAX_IDX * NR_CPUS) - 1,
#endif
FIX_EARLYCON_MEM_BASE, FIX_EARLYCON_MEM_BASE,
__end_of_fixed_addresses __end_of_fixed_addresses
}; };
@ -25,4 +34,9 @@ extern void __set_fixmap(enum fixed_addresses idx,
#include <asm-generic/fixmap.h> #include <asm-generic/fixmap.h>
/*
* Called from pagetable_init()
*/
extern void fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base);
#endif #endif

View File

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* highmem.h: virtual kernel memory mappings for high memory
*
* Used in CONFIG_HIGHMEM systems for memory pages which
* are not addressable by direct kernel virtual addresses.
*
* Copyright (C) 2025 Loongson Technology Corporation Limited
*/
#ifndef _ASM_HIGHMEM_H
#define _ASM_HIGHMEM_H
#ifdef __KERNEL__
#include <asm/kmap_size.h>
#ifndef __ASSEMBLER__
extern pte_t *pkmap_page_table;
#define ARCH_HAS_KMAP_FLUSH_TLB
void kmap_flush_tlb(unsigned long addr);
#endif /* !__ASSEMBLER__ */
/*
* Right now we initialize only a single pte table. It can be extended
* easily, subsequent pte tables have to be allocated in one physical
* chunk of RAM.
*/
#define LAST_PKMAP 1024
#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
#define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT)
#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
#define flush_cache_kmaps() do {} while (0)
#define arch_kmap_local_post_map(vaddr, pteval) local_flush_tlb_one(vaddr)
#define arch_kmap_local_post_unmap(vaddr) local_flush_tlb_one(vaddr)
#endif /* __KERNEL__ */
#endif /* _ASM_HIGHMEM_H */

View File

@ -36,6 +36,7 @@
enum reg0i15_op { enum reg0i15_op {
break_op = 0x54, break_op = 0x54,
dbar_op = 0x70e4,
}; };
enum reg0i26_op { enum reg0i26_op {
@ -194,6 +195,10 @@ enum reg3_op {
fstxs_op = 0x7070, fstxs_op = 0x7070,
fstxd_op = 0x7078, fstxd_op = 0x7078,
scq_op = 0x70ae, scq_op = 0x70ae,
amswapb_op = 0x70b8,
amswaph_op = 0x70b9,
amaddb_op = 0x70ba,
amaddh_op = 0x70bb,
amswapw_op = 0x70c0, amswapw_op = 0x70c0,
amswapd_op = 0x70c1, amswapd_op = 0x70c1,
amaddw_op = 0x70c2, amaddw_op = 0x70c2,
@ -543,6 +548,7 @@ static inline void emit_##NAME(union loongarch_instruction *insn, \
} }
DEF_EMIT_REG0I15_FORMAT(break, break_op) DEF_EMIT_REG0I15_FORMAT(break, break_op)
DEF_EMIT_REG0I15_FORMAT(dbar, dbar_op)
/* like emit_break(imm) but returns a constant expression */ /* like emit_break(imm) but returns a constant expression */
#define __emit_break(imm) ((u32)((imm) | (break_op << 15))) #define __emit_break(imm) ((u32)((imm) | (break_op << 15)))
@ -763,6 +769,8 @@ DEF_EMIT_REG3_FORMAT(stxb, stxb_op)
DEF_EMIT_REG3_FORMAT(stxh, stxh_op) DEF_EMIT_REG3_FORMAT(stxh, stxh_op)
DEF_EMIT_REG3_FORMAT(stxw, stxw_op) DEF_EMIT_REG3_FORMAT(stxw, stxw_op)
DEF_EMIT_REG3_FORMAT(stxd, stxd_op) DEF_EMIT_REG3_FORMAT(stxd, stxd_op)
DEF_EMIT_REG3_FORMAT(amaddb, amaddb_op)
DEF_EMIT_REG3_FORMAT(amaddh, amaddh_op)
DEF_EMIT_REG3_FORMAT(amaddw, amaddw_op) DEF_EMIT_REG3_FORMAT(amaddw, amaddw_op)
DEF_EMIT_REG3_FORMAT(amaddd, amaddd_op) DEF_EMIT_REG3_FORMAT(amaddd, amaddd_op)
DEF_EMIT_REG3_FORMAT(amandw, amandw_op) DEF_EMIT_REG3_FORMAT(amandw, amandw_op)
@ -771,6 +779,8 @@ DEF_EMIT_REG3_FORMAT(amorw, amorw_op)
DEF_EMIT_REG3_FORMAT(amord, amord_op) DEF_EMIT_REG3_FORMAT(amord, amord_op)
DEF_EMIT_REG3_FORMAT(amxorw, amxorw_op) DEF_EMIT_REG3_FORMAT(amxorw, amxorw_op)
DEF_EMIT_REG3_FORMAT(amxord, amxord_op) DEF_EMIT_REG3_FORMAT(amxord, amxord_op)
DEF_EMIT_REG3_FORMAT(amswapb, amswapb_op)
DEF_EMIT_REG3_FORMAT(amswaph, amswaph_op)
DEF_EMIT_REG3_FORMAT(amswapw, amswapw_op) DEF_EMIT_REG3_FORMAT(amswapw, amswapw_op)
DEF_EMIT_REG3_FORMAT(amswapd, amswapd_op) DEF_EMIT_REG3_FORMAT(amswapd, amswapd_op)

View File

@ -4,7 +4,7 @@
static inline bool arch_irq_work_has_interrupt(void) static inline bool arch_irq_work_has_interrupt(void)
{ {
return IS_ENABLED(CONFIG_SMP); return IS_ENABLED(CONFIG_SMP) && cpu_opt(LOONGARCH_CPU_CSRIPI);
} }
#endif /* _ASM_LOONGARCH_IRQ_WORK_H */ #endif /* _ASM_LOONGARCH_IRQ_WORK_H */

View File

@ -13,6 +13,8 @@
#include <linux/stringify.h> #include <linux/stringify.h>
#include <asm/asm.h> #include <asm/asm.h>
#define HAVE_JUMP_LABEL_BATCH
#define JUMP_LABEL_NOP_SIZE 4 #define JUMP_LABEL_NOP_SIZE 4
#ifdef CONFIG_32BIT #ifdef CONFIG_32BIT

View File

@ -36,10 +36,6 @@ extern unsigned long shm_align_mask;
struct page; struct page;
struct vm_area_struct; struct vm_area_struct;
void copy_user_highpage(struct page *to, struct page *from,
unsigned long vaddr, struct vm_area_struct *vma);
#define __HAVE_ARCH_COPY_USER_HIGHPAGE
typedef struct { unsigned long pte; } pte_t; typedef struct { unsigned long pte; } pte_t;
#define pte_val(x) ((x).pte) #define pte_val(x) ((x).pte)

View File

@ -23,6 +23,10 @@
#include <asm-generic/pgtable-nop4d.h> #include <asm-generic/pgtable-nop4d.h>
#endif #endif
#ifdef CONFIG_HIGHMEM
#include <asm/highmem.h>
#endif
#if CONFIG_PGTABLE_LEVELS == 2 #if CONFIG_PGTABLE_LEVELS == 2
#define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PTRLOG)) #define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PTRLOG))
#elif CONFIG_PGTABLE_LEVELS == 3 #elif CONFIG_PGTABLE_LEVELS == 3
@ -77,7 +81,15 @@ struct vm_area_struct;
#ifdef CONFIG_32BIT #ifdef CONFIG_32BIT
#define VMALLOC_START (vm_map_base + PCI_IOSIZE + (2 * PAGE_SIZE)) #define VMALLOC_START (vm_map_base + PCI_IOSIZE + (2 * PAGE_SIZE))
#ifdef CONFIG_HIGHMEM
#define VMALLOC_END (PKMAP_BASE - (2 * PAGE_SIZE))
#else
#define VMALLOC_END (FIXADDR_START - (2 * PAGE_SIZE)) #define VMALLOC_END (FIXADDR_START - (2 * PAGE_SIZE))
#endif
#define PKMAP_BASE (PKMAP_END - (PAGE_SIZE * LAST_PKMAP))
#define PKMAP_END ((FIXADDR_START) & ~((LAST_PKMAP << PAGE_SHIFT)-1))
#endif #endif

View File

@ -80,10 +80,10 @@ BUILD_FPR_ACCESS(32)
BUILD_FPR_ACCESS(64) BUILD_FPR_ACCESS(64)
struct loongarch_fpu { struct loongarch_fpu {
union fpureg fpr[NUM_FPU_REGS];
uint64_t fcc; /* 8x8 */ uint64_t fcc; /* 8x8 */
uint32_t fcsr; uint32_t fcsr;
uint32_t ftop; uint32_t ftop;
union fpureg fpr[NUM_FPU_REGS];
}; };
struct loongarch_lbt { struct loongarch_lbt {

View File

@ -12,9 +12,6 @@
#ifndef _ASM_STACKPROTECTOR_H #ifndef _ASM_STACKPROTECTOR_H
#define _ASM_STACKPROTECTOR_H #define _ASM_STACKPROTECTOR_H
#include <linux/random.h>
#include <linux/version.h>
extern unsigned long __stack_chk_guard; extern unsigned long __stack_chk_guard;
/* /*
@ -25,11 +22,7 @@ extern unsigned long __stack_chk_guard;
*/ */
static __always_inline void boot_init_stack_canary(void) static __always_inline void boot_init_stack_canary(void)
{ {
unsigned long canary; unsigned long canary = get_random_canary();
/* Try to get a semi random initial value. */
get_random_bytes(&canary, sizeof(canary));
canary ^= LINUX_VERSION_CODE;
current->stack_canary = canary; current->stack_canary = canary;
__stack_chk_guard = current->stack_canary; __stack_chk_guard = current->stack_canary;

View File

@ -78,7 +78,11 @@ static inline void syscall_set_arguments(struct task_struct *task,
static inline int syscall_get_arch(struct task_struct *task) static inline int syscall_get_arch(struct task_struct *task)
{ {
#ifdef CONFIG_32BIT
return AUDIT_ARCH_LOONGARCH32;
#else
return AUDIT_ARCH_LOONGARCH64; return AUDIT_ARCH_LOONGARCH64;
#endif
} }
static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs) static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)

View File

@ -19,5 +19,6 @@
#define HWCAP_LOONGARCH_PTW (1 << 13) #define HWCAP_LOONGARCH_PTW (1 << 13)
#define HWCAP_LOONGARCH_LSPW (1 << 14) #define HWCAP_LOONGARCH_LSPW (1 << 14)
#define HWCAP_LOONGARCH_SCQ (1 << 15) #define HWCAP_LOONGARCH_SCQ (1 << 15)
#define HWCAP_LOONGARCH_LAM_BH (1 << 16)
#endif /* _UAPI_ASM_HWCAP_H */ #endif /* _UAPI_ASM_HWCAP_H */

View File

@ -7,6 +7,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/cpu.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/export.h> #include <linux/export.h>
@ -177,6 +178,10 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
c->options |= LOONGARCH_CPU_LAM; c->options |= LOONGARCH_CPU_LAM;
elf_hwcap |= HWCAP_LOONGARCH_LAM; elf_hwcap |= HWCAP_LOONGARCH_LAM;
} }
if (config & CPUCFG2_LAM_BH) {
c->options |= LOONGARCH_CPU_LAM_BH;
elf_hwcap |= HWCAP_LOONGARCH_LAM_BH;
}
if (config & CPUCFG2_SCQ) { if (config & CPUCFG2_SCQ) {
c->options |= LOONGARCH_CPU_SCQ; c->options |= LOONGARCH_CPU_SCQ;
elf_hwcap |= HWCAP_LOONGARCH_SCQ; elf_hwcap |= HWCAP_LOONGARCH_SCQ;
@ -402,3 +407,9 @@ void cpu_probe(void)
cpu_report(); cpu_report();
} }
ssize_t cpu_show_spectre_v1(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sysfs_emit(buf, "Mitigation: __user pointer sanitization\n");
}

View File

@ -97,7 +97,7 @@
.endm .endm
#ifdef CONFIG_32BIT #ifdef CONFIG_32BIT
.macro sc_save_fcc thread tmp0 tmp1 .macro sc_save_fcc base tmp0 tmp1
movcf2gr \tmp0, $fcc0 movcf2gr \tmp0, $fcc0
move \tmp1, \tmp0 move \tmp1, \tmp0
movcf2gr \tmp0, $fcc1 movcf2gr \tmp0, $fcc1
@ -106,7 +106,7 @@
bstrins.w \tmp1, \tmp0, 23, 16 bstrins.w \tmp1, \tmp0, 23, 16
movcf2gr \tmp0, $fcc3 movcf2gr \tmp0, $fcc3
bstrins.w \tmp1, \tmp0, 31, 24 bstrins.w \tmp1, \tmp0, 31, 24
EX st.w \tmp1, \thread, THREAD_FCC EX st.w \tmp1, \base, 0
movcf2gr \tmp0, $fcc4 movcf2gr \tmp0, $fcc4
move \tmp1, \tmp0 move \tmp1, \tmp0
movcf2gr \tmp0, $fcc5 movcf2gr \tmp0, $fcc5
@ -115,11 +115,11 @@
bstrins.w \tmp1, \tmp0, 23, 16 bstrins.w \tmp1, \tmp0, 23, 16
movcf2gr \tmp0, $fcc7 movcf2gr \tmp0, $fcc7
bstrins.w \tmp1, \tmp0, 31, 24 bstrins.w \tmp1, \tmp0, 31, 24
EX st.w \tmp1, \thread, (THREAD_FCC + 4) EX st.w \tmp1, \base, 4
.endm .endm
.macro sc_restore_fcc thread tmp0 tmp1 .macro sc_restore_fcc base tmp0 tmp1
EX ld.w \tmp0, \thread, THREAD_FCC EX ld.w \tmp0, \base, 0
bstrpick.w \tmp1, \tmp0, 7, 0 bstrpick.w \tmp1, \tmp0, 7, 0
movgr2cf $fcc0, \tmp1 movgr2cf $fcc0, \tmp1
bstrpick.w \tmp1, \tmp0, 15, 8 bstrpick.w \tmp1, \tmp0, 15, 8
@ -128,7 +128,7 @@
movgr2cf $fcc2, \tmp1 movgr2cf $fcc2, \tmp1
bstrpick.w \tmp1, \tmp0, 31, 24 bstrpick.w \tmp1, \tmp0, 31, 24
movgr2cf $fcc3, \tmp1 movgr2cf $fcc3, \tmp1
EX ld.w \tmp0, \thread, (THREAD_FCC + 4) EX ld.w \tmp0, \base, 4
bstrpick.w \tmp1, \tmp0, 7, 0 bstrpick.w \tmp1, \tmp0, 7, 0
movgr2cf $fcc4, \tmp1 movgr2cf $fcc4, \tmp1
bstrpick.w \tmp1, \tmp0, 15, 8 bstrpick.w \tmp1, \tmp0, 15, 8

View File

@ -209,6 +209,9 @@ int larch_insn_write(void *addr, u32 insn)
int ret; int ret;
unsigned long flags = 0; unsigned long flags = 0;
if ((unsigned long)addr & 3)
return -EINVAL;
raw_spin_lock_irqsave(&patch_lock, flags); raw_spin_lock_irqsave(&patch_lock, flags);
ret = copy_to_kernel_nofault(addr, &insn, LOONGARCH_INSN_SIZE); ret = copy_to_kernel_nofault(addr, &insn, LOONGARCH_INSN_SIZE);
raw_spin_unlock_irqrestore(&patch_lock, flags); raw_spin_unlock_irqrestore(&patch_lock, flags);
@ -221,9 +224,6 @@ int larch_insn_patch_text(void *addr, u32 insn)
int ret; int ret;
u32 *tp = addr; u32 *tp = addr;
if ((unsigned long)tp & 3)
return -EINVAL;
ret = larch_insn_write(tp, insn); ret = larch_insn_write(tp, insn);
if (!ret) if (!ret)
flush_icache_range((unsigned long)tp, flush_icache_range((unsigned long)tp,

View File

@ -6,9 +6,10 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <asm/cacheflush.h>
#include <asm/inst.h> #include <asm/inst.h>
void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type) bool arch_jump_label_transform_queue(struct jump_entry *entry, enum jump_label_type type)
{ {
u32 insn; u32 insn;
void *addr = (void *)jump_entry_code(entry); void *addr = (void *)jump_entry_code(entry);
@ -18,5 +19,12 @@ void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type ty
else else
insn = larch_insn_gen_nop(); insn = larch_insn_gen_nop();
larch_insn_patch_text(addr, insn); larch_insn_write(addr, insn);
return true;
}
void arch_jump_label_transform_apply(void)
{
flush_icache_all();
} }

View File

@ -64,6 +64,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_puts(m, " cpucfg"); seq_puts(m, " cpucfg");
if (cpu_has_lam) if (cpu_has_lam)
seq_puts(m, " lam"); seq_puts(m, " lam");
if (cpu_has_lam_bh)
seq_puts(m, " lam_bh");
if (cpu_has_scq) if (cpu_has_scq)
seq_puts(m, " scq"); seq_puts(m, " scq");
if (cpu_has_ual) if (cpu_has_ual)

View File

@ -136,6 +136,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
return 0; return 0;
} }
dst->thread.fpu.fcsr = src->thread.fpu.fcsr;
if (!used_math()) if (!used_math())
memcpy(dst, src, offsetof(struct task_struct, thread.fpu.fpr)); memcpy(dst, src, offsetof(struct task_struct, thread.fpu.fpr));
else else

View File

@ -128,24 +128,28 @@ static inline __init unsigned long get_random_boot(void)
static int __init nokaslr(char *p) static int __init nokaslr(char *p)
{ {
pr_info("KASLR is disabled.\n"); return 0; /* Just silence the boot warning */
return 0; /* Print a notice and silence the boot warning */
} }
early_param("nokaslr", nokaslr); early_param("nokaslr", nokaslr);
#define KASLR_DISABLED_MESSAGE "KASLR is disabled by %s in %s cmdline.\n"
static inline __init bool kaslr_disabled(void) static inline __init bool kaslr_disabled(void)
{ {
char *str; char *str;
const char *builtin_cmdline = CONFIG_CMDLINE; const char *builtin_cmdline = CONFIG_CMDLINE;
str = strstr(builtin_cmdline, "nokaslr"); str = strstr(builtin_cmdline, "nokaslr");
if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) {
pr_info(KASLR_DISABLED_MESSAGE, "\'nokaslr\'", "built-in");
return true; return true;
}
str = strstr(boot_command_line, "nokaslr"); str = strstr(boot_command_line, "nokaslr");
if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) {
pr_info(KASLR_DISABLED_MESSAGE, "\'nokaslr\'", "bootloader");
return true; return true;
}
#ifdef CONFIG_HIBERNATION #ifdef CONFIG_HIBERNATION
str = strstr(builtin_cmdline, "nohibernate"); str = strstr(builtin_cmdline, "nohibernate");
@ -165,17 +169,23 @@ static inline __init bool kaslr_disabled(void)
return false; return false;
str = strstr(builtin_cmdline, "resume="); str = strstr(builtin_cmdline, "resume=");
if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) {
pr_info(KASLR_DISABLED_MESSAGE, "\'resume=\'", "built-in");
return true; return true;
}
str = strstr(boot_command_line, "resume="); str = strstr(boot_command_line, "resume=");
if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) {
pr_info(KASLR_DISABLED_MESSAGE, "\'resume=\'", "bootloader");
return true; return true;
}
#endif #endif
str = strstr(boot_command_line, "kexec_file"); str = strstr(boot_command_line, "kexec_file");
if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) {
pr_info(KASLR_DISABLED_MESSAGE, "\'kexec_file\'", "bootloader");
return true; return true;
}
return false; return false;
} }

View File

@ -9,6 +9,7 @@
#include <linux/entry-common.h> #include <linux/entry-common.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/nospec.h>
#include <linux/objtool.h> #include <linux/objtool.h>
#include <linux/randomize_kstack.h> #include <linux/randomize_kstack.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
@ -74,7 +75,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs)
add_random_kstack_offset(); add_random_kstack_offset();
if (nr < NR_syscalls) { if (nr < NR_syscalls) {
syscall_fn = sys_call_table[nr]; syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)];
regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6],
regs->regs[7], regs->regs[8], regs->regs[9]); regs->regs[7], regs->regs[8], regs->regs[9]);
} }

View File

@ -6,7 +6,12 @@
#define PAGE_SIZE _PAGE_SIZE #define PAGE_SIZE _PAGE_SIZE
#define RO_EXCEPTION_TABLE_ALIGN 4 #define RO_EXCEPTION_TABLE_ALIGN 4
#define PHYSADDR_MASK 0xffffffffffff /* 48-bit */
#ifdef CONFIG_32BIT
#define PHYSADDR_MASK 0x1fffffff /* 29-bit */
#else
#define PHYSADDR_MASK 0xffffffffffff /* 48-bit */
#endif
/* /*
* Put .bss..swapper_pg_dir as the first thing in .bss. This will * Put .bss..swapper_pg_dir as the first thing in .bss. This will

View File

@ -19,7 +19,7 @@ if VIRTUALIZATION
config KVM config KVM
tristate "Kernel-based Virtual Machine (KVM) support" tristate "Kernel-based Virtual Machine (KVM) support"
depends on AS_HAS_LVZ_EXTENSION depends on AS_HAS_LVZ_EXTENSION && 64BIT
select HAVE_KVM_DIRTY_RING_ACQ_REL select HAVE_KVM_DIRTY_RING_ACQ_REL
select HAVE_KVM_IRQ_ROUTING select HAVE_KVM_IRQ_ROUTING
select HAVE_KVM_IRQCHIP select HAVE_KVM_IRQCHIP

View File

@ -3,8 +3,10 @@
# Makefile for LoongArch-specific library files. # Makefile for LoongArch-specific library files.
# #
lib-y += delay.o memset.o memcpy.o memmove.o \ lib-y += delay.o clear_user.o copy_user.o dump_tlb.o unaligned.o
clear_user.o copy_user.o csum.o dump_tlb.o unaligned.o
lib-$(CONFIG_32BIT) += bswapsi.o bswapdi.o
lib-$(CONFIG_64BIT) += memset.o memcpy.o memmove.o csum.o
obj-$(CONFIG_ARCH_SUPPORTS_INT128) += tishift.o obj-$(CONFIG_ARCH_SUPPORTS_INT128) += tishift.o

View File

@ -7,6 +7,7 @@ obj-y += init.o cache.o tlb.o tlbex.o extable.o \
fault.o ioremap.o maccess.o mmap.o pgtable.o \ fault.o ioremap.o maccess.o mmap.o pgtable.o \
page.o pageattr.o page.o pageattr.o
obj-$(CONFIG_HIGHMEM) += highmem.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_KASAN) += kasan_init.o obj-$(CONFIG_KASAN) += kasan_init.o

View File

@ -31,16 +31,6 @@ void cache_error_setup(void)
set_merr_handler(0x0, &except_vec_cex, 0x80); set_merr_handler(0x0, &except_vec_cex, 0x80);
} }
/*
* LoongArch maintains ICache/DCache coherency by hardware,
* we just need "ibar" to avoid instruction hazard here.
*/
void local_flush_icache_range(unsigned long start, unsigned long end)
{
asm volatile ("\tibar 0\n"::);
}
EXPORT_SYMBOL(local_flush_icache_range);
static void flush_cache_leaf(unsigned int leaf) static void flush_cache_leaf(unsigned int leaf)
{ {
int i, j, nr_nodes; int i, j, nr_nodes;

View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/init.h>
#include <linux/export.h>
#include <linux/highmem.h>
#include <asm/fixmap.h>
#include <asm/tlbflush.h>
void kmap_flush_tlb(unsigned long addr)
{
flush_tlb_one(addr);
}
EXPORT_SYMBOL(kmap_flush_tlb);

View File

@ -36,20 +36,6 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/tlb.h> #include <asm/tlb.h>
void copy_user_highpage(struct page *to, struct page *from,
unsigned long vaddr, struct vm_area_struct *vma)
{
void *vfrom, *vto;
vfrom = kmap_local_page(from);
vto = kmap_local_page(to);
copy_page(vto, vfrom);
kunmap_local(vfrom);
kunmap_local(vto);
/* Make sure this page is cleared on other CPU's too before using it */
smp_wmb();
}
int __ref page_is_ram(unsigned long pfn) int __ref page_is_ram(unsigned long pfn)
{ {
unsigned long addr = PFN_PHYS(pfn); unsigned long addr = PFN_PHYS(pfn);
@ -63,6 +49,9 @@ void __init arch_zone_limits_init(unsigned long *max_zone_pfns)
max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
#endif #endif
max_zone_pfns[ZONE_NORMAL] = max_low_pfn; max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
#ifdef CONFIG_HIGHMEM
max_zone_pfns[ZONE_HIGHMEM] = max_pfn;
#endif
} }
void __ref free_initmem(void) void __ref free_initmem(void)
@ -70,6 +59,50 @@ void __ref free_initmem(void)
free_initmem_default(POISON_FREE_INITMEM); free_initmem_default(POISON_FREE_INITMEM);
} }
#ifdef CONFIG_HIGHMEM
void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
int i, j, k;
int ptrs_per_pgd;
unsigned long vaddr;
vaddr = start;
i = pgd_index(vaddr);
j = pud_index(vaddr);
k = pmd_index(vaddr);
pgd = pgd_base + i;
ptrs_per_pgd = min((1 << (BITS_PER_LONG - PGDIR_SHIFT)), PTRS_PER_PGD);
for ( ; (i < ptrs_per_pgd) && (vaddr < end); pgd++, i++) {
pud = (pud_t *)pgd;
for ( ; (j < PTRS_PER_PUD) && (vaddr < end); pud++, j++) {
pmd = (pmd_t *)pud;
for (; (k < PTRS_PER_PMD) && (vaddr < end); pmd++, k++) {
if (pmd_none(*pmd)) {
pte = (pte_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
if (!pte)
panic("%s: Failed to allocate %lu bytes align=%lx\n",
__func__, PAGE_SIZE, PAGE_SIZE);
kernel_pte_init(pte);
set_pmd(pmd, __pmd((unsigned long)pte));
BUG_ON(pte != pte_offset_kernel(pmd, 0));
}
vaddr += PMD_SIZE;
}
k = 0;
}
j = 0;
}
}
#endif
#ifdef CONFIG_MEMORY_HOTPLUG #ifdef CONFIG_MEMORY_HOTPLUG
int arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *params) int arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *params)
{ {

View File

@ -5,6 +5,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/fixmap.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
@ -144,6 +145,15 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
void __init pagetable_init(void) void __init pagetable_init(void)
{ {
#ifdef CONFIG_HIGHMEM
unsigned long vaddr;
pgd_t *pgd;
p4d_t *p4d;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
#endif
/* Initialize the entire pgd. */ /* Initialize the entire pgd. */
pgd_init(swapper_pg_dir); pgd_init(swapper_pg_dir);
pgd_init(invalid_pg_dir); pgd_init(invalid_pg_dir);
@ -153,4 +163,21 @@ void __init pagetable_init(void)
#ifndef __PAGETABLE_PMD_FOLDED #ifndef __PAGETABLE_PMD_FOLDED
pmd_init(invalid_pmd_table); pmd_init(invalid_pmd_table);
#endif #endif
#ifdef CONFIG_HIGHMEM
/* Permanent kmaps */
vaddr = PKMAP_BASE;
fixrange_init(vaddr & PMD_MASK, vaddr + PAGE_SIZE * LAST_PKMAP, swapper_pg_dir);
pgd = swapper_pg_dir + pgd_index(vaddr);
p4d = p4d_offset(pgd, vaddr);
pud = pud_offset(p4d, vaddr);
pmd = pmd_offset(pud, vaddr);
pte = pte_offset_kernel(pmd, vaddr);
pkmap_page_table = pte;
/* Fixed mappings */
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1);
fixrange_init(vaddr & PMD_MASK, vaddr + FIXADDR_SIZE, swapper_pg_dir);
#endif
} }

View File

@ -344,7 +344,13 @@ toofar:
#undef jmp_offset #undef jmp_offset
} }
static void emit_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx) static void emit_store_stack_imm64(struct jit_ctx *ctx, int reg, int stack_off, u64 imm64)
{
move_imm(ctx, reg, imm64, false);
emit_insn(ctx, std, reg, LOONGARCH_GPR_FP, stack_off);
}
static int emit_atomic_rmw(const struct bpf_insn *insn, struct jit_ctx *ctx)
{ {
const u8 t1 = LOONGARCH_GPR_T1; const u8 t1 = LOONGARCH_GPR_T1;
const u8 t2 = LOONGARCH_GPR_T2; const u8 t2 = LOONGARCH_GPR_T2;
@ -363,10 +369,28 @@ static void emit_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
switch (imm) { switch (imm) {
/* lock *(size *)(dst + off) <op>= src */ /* lock *(size *)(dst + off) <op>= src */
case BPF_ADD: case BPF_ADD:
if (isdw) switch (BPF_SIZE(insn->code)) {
emit_insn(ctx, amaddd, t2, t1, src); case BPF_B:
else if (!cpu_has_lam_bh) {
pr_err_once("bpf-jit: amadd.b instruction is not supported\n");
return -EINVAL;
}
emit_insn(ctx, amaddb, t2, t1, src);
break;
case BPF_H:
if (!cpu_has_lam_bh) {
pr_err_once("bpf-jit: amadd.h instruction is not supported\n");
return -EINVAL;
}
emit_insn(ctx, amaddh, t2, t1, src);
break;
case BPF_W:
emit_insn(ctx, amaddw, t2, t1, src); emit_insn(ctx, amaddw, t2, t1, src);
break;
case BPF_DW:
emit_insn(ctx, amaddd, t2, t1, src);
break;
}
break; break;
case BPF_AND: case BPF_AND:
if (isdw) if (isdw)
@ -388,11 +412,30 @@ static void emit_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
break; break;
/* src = atomic_fetch_<op>(dst + off, src) */ /* src = atomic_fetch_<op>(dst + off, src) */
case BPF_ADD | BPF_FETCH: case BPF_ADD | BPF_FETCH:
if (isdw) { switch (BPF_SIZE(insn->code)) {
emit_insn(ctx, amaddd, src, t1, t3); case BPF_B:
} else { if (!cpu_has_lam_bh) {
pr_err_once("bpf-jit: amadd.b instruction is not supported\n");
return -EINVAL;
}
emit_insn(ctx, amaddb, src, t1, t3);
emit_zext_32(ctx, src, true);
break;
case BPF_H:
if (!cpu_has_lam_bh) {
pr_err_once("bpf-jit: amadd.h instruction is not supported\n");
return -EINVAL;
}
emit_insn(ctx, amaddh, src, t1, t3);
emit_zext_32(ctx, src, true);
break;
case BPF_W:
emit_insn(ctx, amaddw, src, t1, t3); emit_insn(ctx, amaddw, src, t1, t3);
emit_zext_32(ctx, src, true); emit_zext_32(ctx, src, true);
break;
case BPF_DW:
emit_insn(ctx, amaddd, src, t1, t3);
break;
} }
break; break;
case BPF_AND | BPF_FETCH: case BPF_AND | BPF_FETCH:
@ -421,11 +464,30 @@ static void emit_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
break; break;
/* src = atomic_xchg(dst + off, src); */ /* src = atomic_xchg(dst + off, src); */
case BPF_XCHG: case BPF_XCHG:
if (isdw) { switch (BPF_SIZE(insn->code)) {
emit_insn(ctx, amswapd, src, t1, t3); case BPF_B:
} else { if (!cpu_has_lam_bh) {
pr_err_once("bpf-jit: amswap.b instruction is not supported\n");
return -EINVAL;
}
emit_insn(ctx, amswapb, src, t1, t3);
emit_zext_32(ctx, src, true);
break;
case BPF_H:
if (!cpu_has_lam_bh) {
pr_err_once("bpf-jit: amswap.h instruction is not supported\n");
return -EINVAL;
}
emit_insn(ctx, amswaph, src, t1, t3);
emit_zext_32(ctx, src, true);
break;
case BPF_W:
emit_insn(ctx, amswapw, src, t1, t3); emit_insn(ctx, amswapw, src, t1, t3);
emit_zext_32(ctx, src, true); emit_zext_32(ctx, src, true);
break;
case BPF_DW:
emit_insn(ctx, amswapd, src, t1, t3);
break;
} }
break; break;
/* r0 = atomic_cmpxchg(dst + off, r0, src); */ /* r0 = atomic_cmpxchg(dst + off, r0, src); */
@ -448,7 +510,105 @@ static void emit_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
emit_zext_32(ctx, r0, true); emit_zext_32(ctx, r0, true);
} }
break; break;
default:
pr_err_once("bpf-jit: invalid atomic read-modify-write opcode %02x\n", imm);
return -EINVAL;
} }
return 0;
}
static int emit_atomic_ld_st(const struct bpf_insn *insn, struct jit_ctx *ctx)
{
const u8 t1 = LOONGARCH_GPR_T1;
const u8 src = regmap[insn->src_reg];
const u8 dst = regmap[insn->dst_reg];
const s16 off = insn->off;
const s32 imm = insn->imm;
switch (imm) {
/* dst_reg = load_acquire(src_reg + off16) */
case BPF_LOAD_ACQ:
switch (BPF_SIZE(insn->code)) {
case BPF_B:
if (is_signed_imm12(off)) {
emit_insn(ctx, ldbu, dst, src, off);
} else {
move_imm(ctx, t1, off, false);
emit_insn(ctx, ldxbu, dst, src, t1);
}
break;
case BPF_H:
if (is_signed_imm12(off)) {
emit_insn(ctx, ldhu, dst, src, off);
} else {
move_imm(ctx, t1, off, false);
emit_insn(ctx, ldxhu, dst, src, t1);
}
break;
case BPF_W:
if (is_signed_imm12(off)) {
emit_insn(ctx, ldwu, dst, src, off);
} else {
move_imm(ctx, t1, off, false);
emit_insn(ctx, ldxwu, dst, src, t1);
}
break;
case BPF_DW:
if (is_signed_imm12(off)) {
emit_insn(ctx, ldd, dst, src, off);
} else {
move_imm(ctx, t1, off, false);
emit_insn(ctx, ldxd, dst, src, t1);
}
break;
}
emit_insn(ctx, dbar, 0b10100);
break;
/* store_release(dst_reg + off16, src_reg) */
case BPF_STORE_REL:
emit_insn(ctx, dbar, 0b10010);
switch (BPF_SIZE(insn->code)) {
case BPF_B:
if (is_signed_imm12(off)) {
emit_insn(ctx, stb, src, dst, off);
} else {
move_imm(ctx, t1, off, false);
emit_insn(ctx, stxb, src, dst, t1);
}
break;
case BPF_H:
if (is_signed_imm12(off)) {
emit_insn(ctx, sth, src, dst, off);
} else {
move_imm(ctx, t1, off, false);
emit_insn(ctx, stxh, src, dst, t1);
}
break;
case BPF_W:
if (is_signed_imm12(off)) {
emit_insn(ctx, stw, src, dst, off);
} else {
move_imm(ctx, t1, off, false);
emit_insn(ctx, stxw, src, dst, t1);
}
break;
case BPF_DW:
if (is_signed_imm12(off)) {
emit_insn(ctx, std, src, dst, off);
} else {
move_imm(ctx, t1, off, false);
emit_insn(ctx, stxd, src, dst, t1);
}
break;
}
break;
default:
pr_err_once("bpf-jit: invalid atomic load/store opcode %02x\n", imm);
return -EINVAL;
}
return 0;
} }
static bool is_signed_bpf_cond(u8 cond) static bool is_signed_bpf_cond(u8 cond)
@ -1254,9 +1414,17 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
return ret; return ret;
break; break;
/* Atomics */
case BPF_STX | BPF_ATOMIC | BPF_B:
case BPF_STX | BPF_ATOMIC | BPF_H:
case BPF_STX | BPF_ATOMIC | BPF_W: case BPF_STX | BPF_ATOMIC | BPF_W:
case BPF_STX | BPF_ATOMIC | BPF_DW: case BPF_STX | BPF_ATOMIC | BPF_DW:
emit_atomic(insn, ctx); if (!bpf_atomic_is_load_store(insn))
ret = emit_atomic_rmw(insn, ctx);
else
ret = emit_atomic_ld_st(insn, ctx);
if (ret)
return ret;
break; break;
/* Speculation barrier */ /* Speculation barrier */
@ -1466,26 +1634,46 @@ int bpf_arch_text_invalidate(void *dst, size_t len)
return ret; return ret;
} }
static void store_args(struct jit_ctx *ctx, int nargs, int args_off) static void store_args(struct jit_ctx *ctx, int nr_arg_slots, int args_off)
{ {
int i; int i;
for (i = 0; i < nargs; i++) { for (i = 0; i < nr_arg_slots; i++) {
emit_insn(ctx, std, LOONGARCH_GPR_A0 + i, LOONGARCH_GPR_FP, -args_off); if (i < LOONGARCH_MAX_REG_ARGS)
emit_insn(ctx, std, LOONGARCH_GPR_A0 + i, LOONGARCH_GPR_FP, -args_off);
else {
/* Skip slots for T0 and FP of traced function */
emit_insn(ctx, ldd, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP,
16 + (i - LOONGARCH_MAX_REG_ARGS) * 8);
emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -args_off);
}
args_off -= 8; args_off -= 8;
} }
} }
static void restore_args(struct jit_ctx *ctx, int nargs, int args_off) static void restore_args(struct jit_ctx *ctx, int nr_reg_args, int args_off)
{ {
int i; int i;
for (i = 0; i < nargs; i++) { for (i = 0; i < nr_reg_args; i++) {
emit_insn(ctx, ldd, LOONGARCH_GPR_A0 + i, LOONGARCH_GPR_FP, -args_off); emit_insn(ctx, ldd, LOONGARCH_GPR_A0 + i, LOONGARCH_GPR_FP, -args_off);
args_off -= 8; args_off -= 8;
} }
} }
static void restore_stk_args(struct jit_ctx *ctx, int nr_stk_args, int args_off, int stk_args_off)
{
int i;
for (i = 0; i < nr_stk_args; i++) {
emit_insn(ctx, ldd, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP,
-(args_off - LOONGARCH_MAX_REG_ARGS * 8));
emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -stk_args_off);
args_off -= 8;
stk_args_off -= 8;
}
}
static int invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_link *l, static int invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_link *l,
int args_off, int retval_off, int run_ctx_off, bool save_ret) int args_off, int retval_off, int run_ctx_off, bool save_ret)
{ {
@ -1494,12 +1682,11 @@ static int invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_link *l,
struct bpf_prog *p = l->link.prog; struct bpf_prog *p = l->link.prog;
int cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie); int cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
if (l->cookie) { if (l->cookie)
move_imm(ctx, LOONGARCH_GPR_T1, l->cookie, false); emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1,
emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -run_ctx_off + cookie_off); -run_ctx_off + cookie_off, l->cookie);
} else { else
emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -run_ctx_off + cookie_off); emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -run_ctx_off + cookie_off);
}
/* arg1: prog */ /* arg1: prog */
move_imm(ctx, LOONGARCH_GPR_A0, (const s64)p, false); move_imm(ctx, LOONGARCH_GPR_A0, (const s64)p, false);
@ -1550,18 +1737,27 @@ static int invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_link *l,
return ret; return ret;
} }
static void invoke_bpf_mod_ret(struct jit_ctx *ctx, struct bpf_tramp_links *tl, static int invoke_bpf(struct jit_ctx *ctx, struct bpf_tramp_links *tl,
int args_off, int retval_off, int run_ctx_off, u32 **branches) int args_off, int retval_off, int run_ctx_off,
int func_meta_off, bool save_ret, u64 func_meta, int cookie_off)
{ {
int i; int i, cur_cookie = (cookie_off - args_off) / 8;
emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -retval_off);
for (i = 0; i < tl->nr_links; i++) { for (i = 0; i < tl->nr_links; i++) {
invoke_bpf_prog(ctx, tl->links[i], args_off, retval_off, run_ctx_off, true); int err;
emit_insn(ctx, ldd, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -retval_off);
branches[i] = (u32 *)ctx->image + ctx->idx; if (bpf_prog_calls_session_cookie(tl->links[i])) {
emit_insn(ctx, nop); u64 meta = func_meta | ((u64)cur_cookie << BPF_TRAMP_COOKIE_INDEX_SHIFT);
emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -func_meta_off, meta);
cur_cookie--;
}
err = invoke_bpf_prog(ctx, tl->links[i], args_off, retval_off, run_ctx_off, save_ret);
if (err)
return err;
} }
return 0;
} }
void *arch_alloc_bpf_trampoline(unsigned int size) void *arch_alloc_bpf_trampoline(unsigned int size)
@ -1615,8 +1811,10 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
void *func_addr, u32 flags) void *func_addr, u32 flags)
{ {
int i, ret, save_ret; int i, ret, save_ret;
int stack_size, nargs; int cookie_cnt, cookie_off;
int retval_off, args_off, nargs_off, ip_off, run_ctx_off, sreg_off, tcc_ptr_off; int stack_size, args_off, stk_args_off, nr_arg_slots = 0;
int retval_off, func_meta_off, ip_off, run_ctx_off, sreg_off, tcc_ptr_off;
unsigned long long func_meta;
bool is_struct_ops = flags & BPF_TRAMP_F_INDIRECT; bool is_struct_ops = flags & BPF_TRAMP_F_INDIRECT;
void *orig_call = func_addr; void *orig_call = func_addr;
struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY]; struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY];
@ -1634,30 +1832,44 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
* FP - 16 [ FP of traced func ] frame pointer of traced * FP - 16 [ FP of traced func ] frame pointer of traced
* function * function
* *
* FP - retval_off [ return value ] BPF_TRAMP_F_CALL_ORIG or * FP - retval_off [ return value ] BPF_TRAMP_F_CALL_ORIG or
* BPF_TRAMP_F_RET_FENTRY_RET * BPF_TRAMP_F_RET_FENTRY_RET
* [ argN ] * [ arg regN ]
* [ ... ] * [ ... ]
* FP - args_off [ arg1 ] * FP - args_off [ arg reg1 ]
* *
* FP - nargs_off [ regs count ] * FP - func_meta_off [ regs count, etc ]
* *
* FP - ip_off [ traced func ] BPF_TRAMP_F_IP_ARG * FP - ip_off [ traced func ] BPF_TRAMP_F_IP_ARG
* *
* FP - run_ctx_off [ bpf_tramp_run_ctx ] * [ stack cookie N ]
* [ ... ]
* FP - cookie_off [ stack cookie 1 ]
* *
* FP - sreg_off [ callee saved reg ] * FP - run_ctx_off [ bpf_tramp_run_ctx ]
* *
* FP - tcc_ptr_off [ tail_call_cnt_ptr ] * FP - sreg_off [ callee saved reg ]
*
* FP - tcc_ptr_off [ tail_call_cnt_ptr ]
*
* [ stack_argN ]
* [ ... ]
* FP - stk_args_off [ stack_arg1 ] BPF_TRAMP_F_CALL_ORIG
*/ */
if (m->nr_args > LOONGARCH_MAX_REG_ARGS) if (m->nr_args > MAX_BPF_FUNC_ARGS)
return -ENOTSUPP; return -ENOTSUPP;
/* FIXME: No support of struct argument */ /* Extra registers for struct arguments */
for (i = 0; i < m->nr_args; i++) { for (i = 0; i < m->nr_args; i++) {
if (m->arg_flags[i] & BTF_FMODEL_STRUCT_ARG) /*
return -ENOTSUPP; * The struct argument size is at most 16 bytes,
* enforced by the verifier. The struct argument
* may be passed in a pair of registers if its
* size is more than 8 bytes and no more than 16
* bytes.
*/
nr_arg_slots += round_up(m->arg_size[i], 8) / 8;
} }
if (flags & (BPF_TRAMP_F_ORIG_STACK | BPF_TRAMP_F_SHARE_IPMODIFY)) if (flags & (BPF_TRAMP_F_ORIG_STACK | BPF_TRAMP_F_SHARE_IPMODIFY))
@ -1673,13 +1885,12 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
retval_off = stack_size; retval_off = stack_size;
/* Room of trampoline frame to store args */ /* Room of trampoline frame to store args */
nargs = m->nr_args; stack_size += nr_arg_slots * 8;
stack_size += nargs * 8;
args_off = stack_size; args_off = stack_size;
/* Room of trampoline frame to store args number */ /* Room of function metadata, such as regs count */
stack_size += 8; stack_size += 8;
nargs_off = stack_size; func_meta_off = stack_size;
/* Room of trampoline frame to store ip address */ /* Room of trampoline frame to store ip address */
if (flags & BPF_TRAMP_F_IP_ARG) { if (flags & BPF_TRAMP_F_IP_ARG) {
@ -1687,6 +1898,12 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
ip_off = stack_size; ip_off = stack_size;
} }
cookie_cnt = bpf_fsession_cookie_cnt(tlinks);
/* Room for session cookies */
stack_size += cookie_cnt * 8;
cookie_off = stack_size;
/* Room of trampoline frame to store struct bpf_tramp_run_ctx */ /* Room of trampoline frame to store struct bpf_tramp_run_ctx */
stack_size += round_up(sizeof(struct bpf_tramp_run_ctx), 8); stack_size += round_up(sizeof(struct bpf_tramp_run_ctx), 8);
run_ctx_off = stack_size; run_ctx_off = stack_size;
@ -1700,8 +1917,14 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
tcc_ptr_off = stack_size; tcc_ptr_off = stack_size;
} }
if ((flags & BPF_TRAMP_F_CALL_ORIG) && (nr_arg_slots - LOONGARCH_MAX_REG_ARGS > 0))
stack_size += (nr_arg_slots - LOONGARCH_MAX_REG_ARGS) * 8;
stack_size = round_up(stack_size, 16); stack_size = round_up(stack_size, 16);
/* Room for args on stack must be at the top of stack */
stk_args_off = stack_size;
if (is_struct_ops) { if (is_struct_ops) {
/* /*
* For the trampoline called directly, just handle * For the trampoline called directly, just handle
@ -1737,17 +1960,24 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
emit_insn(ctx, std, LOONGARCH_GPR_S1, LOONGARCH_GPR_FP, -sreg_off); emit_insn(ctx, std, LOONGARCH_GPR_S1, LOONGARCH_GPR_FP, -sreg_off);
/* store ip address of the traced function */ /* store ip address of the traced function */
if (flags & BPF_TRAMP_F_IP_ARG) { if (flags & BPF_TRAMP_F_IP_ARG)
move_imm(ctx, LOONGARCH_GPR_T1, (const s64)func_addr, false); emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -ip_off, (u64)func_addr);
emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -ip_off);
/* store arg regs count */
func_meta = nr_arg_slots;
emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -func_meta_off, func_meta);
store_args(ctx, nr_arg_slots, args_off);
if (bpf_fsession_cnt(tlinks)) {
/* clear all session cookies' value */
for (i = 0; i < cookie_cnt; i++)
emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -cookie_off + 8 * i);
/* clear return value to make sure fentry always get 0 */
emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -retval_off);
} }
/* store nargs number */
move_imm(ctx, LOONGARCH_GPR_T1, nargs, false);
emit_insn(ctx, std, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -nargs_off);
store_args(ctx, nargs, args_off);
/* To traced function */ /* To traced function */
/* Ftrace jump skips 2 NOP instructions */ /* Ftrace jump skips 2 NOP instructions */
if (is_kernel_text((unsigned long)orig_call) || if (is_kernel_text((unsigned long)orig_call) ||
@ -1764,9 +1994,9 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
return ret; return ret;
} }
for (i = 0; i < fentry->nr_links; i++) { if (fentry->nr_links) {
ret = invoke_bpf_prog(ctx, fentry->links[i], args_off, retval_off, ret = invoke_bpf(ctx, fentry, args_off, retval_off, run_ctx_off, func_meta_off,
run_ctx_off, flags & BPF_TRAMP_F_RET_FENTRY_RET); flags & BPF_TRAMP_F_RET_FENTRY_RET, func_meta, cookie_off);
if (ret) if (ret)
return ret; return ret;
} }
@ -1775,11 +2005,21 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
if (!branches) if (!branches)
return -ENOMEM; return -ENOMEM;
invoke_bpf_mod_ret(ctx, fmod_ret, args_off, retval_off, run_ctx_off, branches); emit_insn(ctx, std, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_FP, -retval_off);
for (i = 0; i < fmod_ret->nr_links; i++) {
ret = invoke_bpf_prog(ctx, fmod_ret->links[i],
args_off, retval_off, run_ctx_off, true);
if (ret)
goto out;
emit_insn(ctx, ldd, LOONGARCH_GPR_T1, LOONGARCH_GPR_FP, -retval_off);
branches[i] = (u32 *)ctx->image + ctx->idx;
emit_insn(ctx, nop);
}
} }
if (flags & BPF_TRAMP_F_CALL_ORIG) { if (flags & BPF_TRAMP_F_CALL_ORIG) {
restore_args(ctx, m->nr_args, args_off); restore_args(ctx, min_t(int, nr_arg_slots, LOONGARCH_MAX_REG_ARGS), args_off);
restore_stk_args(ctx, nr_arg_slots - LOONGARCH_MAX_REG_ARGS, args_off, stk_args_off);
if (flags & BPF_TRAMP_F_TAIL_CALL_CTX) if (flags & BPF_TRAMP_F_TAIL_CALL_CTX)
emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_FP, -tcc_ptr_off); emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_FP, -tcc_ptr_off);
@ -1800,8 +2040,14 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
*branches[i] = larch_insn_gen_bne(LOONGARCH_GPR_T1, LOONGARCH_GPR_ZERO, offset); *branches[i] = larch_insn_gen_bne(LOONGARCH_GPR_T1, LOONGARCH_GPR_ZERO, offset);
} }
for (i = 0; i < fexit->nr_links; i++) { /* Set "is_return" flag for fsession */
ret = invoke_bpf_prog(ctx, fexit->links[i], args_off, retval_off, run_ctx_off, false); func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT);
if (bpf_fsession_cnt(tlinks))
emit_store_stack_imm64(ctx, LOONGARCH_GPR_T1, -func_meta_off, func_meta);
if (fexit->nr_links) {
ret = invoke_bpf(ctx, fexit, args_off, retval_off, run_ctx_off,
func_meta_off, false, func_meta, cookie_off);
if (ret) if (ret)
goto out; goto out;
} }
@ -1815,7 +2061,7 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
} }
if (flags & BPF_TRAMP_F_RESTORE_REGS) if (flags & BPF_TRAMP_F_RESTORE_REGS)
restore_args(ctx, m->nr_args, args_off); restore_args(ctx, min_t(int, nr_arg_slots, LOONGARCH_MAX_REG_ARGS), args_off);
if (save_ret) { if (save_ret) {
emit_insn(ctx, ldd, regmap[BPF_REG_0], LOONGARCH_GPR_FP, -(retval_off - 8)); emit_insn(ctx, ldd, regmap[BPF_REG_0], LOONGARCH_GPR_FP, -(retval_off - 8));
@ -2111,6 +2357,11 @@ bool bpf_jit_supports_arena(void)
return true; return true;
} }
bool bpf_jit_supports_fsession(void)
{
return true;
}
/* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */ /* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */
bool bpf_jit_supports_subprog_tailcalls(void) bool bpf_jit_supports_subprog_tailcalls(void)
{ {

View File

@ -96,6 +96,7 @@ zboot-obj-$(CONFIG_KERNEL_ZSTD) := zboot-decompress-zstd.o lib-xxhash.o
CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd
zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o
zboot-obj-$(CONFIG_LOONGARCH) += lib-clz_ctz.o lib-ashldi3.o
lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y) lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)
lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o

View File

@ -187,7 +187,7 @@ config VMD
config PCI_LOONGSON config PCI_LOONGSON
bool "LOONGSON PCIe controller" bool "LOONGSON PCIe controller"
depends on MACH_LOONGSON64 || COMPILE_TEST depends on MACH_LOONGSON32 || MACH_LOONGSON64 || COMPILE_TEST
depends on OF || ACPI depends on OF || ACPI
depends on PCI_QUIRKS depends on PCI_QUIRKS
default MACH_LOONGSON64 default MACH_LOONGSON64

View File

@ -65,7 +65,7 @@ config CRC32_ARCH
depends on CRC32 && CRC_OPTIMIZATIONS depends on CRC32 && CRC_OPTIMIZATIONS
default y if ARM && KERNEL_MODE_NEON default y if ARM && KERNEL_MODE_NEON
default y if ARM64 default y if ARM64
default y if LOONGARCH default y if LOONGARCH && 64BIT
default y if MIPS && CPU_MIPSR6 default y if MIPS && CPU_MIPSR6
default y if PPC64 && ALTIVEC default y if PPC64 && ALTIVEC
default y if RISCV && RISCV_ISA_ZBC default y if RISCV && RISCV_ISA_ZBC

View File

@ -263,8 +263,8 @@
#if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \ #if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \
(defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) || \ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
(defined(__TARGET_ARCH_powerpc)) defined(__TARGET_ARCH_powerpc) || defined(__TARGET_ARCH_loongarch))
#define CAN_USE_LOAD_ACQ_STORE_REL #define CAN_USE_LOAD_ACQ_STORE_REL
#endif #endif

View File

@ -75,8 +75,8 @@ __naked int bpf_end_to_be(void)
#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390)) && \ defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390) || \
__clang_major__ >= 18 defined(__TARGET_ARCH_loongarch)) && __clang_major__ >= 18
SEC("?raw_tp") SEC("?raw_tp")
__success __log_level(2) __success __log_level(2)