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

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

Pull LoongArch updates from Huacai Chen:

- preliminary ClangBuiltLinux enablement

- add support to clone a time namespace

- add vector extensions support

- add SMT (Simultaneous Multi-Threading) support

- support dbar with different hints

- introduce hardware page table walker

- add jump-label implementation

- add rethook and uprobes support

- some bug fixes and other small changes

* tag 'loongarch-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson: (28 commits)
LoongArch: Remove five DIE_* definitions in kdebug.h
LoongArch: Add uprobes support
LoongArch: Use larch_insn_gen_break() for kprobes
LoongArch: Add larch_insn_gen_break() to generate break insns
LoongArch: Check for AMO instructions in insns_not_supported()
LoongArch: Move three functions from kprobes.c to inst.c
LoongArch: Replace kretprobe with rethook
LoongArch: Add jump-label implementation
LoongArch: Select HAVE_DEBUG_KMEMLEAK to support kmemleak
LoongArch: Export some arch-specific pm interfaces
LoongArch: Introduce hardware page table walker
LoongArch: Support dbar with different hints
LoongArch: Add SMT (Simultaneous Multi-Threading) support
LoongArch: Add vector extensions support
LoongArch: Add support to clone a time namespace
Makefile: Add loongarch target flag for Clang compilation
LoongArch: Mark Clang LTO as working
LoongArch: Include KBUILD_CPPFLAGS in CHECKFLAGS invocation
LoongArch: vDSO: Use CLANG_FLAGS instead of filtering out '--target='
LoongArch: Tweak CFLAGS for Clang compatibility
...

