LoongArch: Make -mstrict-align configurable
authorHuacai Chen <chenhuacai@loongson.cn>
Sat, 25 Feb 2023 07:52:56 +0000 (15:52 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Sat, 25 Feb 2023 14:12:16 +0000 (22:12 +0800)
Introduce Kconfig option ARCH_STRICT_ALIGN to make -mstrict-align be
configurable.

Not all LoongArch cores support h/w unaligned access, we can use the
-mstrict-align build parameter to prevent unaligned accesses.

CPUs with h/w unaligned access support:
Loongson-2K2000/2K3000/3A5000/3C5000/3D5000.

CPUs without h/w unaligned access support:
Loongson-2K500/2K1000.

This option is enabled by default to make the kernel be able to run on
all LoongArch systems. But you can disable it manually if you want to
run kernel only on systems with h/w unaligned access support in order to
optimise for performance.

Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/Kconfig
arch/loongarch/Makefile
arch/loongarch/kernel/Makefile
arch/loongarch/kernel/traps.c

index 9cc8b84f7eb03d856900f2fb42f412d25ec5b0d5..0c1c6063cc66175a4d448f38d4a1b1974b506c71 100644 (file)
@@ -94,6 +94,7 @@ config LOONGARCH
        select HAVE_DYNAMIC_FTRACE_WITH_ARGS
        select HAVE_DYNAMIC_FTRACE_WITH_REGS
        select HAVE_EBPF_JIT
+       select HAVE_EFFICIENT_UNALIGNED_ACCESS if !ARCH_STRICT_ALIGN
        select HAVE_EXIT_THREAD
        select HAVE_FAST_GUP
        select HAVE_FTRACE_MCOUNT_RECORD
@@ -441,6 +442,24 @@ config ARCH_IOREMAP
          protection support. However, you can enable LoongArch DMW-based
          ioremap() for better performance.
 
+config ARCH_STRICT_ALIGN
+       bool "Enable -mstrict-align to prevent unaligned accesses" if EXPERT
+       default y
+       help
+         Not all LoongArch cores support h/w unaligned access, we can use
+         -mstrict-align build parameter to prevent unaligned accesses.
+
+         CPUs with h/w unaligned access support:
+         Loongson-2K2000/2K3000/3A5000/3C5000/3D5000.
+
+         CPUs without h/w unaligned access support:
+         Loongson-2K500/2K1000.
+
+         This option is enabled by default to make the kernel be able to run
+         on all LoongArch systems. But you can disable it manually if you want
+         to run kernel only on systems with h/w unaligned access support in
+         order to optimise for performance.
+
 config KEXEC
        bool "Kexec system call"
        select KEXEC_CORE
index 4402387d27551a3601c7a5ea49b6bf42f1377376..6e1c931a8507e0c67dd167736aa51e994212af2d 100644 (file)
@@ -91,10 +91,15 @@ KBUILD_CPPFLAGS += -DVMLINUX_LOAD_ADDRESS=$(load-y)
 # instead of .eh_frame so we don't discard them.
 KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
 
+ifdef CONFIG_ARCH_STRICT_ALIGN
 # Don't emit unaligned accesses.
 # Not all LoongArch cores support unaligned access, and as kernel we can't
 # rely on others to provide emulation for these accesses.
 KBUILD_CFLAGS += $(call cc-option,-mstrict-align)
+else
+# Optimise for performance on hardware supports unaligned access.
+KBUILD_CFLAGS += $(call cc-option,-mno-strict-align)
+endif
 
 KBUILD_CFLAGS += -isystem $(shell $(CC) -print-file-name=include)
 
index c8cfbd562921d63fe2a15aa6fb8a6940ff356fd4..df5dbabfe7a6c95274cf0c95c3d429c1f2d47b0d 100644 (file)
@@ -8,13 +8,15 @@ extra-y               := vmlinux.lds
 obj-y          += head.o cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \
                   traps.o irq.o idle.o process.o dma.o mem.o io.o reset.o switch.o \
                   elf.o syscall.o signal.o time.o topology.o inst.o ptrace.o vdso.o \
-                  alternative.o unaligned.o unwind.o
+                  alternative.o unwind.o
 
 obj-$(CONFIG_ACPI)             += acpi.o
 obj-$(CONFIG_EFI)              += efi.o
 
 obj-$(CONFIG_CPU_HAS_FPU)      += fpu.o
 
+obj-$(CONFIG_ARCH_STRICT_ALIGN)        += unaligned.o
+
 ifdef CONFIG_FUNCTION_TRACER
   ifndef CONFIG_DYNAMIC_FTRACE
     obj-y += mcount.o ftrace.o
index c38a146a973b45beafc0e984bdff77631fbea0bb..05511203732c3c1821f05ed0c39220a959b7399e 100644 (file)
@@ -371,9 +371,14 @@ int no_unaligned_warning __read_mostly = 1;        /* Only 1 warning by default */
 
 asmlinkage void noinstr do_ale(struct pt_regs *regs)
 {
-       unsigned int *pc;
        irqentry_state_t state = irqentry_enter(regs);
 
+#ifndef CONFIG_ARCH_STRICT_ALIGN
+       die_if_kernel("Kernel ale access", regs);
+       force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)regs->csr_badvaddr);
+#else
+       unsigned int *pc;
+
        perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->csr_badvaddr);
 
        /*
@@ -397,8 +402,8 @@ asmlinkage void noinstr do_ale(struct pt_regs *regs)
 sigbus:
        die_if_kernel("Kernel ale access", regs);
        force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)regs->csr_badvaddr);
-
 out:
+#endif
        irqentry_exit(regs, state);
 }