+2378 -368
+1 -1
Documentation/features/core/jump-labels/arch-support.txt
··· 13 13 | csky: | ok | 14 14 | hexagon: | TODO | 15 15 | ia64: | TODO | 16 - | loongarch: | TODO | 16 + | loongarch: | ok | 17 17 | m68k: | TODO | 18 18 | microblaze: | TODO | 19 19 | mips: | ok |
+1 -1
Documentation/features/debug/kmemleak/arch-support.txt
··· 13 13 | csky: | ok | 14 14 | hexagon: | TODO | 15 15 | ia64: | TODO | 16 - | loongarch: | TODO | 16 + | loongarch: | ok | 17 17 | m68k: | TODO | 18 18 | microblaze: | ok | 19 19 | mips: | ok |
+64 -8
arch/loongarch/Kconfig
··· 5 5 select ACPI 6 6 select ACPI_GENERIC_GSI if ACPI 7 7 select ACPI_MCFG if ACPI 8 + select ACPI_PPTT if ACPI 8 9 select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI 9 10 select ARCH_BINFMT_ELF_STATE 10 11 select ARCH_ENABLE_MEMORY_HOTPLUG ··· 50 49 select ARCH_SUPPORTS_ACPI 51 50 select ARCH_SUPPORTS_ATOMIC_RMW 52 51 select ARCH_SUPPORTS_HUGETLBFS 52 + select ARCH_SUPPORTS_LTO_CLANG 53 + select ARCH_SUPPORTS_LTO_CLANG_THIN 53 54 select ARCH_SUPPORTS_NUMA_BALANCING 54 55 select ARCH_USE_BUILTIN_BSWAP 55 56 select ARCH_USE_CMPXCHG_LOCKREF ··· 84 81 select GENERIC_SCHED_CLOCK 85 82 select GENERIC_SMP_IDLE_THREAD 86 83 select GENERIC_TIME_VSYSCALL 84 + select GENERIC_VDSO_TIME_NS 87 85 select GPIOLIB 88 86 select HAS_IOPORT 89 87 select HAVE_ARCH_AUDITSYSCALL 88 + select HAVE_ARCH_JUMP_LABEL 89 + select HAVE_ARCH_JUMP_LABEL_RELATIVE 90 90 select HAVE_ARCH_MMAP_RND_BITS if MMU 91 91 select HAVE_ARCH_SECCOMP_FILTER 92 92 select HAVE_ARCH_TRACEHOOK ··· 97 91 select HAVE_ASM_MODVERSIONS 98 92 select HAVE_CONTEXT_TRACKING_USER 99 93 select HAVE_C_RECORDMCOUNT 94 + select HAVE_DEBUG_KMEMLEAK 100 95 select HAVE_DEBUG_STACKOVERFLOW 101 96 select HAVE_DMA_CONTIGUOUS 102 97 select HAVE_DYNAMIC_FTRACE ··· 128 121 select HAVE_PERF_REGS 129 122 select HAVE_PERF_USER_STACK_DUMP 130 123 select HAVE_REGS_AND_STACK_ACCESS_API 124 + select HAVE_RETHOOK 131 125 select HAVE_RSEQ 132 126 select HAVE_SAMPLE_FTRACE_DIRECT 133 127 select HAVE_SAMPLE_FTRACE_DIRECT_MULTI ··· 170 162 171 163 config 64BIT 172 164 def_bool y 173 - 174 - config CPU_HAS_FPU 175 - bool 176 - default y 177 - 178 - config CPU_HAS_PREFETCH 179 - bool 180 - default y 181 165 182 166 config GENERIC_BUG 183 167 def_bool y ··· 242 242 243 243 config AS_HAS_EXPLICIT_RELOCS 244 244 def_bool $(as-instr,x:pcalau12i \$t0$(comma)%pc_hi20(x)) 245 + 246 + config AS_HAS_FCSR_CLASS 247 + def_bool $(as-instr,movfcsr2gr \$t0$(comma)\$fcsr0) 248 + 249 + config AS_HAS_LSX_EXTENSION 250 + def_bool $(as-instr,vld \$vr0$(comma)\$a0$(comma)0) 251 + 252 + config AS_HAS_LASX_EXTENSION 253 + def_bool $(as-instr,xvld \$xr0$(comma)\$a0$(comma)0) 245 254 246 255 menu "Kernel type and options" 247 256 ··· 383 374 This kernel feature allows the kernel to be loaded directly by 384 375 EFI firmware without the use of a bootloader. 385 376 377 + config SCHED_SMT 378 + bool "SMT scheduler support" 379 + default y 380 + help 381 + Improves scheduler's performance when there are multiple 382 + threads in one physical core. 383 + 386 384 config SMP 387 385 bool "Multi-Processing support" 388 386 help ··· 499 483 to run kernel only on systems with h/w unaligned access support in 500 484 order to optimise for performance. 501 485 486 + config CPU_HAS_FPU 487 + bool 488 + default y 489 + 490 + config CPU_HAS_LSX 491 + bool "Support for the Loongson SIMD Extension" 492 + depends on AS_HAS_LSX_EXTENSION 493 + help 494 + Loongson SIMD Extension (LSX) introduces 128 bit wide vector registers 495 + and a set of SIMD instructions to operate on them. When this option 496 + is enabled the kernel will support allocating & switching LSX 497 + vector register contexts. If you know that your kernel will only be 498 + running on CPUs which do not support LSX or that your userland will 499 + not be making use of it then you may wish to say N here to reduce 500 + the size & complexity of your kernel. 501 + 502 + If unsure, say Y. 503 + 504 + config CPU_HAS_LASX 505 + bool "Support for the Loongson Advanced SIMD Extension" 506 + depends on CPU_HAS_LSX 507 + depends on AS_HAS_LASX_EXTENSION 508 + help 509 + Loongson Advanced SIMD Extension (LASX) introduces 256 bit wide vector 510 + registers and a set of SIMD instructions to operate on them. When this 511 + option is enabled the kernel will support allocating & switching LASX 512 + vector register contexts. If you know that your kernel will only be 513 + running on CPUs which do not support LASX or that your userland will 514 + not be making use of it then you may wish to say N here to reduce 515 + the size & complexity of your kernel. 516 + 517 + If unsure, say Y. 518 + 519 + config CPU_HAS_PREFETCH 520 + bool 521 + default y 522 + 502 523 config KEXEC 503 524 bool "Kexec system call" 504 525 select KEXEC_CORE ··· 644 591 645 592 config ARCH_MMAP_RND_BITS_MAX 646 593 default 18 594 + 595 + config ARCH_SUPPORTS_UPROBES 596 + def_bool y 647 597 648 598 menu "Power management options" 649 599
+14 -9
arch/loongarch/Makefile
··· 46 46 cflags-y += -mabi=lp64s 47 47 endif 48 48 49 - cflags-y += -G0 -pipe -msoft-float 50 - LDFLAGS_vmlinux += -G0 -static -n -nostdlib 49 + cflags-y += -pipe -msoft-float 50 + LDFLAGS_vmlinux += -static -n -nostdlib 51 51 52 52 # When the assembler supports explicit relocation hint, we must use it. 53 53 # GCC may have -mexplicit-relocs off by default if it was built with an old ··· 56 56 # When the assembler does not supports explicit relocation hint, we can't use 57 57 # it. Disable it if the compiler supports it. 58 58 # 59 - # If you've seen "unknown reloc hint" message building the kernel and you are 60 - # now wondering why "-mexplicit-relocs" is not wrapped with cc-option: the 61 - # combination of a "new" assembler and "old" compiler is not supported. Either 62 - # upgrade the compiler or downgrade the assembler. 59 + # The combination of a "new" assembler and "old" GCC is not supported, given 60 + # the rarity of this combo and the extra complexity needed to make it work. 61 + # Either upgrade the compiler or downgrade the assembler; the build will error 62 + # out if it is the case (by probing for the model attribute; all supported 63 + # compilers in this case would have support). 64 + # 65 + # Also, -mdirect-extern-access is useful in case of building with explicit 66 + # relocs, for avoiding unnecessary GOT accesses. It is harmless to not have 67 + # support though. 63 68 ifdef CONFIG_AS_HAS_EXPLICIT_RELOCS 64 - cflags-y += -mexplicit-relocs 65 - KBUILD_CFLAGS_KERNEL += -mdirect-extern-access 69 + cflags-y += $(call cc-option,-mexplicit-relocs) 70 + KBUILD_CFLAGS_KERNEL += $(call cc-option,-mdirect-extern-access) 66 71 else 67 72 cflags-y += $(call cc-option,-mno-explicit-relocs) 68 73 KBUILD_AFLAGS_KERNEL += -Wa,-mla-global-with-pcrel ··· 112 107 KBUILD_LDFLAGS += -m $(ld-emul) 113 108 114 109 ifdef CONFIG_LOONGARCH 115 - CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ 110 + CHECKFLAGS += $(shell $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ 116 111 grep -E -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \ 117 112 sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g') 118 113 endif
-1
arch/loongarch/include/asm/Kbuild
··· 5 5 generic-y += parport.h 6 6 generic-y += early_ioremap.h 7 7 generic-y += qrwlock.h 8 - generic-y += qspinlock.h 9 8 generic-y += rwsem.h 10 9 generic-y += segment.h 11 10 generic-y += user.h
+11 -2
arch/loongarch/include/asm/acpi.h
··· 8 8 #ifndef _ASM_LOONGARCH_ACPI_H 9 9 #define _ASM_LOONGARCH_ACPI_H 10 10 11 + #include <asm/suspend.h> 12 + 11 13 #ifdef CONFIG_ACPI 12 14 extern int acpi_strict; 13 15 extern int acpi_disabled; 14 16 extern int acpi_pci_disabled; 15 17 extern int acpi_noirq; 18 + extern int pptt_enabled; 16 19 17 20 #define acpi_os_ioremap acpi_os_ioremap 18 21 void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size); ··· 33 30 } 34 31 35 32 extern struct list_head acpi_wakeup_device_list; 33 + extern struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; 34 + 35 + extern int __init parse_acpi_topology(void); 36 + 37 + static inline u32 get_acpi_id_for_cpu(unsigned int cpu) 38 + { 39 + return acpi_core_pic[cpu_logical_map(cpu)].processor_id; 40 + } 36 41 37 42 #endif /* !CONFIG_ACPI */ 38 43 ··· 48 37 49 38 extern int loongarch_acpi_suspend(void); 50 39 extern int (*acpi_suspend_lowlevel)(void); 51 - extern void loongarch_suspend_enter(void); 52 40 53 41 static inline unsigned long acpi_get_wakeup_address(void) 54 42 { 55 43 #ifdef CONFIG_SUSPEND 56 - extern void loongarch_wakeup_start(void); 57 44 return (unsigned long)loongarch_wakeup_start; 58 45 #endif 59 46 return 0UL;
+393
arch/loongarch/include/asm/asmmacro.h
··· 270 270 fld.d $f31, \tmp, THREAD_FPR31 - THREAD_FPR0 271 271 .endm 272 272 273 + .macro lsx_save_data thread tmp 274 + li.w \tmp, THREAD_FPR0 275 + PTR_ADD \tmp, \thread, \tmp 276 + vst $vr0, \tmp, THREAD_FPR0 - THREAD_FPR0 277 + vst $vr1, \tmp, THREAD_FPR1 - THREAD_FPR0 278 + vst $vr2, \tmp, THREAD_FPR2 - THREAD_FPR0 279 + vst $vr3, \tmp, THREAD_FPR3 - THREAD_FPR0 280 + vst $vr4, \tmp, THREAD_FPR4 - THREAD_FPR0 281 + vst $vr5, \tmp, THREAD_FPR5 - THREAD_FPR0 282 + vst $vr6, \tmp, THREAD_FPR6 - THREAD_FPR0 283 + vst $vr7, \tmp, THREAD_FPR7 - THREAD_FPR0 284 + vst $vr8, \tmp, THREAD_FPR8 - THREAD_FPR0 285 + vst $vr9, \tmp, THREAD_FPR9 - THREAD_FPR0 286 + vst $vr10, \tmp, THREAD_FPR10 - THREAD_FPR0 287 + vst $vr11, \tmp, THREAD_FPR11 - THREAD_FPR0 288 + vst $vr12, \tmp, THREAD_FPR12 - THREAD_FPR0 289 + vst $vr13, \tmp, THREAD_FPR13 - THREAD_FPR0 290 + vst $vr14, \tmp, THREAD_FPR14 - THREAD_FPR0 291 + vst $vr15, \tmp, THREAD_FPR15 - THREAD_FPR0 292 + vst $vr16, \tmp, THREAD_FPR16 - THREAD_FPR0 293 + vst $vr17, \tmp, THREAD_FPR17 - THREAD_FPR0 294 + vst $vr18, \tmp, THREAD_FPR18 - THREAD_FPR0 295 + vst $vr19, \tmp, THREAD_FPR19 - THREAD_FPR0 296 + vst $vr20, \tmp, THREAD_FPR20 - THREAD_FPR0 297 + vst $vr21, \tmp, THREAD_FPR21 - THREAD_FPR0 298 + vst $vr22, \tmp, THREAD_FPR22 - THREAD_FPR0 299 + vst $vr23, \tmp, THREAD_FPR23 - THREAD_FPR0 300 + vst $vr24, \tmp, THREAD_FPR24 - THREAD_FPR0 301 + vst $vr25, \tmp, THREAD_FPR25 - THREAD_FPR0 302 + vst $vr26, \tmp, THREAD_FPR26 - THREAD_FPR0 303 + vst $vr27, \tmp, THREAD_FPR27 - THREAD_FPR0 304 + vst $vr28, \tmp, THREAD_FPR28 - THREAD_FPR0 305 + vst $vr29, \tmp, THREAD_FPR29 - THREAD_FPR0 306 + vst $vr30, \tmp, THREAD_FPR30 - THREAD_FPR0 307 + vst $vr31, \tmp, THREAD_FPR31 - THREAD_FPR0 308 + .endm 309 + 310 + .macro lsx_restore_data thread tmp 311 + li.w \tmp, THREAD_FPR0 312 + PTR_ADD \tmp, \thread, \tmp 313 + vld $vr0, \tmp, THREAD_FPR0 - THREAD_FPR0 314 + vld $vr1, \tmp, THREAD_FPR1 - THREAD_FPR0 315 + vld $vr2, \tmp, THREAD_FPR2 - THREAD_FPR0 316 + vld $vr3, \tmp, THREAD_FPR3 - THREAD_FPR0 317 + vld $vr4, \tmp, THREAD_FPR4 - THREAD_FPR0 318 + vld $vr5, \tmp, THREAD_FPR5 - THREAD_FPR0 319 + vld $vr6, \tmp, THREAD_FPR6 - THREAD_FPR0 320 + vld $vr7, \tmp, THREAD_FPR7 - THREAD_FPR0 321 + vld $vr8, \tmp, THREAD_FPR8 - THREAD_FPR0 322 + vld $vr9, \tmp, THREAD_FPR9 - THREAD_FPR0 323 + vld $vr10, \tmp, THREAD_FPR10 - THREAD_FPR0 324 + vld $vr11, \tmp, THREAD_FPR11 - THREAD_FPR0 325 + vld $vr12, \tmp, THREAD_FPR12 - THREAD_FPR0 326 + vld $vr13, \tmp, THREAD_FPR13 - THREAD_FPR0 327 + vld $vr14, \tmp, THREAD_FPR14 - THREAD_FPR0 328 + vld $vr15, \tmp, THREAD_FPR15 - THREAD_FPR0 329 + vld $vr16, \tmp, THREAD_FPR16 - THREAD_FPR0 330 + vld $vr17, \tmp, THREAD_FPR17 - THREAD_FPR0 331 + vld $vr18, \tmp, THREAD_FPR18 - THREAD_FPR0 332 + vld $vr19, \tmp, THREAD_FPR19 - THREAD_FPR0 333 + vld $vr20, \tmp, THREAD_FPR20 - THREAD_FPR0 334 + vld $vr21, \tmp, THREAD_FPR21 - THREAD_FPR0 335 + vld $vr22, \tmp, THREAD_FPR22 - THREAD_FPR0 336 + vld $vr23, \tmp, THREAD_FPR23 - THREAD_FPR0 337 + vld $vr24, \tmp, THREAD_FPR24 - THREAD_FPR0 338 + vld $vr25, \tmp, THREAD_FPR25 - THREAD_FPR0 339 + vld $vr26, \tmp, THREAD_FPR26 - THREAD_FPR0 340 + vld $vr27, \tmp, THREAD_FPR27 - THREAD_FPR0 341 + vld $vr28, \tmp, THREAD_FPR28 - THREAD_FPR0 342 + vld $vr29, \tmp, THREAD_FPR29 - THREAD_FPR0 343 + vld $vr30, \tmp, THREAD_FPR30 - THREAD_FPR0 344 + vld $vr31, \tmp, THREAD_FPR31 - THREAD_FPR0 345 + .endm 346 + 347 + .macro lsx_save_all thread tmp0 tmp1 348 + fpu_save_cc \thread, \tmp0, \tmp1 349 + fpu_save_csr \thread, \tmp0 350 + lsx_save_data \thread, \tmp0 351 + .endm 352 + 353 + .macro lsx_restore_all thread tmp0 tmp1 354 + lsx_restore_data \thread, \tmp0 355 + fpu_restore_cc \thread, \tmp0, \tmp1 356 + fpu_restore_csr \thread, \tmp0 357 + .endm 358 + 359 + .macro lsx_save_upper vd base tmp off 360 + vpickve2gr.d \tmp, \vd, 1 361 + st.d \tmp, \base, (\off+8) 362 + .endm 363 + 364 + .macro lsx_save_all_upper thread base tmp 365 + li.w \tmp, THREAD_FPR0 366 + PTR_ADD \base, \thread, \tmp 367 + lsx_save_upper $vr0, \base, \tmp, (THREAD_FPR0-THREAD_FPR0) 368 + lsx_save_upper $vr1, \base, \tmp, (THREAD_FPR1-THREAD_FPR0) 369 + lsx_save_upper $vr2, \base, \tmp, (THREAD_FPR2-THREAD_FPR0) 370 + lsx_save_upper $vr3, \base, \tmp, (THREAD_FPR3-THREAD_FPR0) 371 + lsx_save_upper $vr4, \base, \tmp, (THREAD_FPR4-THREAD_FPR0) 372 + lsx_save_upper $vr5, \base, \tmp, (THREAD_FPR5-THREAD_FPR0) 373 + lsx_save_upper $vr6, \base, \tmp, (THREAD_FPR6-THREAD_FPR0) 374 + lsx_save_upper $vr7, \base, \tmp, (THREAD_FPR7-THREAD_FPR0) 375 + lsx_save_upper $vr8, \base, \tmp, (THREAD_FPR8-THREAD_FPR0) 376 + lsx_save_upper $vr9, \base, \tmp, (THREAD_FPR9-THREAD_FPR0) 377 + lsx_save_upper $vr10, \base, \tmp, (THREAD_FPR10-THREAD_FPR0) 378 + lsx_save_upper $vr11, \base, \tmp, (THREAD_FPR11-THREAD_FPR0) 379 + lsx_save_upper $vr12, \base, \tmp, (THREAD_FPR12-THREAD_FPR0) 380 + lsx_save_upper $vr13, \base, \tmp, (THREAD_FPR13-THREAD_FPR0) 381 + lsx_save_upper $vr14, \base, \tmp, (THREAD_FPR14-THREAD_FPR0) 382 + lsx_save_upper $vr15, \base, \tmp, (THREAD_FPR15-THREAD_FPR0) 383 + lsx_save_upper $vr16, \base, \tmp, (THREAD_FPR16-THREAD_FPR0) 384 + lsx_save_upper $vr17, \base, \tmp, (THREAD_FPR17-THREAD_FPR0) 385 + lsx_save_upper $vr18, \base, \tmp, (THREAD_FPR18-THREAD_FPR0) 386 + lsx_save_upper $vr19, \base, \tmp, (THREAD_FPR19-THREAD_FPR0) 387 + lsx_save_upper $vr20, \base, \tmp, (THREAD_FPR20-THREAD_FPR0) 388 + lsx_save_upper $vr21, \base, \tmp, (THREAD_FPR21-THREAD_FPR0) 389 + lsx_save_upper $vr22, \base, \tmp, (THREAD_FPR22-THREAD_FPR0) 390 + lsx_save_upper $vr23, \base, \tmp, (THREAD_FPR23-THREAD_FPR0) 391 + lsx_save_upper $vr24, \base, \tmp, (THREAD_FPR24-THREAD_FPR0) 392 + lsx_save_upper $vr25, \base, \tmp, (THREAD_FPR25-THREAD_FPR0) 393 + lsx_save_upper $vr26, \base, \tmp, (THREAD_FPR26-THREAD_FPR0) 394 + lsx_save_upper $vr27, \base, \tmp, (THREAD_FPR27-THREAD_FPR0) 395 + lsx_save_upper $vr28, \base, \tmp, (THREAD_FPR28-THREAD_FPR0) 396 + lsx_save_upper $vr29, \base, \tmp, (THREAD_FPR29-THREAD_FPR0) 397 + lsx_save_upper $vr30, \base, \tmp, (THREAD_FPR30-THREAD_FPR0) 398 + lsx_save_upper $vr31, \base, \tmp, (THREAD_FPR31-THREAD_FPR0) 399 + .endm 400 + 401 + .macro lsx_restore_upper vd base tmp off 402 + ld.d \tmp, \base, (\off+8) 403 + vinsgr2vr.d \vd, \tmp, 1 404 + .endm 405 + 406 + .macro lsx_restore_all_upper thread base tmp 407 + li.w \tmp, THREAD_FPR0 408 + PTR_ADD \base, \thread, \tmp 409 + lsx_restore_upper $vr0, \base, \tmp, (THREAD_FPR0-THREAD_FPR0) 410 + lsx_restore_upper $vr1, \base, \tmp, (THREAD_FPR1-THREAD_FPR0) 411 + lsx_restore_upper $vr2, \base, \tmp, (THREAD_FPR2-THREAD_FPR0) 412 + lsx_restore_upper $vr3, \base, \tmp, (THREAD_FPR3-THREAD_FPR0) 413 + lsx_restore_upper $vr4, \base, \tmp, (THREAD_FPR4-THREAD_FPR0) 414 + lsx_restore_upper $vr5, \base, \tmp, (THREAD_FPR5-THREAD_FPR0) 415 + lsx_restore_upper $vr6, \base, \tmp, (THREAD_FPR6-THREAD_FPR0) 416 + lsx_restore_upper $vr7, \base, \tmp, (THREAD_FPR7-THREAD_FPR0) 417 + lsx_restore_upper $vr8, \base, \tmp, (THREAD_FPR8-THREAD_FPR0) 418 + lsx_restore_upper $vr9, \base, \tmp, (THREAD_FPR9-THREAD_FPR0) 419 + lsx_restore_upper $vr10, \base, \tmp, (THREAD_FPR10-THREAD_FPR0) 420 + lsx_restore_upper $vr11, \base, \tmp, (THREAD_FPR11-THREAD_FPR0) 421 + lsx_restore_upper $vr12, \base, \tmp, (THREAD_FPR12-THREAD_FPR0) 422 + lsx_restore_upper $vr13, \base, \tmp, (THREAD_FPR13-THREAD_FPR0) 423 + lsx_restore_upper $vr14, \base, \tmp, (THREAD_FPR14-THREAD_FPR0) 424 + lsx_restore_upper $vr15, \base, \tmp, (THREAD_FPR15-THREAD_FPR0) 425 + lsx_restore_upper $vr16, \base, \tmp, (THREAD_FPR16-THREAD_FPR0) 426 + lsx_restore_upper $vr17, \base, \tmp, (THREAD_FPR17-THREAD_FPR0) 427 + lsx_restore_upper $vr18, \base, \tmp, (THREAD_FPR18-THREAD_FPR0) 428 + lsx_restore_upper $vr19, \base, \tmp, (THREAD_FPR19-THREAD_FPR0) 429 + lsx_restore_upper $vr20, \base, \tmp, (THREAD_FPR20-THREAD_FPR0) 430 + lsx_restore_upper $vr21, \base, \tmp, (THREAD_FPR21-THREAD_FPR0) 431 + lsx_restore_upper $vr22, \base, \tmp, (THREAD_FPR22-THREAD_FPR0) 432 + lsx_restore_upper $vr23, \base, \tmp, (THREAD_FPR23-THREAD_FPR0) 433 + lsx_restore_upper $vr24, \base, \tmp, (THREAD_FPR24-THREAD_FPR0) 434 + lsx_restore_upper $vr25, \base, \tmp, (THREAD_FPR25-THREAD_FPR0) 435 + lsx_restore_upper $vr26, \base, \tmp, (THREAD_FPR26-THREAD_FPR0) 436 + lsx_restore_upper $vr27, \base, \tmp, (THREAD_FPR27-THREAD_FPR0) 437 + lsx_restore_upper $vr28, \base, \tmp, (THREAD_FPR28-THREAD_FPR0) 438 + lsx_restore_upper $vr29, \base, \tmp, (THREAD_FPR29-THREAD_FPR0) 439 + lsx_restore_upper $vr30, \base, \tmp, (THREAD_FPR30-THREAD_FPR0) 440 + lsx_restore_upper $vr31, \base, \tmp, (THREAD_FPR31-THREAD_FPR0) 441 + .endm 442 + 443 + .macro lsx_init_upper vd tmp 444 + vinsgr2vr.d \vd, \tmp, 1 445 + .endm 446 + 447 + .macro lsx_init_all_upper tmp 448 + not \tmp, zero 449 + lsx_init_upper $vr0 \tmp 450 + lsx_init_upper $vr1 \tmp 451 + lsx_init_upper $vr2 \tmp 452 + lsx_init_upper $vr3 \tmp 453 + lsx_init_upper $vr4 \tmp 454 + lsx_init_upper $vr5 \tmp 455 + lsx_init_upper $vr6 \tmp 456 + lsx_init_upper $vr7 \tmp 457 + lsx_init_upper $vr8 \tmp 458 + lsx_init_upper $vr9 \tmp 459 + lsx_init_upper $vr10 \tmp 460 + lsx_init_upper $vr11 \tmp 461 + lsx_init_upper $vr12 \tmp 462 + lsx_init_upper $vr13 \tmp 463 + lsx_init_upper $vr14 \tmp 464 + lsx_init_upper $vr15 \tmp 465 + lsx_init_upper $vr16 \tmp 466 + lsx_init_upper $vr17 \tmp 467 + lsx_init_upper $vr18 \tmp 468 + lsx_init_upper $vr19 \tmp 469 + lsx_init_upper $vr20 \tmp 470 + lsx_init_upper $vr21 \tmp 471 + lsx_init_upper $vr22 \tmp 472 + lsx_init_upper $vr23 \tmp 473 + lsx_init_upper $vr24 \tmp 474 + lsx_init_upper $vr25 \tmp 475 + lsx_init_upper $vr26 \tmp 476 + lsx_init_upper $vr27 \tmp 477 + lsx_init_upper $vr28 \tmp 478 + lsx_init_upper $vr29 \tmp 479 + lsx_init_upper $vr30 \tmp 480 + lsx_init_upper $vr31 \tmp 481 + .endm 482 + 483 + .macro lasx_save_data thread tmp 484 + li.w \tmp, THREAD_FPR0 485 + PTR_ADD \tmp, \thread, \tmp 486 + xvst $xr0, \tmp, THREAD_FPR0 - THREAD_FPR0 487 + xvst $xr1, \tmp, THREAD_FPR1 - THREAD_FPR0 488 + xvst $xr2, \tmp, THREAD_FPR2 - THREAD_FPR0 489 + xvst $xr3, \tmp, THREAD_FPR3 - THREAD_FPR0 490 + xvst $xr4, \tmp, THREAD_FPR4 - THREAD_FPR0 491 + xvst $xr5, \tmp, THREAD_FPR5 - THREAD_FPR0 492 + xvst $xr6, \tmp, THREAD_FPR6 - THREAD_FPR0 493 + xvst $xr7, \tmp, THREAD_FPR7 - THREAD_FPR0 494 + xvst $xr8, \tmp, THREAD_FPR8 - THREAD_FPR0 495 + xvst $xr9, \tmp, THREAD_FPR9 - THREAD_FPR0 496 + xvst $xr10, \tmp, THREAD_FPR10 - THREAD_FPR0 497 + xvst $xr11, \tmp, THREAD_FPR11 - THREAD_FPR0 498 + xvst $xr12, \tmp, THREAD_FPR12 - THREAD_FPR0 499 + xvst $xr13, \tmp, THREAD_FPR13 - THREAD_FPR0 500 + xvst $xr14, \tmp, THREAD_FPR14 - THREAD_FPR0 501 + xvst $xr15, \tmp, THREAD_FPR15 - THREAD_FPR0 502 + xvst $xr16, \tmp, THREAD_FPR16 - THREAD_FPR0 503 + xvst $xr17, \tmp, THREAD_FPR17 - THREAD_FPR0 504 + xvst $xr18, \tmp, THREAD_FPR18 - THREAD_FPR0 505 + xvst $xr19, \tmp, THREAD_FPR19 - THREAD_FPR0 506 + xvst $xr20, \tmp, THREAD_FPR20 - THREAD_FPR0 507 + xvst $xr21, \tmp, THREAD_FPR21 - THREAD_FPR0 508 + xvst $xr22, \tmp, THREAD_FPR22 - THREAD_FPR0 509 + xvst $xr23, \tmp, THREAD_FPR23 - THREAD_FPR0 510 + xvst $xr24, \tmp, THREAD_FPR24 - THREAD_FPR0 511 + xvst $xr25, \tmp, THREAD_FPR25 - THREAD_FPR0 512 + xvst $xr26, \tmp, THREAD_FPR26 - THREAD_FPR0 513 + xvst $xr27, \tmp, THREAD_FPR27 - THREAD_FPR0 514 + xvst $xr28, \tmp, THREAD_FPR28 - THREAD_FPR0 515 + xvst $xr29, \tmp, THREAD_FPR29 - THREAD_FPR0 516 + xvst $xr30, \tmp, THREAD_FPR30 - THREAD_FPR0 517 + xvst $xr31, \tmp, THREAD_FPR31 - THREAD_FPR0 518 + .endm 519 + 520 + .macro lasx_restore_data thread tmp 521 + li.w \tmp, THREAD_FPR0 522 + PTR_ADD \tmp, \thread, \tmp 523 + xvld $xr0, \tmp, THREAD_FPR0 - THREAD_FPR0 524 + xvld $xr1, \tmp, THREAD_FPR1 - THREAD_FPR0 525 + xvld $xr2, \tmp, THREAD_FPR2 - THREAD_FPR0 526 + xvld $xr3, \tmp, THREAD_FPR3 - THREAD_FPR0 527 + xvld $xr4, \tmp, THREAD_FPR4 - THREAD_FPR0 528 + xvld $xr5, \tmp, THREAD_FPR5 - THREAD_FPR0 529 + xvld $xr6, \tmp, THREAD_FPR6 - THREAD_FPR0 530 + xvld $xr7, \tmp, THREAD_FPR7 - THREAD_FPR0 531 + xvld $xr8, \tmp, THREAD_FPR8 - THREAD_FPR0 532 + xvld $xr9, \tmp, THREAD_FPR9 - THREAD_FPR0 533 + xvld $xr10, \tmp, THREAD_FPR10 - THREAD_FPR0 534 + xvld $xr11, \tmp, THREAD_FPR11 - THREAD_FPR0 535 + xvld $xr12, \tmp, THREAD_FPR12 - THREAD_FPR0 536 + xvld $xr13, \tmp, THREAD_FPR13 - THREAD_FPR0 537 + xvld $xr14, \tmp, THREAD_FPR14 - THREAD_FPR0 538 + xvld $xr15, \tmp, THREAD_FPR15 - THREAD_FPR0 539 + xvld $xr16, \tmp, THREAD_FPR16 - THREAD_FPR0 540 + xvld $xr17, \tmp, THREAD_FPR17 - THREAD_FPR0 541 + xvld $xr18, \tmp, THREAD_FPR18 - THREAD_FPR0 542 + xvld $xr19, \tmp, THREAD_FPR19 - THREAD_FPR0 543 + xvld $xr20, \tmp, THREAD_FPR20 - THREAD_FPR0 544 + xvld $xr21, \tmp, THREAD_FPR21 - THREAD_FPR0 545 + xvld $xr22, \tmp, THREAD_FPR22 - THREAD_FPR0 546 + xvld $xr23, \tmp, THREAD_FPR23 - THREAD_FPR0 547 + xvld $xr24, \tmp, THREAD_FPR24 - THREAD_FPR0 548 + xvld $xr25, \tmp, THREAD_FPR25 - THREAD_FPR0 549 + xvld $xr26, \tmp, THREAD_FPR26 - THREAD_FPR0 550 + xvld $xr27, \tmp, THREAD_FPR27 - THREAD_FPR0 551 + xvld $xr28, \tmp, THREAD_FPR28 - THREAD_FPR0 552 + xvld $xr29, \tmp, THREAD_FPR29 - THREAD_FPR0 553 + xvld $xr30, \tmp, THREAD_FPR30 - THREAD_FPR0 554 + xvld $xr31, \tmp, THREAD_FPR31 - THREAD_FPR0 555 + .endm 556 + 557 + .macro lasx_save_all thread tmp0 tmp1 558 + fpu_save_cc \thread, \tmp0, \tmp1 559 + fpu_save_csr \thread, \tmp0 560 + lasx_save_data \thread, \tmp0 561 + .endm 562 + 563 + .macro lasx_restore_all thread tmp0 tmp1 564 + lasx_restore_data \thread, \tmp0 565 + fpu_restore_cc \thread, \tmp0, \tmp1 566 + fpu_restore_csr \thread, \tmp0 567 + .endm 568 + 569 + .macro lasx_save_upper xd base tmp off 570 + /* Nothing */ 571 + .endm 572 + 573 + .macro lasx_save_all_upper thread base tmp 574 + /* Nothing */ 575 + .endm 576 + 577 + .macro lasx_restore_upper xd base tmp0 tmp1 off 578 + vld \tmp0, \base, (\off+16) 579 + xvpermi.q \xd, \tmp1, 0x2 580 + .endm 581 + 582 + .macro lasx_restore_all_upper thread base tmp 583 + li.w \tmp, THREAD_FPR0 584 + PTR_ADD \base, \thread, \tmp 585 + /* Save $vr31 ($xr31 lower bits) with xvpickve2gr */ 586 + xvpickve2gr.d $r17, $xr31, 0 587 + xvpickve2gr.d $r18, $xr31, 1 588 + lasx_restore_upper $xr0, \base, $vr31, $xr31, (THREAD_FPR0-THREAD_FPR0) 589 + lasx_restore_upper $xr1, \base, $vr31, $xr31, (THREAD_FPR1-THREAD_FPR0) 590 + lasx_restore_upper $xr2, \base, $vr31, $xr31, (THREAD_FPR2-THREAD_FPR0) 591 + lasx_restore_upper $xr3, \base, $vr31, $xr31, (THREAD_FPR3-THREAD_FPR0) 592 + lasx_restore_upper $xr4, \base, $vr31, $xr31, (THREAD_FPR4-THREAD_FPR0) 593 + lasx_restore_upper $xr5, \base, $vr31, $xr31, (THREAD_FPR5-THREAD_FPR0) 594 + lasx_restore_upper $xr6, \base, $vr31, $xr31, (THREAD_FPR6-THREAD_FPR0) 595 + lasx_restore_upper $xr7, \base, $vr31, $xr31, (THREAD_FPR7-THREAD_FPR0) 596 + lasx_restore_upper $xr8, \base, $vr31, $xr31, (THREAD_FPR8-THREAD_FPR0) 597 + lasx_restore_upper $xr9, \base, $vr31, $xr31, (THREAD_FPR9-THREAD_FPR0) 598 + lasx_restore_upper $xr10, \base, $vr31, $xr31, (THREAD_FPR10-THREAD_FPR0) 599 + lasx_restore_upper $xr11, \base, $vr31, $xr31, (THREAD_FPR11-THREAD_FPR0) 600 + lasx_restore_upper $xr12, \base, $vr31, $xr31, (THREAD_FPR12-THREAD_FPR0) 601 + lasx_restore_upper $xr13, \base, $vr31, $xr31, (THREAD_FPR13-THREAD_FPR0) 602 + lasx_restore_upper $xr14, \base, $vr31, $xr31, (THREAD_FPR14-THREAD_FPR0) 603 + lasx_restore_upper $xr15, \base, $vr31, $xr31, (THREAD_FPR15-THREAD_FPR0) 604 + lasx_restore_upper $xr16, \base, $vr31, $xr31, (THREAD_FPR16-THREAD_FPR0) 605 + lasx_restore_upper $xr17, \base, $vr31, $xr31, (THREAD_FPR17-THREAD_FPR0) 606 + lasx_restore_upper $xr18, \base, $vr31, $xr31, (THREAD_FPR18-THREAD_FPR0) 607 + lasx_restore_upper $xr19, \base, $vr31, $xr31, (THREAD_FPR19-THREAD_FPR0) 608 + lasx_restore_upper $xr20, \base, $vr31, $xr31, (THREAD_FPR20-THREAD_FPR0) 609 + lasx_restore_upper $xr21, \base, $vr31, $xr31, (THREAD_FPR21-THREAD_FPR0) 610 + lasx_restore_upper $xr22, \base, $vr31, $xr31, (THREAD_FPR22-THREAD_FPR0) 611 + lasx_restore_upper $xr23, \base, $vr31, $xr31, (THREAD_FPR23-THREAD_FPR0) 612 + lasx_restore_upper $xr24, \base, $vr31, $xr31, (THREAD_FPR24-THREAD_FPR0) 613 + lasx_restore_upper $xr25, \base, $vr31, $xr31, (THREAD_FPR25-THREAD_FPR0) 614 + lasx_restore_upper $xr26, \base, $vr31, $xr31, (THREAD_FPR26-THREAD_FPR0) 615 + lasx_restore_upper $xr27, \base, $vr31, $xr31, (THREAD_FPR27-THREAD_FPR0) 616 + lasx_restore_upper $xr28, \base, $vr31, $xr31, (THREAD_FPR28-THREAD_FPR0) 617 + lasx_restore_upper $xr29, \base, $vr31, $xr31, (THREAD_FPR29-THREAD_FPR0) 618 + lasx_restore_upper $xr30, \base, $vr31, $xr31, (THREAD_FPR30-THREAD_FPR0) 619 + lasx_restore_upper $xr31, \base, $vr31, $xr31, (THREAD_FPR31-THREAD_FPR0) 620 + /* Restore $vr31 ($xr31 lower bits) with xvinsgr2vr */ 621 + xvinsgr2vr.d $xr31, $r17, 0 622 + xvinsgr2vr.d $xr31, $r18, 1 623 + .endm 624 + 625 + .macro lasx_init_upper xd tmp 626 + xvinsgr2vr.d \xd, \tmp, 2 627 + xvinsgr2vr.d \xd, \tmp, 3 628 + .endm 629 + 630 + .macro lasx_init_all_upper tmp 631 + not \tmp, zero 632 + lasx_init_upper $xr0 \tmp 633 + lasx_init_upper $xr1 \tmp 634 + lasx_init_upper $xr2 \tmp 635 + lasx_init_upper $xr3 \tmp 636 + lasx_init_upper $xr4 \tmp 637 + lasx_init_upper $xr5 \tmp 638 + lasx_init_upper $xr6 \tmp 639 + lasx_init_upper $xr7 \tmp 640 + lasx_init_upper $xr8 \tmp 641 + lasx_init_upper $xr9 \tmp 642 + lasx_init_upper $xr10 \tmp 643 + lasx_init_upper $xr11 \tmp 644 + lasx_init_upper $xr12 \tmp 645 + lasx_init_upper $xr13 \tmp 646 + lasx_init_upper $xr14 \tmp 647 + lasx_init_upper $xr15 \tmp 648 + lasx_init_upper $xr16 \tmp 649 + lasx_init_upper $xr17 \tmp 650 + lasx_init_upper $xr18 \tmp 651 + lasx_init_upper $xr19 \tmp 652 + lasx_init_upper $xr20 \tmp 653 + lasx_init_upper $xr21 \tmp 654 + lasx_init_upper $xr22 \tmp 655 + lasx_init_upper $xr23 \tmp 656 + lasx_init_upper $xr24 \tmp 657 + lasx_init_upper $xr25 \tmp 658 + lasx_init_upper $xr26 \tmp 659 + lasx_init_upper $xr27 \tmp 660 + lasx_init_upper $xr28 \tmp 661 + lasx_init_upper $xr29 \tmp 662 + lasx_init_upper $xr30 \tmp 663 + lasx_init_upper $xr31 \tmp 664 + .endm 665 + 273 666 .macro not dst src 274 667 nor \dst, \src, zero 275 668 .endm
+55 -75
arch/loongarch/include/asm/barrier.h
··· 5 5 #ifndef __ASM_BARRIER_H 6 6 #define __ASM_BARRIER_H 7 7 8 - #define __sync() __asm__ __volatile__("dbar 0" : : : "memory") 8 + /* 9 + * Hint encoding: 10 + * 11 + * Bit4: ordering or completion (0: completion, 1: ordering) 12 + * Bit3: barrier for previous read (0: true, 1: false) 13 + * Bit2: barrier for previous write (0: true, 1: false) 14 + * Bit1: barrier for succeeding read (0: true, 1: false) 15 + * Bit0: barrier for succeeding write (0: true, 1: false) 16 + * 17 + * Hint 0x700: barrier for "read after read" from the same address 18 + */ 9 19 10 - #define fast_wmb() __sync() 11 - #define fast_rmb() __sync() 12 - #define fast_mb() __sync() 13 - #define fast_iob() __sync() 14 - #define wbflush() __sync() 20 + #define DBAR(hint) __asm__ __volatile__("dbar %0 " : : "I"(hint) : "memory") 15 21 16 - #define wmb() fast_wmb() 17 - #define rmb() fast_rmb() 18 - #define mb() fast_mb() 19 - #define iob() fast_iob() 22 + #define crwrw 0b00000 23 + #define cr_r_ 0b00101 24 + #define c_w_w 0b01010 20 25 21 - #define __smp_mb() __asm__ __volatile__("dbar 0" : : : "memory") 22 - #define __smp_rmb() __asm__ __volatile__("dbar 0" : : : "memory") 23 - #define __smp_wmb() __asm__ __volatile__("dbar 0" : : : "memory") 26 + #define orwrw 0b10000 27 + #define or_r_ 0b10101 28 + #define o_w_w 0b11010 29 + 30 + #define orw_w 0b10010 31 + #define or_rw 0b10100 32 + 33 + #define c_sync() DBAR(crwrw) 34 + #define c_rsync() DBAR(cr_r_) 35 + #define c_wsync() DBAR(c_w_w) 36 + 37 + #define o_sync() DBAR(orwrw) 38 + #define o_rsync() DBAR(or_r_) 39 + #define o_wsync() DBAR(o_w_w) 40 + 41 + #define ldacq_mb() DBAR(or_rw) 42 + #define strel_mb() DBAR(orw_w) 43 + 44 + #define mb() c_sync() 45 + #define rmb() c_rsync() 46 + #define wmb() c_wsync() 47 + #define iob() c_sync() 48 + #define wbflush() c_sync() 49 + 50 + #define __smp_mb() o_sync() 51 + #define __smp_rmb() o_rsync() 52 + #define __smp_wmb() o_wsync() 24 53 25 54 #ifdef CONFIG_SMP 26 - #define __WEAK_LLSC_MB " dbar 0 \n" 55 + #define __WEAK_LLSC_MB " dbar 0x700 \n" 27 56 #else 28 - #define __WEAK_LLSC_MB " \n" 57 + #define __WEAK_LLSC_MB " \n" 29 58 #endif 30 59 31 60 #define __smp_mb__before_atomic() barrier() ··· 88 59 return mask; 89 60 } 90 61 91 - #define __smp_load_acquire(p) \ 92 - ({ \ 93 - union { typeof(*p) __val; char __c[1]; } __u; \ 94 - unsigned long __tmp = 0; \ 95 - compiletime_assert_atomic_type(*p); \ 96 - switch (sizeof(*p)) { \ 97 - case 1: \ 98 - *(__u8 *)__u.__c = *(volatile __u8 *)p; \ 99 - __smp_mb(); \ 100 - break; \ 101 - case 2: \ 102 - *(__u16 *)__u.__c = *(volatile __u16 *)p; \ 103 - __smp_mb(); \ 104 - break; \ 105 - case 4: \ 106 - __asm__ __volatile__( \ 107 - "amor_db.w %[val], %[tmp], %[mem] \n" \ 108 - : [val] "=&r" (*(__u32 *)__u.__c) \ 109 - : [mem] "ZB" (*(u32 *) p), [tmp] "r" (__tmp) \ 110 - : "memory"); \ 111 - break; \ 112 - case 8: \ 113 - __asm__ __volatile__( \ 114 - "amor_db.d %[val], %[tmp], %[mem] \n" \ 115 - : [val] "=&r" (*(__u64 *)__u.__c) \ 116 - : [mem] "ZB" (*(u64 *) p), [tmp] "r" (__tmp) \ 117 - : "memory"); \ 118 - break; \ 119 - } \ 120 - (typeof(*p))__u.__val; \ 62 + #define __smp_load_acquire(p) \ 63 + ({ \ 64 + typeof(*p) ___p1 = READ_ONCE(*p); \ 65 + compiletime_assert_atomic_type(*p); \ 66 + ldacq_mb(); \ 67 + ___p1; \ 121 68 }) 122 69 123 - #define __smp_store_release(p, v) \ 124 - do { \ 125 - union { typeof(*p) __val; char __c[1]; } __u = \ 126 - { .__val = (__force typeof(*p)) (v) }; \ 127 - unsigned long __tmp; \ 128 - compiletime_assert_atomic_type(*p); \ 129 - switch (sizeof(*p)) { \ 130 - case 1: \ 131 - __smp_mb(); \ 132 - *(volatile __u8 *)p = *(__u8 *)__u.__c; \ 133 - break; \ 134 - case 2: \ 135 - __smp_mb(); \ 136 - *(volatile __u16 *)p = *(__u16 *)__u.__c; \ 137 - break; \ 138 - case 4: \ 139 - __asm__ __volatile__( \ 140 - "amswap_db.w %[tmp], %[val], %[mem] \n" \ 141 - : [mem] "+ZB" (*(u32 *)p), [tmp] "=&r" (__tmp) \ 142 - : [val] "r" (*(__u32 *)__u.__c) \ 143 - : ); \ 144 - break; \ 145 - case 8: \ 146 - __asm__ __volatile__( \ 147 - "amswap_db.d %[tmp], %[val], %[mem] \n" \ 148 - : [mem] "+ZB" (*(u64 *)p), [tmp] "=&r" (__tmp) \ 149 - : [val] "r" (*(__u64 *)__u.__c) \ 150 - : ); \ 151 - break; \ 152 - } \ 70 + #define __smp_store_release(p, v) \ 71 + do { \ 72 + compiletime_assert_atomic_type(*p); \ 73 + strel_mb(); \ 74 + WRITE_ONCE(*p, v); \ 153 75 } while (0) 154 76 155 77 #define __smp_store_mb(p, v) \
+1 -1
arch/loongarch/include/asm/cpu-features.h
··· 64 64 #define cpu_has_eiodecode cpu_opt(LOONGARCH_CPU_EIODECODE) 65 65 #define cpu_has_guestid cpu_opt(LOONGARCH_CPU_GUESTID) 66 66 #define cpu_has_hypervisor cpu_opt(LOONGARCH_CPU_HYPERVISOR) 67 - 67 + #define cpu_has_ptw cpu_opt(LOONGARCH_CPU_PTW) 68 68 69 69 #endif /* __ASM_CPU_FEATURES_H */
+1
arch/loongarch/include/asm/cpu-info.h
··· 54 54 struct cache_desc cache_leaves[CACHE_LEAVES_MAX]; 55 55 int core; /* physical core number in package */ 56 56 int package;/* physical package number */ 57 + int global_id; /* physical global thread number */ 57 58 int vabits; /* Virtual Address size in bits */ 58 59 int pabits; /* Physical Address size in bits */ 59 60 unsigned int ksave_mask; /* Usable KSave mask. */
+2
arch/loongarch/include/asm/cpu.h
··· 98 98 #define CPU_FEATURE_EIODECODE 23 /* CPU has EXTIOI interrupt pin decode mode */ 99 99 #define CPU_FEATURE_GUESTID 24 /* CPU has GuestID feature */ 100 100 #define CPU_FEATURE_HYPERVISOR 25 /* CPU has hypervisor (running in VM) */ 101 + #define CPU_FEATURE_PTW 26 /* CPU has hardware page table walker */ 101 102 102 103 #define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG) 103 104 #define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM) ··· 126 125 #define LOONGARCH_CPU_EIODECODE BIT_ULL(CPU_FEATURE_EIODECODE) 127 126 #define LOONGARCH_CPU_GUESTID BIT_ULL(CPU_FEATURE_GUESTID) 128 127 #define LOONGARCH_CPU_HYPERVISOR BIT_ULL(CPU_FEATURE_HYPERVISOR) 128 + #define LOONGARCH_CPU_PTW BIT_ULL(CPU_FEATURE_PTW) 129 129 130 130 #endif /* _ASM_CPU_H */
+7
arch/loongarch/include/asm/fpregdef.h
··· 40 40 #define fs6 $f30 41 41 #define fs7 $f31 42 42 43 + #ifndef CONFIG_AS_HAS_FCSR_CLASS 43 44 /* 44 45 * Current binutils expects *GPRs* at FCSR position for the FCSR 45 46 * operation instructions, so define aliases for those used. ··· 49 48 #define fcsr1 $r1 50 49 #define fcsr2 $r2 51 50 #define fcsr3 $r3 51 + #else 52 + #define fcsr0 $fcsr0 53 + #define fcsr1 $fcsr1 54 + #define fcsr2 $fcsr2 55 + #define fcsr3 $fcsr3 56 + #endif 52 57 53 58 #endif /* _ASM_FPREGDEF_H */
+182 -3
arch/loongarch/include/asm/fpu.h
··· 28 28 extern void _save_fp(struct loongarch_fpu *); 29 29 extern void _restore_fp(struct loongarch_fpu *); 30 30 31 + extern void _save_lsx(struct loongarch_fpu *fpu); 32 + extern void _restore_lsx(struct loongarch_fpu *fpu); 33 + extern void _init_lsx_upper(void); 34 + extern void _restore_lsx_upper(struct loongarch_fpu *fpu); 35 + 36 + extern void _save_lasx(struct loongarch_fpu *fpu); 37 + extern void _restore_lasx(struct loongarch_fpu *fpu); 38 + extern void _init_lasx_upper(void); 39 + extern void _restore_lasx_upper(struct loongarch_fpu *fpu); 40 + 41 + static inline void enable_lsx(void); 42 + static inline void disable_lsx(void); 43 + static inline void save_lsx(struct task_struct *t); 44 + static inline void restore_lsx(struct task_struct *t); 45 + 46 + static inline void enable_lasx(void); 47 + static inline void disable_lasx(void); 48 + static inline void save_lasx(struct task_struct *t); 49 + static inline void restore_lasx(struct task_struct *t); 50 + 31 51 /* 32 52 * Mask the FCSR Cause bits according to the Enable bits, observing 33 53 * that Unimplemented is always enabled. ··· 62 42 { 63 43 return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_FPEN) ? 64 44 1 : 0; 45 + } 46 + 47 + static inline int is_lsx_enabled(void) 48 + { 49 + if (!cpu_has_lsx) 50 + return 0; 51 + 52 + return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_LSXEN) ? 53 + 1 : 0; 54 + } 55 + 56 + static inline int is_lasx_enabled(void) 57 + { 58 + if (!cpu_has_lasx) 59 + return 0; 60 + 61 + return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_LASXEN) ? 62 + 1 : 0; 63 + } 64 + 65 + static inline int is_simd_enabled(void) 66 + { 67 + return is_lsx_enabled() | is_lasx_enabled(); 65 68 } 66 69 67 70 #define enable_fpu() set_csr_euen(CSR_EUEN_FPEN) ··· 124 81 static inline void lose_fpu_inatomic(int save, struct task_struct *tsk) 125 82 { 126 83 if (is_fpu_owner()) { 127 - if (save) 128 - _save_fp(&tsk->thread.fpu); 129 - disable_fpu(); 84 + if (!is_simd_enabled()) { 85 + if (save) 86 + _save_fp(&tsk->thread.fpu); 87 + disable_fpu(); 88 + } else { 89 + if (save) { 90 + if (!is_lasx_enabled()) 91 + save_lsx(tsk); 92 + else 93 + save_lasx(tsk); 94 + } 95 + disable_fpu(); 96 + disable_lsx(); 97 + disable_lasx(); 98 + clear_tsk_thread_flag(tsk, TIF_USEDSIMD); 99 + } 130 100 clear_tsk_thread_flag(tsk, TIF_USEDFPU); 131 101 } 132 102 KSTK_EUEN(tsk) &= ~(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN); ··· 183 127 } 184 128 185 129 return tsk->thread.fpu.fpr; 130 + } 131 + 132 + static inline int is_simd_owner(void) 133 + { 134 + return test_thread_flag(TIF_USEDSIMD); 135 + } 136 + 137 + #ifdef CONFIG_CPU_HAS_LSX 138 + 139 + static inline void enable_lsx(void) 140 + { 141 + if (cpu_has_lsx) 142 + csr_xchg32(CSR_EUEN_LSXEN, CSR_EUEN_LSXEN, LOONGARCH_CSR_EUEN); 143 + } 144 + 145 + static inline void disable_lsx(void) 146 + { 147 + if (cpu_has_lsx) 148 + csr_xchg32(0, CSR_EUEN_LSXEN, LOONGARCH_CSR_EUEN); 149 + } 150 + 151 + static inline void save_lsx(struct task_struct *t) 152 + { 153 + if (cpu_has_lsx) 154 + _save_lsx(&t->thread.fpu); 155 + } 156 + 157 + static inline void restore_lsx(struct task_struct *t) 158 + { 159 + if (cpu_has_lsx) 160 + _restore_lsx(&t->thread.fpu); 161 + } 162 + 163 + static inline void init_lsx_upper(void) 164 + { 165 + /* 166 + * Check cpu_has_lsx only if it's a constant. This will allow the 167 + * compiler to optimise out code for CPUs without LSX without adding 168 + * an extra redundant check for CPUs with LSX. 169 + */ 170 + if (__builtin_constant_p(cpu_has_lsx) && !cpu_has_lsx) 171 + return; 172 + 173 + _init_lsx_upper(); 174 + } 175 + 176 + static inline void restore_lsx_upper(struct task_struct *t) 177 + { 178 + if (cpu_has_lsx) 179 + _restore_lsx_upper(&t->thread.fpu); 180 + } 181 + 182 + #else 183 + static inline void enable_lsx(void) {} 184 + static inline void disable_lsx(void) {} 185 + static inline void save_lsx(struct task_struct *t) {} 186 + static inline void restore_lsx(struct task_struct *t) {} 187 + static inline void init_lsx_upper(void) {} 188 + static inline void restore_lsx_upper(struct task_struct *t) {} 189 + #endif 190 + 191 + #ifdef CONFIG_CPU_HAS_LASX 192 + 193 + static inline void enable_lasx(void) 194 + { 195 + 196 + if (cpu_has_lasx) 197 + csr_xchg32(CSR_EUEN_LASXEN, CSR_EUEN_LASXEN, LOONGARCH_CSR_EUEN); 198 + } 199 + 200 + static inline void disable_lasx(void) 201 + { 202 + if (cpu_has_lasx) 203 + csr_xchg32(0, CSR_EUEN_LASXEN, LOONGARCH_CSR_EUEN); 204 + } 205 + 206 + static inline void save_lasx(struct task_struct *t) 207 + { 208 + if (cpu_has_lasx) 209 + _save_lasx(&t->thread.fpu); 210 + } 211 + 212 + static inline void restore_lasx(struct task_struct *t) 213 + { 214 + if (cpu_has_lasx) 215 + _restore_lasx(&t->thread.fpu); 216 + } 217 + 218 + static inline void init_lasx_upper(void) 219 + { 220 + if (cpu_has_lasx) 221 + _init_lasx_upper(); 222 + } 223 + 224 + static inline void restore_lasx_upper(struct task_struct *t) 225 + { 226 + if (cpu_has_lasx) 227 + _restore_lasx_upper(&t->thread.fpu); 228 + } 229 + 230 + #else 231 + static inline void enable_lasx(void) {} 232 + static inline void disable_lasx(void) {} 233 + static inline void save_lasx(struct task_struct *t) {} 234 + static inline void restore_lasx(struct task_struct *t) {} 235 + static inline void init_lasx_upper(void) {} 236 + static inline void restore_lasx_upper(struct task_struct *t) {} 237 + #endif 238 + 239 + static inline int thread_lsx_context_live(void) 240 + { 241 + if (__builtin_constant_p(cpu_has_lsx) && !cpu_has_lsx) 242 + return 0; 243 + 244 + return test_thread_flag(TIF_LSX_CTX_LIVE); 245 + } 246 + 247 + static inline int thread_lasx_context_live(void) 248 + { 249 + if (__builtin_constant_p(cpu_has_lasx) && !cpu_has_lasx) 250 + return 0; 251 + 252 + return test_thread_flag(TIF_LASX_CTX_LIVE); 186 253 } 187 254 188 255 #endif /* _ASM_FPU_H */
+30
arch/loongarch/include/asm/gpr-num.h
··· 9 9 .equ .L__gpr_num_$r\num, \num 10 10 .endr 11 11 12 + /* ABI names of registers */ 13 + .equ .L__gpr_num_$ra, 1 14 + .equ .L__gpr_num_$tp, 2 15 + .equ .L__gpr_num_$sp, 3 16 + .irp num,0,1,2,3,4,5,6,7 17 + .equ .L__gpr_num_$a\num, 4 + \num 18 + .endr 19 + .irp num,0,1,2,3,4,5,6,7,8 20 + .equ .L__gpr_num_$t\num, 12 + \num 21 + .endr 22 + .equ .L__gpr_num_$s9, 22 23 + .equ .L__gpr_num_$fp, 22 24 + .irp num,0,1,2,3,4,5,6,7,8 25 + .equ .L__gpr_num_$s\num, 23 + \num 26 + .endr 27 + 12 28 #else /* __ASSEMBLY__ */ 13 29 14 30 #define __DEFINE_ASM_GPR_NUMS \ 15 31 " .equ .L__gpr_num_zero, 0\n" \ 16 32 " .irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31\n" \ 17 33 " .equ .L__gpr_num_$r\\num, \\num\n" \ 34 + " .endr\n" \ 35 + " .equ .L__gpr_num_$ra, 1\n" \ 36 + " .equ .L__gpr_num_$tp, 2\n" \ 37 + " .equ .L__gpr_num_$sp, 3\n" \ 38 + " .irp num,0,1,2,3,4,5,6,7\n" \ 39 + " .equ .L__gpr_num_$a\\num, 4 + \\num\n" \ 40 + " .endr\n" \ 41 + " .irp num,0,1,2,3,4,5,6,7,8\n" \ 42 + " .equ .L__gpr_num_$t\\num, 12 + \\num\n" \ 43 + " .endr\n" \ 44 + " .equ .L__gpr_num_$s9, 22\n" \ 45 + " .equ .L__gpr_num_$fp, 22\n" \ 46 + " .irp num,0,1,2,3,4,5,6,7,8\n" \ 47 + " .equ .L__gpr_num_$s\\num, 23 + \\num\n" \ 18 48 " .endr\n" \ 19 49 20 50 #endif /* __ASSEMBLY__ */
+53 -2
arch/loongarch/include/asm/inst.h
··· 5 5 #ifndef _ASM_INST_H 6 6 #define _ASM_INST_H 7 7 8 + #include <linux/bitops.h> 8 9 #include <linux/types.h> 9 10 #include <asm/asm.h> 10 11 #include <asm/ptrace.h> ··· 16 15 #define ADDR_IMMMASK_LU52ID 0xFFF0000000000000 17 16 #define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000 18 17 #define ADDR_IMMMASK_LU12IW 0x00000000FFFFF000 18 + #define ADDR_IMMMASK_ORI 0x0000000000000FFF 19 19 #define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000 20 20 21 21 #define ADDR_IMMSHIFT_LU52ID 52 22 + #define ADDR_IMMSBIDX_LU52ID 11 22 23 #define ADDR_IMMSHIFT_LU32ID 32 24 + #define ADDR_IMMSBIDX_LU32ID 19 23 25 #define ADDR_IMMSHIFT_LU12IW 12 26 + #define ADDR_IMMSBIDX_LU12IW 19 27 + #define ADDR_IMMSHIFT_ORI 0 28 + #define ADDR_IMMSBIDX_ORI 63 24 29 #define ADDR_IMMSHIFT_ADDU16ID 16 30 + #define ADDR_IMMSBIDX_ADDU16ID 15 25 31 26 - #define ADDR_IMM(addr, INSN) ((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN) 32 + #define ADDR_IMM(addr, INSN) \ 33 + (sign_extend64(((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN), ADDR_IMMSBIDX_##INSN)) 27 34 28 35 enum reg0i15_op { 29 36 break_op = 0x54, ··· 187 178 amord_op = 0x70c7, 188 179 amxorw_op = 0x70c8, 189 180 amxord_op = 0x70c9, 181 + ammaxw_op = 0x70ca, 182 + ammaxd_op = 0x70cb, 183 + amminw_op = 0x70cc, 184 + ammind_op = 0x70cd, 185 + ammaxwu_op = 0x70ce, 186 + ammaxdu_op = 0x70cf, 187 + amminwu_op = 0x70d0, 188 + ammindu_op = 0x70d1, 189 + amswapdbw_op = 0x70d2, 190 + amswapdbd_op = 0x70d3, 191 + amadddbw_op = 0x70d4, 192 + amadddbd_op = 0x70d5, 193 + amanddbw_op = 0x70d6, 194 + amanddbd_op = 0x70d7, 195 + amordbw_op = 0x70d8, 196 + amordbd_op = 0x70d9, 197 + amxordbw_op = 0x70da, 198 + amxordbd_op = 0x70db, 199 + ammaxdbw_op = 0x70dc, 200 + ammaxdbd_op = 0x70dd, 201 + ammindbw_op = 0x70de, 202 + ammindbd_op = 0x70df, 203 + ammaxdbwu_op = 0x70e0, 204 + ammaxdbdu_op = 0x70e1, 205 + ammindbwu_op = 0x70e2, 206 + ammindbdu_op = 0x70e3, 190 207 fldgts_op = 0x70e8, 191 208 fldgtd_op = 0x70e9, 192 209 fldles_op = 0x70ea, ··· 470 435 void simu_pc(struct pt_regs *regs, union loongarch_instruction insn); 471 436 void simu_branch(struct pt_regs *regs, union loongarch_instruction insn); 472 437 438 + bool insns_not_supported(union loongarch_instruction insn); 439 + bool insns_need_simulation(union loongarch_instruction insn); 440 + void arch_simulate_insn(union loongarch_instruction insn, struct pt_regs *regs); 441 + 473 442 int larch_insn_read(void *addr, u32 *insnp); 474 443 int larch_insn_write(void *addr, u32 insn); 475 444 int larch_insn_patch_text(void *addr, u32 insn); ··· 482 443 u32 larch_insn_gen_b(unsigned long pc, unsigned long dest); 483 444 u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest); 484 445 446 + u32 larch_insn_gen_break(int imm); 447 + 485 448 u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk); 486 449 u32 larch_insn_gen_move(enum loongarch_gpr rd, enum loongarch_gpr rj); 487 450 488 451 u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm); 489 452 u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm); 490 453 u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm); 491 - u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest); 454 + u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm); 492 455 493 456 static inline bool signed_imm_check(long val, unsigned int bit) 494 457 { ··· 501 460 { 502 461 return val < (1UL << bit); 503 462 } 463 + 464 + #define DEF_EMIT_REG0I15_FORMAT(NAME, OP) \ 465 + static inline void emit_##NAME(union loongarch_instruction *insn, \ 466 + int imm) \ 467 + { \ 468 + insn->reg0i15_format.opcode = OP; \ 469 + insn->reg0i15_format.immediate = imm; \ 470 + } 471 + 472 + DEF_EMIT_REG0I15_FORMAT(break, break_op) 504 473 505 474 #define DEF_EMIT_REG0I26_FORMAT(NAME, OP) \ 506 475 static inline void emit_##NAME(union loongarch_instruction *insn, \
+1 -1
arch/loongarch/include/asm/io.h
··· 62 62 #define ioremap_cache(offset, size) \ 63 63 ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL)) 64 64 65 - #define mmiowb() asm volatile ("dbar 0" ::: "memory") 65 + #define mmiowb() wmb() 66 66 67 67 /* 68 68 * String version of I/O memory access operations.
+50
arch/loongarch/include/asm/jump_label.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (C) 2023 Loongson Technology Corporation Limited 4 + * 5 + * Based on arch/arm64/include/asm/jump_label.h 6 + */ 7 + #ifndef __ASM_JUMP_LABEL_H 8 + #define __ASM_JUMP_LABEL_H 9 + 10 + #ifndef __ASSEMBLY__ 11 + 12 + #include <linux/types.h> 13 + 14 + #define JUMP_LABEL_NOP_SIZE 4 15 + 16 + #define JUMP_TABLE_ENTRY \ 17 + ".pushsection __jump_table, \"aw\" \n\t" \ 18 + ".align 3 \n\t" \ 19 + ".long 1b - ., %l[l_yes] - . \n\t" \ 20 + ".quad %0 - . \n\t" \ 21 + ".popsection \n\t" 22 + 23 + static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch) 24 + { 25 + asm_volatile_goto( 26 + "1: nop \n\t" 27 + JUMP_TABLE_ENTRY 28 + : : "i"(&((char *)key)[branch]) : : l_yes); 29 + 30 + return false; 31 + 32 + l_yes: 33 + return true; 34 + } 35 + 36 + static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch) 37 + { 38 + asm_volatile_goto( 39 + "1: b %l[l_yes] \n\t" 40 + JUMP_TABLE_ENTRY 41 + : : "i"(&((char *)key)[branch]) : : l_yes); 42 + 43 + return false; 44 + 45 + l_yes: 46 + return true; 47 + } 48 + 49 + #endif /* __ASSEMBLY__ */ 50 + #endif /* __ASM_JUMP_LABEL_H */
-5
arch/loongarch/include/asm/kdebug.h
··· 13 13 DIE_FP, 14 14 DIE_SIMD, 15 15 DIE_TRAP, 16 - DIE_PAGE_FAULT, 17 - DIE_BREAK, 18 - DIE_SSTEPBP, 19 - DIE_UPROBE, 20 - DIE_UPROBE_XOL, 21 16 }; 22 17 23 18 #endif /* _ASM_LOONGARCH_KDEBUG_H */
+1 -4
arch/loongarch/include/asm/kprobes.h
··· 22 22 23 23 #define kretprobe_blacklist_size 0 24 24 25 - typedef union loongarch_instruction kprobe_opcode_t; 25 + typedef u32 kprobe_opcode_t; 26 26 27 27 /* Architecture specific copy of original instruction */ 28 28 struct arch_specific_insn { ··· 48 48 bool kprobe_fault_handler(struct pt_regs *regs, int trapnr); 49 49 bool kprobe_breakpoint_handler(struct pt_regs *regs); 50 50 bool kprobe_singlestep_handler(struct pt_regs *regs); 51 - 52 - void __kretprobe_trampoline(void); 53 - void *trampoline_probe_handler(struct pt_regs *regs); 54 51 55 52 #else /* !CONFIG_KPROBES */ 56 53
+23 -53
arch/loongarch/include/asm/loongarch.h
··· 56 56 #undef _IFC_REG 57 57 58 58 /* CPUCFG */ 59 - static inline u32 read_cpucfg(u32 reg) 60 - { 61 - return __cpucfg(reg); 62 - } 59 + #define read_cpucfg(reg) __cpucfg(reg) 63 60 64 61 #endif /* !__ASSEMBLY__ */ 65 62 ··· 135 138 #define CPUCFG2_MIPSBT BIT(20) 136 139 #define CPUCFG2_LSPW BIT(21) 137 140 #define CPUCFG2_LAM BIT(22) 141 + #define CPUCFG2_PTW BIT(24) 138 142 139 143 #define LOONGARCH_CPUCFG3 0x3 140 144 #define CPUCFG3_CCDMA BIT(0) ··· 204 206 #ifndef __ASSEMBLY__ 205 207 206 208 /* CSR */ 207 - static __always_inline u32 csr_read32(u32 reg) 208 - { 209 - return __csrrd_w(reg); 210 - } 211 - 212 - static __always_inline u64 csr_read64(u32 reg) 213 - { 214 - return __csrrd_d(reg); 215 - } 216 - 217 - static __always_inline void csr_write32(u32 val, u32 reg) 218 - { 219 - __csrwr_w(val, reg); 220 - } 221 - 222 - static __always_inline void csr_write64(u64 val, u32 reg) 223 - { 224 - __csrwr_d(val, reg); 225 - } 226 - 227 - static __always_inline u32 csr_xchg32(u32 val, u32 mask, u32 reg) 228 - { 229 - return __csrxchg_w(val, mask, reg); 230 - } 231 - 232 - static __always_inline u64 csr_xchg64(u64 val, u64 mask, u32 reg) 233 - { 234 - return __csrxchg_d(val, mask, reg); 235 - } 209 + #define csr_read32(reg) __csrrd_w(reg) 210 + #define csr_read64(reg) __csrrd_d(reg) 211 + #define csr_write32(val, reg) __csrwr_w(val, reg) 212 + #define csr_write64(val, reg) __csrwr_d(val, reg) 213 + #define csr_xchg32(val, mask, reg) __csrxchg_w(val, mask, reg) 214 + #define csr_xchg64(val, mask, reg) __csrxchg_d(val, mask, reg) 236 215 237 216 /* IOCSR */ 238 - static __always_inline u32 iocsr_read32(u32 reg) 239 - { 240 - return __iocsrrd_w(reg); 241 - } 242 - 243 - static __always_inline u64 iocsr_read64(u32 reg) 244 - { 245 - return __iocsrrd_d(reg); 246 - } 247 - 248 - static __always_inline void iocsr_write32(u32 val, u32 reg) 249 - { 250 - __iocsrwr_w(val, reg); 251 - } 252 - 253 - static __always_inline void iocsr_write64(u64 val, u32 reg) 254 - { 255 - __iocsrwr_d(val, reg); 256 - } 217 + #define iocsr_read32(reg) __iocsrrd_w(reg) 218 + #define iocsr_read64(reg) __iocsrrd_d(reg) 219 + #define iocsr_write32(val, reg) __iocsrwr_w(val, reg) 220 + #define iocsr_write64(val, reg) __iocsrwr_d(val, reg) 257 221 258 222 #endif /* !__ASSEMBLY__ */ 259 223 ··· 413 453 #define CSR_PWCTL0_PTBASE (_ULCAST_(0x1f) << CSR_PWCTL0_PTBASE_SHIFT) 414 454 415 455 #define LOONGARCH_CSR_PWCTL1 0x1d /* PWCtl1 */ 456 + #define CSR_PWCTL1_PTW_SHIFT 24 457 + #define CSR_PWCTL1_PTW_WIDTH 1 458 + #define CSR_PWCTL1_PTW (_ULCAST_(0x1) << CSR_PWCTL1_PTW_SHIFT) 416 459 #define CSR_PWCTL1_DIR3WIDTH_SHIFT 18 417 460 #define CSR_PWCTL1_DIR3WIDTH_WIDTH 5 418 461 #define CSR_PWCTL1_DIR3WIDTH (_ULCAST_(0x1f) << CSR_PWCTL1_DIR3WIDTH_SHIFT) ··· 1404 1441 #define EXCCODE_INT_START 64 1405 1442 #define EXCCODE_INT_END (EXCCODE_INT_START + EXCCODE_INT_NUM - 1) 1406 1443 1407 - /* FPU register names */ 1444 + /* FPU Status Register Names */ 1445 + #ifndef CONFIG_AS_HAS_FCSR_CLASS 1408 1446 #define LOONGARCH_FCSR0 $r0 1409 1447 #define LOONGARCH_FCSR1 $r1 1410 1448 #define LOONGARCH_FCSR2 $r2 1411 1449 #define LOONGARCH_FCSR3 $r3 1450 + #else 1451 + #define LOONGARCH_FCSR0 $fcsr0 1452 + #define LOONGARCH_FCSR1 $fcsr1 1453 + #define LOONGARCH_FCSR2 $fcsr2 1454 + #define LOONGARCH_FCSR3 $fcsr3 1455 + #endif 1412 1456 1413 1457 /* FPU Status Register Values */ 1414 1458 #define FPU_CSR_RSVD 0xe0e0fce0
+1 -1
arch/loongarch/include/asm/module.h
··· 55 55 lu12iw = larch_insn_gen_lu12iw(LOONGARCH_GPR_T1, ADDR_IMM(val, LU12IW)); 56 56 lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID)); 57 57 lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID)); 58 - jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, 0, (val & 0xfff)); 58 + jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, ADDR_IMM(val, ORI)); 59 59 60 60 return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl }; 61 61 }
+1
arch/loongarch/include/asm/page.h
··· 81 81 #define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET)) 82 82 83 83 #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) 84 + #define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x)) 84 85 85 86 #define virt_to_pfn(kaddr) PFN_DOWN(PHYSADDR(kaddr)) 86 87 #define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
+5 -1
arch/loongarch/include/asm/percpu.h
··· 14 14 * loaded. Tell the compiler this fact when using explicit relocs. 15 15 */ 16 16 #if defined(MODULE) && defined(CONFIG_AS_HAS_EXPLICIT_RELOCS) 17 - #define PER_CPU_ATTRIBUTES __attribute__((model("extreme"))) 17 + # if __has_attribute(model) 18 + # define PER_CPU_ATTRIBUTES __attribute__((model("extreme"))) 19 + # else 20 + # error compiler support for the model attribute is necessary when a recent assembler is used 21 + # endif 18 22 #endif 19 23 20 24 /* Use r21 for fast access */
+2 -2
arch/loongarch/include/asm/pgtable.h
··· 362 362 */ 363 363 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } 364 364 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } 365 - static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; } 365 + static inline int pte_dirty(pte_t pte) { return pte_val(pte) & (_PAGE_DIRTY | _PAGE_MODIFIED); } 366 366 367 367 static inline pte_t pte_mkold(pte_t pte) 368 368 { ··· 506 506 507 507 static inline int pmd_dirty(pmd_t pmd) 508 508 { 509 - return !!(pmd_val(pmd) & _PAGE_MODIFIED); 509 + return !!(pmd_val(pmd) & (_PAGE_DIRTY | _PAGE_MODIFIED)); 510 510 } 511 511 512 512 static inline pmd_t pmd_mkclean(pmd_t pmd)
+18
arch/loongarch/include/asm/qspinlock.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _ASM_QSPINLOCK_H 3 + #define _ASM_QSPINLOCK_H 4 + 5 + #include <asm-generic/qspinlock_types.h> 6 + 7 + #define queued_spin_unlock queued_spin_unlock 8 + 9 + static inline void queued_spin_unlock(struct qspinlock *lock) 10 + { 11 + compiletime_assert_atomic_type(lock->locked); 12 + c_sync(); 13 + WRITE_ONCE(lock->locked, 0); 14 + } 15 + 16 + #include <asm-generic/qspinlock.h> 17 + 18 + #endif /* _ASM_QSPINLOCK_H */
+10
arch/loongarch/include/asm/suspend.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __ASM_SUSPEND_H 3 + #define __ASM_SUSPEND_H 4 + 5 + void loongarch_common_suspend(void); 6 + void loongarch_common_resume(void); 7 + void loongarch_suspend_enter(void); 8 + void loongarch_wakeup_start(void); 9 + 10 + #endif
+22 -24
arch/loongarch/include/asm/tlb.h
··· 88 88 INVTLB_GID_ADDR = 0x16, 89 89 }; 90 90 91 - /* 92 - * invtlb op info addr 93 - * (0x1 << 26) | (0x24 << 20) | (0x13 << 15) | 94 - * (addr << 10) | (info << 5) | op 95 - */ 96 - static inline void invtlb(u32 op, u32 info, u64 addr) 91 + static __always_inline void invtlb(u32 op, u32 info, u64 addr) 97 92 { 98 93 __asm__ __volatile__( 99 - "parse_r addr,%0\n\t" 100 - "parse_r info,%1\n\t" 101 - ".word ((0x6498000) | (addr << 10) | (info << 5) | %2)\n\t" 94 + "invtlb %0, %1, %2\n\t" 102 95 : 103 - : "r"(addr), "r"(info), "i"(op) 104 - : 96 + : "i"(op), "r"(info), "r"(addr) 97 + : "memory" 105 98 ); 106 99 } 107 100 108 - static inline void invtlb_addr(u32 op, u32 info, u64 addr) 101 + static __always_inline void invtlb_addr(u32 op, u32 info, u64 addr) 109 102 { 103 + BUILD_BUG_ON(!__builtin_constant_p(info) || info != 0); 110 104 __asm__ __volatile__( 111 - "parse_r addr,%0\n\t" 112 - ".word ((0x6498000) | (addr << 10) | (0 << 5) | %1)\n\t" 105 + "invtlb %0, $zero, %1\n\t" 113 106 : 114 - : "r"(addr), "i"(op) 115 - : 107 + : "i"(op), "r"(addr) 108 + : "memory" 116 109 ); 117 110 } 118 111 119 - static inline void invtlb_info(u32 op, u32 info, u64 addr) 112 + static __always_inline void invtlb_info(u32 op, u32 info, u64 addr) 120 113 { 114 + BUILD_BUG_ON(!__builtin_constant_p(addr) || addr != 0); 121 115 __asm__ __volatile__( 122 - "parse_r info,%0\n\t" 123 - ".word ((0x6498000) | (0 << 10) | (info << 5) | %1)\n\t" 116 + "invtlb %0, %1, $zero\n\t" 124 117 : 125 - : "r"(info), "i"(op) 126 - : 118 + : "i"(op), "r"(info) 119 + : "memory" 127 120 ); 128 121 } 129 122 130 - static inline void invtlb_all(u32 op, u32 info, u64 addr) 123 + static __always_inline void invtlb_all(u32 op, u32 info, u64 addr) 131 124 { 125 + BUILD_BUG_ON(!__builtin_constant_p(info) || info != 0); 126 + BUILD_BUG_ON(!__builtin_constant_p(addr) || addr != 0); 132 127 __asm__ __volatile__( 133 - ".word ((0x6498000) | (0 << 10) | (0 << 5) | %0)\n\t" 128 + "invtlb %0, $zero, $zero\n\t" 134 129 : 135 130 : "i"(op) 136 - : 131 + : "memory" 137 132 ); 138 133 } 139 134 ··· 158 163 extern void handle_tlb_modify(void); 159 164 extern void handle_tlb_refill(void); 160 165 extern void handle_tlb_protect(void); 166 + extern void handle_tlb_load_ptw(void); 167 + extern void handle_tlb_store_ptw(void); 168 + extern void handle_tlb_modify_ptw(void); 161 169 162 170 extern void dump_tlb_all(void); 163 171 extern void dump_tlb_regs(void);
+36
arch/loongarch/include/asm/uprobes.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + #ifndef __ASM_LOONGARCH_UPROBES_H 3 + #define __ASM_LOONGARCH_UPROBES_H 4 + 5 + #include <asm/inst.h> 6 + 7 + typedef u32 uprobe_opcode_t; 8 + 9 + #define MAX_UINSN_BYTES 8 10 + #define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES 11 + 12 + #define UPROBE_SWBP_INSN larch_insn_gen_break(BRK_UPROBE_BP) 13 + #define UPROBE_SWBP_INSN_SIZE LOONGARCH_INSN_SIZE 14 + 15 + #define UPROBE_XOLBP_INSN larch_insn_gen_break(BRK_UPROBE_XOLBP) 16 + 17 + struct arch_uprobe { 18 + unsigned long resume_era; 19 + u32 insn[2]; 20 + u32 ixol[2]; 21 + bool simulate; 22 + }; 23 + 24 + struct arch_uprobe_task { 25 + unsigned long saved_trap_nr; 26 + }; 27 + 28 + #ifdef CONFIG_UPROBES 29 + bool uprobe_breakpoint_handler(struct pt_regs *regs); 30 + bool uprobe_singlestep_handler(struct pt_regs *regs); 31 + #else /* !CONFIG_UPROBES */ 32 + static inline bool uprobe_breakpoint_handler(struct pt_regs *regs) { return false; } 33 + static inline bool uprobe_singlestep_handler(struct pt_regs *regs) { return false; } 34 + #endif /* CONFIG_UPROBES */ 35 + 36 + #endif /* __ASM_LOONGARCH_UPROBES_H */
+8 -1
arch/loongarch/include/asm/vdso/gettimeofday.h
··· 91 91 92 92 static __always_inline const struct vdso_data *__arch_get_vdso_data(void) 93 93 { 94 - return get_vdso_data(); 94 + return (const struct vdso_data *)get_vdso_data(); 95 95 } 96 96 97 + #ifdef CONFIG_TIME_NS 98 + static __always_inline 99 + const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) 100 + { 101 + return (const struct vdso_data *)(get_vdso_data() + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE); 102 + } 103 + #endif 97 104 #endif /* !__ASSEMBLY__ */ 98 105 99 106 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
+27 -5
arch/loongarch/include/asm/vdso/vdso.h
··· 16 16 17 17 struct loongarch_vdso_data { 18 18 struct vdso_pcpu_data pdata[NR_CPUS]; 19 - struct vdso_data data[CS_BASES]; /* Arch-independent data */ 20 19 }; 21 20 22 - #define VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data)) 21 + /* 22 + * The layout of vvar: 23 + * 24 + * high 25 + * +---------------------+--------------------------+ 26 + * | loongarch vdso data | LOONGARCH_VDSO_DATA_SIZE | 27 + * +---------------------+--------------------------+ 28 + * | time-ns vdso data | PAGE_SIZE | 29 + * +---------------------+--------------------------+ 30 + * | generic vdso data | PAGE_SIZE | 31 + * +---------------------+--------------------------+ 32 + * low 33 + */ 34 + #define LOONGARCH_VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data)) 35 + #define LOONGARCH_VDSO_DATA_PAGES (LOONGARCH_VDSO_DATA_SIZE >> PAGE_SHIFT) 36 + 37 + enum vvar_pages { 38 + VVAR_GENERIC_PAGE_OFFSET, 39 + VVAR_TIMENS_PAGE_OFFSET, 40 + VVAR_LOONGARCH_PAGES_START, 41 + VVAR_LOONGARCH_PAGES_END = VVAR_LOONGARCH_PAGES_START + LOONGARCH_VDSO_DATA_PAGES - 1, 42 + VVAR_NR_PAGES, 43 + }; 44 + 45 + #define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT) 23 46 24 47 static inline unsigned long get_vdso_base(void) 25 48 { ··· 57 34 return addr; 58 35 } 59 36 60 - static inline const struct vdso_data *get_vdso_data(void) 37 + static inline unsigned long get_vdso_data(void) 61 38 { 62 - return (const struct vdso_data *)(get_vdso_base() 63 - - VDSO_DATA_SIZE + SMP_CACHE_BYTES * NR_CPUS); 39 + return get_vdso_base() - VVAR_SIZE; 64 40 } 65 41 66 42 #endif /* __ASSEMBLY__ */
+1
arch/loongarch/include/uapi/asm/hwcap.h
··· 16 16 #define HWCAP_LOONGARCH_LBT_X86 (1 << 10) 17 17 #define HWCAP_LOONGARCH_LBT_ARM (1 << 11) 18 18 #define HWCAP_LOONGARCH_LBT_MIPS (1 << 12) 19 + #define HWCAP_LOONGARCH_PTW (1 << 13) 19 20 20 21 #endif /* _UAPI_ASM_HWCAP_H */
+13 -3
arch/loongarch/include/uapi/asm/ptrace.h
··· 41 41 } __attribute__((aligned(8))); 42 42 43 43 struct user_fp_state { 44 - uint64_t fpr[32]; 45 - uint64_t fcc; 46 - uint32_t fcsr; 44 + uint64_t fpr[32]; 45 + uint64_t fcc; 46 + uint32_t fcsr; 47 + }; 48 + 49 + struct user_lsx_state { 50 + /* 32 registers, 128 bits width per register. */ 51 + uint64_t vregs[32*2]; 52 + }; 53 + 54 + struct user_lasx_state { 55 + /* 32 registers, 256 bits width per register. */ 56 + uint64_t vregs[32*4]; 47 57 }; 48 58 49 59 struct user_watch_state {
+18
arch/loongarch/include/uapi/asm/sigcontext.h
··· 41 41 __u32 fcsr; 42 42 }; 43 43 44 + /* LSX context */ 45 + #define LSX_CTX_MAGIC 0x53580001 46 + #define LSX_CTX_ALIGN 16 47 + struct lsx_context { 48 + __u64 regs[2*32]; 49 + __u64 fcc; 50 + __u32 fcsr; 51 + }; 52 + 53 + /* LASX context */ 54 + #define LASX_CTX_MAGIC 0x41535801 55 + #define LASX_CTX_ALIGN 32 56 + struct lasx_context { 57 + __u64 regs[4*32]; 58 + __u64 fcc; 59 + __u32 fcsr; 60 + }; 61 + 44 62 #endif /* _UAPI_ASM_SIGCONTEXT_H */
+7 -1
arch/loongarch/kernel/Makefile
··· 28 28 CFLAGS_REMOVE_inst.o = $(CC_FLAGS_FTRACE) 29 29 CFLAGS_REMOVE_time.o = $(CC_FLAGS_FTRACE) 30 30 CFLAGS_REMOVE_perf_event.o = $(CC_FLAGS_FTRACE) 31 + CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE) 32 + CFLAGS_REMOVE_rethook_trampoline.o = $(CC_FLAGS_FTRACE) 31 33 endif 32 34 33 35 obj-$(CONFIG_MODULES) += module.o module-sections.o ··· 54 52 obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_regs.o 55 53 obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o 56 54 57 - obj-$(CONFIG_KPROBES) += kprobes.o kprobes_trampoline.o 55 + obj-$(CONFIG_KPROBES) += kprobes.o 56 + obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o 57 + obj-$(CONFIG_UPROBES) += uprobes.o 58 + 59 + obj-$(CONFIG_JUMP_LABEL) += jump_label.o 58 60 59 61 CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
+32
arch/loongarch/kernel/acpi.c
··· 33 33 34 34 #define PREFIX "ACPI: " 35 35 36 + struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; 37 + 36 38 void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size) 37 39 { 38 40 ··· 101 99 102 100 acpi_table_print_madt_entry(&header->common); 103 101 #ifdef CONFIG_SMP 102 + acpi_core_pic[processor->core_id] = *processor; 104 103 set_processor_mask(processor->core_id, processor->flags); 105 104 #endif 106 105 ··· 141 138 acpi_parse_eio_master, MAX_IO_PICS); 142 139 143 140 loongson_sysconf.nr_cpus = num_processors; 141 + } 142 + 143 + int pptt_enabled; 144 + 145 + int __init parse_acpi_topology(void) 146 + { 147 + int cpu, topology_id; 148 + 149 + for_each_possible_cpu(cpu) { 150 + topology_id = find_acpi_cpu_topology(cpu, 0); 151 + if (topology_id < 0) { 152 + pr_warn("Invalid BIOS PPTT\n"); 153 + return -ENOENT; 154 + } 155 + 156 + if (acpi_pptt_cpu_is_thread(cpu) <= 0) 157 + cpu_data[cpu].core = topology_id; 158 + else { 159 + topology_id = find_acpi_cpu_topology(cpu, 1); 160 + if (topology_id < 0) 161 + return -ENOENT; 162 + 163 + cpu_data[cpu].core = topology_id; 164 + } 165 + } 166 + 167 + pptt_enabled = 1; 168 + 169 + return 0; 144 170 } 145 171 146 172 #ifndef CONFIG_SUSPEND
+16
arch/loongarch/kernel/cpu-probe.c
··· 116 116 c->options |= LOONGARCH_CPU_FPU; 117 117 elf_hwcap |= HWCAP_LOONGARCH_FPU; 118 118 } 119 + #ifdef CONFIG_CPU_HAS_LSX 120 + if (config & CPUCFG2_LSX) { 121 + c->options |= LOONGARCH_CPU_LSX; 122 + elf_hwcap |= HWCAP_LOONGARCH_LSX; 123 + } 124 + #endif 125 + #ifdef CONFIG_CPU_HAS_LASX 126 + if (config & CPUCFG2_LASX) { 127 + c->options |= LOONGARCH_CPU_LASX; 128 + elf_hwcap |= HWCAP_LOONGARCH_LASX; 129 + } 130 + #endif 119 131 if (config & CPUCFG2_COMPLEX) { 120 132 c->options |= LOONGARCH_CPU_COMPLEX; 121 133 elf_hwcap |= HWCAP_LOONGARCH_COMPLEX; ··· 135 123 if (config & CPUCFG2_CRYPTO) { 136 124 c->options |= LOONGARCH_CPU_CRYPTO; 137 125 elf_hwcap |= HWCAP_LOONGARCH_CRYPTO; 126 + } 127 + if (config & CPUCFG2_PTW) { 128 + c->options |= LOONGARCH_CPU_PTW; 129 + elf_hwcap |= HWCAP_LOONGARCH_PTW; 138 130 } 139 131 if (config & CPUCFG2_LVZP) { 140 132 c->options |= LOONGARCH_CPU_LVZ;
+3 -3
arch/loongarch/kernel/efi-header.S
··· 24 24 .byte 0x02 /* MajorLinkerVersion */ 25 25 .byte 0x14 /* MinorLinkerVersion */ 26 26 .long __inittext_end - .Lefi_header_end /* SizeOfCode */ 27 - .long _end - __initdata_begin /* SizeOfInitializedData */ 27 + .long _kernel_vsize /* SizeOfInitializedData */ 28 28 .long 0 /* SizeOfUninitializedData */ 29 29 .long __efistub_efi_pe_entry - _head /* AddressOfEntryPoint */ 30 30 .long .Lefi_header_end - _head /* BaseOfCode */ ··· 79 79 IMAGE_SCN_MEM_EXECUTE /* Characteristics */ 80 80 81 81 .ascii ".data\0\0\0" 82 - .long _end - __initdata_begin /* VirtualSize */ 82 + .long _kernel_vsize /* VirtualSize */ 83 83 .long __initdata_begin - _head /* VirtualAddress */ 84 - .long _edata - __initdata_begin /* SizeOfRawData */ 84 + .long _kernel_rsize /* SizeOfRawData */ 85 85 .long __initdata_begin - _head /* PointerToRawData */ 86 86 87 87 .long 0 /* PointerToRelocations */
+270
arch/loongarch/kernel/fpu.S
··· 145 145 movgr2fcsr fcsr0, \tmp0 146 146 .endm 147 147 148 + .macro sc_save_lsx base 149 + #ifdef CONFIG_CPU_HAS_LSX 150 + EX vst $vr0, \base, (0 * LSX_REG_WIDTH) 151 + EX vst $vr1, \base, (1 * LSX_REG_WIDTH) 152 + EX vst $vr2, \base, (2 * LSX_REG_WIDTH) 153 + EX vst $vr3, \base, (3 * LSX_REG_WIDTH) 154 + EX vst $vr4, \base, (4 * LSX_REG_WIDTH) 155 + EX vst $vr5, \base, (5 * LSX_REG_WIDTH) 156 + EX vst $vr6, \base, (6 * LSX_REG_WIDTH) 157 + EX vst $vr7, \base, (7 * LSX_REG_WIDTH) 158 + EX vst $vr8, \base, (8 * LSX_REG_WIDTH) 159 + EX vst $vr9, \base, (9 * LSX_REG_WIDTH) 160 + EX vst $vr10, \base, (10 * LSX_REG_WIDTH) 161 + EX vst $vr11, \base, (11 * LSX_REG_WIDTH) 162 + EX vst $vr12, \base, (12 * LSX_REG_WIDTH) 163 + EX vst $vr13, \base, (13 * LSX_REG_WIDTH) 164 + EX vst $vr14, \base, (14 * LSX_REG_WIDTH) 165 + EX vst $vr15, \base, (15 * LSX_REG_WIDTH) 166 + EX vst $vr16, \base, (16 * LSX_REG_WIDTH) 167 + EX vst $vr17, \base, (17 * LSX_REG_WIDTH) 168 + EX vst $vr18, \base, (18 * LSX_REG_WIDTH) 169 + EX vst $vr19, \base, (19 * LSX_REG_WIDTH) 170 + EX vst $vr20, \base, (20 * LSX_REG_WIDTH) 171 + EX vst $vr21, \base, (21 * LSX_REG_WIDTH) 172 + EX vst $vr22, \base, (22 * LSX_REG_WIDTH) 173 + EX vst $vr23, \base, (23 * LSX_REG_WIDTH) 174 + EX vst $vr24, \base, (24 * LSX_REG_WIDTH) 175 + EX vst $vr25, \base, (25 * LSX_REG_WIDTH) 176 + EX vst $vr26, \base, (26 * LSX_REG_WIDTH) 177 + EX vst $vr27, \base, (27 * LSX_REG_WIDTH) 178 + EX vst $vr28, \base, (28 * LSX_REG_WIDTH) 179 + EX vst $vr29, \base, (29 * LSX_REG_WIDTH) 180 + EX vst $vr30, \base, (30 * LSX_REG_WIDTH) 181 + EX vst $vr31, \base, (31 * LSX_REG_WIDTH) 182 + #endif 183 + .endm 184 + 185 + .macro sc_restore_lsx base 186 + #ifdef CONFIG_CPU_HAS_LSX 187 + EX vld $vr0, \base, (0 * LSX_REG_WIDTH) 188 + EX vld $vr1, \base, (1 * LSX_REG_WIDTH) 189 + EX vld $vr2, \base, (2 * LSX_REG_WIDTH) 190 + EX vld $vr3, \base, (3 * LSX_REG_WIDTH) 191 + EX vld $vr4, \base, (4 * LSX_REG_WIDTH) 192 + EX vld $vr5, \base, (5 * LSX_REG_WIDTH) 193 + EX vld $vr6, \base, (6 * LSX_REG_WIDTH) 194 + EX vld $vr7, \base, (7 * LSX_REG_WIDTH) 195 + EX vld $vr8, \base, (8 * LSX_REG_WIDTH) 196 + EX vld $vr9, \base, (9 * LSX_REG_WIDTH) 197 + EX vld $vr10, \base, (10 * LSX_REG_WIDTH) 198 + EX vld $vr11, \base, (11 * LSX_REG_WIDTH) 199 + EX vld $vr12, \base, (12 * LSX_REG_WIDTH) 200 + EX vld $vr13, \base, (13 * LSX_REG_WIDTH) 201 + EX vld $vr14, \base, (14 * LSX_REG_WIDTH) 202 + EX vld $vr15, \base, (15 * LSX_REG_WIDTH) 203 + EX vld $vr16, \base, (16 * LSX_REG_WIDTH) 204 + EX vld $vr17, \base, (17 * LSX_REG_WIDTH) 205 + EX vld $vr18, \base, (18 * LSX_REG_WIDTH) 206 + EX vld $vr19, \base, (19 * LSX_REG_WIDTH) 207 + EX vld $vr20, \base, (20 * LSX_REG_WIDTH) 208 + EX vld $vr21, \base, (21 * LSX_REG_WIDTH) 209 + EX vld $vr22, \base, (22 * LSX_REG_WIDTH) 210 + EX vld $vr23, \base, (23 * LSX_REG_WIDTH) 211 + EX vld $vr24, \base, (24 * LSX_REG_WIDTH) 212 + EX vld $vr25, \base, (25 * LSX_REG_WIDTH) 213 + EX vld $vr26, \base, (26 * LSX_REG_WIDTH) 214 + EX vld $vr27, \base, (27 * LSX_REG_WIDTH) 215 + EX vld $vr28, \base, (28 * LSX_REG_WIDTH) 216 + EX vld $vr29, \base, (29 * LSX_REG_WIDTH) 217 + EX vld $vr30, \base, (30 * LSX_REG_WIDTH) 218 + EX vld $vr31, \base, (31 * LSX_REG_WIDTH) 219 + #endif 220 + .endm 221 + 222 + .macro sc_save_lasx base 223 + #ifdef CONFIG_CPU_HAS_LASX 224 + EX xvst $xr0, \base, (0 * LASX_REG_WIDTH) 225 + EX xvst $xr1, \base, (1 * LASX_REG_WIDTH) 226 + EX xvst $xr2, \base, (2 * LASX_REG_WIDTH) 227 + EX xvst $xr3, \base, (3 * LASX_REG_WIDTH) 228 + EX xvst $xr4, \base, (4 * LASX_REG_WIDTH) 229 + EX xvst $xr5, \base, (5 * LASX_REG_WIDTH) 230 + EX xvst $xr6, \base, (6 * LASX_REG_WIDTH) 231 + EX xvst $xr7, \base, (7 * LASX_REG_WIDTH) 232 + EX xvst $xr8, \base, (8 * LASX_REG_WIDTH) 233 + EX xvst $xr9, \base, (9 * LASX_REG_WIDTH) 234 + EX xvst $xr10, \base, (10 * LASX_REG_WIDTH) 235 + EX xvst $xr11, \base, (11 * LASX_REG_WIDTH) 236 + EX xvst $xr12, \base, (12 * LASX_REG_WIDTH) 237 + EX xvst $xr13, \base, (13 * LASX_REG_WIDTH) 238 + EX xvst $xr14, \base, (14 * LASX_REG_WIDTH) 239 + EX xvst $xr15, \base, (15 * LASX_REG_WIDTH) 240 + EX xvst $xr16, \base, (16 * LASX_REG_WIDTH) 241 + EX xvst $xr17, \base, (17 * LASX_REG_WIDTH) 242 + EX xvst $xr18, \base, (18 * LASX_REG_WIDTH) 243 + EX xvst $xr19, \base, (19 * LASX_REG_WIDTH) 244 + EX xvst $xr20, \base, (20 * LASX_REG_WIDTH) 245 + EX xvst $xr21, \base, (21 * LASX_REG_WIDTH) 246 + EX xvst $xr22, \base, (22 * LASX_REG_WIDTH) 247 + EX xvst $xr23, \base, (23 * LASX_REG_WIDTH) 248 + EX xvst $xr24, \base, (24 * LASX_REG_WIDTH) 249 + EX xvst $xr25, \base, (25 * LASX_REG_WIDTH) 250 + EX xvst $xr26, \base, (26 * LASX_REG_WIDTH) 251 + EX xvst $xr27, \base, (27 * LASX_REG_WIDTH) 252 + EX xvst $xr28, \base, (28 * LASX_REG_WIDTH) 253 + EX xvst $xr29, \base, (29 * LASX_REG_WIDTH) 254 + EX xvst $xr30, \base, (30 * LASX_REG_WIDTH) 255 + EX xvst $xr31, \base, (31 * LASX_REG_WIDTH) 256 + #endif 257 + .endm 258 + 259 + .macro sc_restore_lasx base 260 + #ifdef CONFIG_CPU_HAS_LASX 261 + EX xvld $xr0, \base, (0 * LASX_REG_WIDTH) 262 + EX xvld $xr1, \base, (1 * LASX_REG_WIDTH) 263 + EX xvld $xr2, \base, (2 * LASX_REG_WIDTH) 264 + EX xvld $xr3, \base, (3 * LASX_REG_WIDTH) 265 + EX xvld $xr4, \base, (4 * LASX_REG_WIDTH) 266 + EX xvld $xr5, \base, (5 * LASX_REG_WIDTH) 267 + EX xvld $xr6, \base, (6 * LASX_REG_WIDTH) 268 + EX xvld $xr7, \base, (7 * LASX_REG_WIDTH) 269 + EX xvld $xr8, \base, (8 * LASX_REG_WIDTH) 270 + EX xvld $xr9, \base, (9 * LASX_REG_WIDTH) 271 + EX xvld $xr10, \base, (10 * LASX_REG_WIDTH) 272 + EX xvld $xr11, \base, (11 * LASX_REG_WIDTH) 273 + EX xvld $xr12, \base, (12 * LASX_REG_WIDTH) 274 + EX xvld $xr13, \base, (13 * LASX_REG_WIDTH) 275 + EX xvld $xr14, \base, (14 * LASX_REG_WIDTH) 276 + EX xvld $xr15, \base, (15 * LASX_REG_WIDTH) 277 + EX xvld $xr16, \base, (16 * LASX_REG_WIDTH) 278 + EX xvld $xr17, \base, (17 * LASX_REG_WIDTH) 279 + EX xvld $xr18, \base, (18 * LASX_REG_WIDTH) 280 + EX xvld $xr19, \base, (19 * LASX_REG_WIDTH) 281 + EX xvld $xr20, \base, (20 * LASX_REG_WIDTH) 282 + EX xvld $xr21, \base, (21 * LASX_REG_WIDTH) 283 + EX xvld $xr22, \base, (22 * LASX_REG_WIDTH) 284 + EX xvld $xr23, \base, (23 * LASX_REG_WIDTH) 285 + EX xvld $xr24, \base, (24 * LASX_REG_WIDTH) 286 + EX xvld $xr25, \base, (25 * LASX_REG_WIDTH) 287 + EX xvld $xr26, \base, (26 * LASX_REG_WIDTH) 288 + EX xvld $xr27, \base, (27 * LASX_REG_WIDTH) 289 + EX xvld $xr28, \base, (28 * LASX_REG_WIDTH) 290 + EX xvld $xr29, \base, (29 * LASX_REG_WIDTH) 291 + EX xvld $xr30, \base, (30 * LASX_REG_WIDTH) 292 + EX xvld $xr31, \base, (31 * LASX_REG_WIDTH) 293 + #endif 294 + .endm 295 + 148 296 /* 149 297 * Save a thread's fp context. 150 298 */ ··· 313 165 fpu_restore_cc a0 t1 t2 # clobbers t1, t2 314 166 jr ra 315 167 SYM_FUNC_END(_restore_fp) 168 + 169 + #ifdef CONFIG_CPU_HAS_LSX 170 + 171 + /* 172 + * Save a thread's LSX vector context. 173 + */ 174 + SYM_FUNC_START(_save_lsx) 175 + lsx_save_all a0 t1 t2 176 + jr ra 177 + SYM_FUNC_END(_save_lsx) 178 + EXPORT_SYMBOL(_save_lsx) 179 + 180 + /* 181 + * Restore a thread's LSX vector context. 182 + */ 183 + SYM_FUNC_START(_restore_lsx) 184 + lsx_restore_all a0 t1 t2 185 + jr ra 186 + SYM_FUNC_END(_restore_lsx) 187 + 188 + SYM_FUNC_START(_save_lsx_upper) 189 + lsx_save_all_upper a0 t0 t1 190 + jr ra 191 + SYM_FUNC_END(_save_lsx_upper) 192 + 193 + SYM_FUNC_START(_restore_lsx_upper) 194 + lsx_restore_all_upper a0 t0 t1 195 + jr ra 196 + SYM_FUNC_END(_restore_lsx_upper) 197 + 198 + SYM_FUNC_START(_init_lsx_upper) 199 + lsx_init_all_upper t1 200 + jr ra 201 + SYM_FUNC_END(_init_lsx_upper) 202 + #endif 203 + 204 + #ifdef CONFIG_CPU_HAS_LASX 205 + 206 + /* 207 + * Save a thread's LASX vector context. 208 + */ 209 + SYM_FUNC_START(_save_lasx) 210 + lasx_save_all a0 t1 t2 211 + jr ra 212 + SYM_FUNC_END(_save_lasx) 213 + EXPORT_SYMBOL(_save_lasx) 214 + 215 + /* 216 + * Restore a thread's LASX vector context. 217 + */ 218 + SYM_FUNC_START(_restore_lasx) 219 + lasx_restore_all a0 t1 t2 220 + jr ra 221 + SYM_FUNC_END(_restore_lasx) 222 + 223 + SYM_FUNC_START(_save_lasx_upper) 224 + lasx_save_all_upper a0 t0 t1 225 + jr ra 226 + SYM_FUNC_END(_save_lasx_upper) 227 + 228 + SYM_FUNC_START(_restore_lasx_upper) 229 + lasx_restore_all_upper a0 t0 t1 230 + jr ra 231 + SYM_FUNC_END(_restore_lasx_upper) 232 + 233 + SYM_FUNC_START(_init_lasx_upper) 234 + lasx_init_all_upper t1 235 + jr ra 236 + SYM_FUNC_END(_init_lasx_upper) 237 + #endif 316 238 317 239 /* 318 240 * Load the FPU with signalling NANS. This bit pattern we're using has ··· 461 243 li.w a0, 0 # success 462 244 jr ra 463 245 SYM_FUNC_END(_restore_fp_context) 246 + 247 + /* 248 + * a0: fpregs 249 + * a1: fcc 250 + * a2: fcsr 251 + */ 252 + SYM_FUNC_START(_save_lsx_context) 253 + sc_save_fcc a1, t0, t1 254 + sc_save_fcsr a2, t0 255 + sc_save_lsx a0 256 + li.w a0, 0 # success 257 + jr ra 258 + SYM_FUNC_END(_save_lsx_context) 259 + 260 + /* 261 + * a0: fpregs 262 + * a1: fcc 263 + * a2: fcsr 264 + */ 265 + SYM_FUNC_START(_restore_lsx_context) 266 + sc_restore_lsx a0 267 + sc_restore_fcc a1, t1, t2 268 + sc_restore_fcsr a2, t1 269 + li.w a0, 0 # success 270 + jr ra 271 + SYM_FUNC_END(_restore_lsx_context) 272 + 273 + /* 274 + * a0: fpregs 275 + * a1: fcc 276 + * a2: fcsr 277 + */ 278 + SYM_FUNC_START(_save_lasx_context) 279 + sc_save_fcc a1, t0, t1 280 + sc_save_fcsr a2, t0 281 + sc_save_lasx a0 282 + li.w a0, 0 # success 283 + jr ra 284 + SYM_FUNC_END(_save_lasx_context) 285 + 286 + /* 287 + * a0: fpregs 288 + * a1: fcc 289 + * a2: fcsr 290 + */ 291 + SYM_FUNC_START(_restore_lasx_context) 292 + sc_restore_lasx a0 293 + sc_restore_fcc a1, t1, t2 294 + sc_restore_fcsr a2, t1 295 + li.w a0, 0 # success 296 + jr ra 297 + SYM_FUNC_END(_restore_lasx_context) 464 298 465 299 SYM_FUNC_START(fault) 466 300 li.w a0, -EFAULT # failure
+4 -4
arch/loongarch/kernel/head.S
··· 23 23 .word MZ_MAGIC /* "MZ", MS-DOS header */ 24 24 .org 0x8 25 25 .dword kernel_entry /* Kernel entry point */ 26 - .dword _end - _text /* Kernel image effective size */ 26 + .dword _kernel_asize /* Kernel image effective size */ 27 27 .quad PHYS_LINK_KADDR /* Kernel image load offset from start of RAM */ 28 28 .org 0x38 /* 0x20 ~ 0x37 reserved */ 29 29 .long LINUX_PE_MAGIC ··· 32 32 pe_header: 33 33 __EFI_PE_HEADER 34 34 35 - SYM_DATA(kernel_asize, .long _end - _text); 36 - SYM_DATA(kernel_fsize, .long _edata - _text); 37 - SYM_DATA(kernel_offset, .long kernel_offset - _text); 35 + SYM_DATA(kernel_asize, .long _kernel_asize); 36 + SYM_DATA(kernel_fsize, .long _kernel_fsize); 37 + SYM_DATA(kernel_offset, .long _kernel_offset); 38 38 39 39 #endif 40 40
+81 -2
arch/loongarch/kernel/inst.c
··· 133 133 } 134 134 } 135 135 136 + bool insns_not_supported(union loongarch_instruction insn) 137 + { 138 + switch (insn.reg3_format.opcode) { 139 + case amswapw_op ... ammindbdu_op: 140 + pr_notice("atomic memory access instructions are not supported\n"); 141 + return true; 142 + } 143 + 144 + switch (insn.reg2i14_format.opcode) { 145 + case llw_op: 146 + case lld_op: 147 + case scw_op: 148 + case scd_op: 149 + pr_notice("ll and sc instructions are not supported\n"); 150 + return true; 151 + } 152 + 153 + switch (insn.reg1i21_format.opcode) { 154 + case bceqz_op: 155 + pr_notice("bceqz and bcnez instructions are not supported\n"); 156 + return true; 157 + } 158 + 159 + return false; 160 + } 161 + 162 + bool insns_need_simulation(union loongarch_instruction insn) 163 + { 164 + if (is_pc_ins(&insn)) 165 + return true; 166 + 167 + if (is_branch_ins(&insn)) 168 + return true; 169 + 170 + return false; 171 + } 172 + 173 + void arch_simulate_insn(union loongarch_instruction insn, struct pt_regs *regs) 174 + { 175 + if (is_pc_ins(&insn)) 176 + simu_pc(regs, insn); 177 + else if (is_branch_ins(&insn)) 178 + simu_branch(regs, insn); 179 + } 180 + 136 181 int larch_insn_read(void *addr, u32 *insnp) 137 182 { 138 183 int ret; ··· 253 208 return insn.word; 254 209 } 255 210 211 + u32 larch_insn_gen_break(int imm) 212 + { 213 + union loongarch_instruction insn; 214 + 215 + if (imm < 0 || imm >= SZ_32K) { 216 + pr_warn("The generated break instruction is out of range.\n"); 217 + return INSN_BREAK; 218 + } 219 + 220 + emit_break(&insn, imm); 221 + 222 + return insn.word; 223 + } 224 + 256 225 u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk) 257 226 { 258 227 union loongarch_instruction insn; ··· 285 226 { 286 227 union loongarch_instruction insn; 287 228 229 + if (imm < -SZ_512K || imm >= SZ_512K) { 230 + pr_warn("The generated lu12i.w instruction is out of range.\n"); 231 + return INSN_BREAK; 232 + } 233 + 288 234 emit_lu12iw(&insn, rd, imm); 289 235 290 236 return insn.word; ··· 298 234 u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm) 299 235 { 300 236 union loongarch_instruction insn; 237 + 238 + if (imm < -SZ_512K || imm >= SZ_512K) { 239 + pr_warn("The generated lu32i.d instruction is out of range.\n"); 240 + return INSN_BREAK; 241 + } 301 242 302 243 emit_lu32id(&insn, rd, imm); 303 244 ··· 313 244 { 314 245 union loongarch_instruction insn; 315 246 247 + if (imm < -SZ_2K || imm >= SZ_2K) { 248 + pr_warn("The generated lu52i.d instruction is out of range.\n"); 249 + return INSN_BREAK; 250 + } 251 + 316 252 emit_lu52id(&insn, rd, rj, imm); 317 253 318 254 return insn.word; 319 255 } 320 256 321 - u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest) 257 + u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm) 322 258 { 323 259 union loongarch_instruction insn; 324 260 325 - emit_jirl(&insn, rj, rd, (dest - pc) >> 2); 261 + if ((imm & 3) || imm < -SZ_128K || imm >= SZ_128K) { 262 + pr_warn("The generated jirl instruction is out of range.\n"); 263 + return INSN_BREAK; 264 + } 265 + 266 + emit_jirl(&insn, rj, rd, imm >> 2); 326 267 327 268 return insn.word; 328 269 }
+22
arch/loongarch/kernel/jump_label.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2023 Loongson Technology Corporation Limited 4 + * 5 + * Based on arch/arm64/kernel/jump_label.c 6 + */ 7 + #include <linux/kernel.h> 8 + #include <linux/jump_label.h> 9 + #include <asm/inst.h> 10 + 11 + void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type) 12 + { 13 + u32 insn; 14 + void *addr = (void *)jump_entry_code(entry); 15 + 16 + if (type == JUMP_LABEL_JMP) 17 + insn = larch_insn_gen_b(jump_entry_code(entry), jump_entry_target(entry)); 18 + else 19 + insn = larch_insn_gen_nop(); 20 + 21 + larch_insn_patch_text(addr, insn); 22 + }
+14 -82
arch/loongarch/kernel/kprobes.c
··· 4 4 #include <linux/preempt.h> 5 5 #include <asm/break.h> 6 6 7 - static const union loongarch_instruction breakpoint_insn = { 8 - .reg0i15_format = { 9 - .opcode = break_op, 10 - .immediate = BRK_KPROBE_BP, 11 - } 12 - }; 13 - 14 - static const union loongarch_instruction singlestep_insn = { 15 - .reg0i15_format = { 16 - .opcode = break_op, 17 - .immediate = BRK_KPROBE_SSTEPBP, 18 - } 19 - }; 7 + #define KPROBE_BP_INSN larch_insn_gen_break(BRK_KPROBE_BP) 8 + #define KPROBE_SSTEPBP_INSN larch_insn_gen_break(BRK_KPROBE_SSTEPBP) 20 9 21 10 DEFINE_PER_CPU(struct kprobe *, current_kprobe); 22 11 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); 23 12 24 - static bool insns_not_supported(union loongarch_instruction insn) 25 - { 26 - switch (insn.reg2i14_format.opcode) { 27 - case llw_op: 28 - case lld_op: 29 - case scw_op: 30 - case scd_op: 31 - pr_notice("kprobe: ll and sc instructions are not supported\n"); 32 - return true; 33 - } 34 - 35 - switch (insn.reg1i21_format.opcode) { 36 - case bceqz_op: 37 - pr_notice("kprobe: bceqz and bcnez instructions are not supported\n"); 38 - return true; 39 - } 40 - 41 - return false; 42 - } 43 - NOKPROBE_SYMBOL(insns_not_supported); 44 - 45 - static bool insns_need_simulation(struct kprobe *p) 46 - { 47 - if (is_pc_ins(&p->opcode)) 48 - return true; 49 - 50 - if (is_branch_ins(&p->opcode)) 51 - return true; 52 - 53 - return false; 54 - } 55 - NOKPROBE_SYMBOL(insns_need_simulation); 56 - 57 - static void arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) 58 - { 59 - if (is_pc_ins(&p->opcode)) 60 - simu_pc(regs, p->opcode); 61 - else if (is_branch_ins(&p->opcode)) 62 - simu_branch(regs, p->opcode); 63 - } 64 - NOKPROBE_SYMBOL(arch_simulate_insn); 65 - 66 13 static void arch_prepare_ss_slot(struct kprobe *p) 67 14 { 68 15 p->ainsn.insn[0] = *p->addr; 69 - p->ainsn.insn[1] = singlestep_insn; 16 + p->ainsn.insn[1] = KPROBE_SSTEPBP_INSN; 70 17 p->ainsn.restore = (unsigned long)p->addr + LOONGARCH_INSN_SIZE; 71 18 } 72 19 NOKPROBE_SYMBOL(arch_prepare_ss_slot); ··· 26 79 27 80 int arch_prepare_kprobe(struct kprobe *p) 28 81 { 82 + union loongarch_instruction insn; 83 + 29 84 if ((unsigned long)p->addr & 0x3) 30 85 return -EILSEQ; 31 86 32 87 /* copy instruction */ 33 88 p->opcode = *p->addr; 89 + insn.word = p->opcode; 34 90 35 91 /* decode instruction */ 36 - if (insns_not_supported(p->opcode)) 92 + if (insns_not_supported(insn)) 37 93 return -EINVAL; 38 94 39 - if (insns_need_simulation(p)) { 95 + if (insns_need_simulation(insn)) { 40 96 p->ainsn.insn = NULL; 41 97 } else { 42 98 p->ainsn.insn = get_insn_slot(); ··· 60 110 /* Install breakpoint in text */ 61 111 void arch_arm_kprobe(struct kprobe *p) 62 112 { 63 - *p->addr = breakpoint_insn; 113 + *p->addr = KPROBE_BP_INSN; 64 114 flush_insn_slot(p); 65 115 } 66 116 NOKPROBE_SYMBOL(arch_arm_kprobe); ··· 155 205 static void setup_singlestep(struct kprobe *p, struct pt_regs *regs, 156 206 struct kprobe_ctlblk *kcb, int reenter) 157 207 { 208 + union loongarch_instruction insn; 209 + 158 210 if (reenter) { 159 211 save_previous_kprobe(kcb); 160 212 set_current_kprobe(p); ··· 172 220 regs->csr_era = (unsigned long)p->ainsn.insn; 173 221 } else { 174 222 /* simulate single steping */ 175 - arch_simulate_insn(p, regs); 223 + insn.word = p->opcode; 224 + arch_simulate_insn(insn, regs); 176 225 /* now go for post processing */ 177 226 post_kprobe_handler(p, kcb, regs); 178 227 } ··· 248 295 } 249 296 } 250 297 251 - if (addr->word != breakpoint_insn.word) { 298 + if (*addr != KPROBE_BP_INSN) { 252 299 /* 253 300 * The breakpoint instruction was removed right 254 301 * after we hit it. Another cpu has removed ··· 330 377 { 331 378 return 0; 332 379 } 333 - 334 - /* ASM function that handles the kretprobes must not be probed */ 335 - NOKPROBE_SYMBOL(__kretprobe_trampoline); 336 - 337 - /* Called from __kretprobe_trampoline */ 338 - void __used *trampoline_probe_handler(struct pt_regs *regs) 339 - { 340 - return (void *)kretprobe_trampoline_handler(regs, NULL); 341 - } 342 - NOKPROBE_SYMBOL(trampoline_probe_handler); 343 - 344 - void arch_prepare_kretprobe(struct kretprobe_instance *ri, 345 - struct pt_regs *regs) 346 - { 347 - ri->ret_addr = (kprobe_opcode_t *)regs->regs[1]; 348 - ri->fp = NULL; 349 - 350 - /* Replace the return addr with trampoline addr */ 351 - regs->regs[1] = (unsigned long)&__kretprobe_trampoline; 352 - } 353 - NOKPROBE_SYMBOL(arch_prepare_kretprobe); 354 380 355 381 int arch_trampoline_kprobe(struct kprobe *p) 356 382 {
+3 -3
arch/loongarch/kernel/kprobes_trampoline.S arch/loongarch/kernel/rethook_trampoline.S
··· 75 75 csrxchg t0, t1, LOONGARCH_CSR_CRMD 76 76 .endm 77 77 78 - SYM_CODE_START(__kretprobe_trampoline) 78 + SYM_CODE_START(arch_rethook_trampoline) 79 79 addi.d sp, sp, -PT_SIZE 80 80 save_all_base_regs 81 81 ··· 84 84 85 85 move a0, sp /* pt_regs */ 86 86 87 - bl trampoline_probe_handler 87 + bl arch_rethook_trampoline_callback 88 88 89 89 /* use the result as the return-address */ 90 90 move ra, a0 ··· 93 93 addi.d sp, sp, PT_SIZE 94 94 95 95 jr ra 96 - SYM_CODE_END(__kretprobe_trampoline) 96 + SYM_CODE_END(arch_rethook_trampoline)
+2
arch/loongarch/kernel/proc.c
··· 49 49 seq_printf(m, "processor\t\t: %ld\n", n); 50 50 seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package); 51 51 seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); 52 + seq_printf(m, "global_id\t\t: %d\n", cpu_data[n].global_id); 52 53 seq_printf(m, "CPU Family\t\t: %s\n", __cpu_family[n]); 53 54 seq_printf(m, "Model Name\t\t: %s\n", __cpu_full_name[n]); 54 55 seq_printf(m, "CPU Revision\t\t: 0x%02x\n", version); ··· 80 79 if (cpu_has_crc32) seq_printf(m, " crc32"); 81 80 if (cpu_has_complex) seq_printf(m, " complex"); 82 81 if (cpu_has_crypto) seq_printf(m, " crypto"); 82 + if (cpu_has_ptw) seq_printf(m, " ptw"); 83 83 if (cpu_has_lvz) seq_printf(m, " lvz"); 84 84 if (cpu_has_lbt_x86) seq_printf(m, " lbt_x86"); 85 85 if (cpu_has_lbt_arm) seq_printf(m, " lbt_arm");
+9 -3
arch/loongarch/kernel/process.c
··· 117 117 */ 118 118 preempt_disable(); 119 119 120 - if (is_fpu_owner()) 121 - save_fp(current); 120 + if (is_fpu_owner()) { 121 + if (is_lasx_enabled()) 122 + save_lasx(current); 123 + else if (is_lsx_enabled()) 124 + save_lsx(current); 125 + else 126 + save_fp(current); 127 + } 122 128 123 129 preempt_enable(); 124 130 ··· 291 285 292 286 /* Space for the VDSO & data page */ 293 287 top -= PAGE_ALIGN(current->thread.vdso->size); 294 - top -= PAGE_SIZE; 288 + top -= VVAR_SIZE; 295 289 296 290 /* Space to randomize the VDSO base */ 297 291 if (current->flags & PF_RANDOMIZE)
+110
arch/loongarch/kernel/ptrace.c
··· 250 250 return 0; 251 251 } 252 252 253 + #ifdef CONFIG_CPU_HAS_LSX 254 + 255 + static void copy_pad_fprs(struct task_struct *target, 256 + const struct user_regset *regset, 257 + struct membuf *to, unsigned int live_sz) 258 + { 259 + int i, j; 260 + unsigned long long fill = ~0ull; 261 + unsigned int cp_sz, pad_sz; 262 + 263 + cp_sz = min(regset->size, live_sz); 264 + pad_sz = regset->size - cp_sz; 265 + WARN_ON(pad_sz % sizeof(fill)); 266 + 267 + for (i = 0; i < NUM_FPU_REGS; i++) { 268 + membuf_write(to, &target->thread.fpu.fpr[i], cp_sz); 269 + for (j = 0; j < (pad_sz / sizeof(fill)); j++) { 270 + membuf_store(to, fill); 271 + } 272 + } 273 + } 274 + 275 + static int simd_get(struct task_struct *target, 276 + const struct user_regset *regset, 277 + struct membuf to) 278 + { 279 + const unsigned int wr_size = NUM_FPU_REGS * regset->size; 280 + 281 + if (!tsk_used_math(target)) { 282 + /* The task hasn't used FP or LSX, fill with 0xff */ 283 + copy_pad_fprs(target, regset, &to, 0); 284 + } else if (!test_tsk_thread_flag(target, TIF_LSX_CTX_LIVE)) { 285 + /* Copy scalar FP context, fill the rest with 0xff */ 286 + copy_pad_fprs(target, regset, &to, 8); 287 + #ifdef CONFIG_CPU_HAS_LASX 288 + } else if (!test_tsk_thread_flag(target, TIF_LASX_CTX_LIVE)) { 289 + /* Copy LSX 128 Bit context, fill the rest with 0xff */ 290 + copy_pad_fprs(target, regset, &to, 16); 291 + #endif 292 + } else if (sizeof(target->thread.fpu.fpr[0]) == regset->size) { 293 + /* Trivially copy the vector registers */ 294 + membuf_write(&to, &target->thread.fpu.fpr, wr_size); 295 + } else { 296 + /* Copy as much context as possible, fill the rest with 0xff */ 297 + copy_pad_fprs(target, regset, &to, sizeof(target->thread.fpu.fpr[0])); 298 + } 299 + 300 + return 0; 301 + } 302 + 303 + static int simd_set(struct task_struct *target, 304 + const struct user_regset *regset, 305 + unsigned int pos, unsigned int count, 306 + const void *kbuf, const void __user *ubuf) 307 + { 308 + const unsigned int wr_size = NUM_FPU_REGS * regset->size; 309 + unsigned int cp_sz; 310 + int i, err, start; 311 + 312 + init_fp_ctx(target); 313 + 314 + if (sizeof(target->thread.fpu.fpr[0]) == regset->size) { 315 + /* Trivially copy the vector registers */ 316 + err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 317 + &target->thread.fpu.fpr, 318 + 0, wr_size); 319 + } else { 320 + /* Copy as much context as possible */ 321 + cp_sz = min_t(unsigned int, regset->size, 322 + sizeof(target->thread.fpu.fpr[0])); 323 + 324 + i = start = err = 0; 325 + for (; i < NUM_FPU_REGS; i++, start += regset->size) { 326 + err |= user_regset_copyin(&pos, &count, &kbuf, &ubuf, 327 + &target->thread.fpu.fpr[i], 328 + start, start + cp_sz); 329 + } 330 + } 331 + 332 + return err; 333 + } 334 + 335 + #endif /* CONFIG_CPU_HAS_LSX */ 336 + 253 337 #ifdef CONFIG_HAVE_HW_BREAKPOINT 254 338 255 339 /* ··· 792 708 REGSET_GPR, 793 709 REGSET_FPR, 794 710 REGSET_CPUCFG, 711 + #ifdef CONFIG_CPU_HAS_LSX 712 + REGSET_LSX, 713 + #endif 714 + #ifdef CONFIG_CPU_HAS_LASX 715 + REGSET_LASX, 716 + #endif 795 717 #ifdef CONFIG_HAVE_HW_BREAKPOINT 796 718 REGSET_HW_BREAK, 797 719 REGSET_HW_WATCH, ··· 829 739 .regset_get = cfg_get, 830 740 .set = cfg_set, 831 741 }, 742 + #ifdef CONFIG_CPU_HAS_LSX 743 + [REGSET_LSX] = { 744 + .core_note_type = NT_LOONGARCH_LSX, 745 + .n = NUM_FPU_REGS, 746 + .size = 16, 747 + .align = 16, 748 + .regset_get = simd_get, 749 + .set = simd_set, 750 + }, 751 + #endif 752 + #ifdef CONFIG_CPU_HAS_LASX 753 + [REGSET_LASX] = { 754 + .core_note_type = NT_LOONGARCH_LASX, 755 + .n = NUM_FPU_REGS, 756 + .size = 32, 757 + .align = 32, 758 + .regset_get = simd_get, 759 + .set = simd_set, 760 + }, 761 + #endif 832 762 #ifdef CONFIG_HAVE_HW_BREAKPOINT 833 763 [REGSET_HW_BREAK] = { 834 764 .core_note_type = NT_LOONGARCH_HW_BREAK,
+28
arch/loongarch/kernel/rethook.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Generic return hook for LoongArch. 4 + */ 5 + 6 + #include <linux/kprobes.h> 7 + #include <linux/rethook.h> 8 + #include "rethook.h" 9 + 10 + /* This is called from arch_rethook_trampoline() */ 11 + unsigned long __used arch_rethook_trampoline_callback(struct pt_regs *regs) 12 + { 13 + return rethook_trampoline_handler(regs, 0); 14 + } 15 + NOKPROBE_SYMBOL(arch_rethook_trampoline_callback); 16 + 17 + void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount) 18 + { 19 + rhn->frame = 0; 20 + rhn->ret_addr = regs->regs[1]; 21 + 22 + /* replace return addr with trampoline */ 23 + regs->regs[1] = (unsigned long)arch_rethook_trampoline; 24 + } 25 + NOKPROBE_SYMBOL(arch_rethook_prepare); 26 + 27 + /* ASM function that handles the rethook must not be probed itself */ 28 + NOKPROBE_SYMBOL(arch_rethook_trampoline);
+8
arch/loongarch/kernel/rethook.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __LOONGARCH_RETHOOK_H 3 + #define __LOONGARCH_RETHOOK_H 4 + 5 + unsigned long arch_rethook_trampoline_callback(struct pt_regs *regs); 6 + void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount); 7 + 8 + #endif
+323 -3
arch/loongarch/kernel/signal.c
··· 50 50 _save_fp_context(void __user *fpregs, void __user *fcc, void __user *csr); 51 51 extern asmlinkage int 52 52 _restore_fp_context(void __user *fpregs, void __user *fcc, void __user *csr); 53 + extern asmlinkage int 54 + _save_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr); 55 + extern asmlinkage int 56 + _restore_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr); 57 + extern asmlinkage int 58 + _save_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr); 59 + extern asmlinkage int 60 + _restore_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr); 53 61 54 62 struct rt_sigframe { 55 63 struct siginfo rs_info; ··· 73 65 unsigned long size; 74 66 unsigned int flags; 75 67 struct _ctx_layout fpu; 68 + struct _ctx_layout lsx; 69 + struct _ctx_layout lasx; 76 70 struct _ctx_layout end; 77 71 }; 78 72 ··· 125 115 return err; 126 116 } 127 117 118 + static int copy_lsx_to_sigcontext(struct lsx_context __user *ctx) 119 + { 120 + int i; 121 + int err = 0; 122 + uint64_t __user *regs = (uint64_t *)&ctx->regs; 123 + uint64_t __user *fcc = &ctx->fcc; 124 + uint32_t __user *fcsr = &ctx->fcsr; 125 + 126 + for (i = 0; i < NUM_FPU_REGS; i++) { 127 + err |= __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0), 128 + &regs[2*i]); 129 + err |= __put_user(get_fpr64(&current->thread.fpu.fpr[i], 1), 130 + &regs[2*i+1]); 131 + } 132 + err |= __put_user(current->thread.fpu.fcc, fcc); 133 + err |= __put_user(current->thread.fpu.fcsr, fcsr); 134 + 135 + return err; 136 + } 137 + 138 + static int copy_lsx_from_sigcontext(struct lsx_context __user *ctx) 139 + { 140 + int i; 141 + int err = 0; 142 + u64 fpr_val; 143 + uint64_t __user *regs = (uint64_t *)&ctx->regs; 144 + uint64_t __user *fcc = &ctx->fcc; 145 + uint32_t __user *fcsr = &ctx->fcsr; 146 + 147 + for (i = 0; i < NUM_FPU_REGS; i++) { 148 + err |= __get_user(fpr_val, &regs[2*i]); 149 + set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val); 150 + err |= __get_user(fpr_val, &regs[2*i+1]); 151 + set_fpr64(&current->thread.fpu.fpr[i], 1, fpr_val); 152 + } 153 + err |= __get_user(current->thread.fpu.fcc, fcc); 154 + err |= __get_user(current->thread.fpu.fcsr, fcsr); 155 + 156 + return err; 157 + } 158 + 159 + static int copy_lasx_to_sigcontext(struct lasx_context __user *ctx) 160 + { 161 + int i; 162 + int err = 0; 163 + uint64_t __user *regs = (uint64_t *)&ctx->regs; 164 + uint64_t __user *fcc = &ctx->fcc; 165 + uint32_t __user *fcsr = &ctx->fcsr; 166 + 167 + for (i = 0; i < NUM_FPU_REGS; i++) { 168 + err |= __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0), 169 + &regs[4*i]); 170 + err |= __put_user(get_fpr64(&current->thread.fpu.fpr[i], 1), 171 + &regs[4*i+1]); 172 + err |= __put_user(get_fpr64(&current->thread.fpu.fpr[i], 2), 173 + &regs[4*i+2]); 174 + err |= __put_user(get_fpr64(&current->thread.fpu.fpr[i], 3), 175 + &regs[4*i+3]); 176 + } 177 + err |= __put_user(current->thread.fpu.fcc, fcc); 178 + err |= __put_user(current->thread.fpu.fcsr, fcsr); 179 + 180 + return err; 181 + } 182 + 183 + static int copy_lasx_from_sigcontext(struct lasx_context __user *ctx) 184 + { 185 + int i; 186 + int err = 0; 187 + u64 fpr_val; 188 + uint64_t __user *regs = (uint64_t *)&ctx->regs; 189 + uint64_t __user *fcc = &ctx->fcc; 190 + uint32_t __user *fcsr = &ctx->fcsr; 191 + 192 + for (i = 0; i < NUM_FPU_REGS; i++) { 193 + err |= __get_user(fpr_val, &regs[4*i]); 194 + set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val); 195 + err |= __get_user(fpr_val, &regs[4*i+1]); 196 + set_fpr64(&current->thread.fpu.fpr[i], 1, fpr_val); 197 + err |= __get_user(fpr_val, &regs[4*i+2]); 198 + set_fpr64(&current->thread.fpu.fpr[i], 2, fpr_val); 199 + err |= __get_user(fpr_val, &regs[4*i+3]); 200 + set_fpr64(&current->thread.fpu.fpr[i], 3, fpr_val); 201 + } 202 + err |= __get_user(current->thread.fpu.fcc, fcc); 203 + err |= __get_user(current->thread.fpu.fcsr, fcsr); 204 + 205 + return err; 206 + } 207 + 128 208 /* 129 209 * Wrappers for the assembly _{save,restore}_fp_context functions. 130 210 */ ··· 234 134 uint32_t __user *fcsr = &ctx->fcsr; 235 135 236 136 return _restore_fp_context(regs, fcc, fcsr); 137 + } 138 + 139 + static int save_hw_lsx_context(struct lsx_context __user *ctx) 140 + { 141 + uint64_t __user *regs = (uint64_t *)&ctx->regs; 142 + uint64_t __user *fcc = &ctx->fcc; 143 + uint32_t __user *fcsr = &ctx->fcsr; 144 + 145 + return _save_lsx_context(regs, fcc, fcsr); 146 + } 147 + 148 + static int restore_hw_lsx_context(struct lsx_context __user *ctx) 149 + { 150 + uint64_t __user *regs = (uint64_t *)&ctx->regs; 151 + uint64_t __user *fcc = &ctx->fcc; 152 + uint32_t __user *fcsr = &ctx->fcsr; 153 + 154 + return _restore_lsx_context(regs, fcc, fcsr); 155 + } 156 + 157 + static int save_hw_lasx_context(struct lasx_context __user *ctx) 158 + { 159 + uint64_t __user *regs = (uint64_t *)&ctx->regs; 160 + uint64_t __user *fcc = &ctx->fcc; 161 + uint32_t __user *fcsr = &ctx->fcsr; 162 + 163 + return _save_lasx_context(regs, fcc, fcsr); 164 + } 165 + 166 + static int restore_hw_lasx_context(struct lasx_context __user *ctx) 167 + { 168 + uint64_t __user *regs = (uint64_t *)&ctx->regs; 169 + uint64_t __user *fcc = &ctx->fcc; 170 + uint32_t __user *fcsr = &ctx->fcsr; 171 + 172 + return _restore_lasx_context(regs, fcc, fcsr); 237 173 } 238 174 239 175 static int fcsr_pending(unsigned int __user *fcsr) ··· 363 227 return err ?: sig; 364 228 } 365 229 230 + static int protected_save_lsx_context(struct extctx_layout *extctx) 231 + { 232 + int err = 0; 233 + struct sctx_info __user *info = extctx->lsx.addr; 234 + struct lsx_context __user *lsx_ctx = (struct lsx_context *)get_ctx_through_ctxinfo(info); 235 + uint64_t __user *regs = (uint64_t *)&lsx_ctx->regs; 236 + uint64_t __user *fcc = &lsx_ctx->fcc; 237 + uint32_t __user *fcsr = &lsx_ctx->fcsr; 238 + 239 + while (1) { 240 + lock_fpu_owner(); 241 + if (is_lsx_enabled()) 242 + err = save_hw_lsx_context(lsx_ctx); 243 + else { 244 + if (is_fpu_owner()) 245 + save_fp(current); 246 + err = copy_lsx_to_sigcontext(lsx_ctx); 247 + } 248 + unlock_fpu_owner(); 249 + 250 + err |= __put_user(LSX_CTX_MAGIC, &info->magic); 251 + err |= __put_user(extctx->lsx.size, &info->size); 252 + 253 + if (likely(!err)) 254 + break; 255 + /* Touch the LSX context and try again */ 256 + err = __put_user(0, &regs[0]) | 257 + __put_user(0, &regs[32*2-1]) | 258 + __put_user(0, fcc) | 259 + __put_user(0, fcsr); 260 + if (err) 261 + return err; /* really bad sigcontext */ 262 + } 263 + 264 + return err; 265 + } 266 + 267 + static int protected_restore_lsx_context(struct extctx_layout *extctx) 268 + { 269 + int err = 0, sig = 0, tmp __maybe_unused; 270 + struct sctx_info __user *info = extctx->lsx.addr; 271 + struct lsx_context __user *lsx_ctx = (struct lsx_context *)get_ctx_through_ctxinfo(info); 272 + uint64_t __user *regs = (uint64_t *)&lsx_ctx->regs; 273 + uint64_t __user *fcc = &lsx_ctx->fcc; 274 + uint32_t __user *fcsr = &lsx_ctx->fcsr; 275 + 276 + err = sig = fcsr_pending(fcsr); 277 + if (err < 0) 278 + return err; 279 + 280 + while (1) { 281 + lock_fpu_owner(); 282 + if (is_lsx_enabled()) 283 + err = restore_hw_lsx_context(lsx_ctx); 284 + else { 285 + err = copy_lsx_from_sigcontext(lsx_ctx); 286 + if (is_fpu_owner()) 287 + restore_fp(current); 288 + } 289 + unlock_fpu_owner(); 290 + 291 + if (likely(!err)) 292 + break; 293 + /* Touch the LSX context and try again */ 294 + err = __get_user(tmp, &regs[0]) | 295 + __get_user(tmp, &regs[32*2-1]) | 296 + __get_user(tmp, fcc) | 297 + __get_user(tmp, fcsr); 298 + if (err) 299 + break; /* really bad sigcontext */ 300 + } 301 + 302 + return err ?: sig; 303 + } 304 + 305 + static int protected_save_lasx_context(struct extctx_layout *extctx) 306 + { 307 + int err = 0; 308 + struct sctx_info __user *info = extctx->lasx.addr; 309 + struct lasx_context __user *lasx_ctx = 310 + (struct lasx_context *)get_ctx_through_ctxinfo(info); 311 + uint64_t __user *regs = (uint64_t *)&lasx_ctx->regs; 312 + uint64_t __user *fcc = &lasx_ctx->fcc; 313 + uint32_t __user *fcsr = &lasx_ctx->fcsr; 314 + 315 + while (1) { 316 + lock_fpu_owner(); 317 + if (is_lasx_enabled()) 318 + err = save_hw_lasx_context(lasx_ctx); 319 + else { 320 + if (is_lsx_enabled()) 321 + save_lsx(current); 322 + else if (is_fpu_owner()) 323 + save_fp(current); 324 + err = copy_lasx_to_sigcontext(lasx_ctx); 325 + } 326 + unlock_fpu_owner(); 327 + 328 + err |= __put_user(LASX_CTX_MAGIC, &info->magic); 329 + err |= __put_user(extctx->lasx.size, &info->size); 330 + 331 + if (likely(!err)) 332 + break; 333 + /* Touch the LASX context and try again */ 334 + err = __put_user(0, &regs[0]) | 335 + __put_user(0, &regs[32*4-1]) | 336 + __put_user(0, fcc) | 337 + __put_user(0, fcsr); 338 + if (err) 339 + return err; /* really bad sigcontext */ 340 + } 341 + 342 + return err; 343 + } 344 + 345 + static int protected_restore_lasx_context(struct extctx_layout *extctx) 346 + { 347 + int err = 0, sig = 0, tmp __maybe_unused; 348 + struct sctx_info __user *info = extctx->lasx.addr; 349 + struct lasx_context __user *lasx_ctx = 350 + (struct lasx_context *)get_ctx_through_ctxinfo(info); 351 + uint64_t __user *regs = (uint64_t *)&lasx_ctx->regs; 352 + uint64_t __user *fcc = &lasx_ctx->fcc; 353 + uint32_t __user *fcsr = &lasx_ctx->fcsr; 354 + 355 + err = sig = fcsr_pending(fcsr); 356 + if (err < 0) 357 + return err; 358 + 359 + while (1) { 360 + lock_fpu_owner(); 361 + if (is_lasx_enabled()) 362 + err = restore_hw_lasx_context(lasx_ctx); 363 + else { 364 + err = copy_lasx_from_sigcontext(lasx_ctx); 365 + if (is_lsx_enabled()) 366 + restore_lsx(current); 367 + else if (is_fpu_owner()) 368 + restore_fp(current); 369 + } 370 + unlock_fpu_owner(); 371 + 372 + if (likely(!err)) 373 + break; 374 + /* Touch the LASX context and try again */ 375 + err = __get_user(tmp, &regs[0]) | 376 + __get_user(tmp, &regs[32*4-1]) | 377 + __get_user(tmp, fcc) | 378 + __get_user(tmp, fcsr); 379 + if (err) 380 + break; /* really bad sigcontext */ 381 + } 382 + 383 + return err ?: sig; 384 + } 385 + 366 386 static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, 367 387 struct extctx_layout *extctx) 368 388 { ··· 532 240 for (i = 1; i < 32; i++) 533 241 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); 534 242 535 - if (extctx->fpu.addr) 243 + if (extctx->lasx.addr) 244 + err |= protected_save_lasx_context(extctx); 245 + else if (extctx->lsx.addr) 246 + err |= protected_save_lsx_context(extctx); 247 + else if (extctx->fpu.addr) 536 248 err |= protected_save_fpu_context(extctx); 537 249 538 250 /* Set the "end" magic */ ··· 568 272 sizeof(struct fpu_context))) 569 273 goto invalid; 570 274 extctx->fpu.addr = info; 275 + break; 276 + 277 + case LSX_CTX_MAGIC: 278 + if (size < (sizeof(struct sctx_info) + 279 + sizeof(struct lsx_context))) 280 + goto invalid; 281 + extctx->lsx.addr = info; 282 + break; 283 + 284 + case LASX_CTX_MAGIC: 285 + if (size < (sizeof(struct sctx_info) + 286 + sizeof(struct lasx_context))) 287 + goto invalid; 288 + extctx->lasx.addr = info; 571 289 break; 572 290 573 291 default: ··· 629 319 for (i = 1; i < 32; i++) 630 320 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); 631 321 632 - if (extctx.fpu.addr) 322 + if (extctx.lasx.addr) 323 + err |= protected_restore_lasx_context(&extctx); 324 + else if (extctx.lsx.addr) 325 + err |= protected_restore_lsx_context(&extctx); 326 + else if (extctx.fpu.addr) 633 327 err |= protected_restore_fpu_context(&extctx); 634 328 635 329 bad: ··· 689 375 extctx->size += extctx->end.size; 690 376 691 377 if (extctx->flags & SC_USED_FP) { 692 - if (cpu_has_fpu) 378 + if (cpu_has_lasx && thread_lasx_context_live()) 379 + new_sp = extframe_alloc(extctx, &extctx->lasx, 380 + sizeof(struct lasx_context), LASX_CTX_ALIGN, new_sp); 381 + else if (cpu_has_lsx && thread_lsx_context_live()) 382 + new_sp = extframe_alloc(extctx, &extctx->lsx, 383 + sizeof(struct lsx_context), LSX_CTX_ALIGN, new_sp); 384 + else if (cpu_has_fpu) 693 385 new_sp = extframe_alloc(extctx, &extctx->fpu, 694 386 sizeof(struct fpu_context), FPU_CTX_ALIGN, new_sp); 695 387 }
+12 -15
arch/loongarch/kernel/smp.c
··· 8 8 * Copyright (C) 2000, 2001 Silicon Graphics, Inc. 9 9 * Copyright (C) 2000, 2001, 2003 Broadcom Corporation 10 10 */ 11 + #include <linux/acpi.h> 11 12 #include <linux/cpu.h> 12 13 #include <linux/cpumask.h> 13 14 #include <linux/init.h> ··· 37 36 38 37 int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ 39 38 EXPORT_SYMBOL(__cpu_logical_map); 40 - 41 - /* Number of threads (siblings) per CPU core */ 42 - int smp_num_siblings = 1; 43 - EXPORT_SYMBOL(smp_num_siblings); 44 39 45 40 /* Representing the threads (siblings) of each logical CPU */ 46 41 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; ··· 115 118 action = iocsr_read32(LOONGARCH_IOCSR_IPI_STATUS); 116 119 /* Clear the ipi register to clear the interrupt */ 117 120 iocsr_write32(action, LOONGARCH_IOCSR_IPI_CLEAR); 118 - smp_mb(); 121 + wbflush(); 119 122 120 123 return action; 121 124 } ··· 207 210 } 208 211 209 212 loongson_sysconf.nr_cpus = num_processors; 213 + set_bit(0, &(loongson_sysconf.cores_io_master)); 210 214 #endif 211 215 } 212 216 ··· 226 228 { 227 229 int i = 0; 228 230 231 + parse_acpi_topology(); 232 + 229 233 for (i = 0; i < loongson_sysconf.nr_cpus; i++) { 230 234 set_cpu_present(i, true); 231 235 csr_mail_send(0, __cpu_logical_map[i], 0); 236 + cpu_data[i].global_id = __cpu_logical_map[i]; 232 237 } 233 238 234 239 per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; ··· 272 271 numa_add_cpu(cpu); 273 272 #endif 274 273 per_cpu(cpu_state, cpu) = CPU_ONLINE; 275 - cpu_data[cpu].core = 276 - cpu_logical_map(cpu) % loongson_sysconf.cores_per_package; 277 274 cpu_data[cpu].package = 278 275 cpu_logical_map(cpu) / loongson_sysconf.cores_per_package; 276 + cpu_data[cpu].core = pptt_enabled ? cpu_data[cpu].core : 277 + cpu_logical_map(cpu) % loongson_sysconf.cores_per_package; 279 278 } 280 279 281 280 void loongson_smp_finish(void) ··· 381 380 382 381 cpumask_set_cpu(cpu, &cpu_sibling_setup_map); 383 382 384 - if (smp_num_siblings <= 1) 385 - cpumask_set_cpu(cpu, &cpu_sibling_map[cpu]); 386 - else { 387 - for_each_cpu(i, &cpu_sibling_setup_map) { 388 - if (cpus_are_siblings(cpu, i)) { 389 - cpumask_set_cpu(i, &cpu_sibling_map[cpu]); 390 - cpumask_set_cpu(cpu, &cpu_sibling_map[i]); 391 - } 383 + for_each_cpu(i, &cpu_sibling_setup_map) { 384 + if (cpus_are_siblings(cpu, i)) { 385 + cpumask_set_cpu(i, &cpu_sibling_map[cpu]); 386 + cpumask_set_cpu(cpu, &cpu_sibling_map[i]); 392 387 } 393 388 } 394 389 }
+85 -10
arch/loongarch/kernel/traps.c
··· 47 47 #include <asm/tlb.h> 48 48 #include <asm/types.h> 49 49 #include <asm/unwind.h> 50 + #include <asm/uprobes.h> 50 51 51 52 #include "access-helper.h" 52 53 ··· 690 689 if (regs->csr_prmd & CSR_PRMD_PIE) 691 690 local_irq_enable(); 692 691 693 - current->thread.trap_nr = read_csr_excode(); 694 692 if (__get_inst(&opcode, (u32 *)era, user)) 695 693 goto out_sigsegv; 696 694 ··· 711 711 else 712 712 break; 713 713 case BRK_UPROBE_BP: 714 - if (notify_die(DIE_UPROBE, "Uprobe", regs, bcode, 715 - current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP) 714 + if (uprobe_breakpoint_handler(regs)) 716 715 goto out; 717 716 else 718 717 break; 719 718 case BRK_UPROBE_XOLBP: 720 - if (notify_die(DIE_UPROBE_XOL, "Uprobe_XOL", regs, bcode, 721 - current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP) 719 + if (uprobe_singlestep_handler(regs)) 722 720 goto out; 723 721 else 724 722 break; 725 723 default: 724 + current->thread.trap_nr = read_csr_excode(); 726 725 if (notify_die(DIE_TRAP, "Break", regs, bcode, 727 726 current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP) 728 727 goto out; ··· 851 852 BUG_ON(!is_fp_enabled()); 852 853 } 853 854 855 + static void init_restore_lsx(void) 856 + { 857 + enable_lsx(); 858 + 859 + if (!thread_lsx_context_live()) { 860 + /* First time LSX context user */ 861 + init_restore_fp(); 862 + init_lsx_upper(); 863 + set_thread_flag(TIF_LSX_CTX_LIVE); 864 + } else { 865 + if (!is_simd_owner()) { 866 + if (is_fpu_owner()) { 867 + restore_lsx_upper(current); 868 + } else { 869 + __own_fpu(); 870 + restore_lsx(current); 871 + } 872 + } 873 + } 874 + 875 + set_thread_flag(TIF_USEDSIMD); 876 + 877 + BUG_ON(!is_fp_enabled()); 878 + BUG_ON(!is_lsx_enabled()); 879 + } 880 + 881 + static void init_restore_lasx(void) 882 + { 883 + enable_lasx(); 884 + 885 + if (!thread_lasx_context_live()) { 886 + /* First time LASX context user */ 887 + init_restore_lsx(); 888 + init_lasx_upper(); 889 + set_thread_flag(TIF_LASX_CTX_LIVE); 890 + } else { 891 + if (is_fpu_owner() || is_simd_owner()) { 892 + init_restore_lsx(); 893 + restore_lasx_upper(current); 894 + } else { 895 + __own_fpu(); 896 + enable_lsx(); 897 + restore_lasx(current); 898 + } 899 + } 900 + 901 + set_thread_flag(TIF_USEDSIMD); 902 + 903 + BUG_ON(!is_fp_enabled()); 904 + BUG_ON(!is_lsx_enabled()); 905 + BUG_ON(!is_lasx_enabled()); 906 + } 907 + 854 908 asmlinkage void noinstr do_fpu(struct pt_regs *regs) 855 909 { 856 910 irqentry_state_t state = irqentry_enter(regs); 857 911 858 912 local_irq_enable(); 859 913 die_if_kernel("do_fpu invoked from kernel context!", regs); 914 + BUG_ON(is_lsx_enabled()); 915 + BUG_ON(is_lasx_enabled()); 860 916 861 917 preempt_disable(); 862 918 init_restore_fp(); ··· 926 872 irqentry_state_t state = irqentry_enter(regs); 927 873 928 874 local_irq_enable(); 929 - force_sig(SIGILL); 930 - local_irq_disable(); 875 + if (!cpu_has_lsx) { 876 + force_sig(SIGILL); 877 + goto out; 878 + } 931 879 880 + die_if_kernel("do_lsx invoked from kernel context!", regs); 881 + BUG_ON(is_lasx_enabled()); 882 + 883 + preempt_disable(); 884 + init_restore_lsx(); 885 + preempt_enable(); 886 + 887 + out: 888 + local_irq_disable(); 932 889 irqentry_exit(regs, state); 933 890 } 934 891 ··· 948 883 irqentry_state_t state = irqentry_enter(regs); 949 884 950 885 local_irq_enable(); 951 - force_sig(SIGILL); 952 - local_irq_disable(); 886 + if (!cpu_has_lasx) { 887 + force_sig(SIGILL); 888 + goto out; 889 + } 953 890 891 + die_if_kernel("do_lasx invoked from kernel context!", regs); 892 + 893 + preempt_disable(); 894 + init_restore_lasx(); 895 + preempt_enable(); 896 + 897 + out: 898 + local_irq_disable(); 954 899 irqentry_exit(regs, state); 955 900 } 956 901 ··· 999 924 /* For the moment, report the problem and hang. */ 1000 925 pr_err("Cache error exception:\n"); 1001 926 pr_err("csr_merrctl == %08x\n", csr_read32(LOONGARCH_CSR_MERRCTL)); 1002 - pr_err("csr_merrera == %016llx\n", csr_read64(LOONGARCH_CSR_MERRERA)); 927 + pr_err("csr_merrera == %016lx\n", csr_read64(LOONGARCH_CSR_MERRERA)); 1003 928 panic("Can't handle the cache error!"); 1004 929 } 1005 930
-2
arch/loongarch/kernel/unaligned.c
··· 485 485 struct dentry *d; 486 486 487 487 d = debugfs_create_dir("loongarch", NULL); 488 - if (IS_ERR_OR_NULL(d)) 489 - return -ENOMEM; 490 488 491 489 debugfs_create_u32("unaligned_instructions_user", 492 490 S_IRUGO, d, &unaligned_instructions_user);
+153
arch/loongarch/kernel/uprobes.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + #include <linux/highmem.h> 3 + #include <linux/ptrace.h> 4 + #include <linux/sched.h> 5 + #include <linux/uprobes.h> 6 + #include <asm/cacheflush.h> 7 + 8 + #define UPROBE_TRAP_NR UINT_MAX 9 + 10 + int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, 11 + struct mm_struct *mm, unsigned long addr) 12 + { 13 + int idx; 14 + union loongarch_instruction insn; 15 + 16 + if (addr & 0x3) 17 + return -EILSEQ; 18 + 19 + for (idx = ARRAY_SIZE(auprobe->insn) - 1; idx >= 0; idx--) { 20 + insn.word = auprobe->insn[idx]; 21 + if (insns_not_supported(insn)) 22 + return -EINVAL; 23 + } 24 + 25 + if (insns_need_simulation(insn)) { 26 + auprobe->ixol[0] = larch_insn_gen_nop(); 27 + auprobe->simulate = true; 28 + } else { 29 + auprobe->ixol[0] = auprobe->insn[0]; 30 + auprobe->simulate = false; 31 + } 32 + 33 + auprobe->ixol[1] = UPROBE_XOLBP_INSN; 34 + 35 + return 0; 36 + } 37 + 38 + int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 39 + { 40 + struct uprobe_task *utask = current->utask; 41 + 42 + utask->autask.saved_trap_nr = current->thread.trap_nr; 43 + current->thread.trap_nr = UPROBE_TRAP_NR; 44 + instruction_pointer_set(regs, utask->xol_vaddr); 45 + user_enable_single_step(current); 46 + 47 + return 0; 48 + } 49 + 50 + int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 51 + { 52 + struct uprobe_task *utask = current->utask; 53 + 54 + WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); 55 + current->thread.trap_nr = utask->autask.saved_trap_nr; 56 + 57 + if (auprobe->simulate) 58 + instruction_pointer_set(regs, auprobe->resume_era); 59 + else 60 + instruction_pointer_set(regs, utask->vaddr + LOONGARCH_INSN_SIZE); 61 + 62 + user_disable_single_step(current); 63 + 64 + return 0; 65 + } 66 + 67 + void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 68 + { 69 + struct uprobe_task *utask = current->utask; 70 + 71 + current->thread.trap_nr = utask->autask.saved_trap_nr; 72 + instruction_pointer_set(regs, utask->vaddr); 73 + user_disable_single_step(current); 74 + } 75 + 76 + bool arch_uprobe_xol_was_trapped(struct task_struct *t) 77 + { 78 + if (t->thread.trap_nr != UPROBE_TRAP_NR) 79 + return true; 80 + 81 + return false; 82 + } 83 + 84 + bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 85 + { 86 + union loongarch_instruction insn; 87 + 88 + if (!auprobe->simulate) 89 + return false; 90 + 91 + insn.word = auprobe->insn[0]; 92 + arch_simulate_insn(insn, regs); 93 + auprobe->resume_era = regs->csr_era; 94 + 95 + return true; 96 + } 97 + 98 + unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, 99 + struct pt_regs *regs) 100 + { 101 + unsigned long ra = regs->regs[1]; 102 + 103 + regs->regs[1] = trampoline_vaddr; 104 + 105 + return ra; 106 + } 107 + 108 + bool arch_uretprobe_is_alive(struct return_instance *ret, 109 + enum rp_check ctx, struct pt_regs *regs) 110 + { 111 + if (ctx == RP_CHECK_CHAIN_CALL) 112 + return regs->regs[3] <= ret->stack; 113 + else 114 + return regs->regs[3] < ret->stack; 115 + } 116 + 117 + int arch_uprobe_exception_notify(struct notifier_block *self, 118 + unsigned long val, void *data) 119 + { 120 + return NOTIFY_DONE; 121 + } 122 + 123 + bool uprobe_breakpoint_handler(struct pt_regs *regs) 124 + { 125 + if (uprobe_pre_sstep_notifier(regs)) 126 + return true; 127 + 128 + return false; 129 + } 130 + 131 + bool uprobe_singlestep_handler(struct pt_regs *regs) 132 + { 133 + if (uprobe_post_sstep_notifier(regs)) 134 + return true; 135 + 136 + return false; 137 + } 138 + 139 + unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) 140 + { 141 + return instruction_pointer(regs); 142 + } 143 + 144 + void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, 145 + void *src, unsigned long len) 146 + { 147 + void *kaddr = kmap_local_page(page); 148 + void *dst = kaddr + (vaddr & ~PAGE_MASK); 149 + 150 + memcpy(dst, src, len); 151 + flush_icache_range((unsigned long)dst, (unsigned long)dst + len); 152 + kunmap_local(kaddr); 153 + }
+82 -16
arch/loongarch/kernel/vdso.c
··· 14 14 #include <linux/random.h> 15 15 #include <linux/sched.h> 16 16 #include <linux/slab.h> 17 + #include <linux/time_namespace.h> 17 18 #include <linux/timekeeper_internal.h> 18 19 19 20 #include <asm/page.h> ··· 27 26 28 27 /* Kernel-provided data used by the VDSO. */ 29 28 static union { 30 - u8 page[VDSO_DATA_SIZE]; 29 + u8 page[PAGE_SIZE]; 30 + struct vdso_data data[CS_BASES]; 31 + } generic_vdso_data __page_aligned_data; 32 + 33 + static union { 34 + u8 page[LOONGARCH_VDSO_DATA_SIZE]; 31 35 struct loongarch_vdso_data vdata; 32 36 } loongarch_vdso_data __page_aligned_data; 33 37 34 38 static struct page *vdso_pages[] = { NULL }; 35 - struct vdso_data *vdso_data = loongarch_vdso_data.vdata.data; 39 + struct vdso_data *vdso_data = generic_vdso_data.data; 36 40 struct vdso_pcpu_data *vdso_pdata = loongarch_vdso_data.vdata.pdata; 37 41 38 42 static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma) ··· 45 39 current->mm->context.vdso = (void *)(new_vma->vm_start); 46 40 47 41 return 0; 42 + } 43 + 44 + static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, 45 + struct vm_area_struct *vma, struct vm_fault *vmf) 46 + { 47 + unsigned long pfn; 48 + struct page *timens_page = find_timens_vvar_page(vma); 49 + 50 + switch (vmf->pgoff) { 51 + case VVAR_GENERIC_PAGE_OFFSET: 52 + if (!timens_page) 53 + pfn = sym_to_pfn(vdso_data); 54 + else 55 + pfn = page_to_pfn(timens_page); 56 + break; 57 + #ifdef CONFIG_TIME_NS 58 + case VVAR_TIMENS_PAGE_OFFSET: 59 + /* 60 + * If a task belongs to a time namespace then a namespace specific 61 + * VVAR is mapped with the VVAR_GENERIC_PAGE_OFFSET and the real 62 + * VVAR page is mapped with the VVAR_TIMENS_PAGE_OFFSET offset. 63 + * See also the comment near timens_setup_vdso_data(). 64 + */ 65 + if (!timens_page) 66 + return VM_FAULT_SIGBUS; 67 + else 68 + pfn = sym_to_pfn(vdso_data); 69 + break; 70 + #endif /* CONFIG_TIME_NS */ 71 + case VVAR_LOONGARCH_PAGES_START ... VVAR_LOONGARCH_PAGES_END: 72 + pfn = sym_to_pfn(&loongarch_vdso_data) + vmf->pgoff - VVAR_LOONGARCH_PAGES_START; 73 + break; 74 + default: 75 + return VM_FAULT_SIGBUS; 76 + } 77 + 78 + return vmf_insert_pfn(vma, vmf->address, pfn); 48 79 } 49 80 50 81 struct loongarch_vdso_info vdso_info = { ··· 94 51 }, 95 52 .data_mapping = { 96 53 .name = "[vvar]", 54 + .fault = vvar_fault, 97 55 }, 98 56 .offset_sigreturn = vdso_offset_sigreturn, 99 57 }; ··· 117 73 } 118 74 subsys_initcall(init_vdso); 119 75 76 + #ifdef CONFIG_TIME_NS 77 + struct vdso_data *arch_get_vdso_data(void *vvar_page) 78 + { 79 + return (struct vdso_data *)(vvar_page); 80 + } 81 + 82 + /* 83 + * The vvar mapping contains data for a specific time namespace, so when a 84 + * task changes namespace we must unmap its vvar data for the old namespace. 85 + * Subsequent faults will map in data for the new namespace. 86 + * 87 + * For more details see timens_setup_vdso_data(). 88 + */ 89 + int vdso_join_timens(struct task_struct *task, struct time_namespace *ns) 90 + { 91 + struct mm_struct *mm = task->mm; 92 + struct vm_area_struct *vma; 93 + 94 + VMA_ITERATOR(vmi, mm, 0); 95 + 96 + mmap_read_lock(mm); 97 + for_each_vma(vmi, vma) { 98 + if (vma_is_special_mapping(vma, &vdso_info.data_mapping)) 99 + zap_vma_pages(vma); 100 + } 101 + mmap_read_unlock(mm); 102 + 103 + return 0; 104 + } 105 + #endif 106 + 120 107 static unsigned long vdso_base(void) 121 108 { 122 109 unsigned long base = STACK_TOP; ··· 163 88 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 164 89 { 165 90 int ret; 166 - unsigned long vvar_size, size, data_addr, vdso_addr; 91 + unsigned long size, data_addr, vdso_addr; 167 92 struct mm_struct *mm = current->mm; 168 93 struct vm_area_struct *vma; 169 94 struct loongarch_vdso_info *info = current->thread.vdso; ··· 175 100 * Determine total area size. This includes the VDSO data itself 176 101 * and the data pages. 177 102 */ 178 - vvar_size = VDSO_DATA_SIZE; 179 - size = vvar_size + info->size; 103 + size = VVAR_SIZE + info->size; 180 104 181 105 data_addr = get_unmapped_area(NULL, vdso_base(), size, 0, 0); 182 106 if (IS_ERR_VALUE(data_addr)) { 183 107 ret = data_addr; 184 108 goto out; 185 109 } 186 - vdso_addr = data_addr + VDSO_DATA_SIZE; 187 110 188 - vma = _install_special_mapping(mm, data_addr, vvar_size, 189 - VM_READ | VM_MAYREAD, 111 + vma = _install_special_mapping(mm, data_addr, VVAR_SIZE, 112 + VM_READ | VM_MAYREAD | VM_PFNMAP, 190 113 &info->data_mapping); 191 114 if (IS_ERR(vma)) { 192 115 ret = PTR_ERR(vma); 193 116 goto out; 194 117 } 195 118 196 - /* Map VDSO data page. */ 197 - ret = remap_pfn_range(vma, data_addr, 198 - virt_to_phys(&loongarch_vdso_data) >> PAGE_SHIFT, 199 - vvar_size, PAGE_READONLY); 200 - if (ret) 201 - goto out; 202 - 203 - /* Map VDSO code page. */ 119 + vdso_addr = data_addr + VVAR_SIZE; 204 120 vma = _install_special_mapping(mm, vdso_addr, info->size, 205 121 VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, 206 122 &info->code_mapping);
+9
arch/loongarch/kernel/vmlinux.lds.S
··· 136 136 DWARF_DEBUG 137 137 ELF_DETAILS 138 138 139 + #ifdef CONFIG_EFI_STUB 140 + /* header symbols */ 141 + _kernel_asize = _end - _text; 142 + _kernel_fsize = _edata - _text; 143 + _kernel_vsize = _end - __initdata_begin; 144 + _kernel_rsize = _edata - __initdata_begin; 145 + _kernel_offset = kernel_offset - _text; 146 + #endif 147 + 139 148 .gptab.sdata : { 140 149 *(.gptab.data) 141 150 *(.gptab.sdata)
+3 -3
arch/loongarch/lib/dump_tlb.c
··· 20 20 21 21 pr_info("Index : 0x%0x\n", read_csr_tlbidx()); 22 22 pr_info("PageSize : 0x%0x\n", read_csr_pagesize()); 23 - pr_info("EntryHi : 0x%0*llx\n", field, read_csr_entryhi()); 24 - pr_info("EntryLo0 : 0x%0*llx\n", field, read_csr_entrylo0()); 25 - pr_info("EntryLo1 : 0x%0*llx\n", field, read_csr_entrylo1()); 23 + pr_info("EntryHi : 0x%0*lx\n", field, read_csr_entryhi()); 24 + pr_info("EntryLo0 : 0x%0*lx\n", field, read_csr_entrylo0()); 25 + pr_info("EntryLo1 : 0x%0*lx\n", field, read_csr_entrylo1()); 26 26 } 27 27 28 28 static void dump_tlb(int first, int last)
+17 -4
arch/loongarch/mm/tlb.c
··· 167 167 int idx; 168 168 unsigned long flags; 169 169 170 + if (cpu_has_ptw) 171 + return; 172 + 170 173 /* 171 174 * Handle debugger faulting in for debugee. 172 175 */ ··· 225 222 pwctl0 = pte_i | pte_w << 5 | pmd_i << 10 | pmd_w << 15 | pud_i << 20 | pud_w << 25; 226 223 pwctl1 = pgd_i | pgd_w << 6; 227 224 225 + if (cpu_has_ptw) 226 + pwctl1 |= CSR_PWCTL1_PTW; 227 + 228 228 csr_write64(pwctl0, LOONGARCH_CSR_PWCTL0); 229 229 csr_write64(pwctl1, LOONGARCH_CSR_PWCTL1); 230 230 csr_write64((long)swapper_pg_dir, LOONGARCH_CSR_PGDH); ··· 270 264 if (cpu == 0) { 271 265 memcpy((void *)tlbrentry, handle_tlb_refill, 0x80); 272 266 local_flush_icache_range(tlbrentry, tlbrentry + 0x80); 273 - set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load, VECSIZE); 274 - set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load, VECSIZE); 275 - set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store, VECSIZE); 276 - set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify, VECSIZE); 267 + if (!cpu_has_ptw) { 268 + set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load, VECSIZE); 269 + set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load, VECSIZE); 270 + set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store, VECSIZE); 271 + set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify, VECSIZE); 272 + } else { 273 + set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load_ptw, VECSIZE); 274 + set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load_ptw, VECSIZE); 275 + set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store_ptw, VECSIZE); 276 + set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify_ptw, VECSIZE); 277 + } 277 278 set_handler(EXCCODE_TLBNR * VECSIZE, handle_tlb_protect, VECSIZE); 278 279 set_handler(EXCCODE_TLBNX * VECSIZE, handle_tlb_protect, VECSIZE); 279 280 set_handler(EXCCODE_TLBPE * VECSIZE, handle_tlb_protect, VECSIZE);
+24 -3
arch/loongarch/mm/tlbex.S
··· 184 184 ertn 185 185 186 186 nopage_tlb_load: 187 - dbar 0 187 + dbar 0x700 188 188 csrrd ra, EXCEPTION_KS2 189 189 la_abs t0, tlb_do_page_fault_0 190 190 jr t0 191 191 SYM_FUNC_END(handle_tlb_load) 192 + 193 + SYM_FUNC_START(handle_tlb_load_ptw) 194 + csrwr t0, LOONGARCH_CSR_KS0 195 + csrwr t1, LOONGARCH_CSR_KS1 196 + la_abs t0, tlb_do_page_fault_0 197 + jr t0 198 + SYM_FUNC_END(handle_tlb_load_ptw) 192 199 193 200 SYM_FUNC_START(handle_tlb_store) 194 201 csrwr t0, EXCEPTION_KS0 ··· 340 333 ertn 341 334 342 335 nopage_tlb_store: 343 - dbar 0 336 + dbar 0x700 344 337 csrrd ra, EXCEPTION_KS2 345 338 la_abs t0, tlb_do_page_fault_1 346 339 jr t0 347 340 SYM_FUNC_END(handle_tlb_store) 341 + 342 + SYM_FUNC_START(handle_tlb_store_ptw) 343 + csrwr t0, LOONGARCH_CSR_KS0 344 + csrwr t1, LOONGARCH_CSR_KS1 345 + la_abs t0, tlb_do_page_fault_1 346 + jr t0 347 + SYM_FUNC_END(handle_tlb_store_ptw) 348 348 349 349 SYM_FUNC_START(handle_tlb_modify) 350 350 csrwr t0, EXCEPTION_KS0 ··· 494 480 ertn 495 481 496 482 nopage_tlb_modify: 497 - dbar 0 483 + dbar 0x700 498 484 csrrd ra, EXCEPTION_KS2 499 485 la_abs t0, tlb_do_page_fault_1 500 486 jr t0 501 487 SYM_FUNC_END(handle_tlb_modify) 488 + 489 + SYM_FUNC_START(handle_tlb_modify_ptw) 490 + csrwr t0, LOONGARCH_CSR_KS0 491 + csrwr t1, LOONGARCH_CSR_KS1 492 + la_abs t0, tlb_do_page_fault_1 493 + jr t0 494 + SYM_FUNC_END(handle_tlb_modify_ptw) 502 495 503 496 SYM_FUNC_START(handle_tlb_refill) 504 497 csrwr t0, LOONGARCH_CSR_TLBRSAVE
+4 -4
arch/loongarch/power/suspend.c
··· 27 27 }; 28 28 static struct saved_registers saved_regs; 29 29 30 - static void arch_common_suspend(void) 30 + void loongarch_common_suspend(void) 31 31 { 32 32 save_counter(); 33 33 saved_regs.pgd = csr_read64(LOONGARCH_CSR_PGDL); ··· 40 40 loongarch_suspend_addr = loongson_sysconf.suspend_addr; 41 41 } 42 42 43 - static void arch_common_resume(void) 43 + void loongarch_common_resume(void) 44 44 { 45 45 sync_counter(); 46 46 local_flush_tlb_all(); ··· 62 62 enable_gpe_wakeup(); 63 63 enable_pci_wakeup(); 64 64 65 - arch_common_suspend(); 65 + loongarch_common_suspend(); 66 66 67 67 /* processor specific suspend */ 68 68 loongarch_suspend_enter(); 69 69 70 - arch_common_resume(); 70 + loongarch_common_resume(); 71 71 72 72 return 0; 73 73 }
+2 -5
arch/loongarch/vdso/Makefile
··· 12 12 $(filter -E%,$(KBUILD_CFLAGS)) \ 13 13 $(filter -march=%,$(KBUILD_CFLAGS)) \ 14 14 $(filter -m%-float,$(KBUILD_CFLAGS)) \ 15 + $(CLANG_FLAGS) \ 15 16 -D__VDSO__ 16 - 17 - ifeq ($(cc-name),clang) 18 - ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS)) 19 - endif 20 17 21 18 cflags-vdso := $(ccflags-vdso) \ 22 19 -isystem $(shell $(CC) -print-file-name=include) \ 23 20 $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ 24 - -O2 -g -fno-strict-aliasing -fno-common -fno-builtin -G0 \ 21 + -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \ 25 22 -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \ 26 23 $(call cc-option, -fno-asynchronous-unwind-tables) \ 27 24 $(call cc-option, -fno-stack-protector)
+1 -1
arch/loongarch/vdso/vgetcpu.c
··· 21 21 22 22 static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void) 23 23 { 24 - return (struct vdso_pcpu_data *)(get_vdso_base() - VDSO_DATA_SIZE); 24 + return (struct vdso_pcpu_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * PAGE_SIZE); 25 25 } 26 26 27 27 extern
+1 -1
drivers/acpi/Kconfig
··· 542 542 543 543 if ARM64 544 544 source "drivers/acpi/arm64/Kconfig" 545 + endif 545 546 546 547 config ACPI_PPTT 547 548 bool 548 - endif 549 549 550 550 config ACPI_PCC 551 551 bool "ACPI PCC Address Space"
+1
scripts/Makefile.clang
··· 4 4 CLANG_TARGET_FLAGS_arm := arm-linux-gnueabi 5 5 CLANG_TARGET_FLAGS_arm64 := aarch64-linux-gnu 6 6 CLANG_TARGET_FLAGS_hexagon := hexagon-linux-musl 7 + CLANG_TARGET_FLAGS_loongarch := loongarch64-linux-gnusf 7 8 CLANG_TARGET_FLAGS_m68k := m68k-linux-gnu 8 9 CLANG_TARGET_FLAGS_mips := mipsel-linux-gnu 9 10 CLANG_TARGET_FLAGS_powerpc := powerpc64le-linux-gnu