Commit 41596803 authored by Huacai Chen's avatar Huacai Chen
Browse files

LoongArch: Make -mstrict-align configurable



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: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent bb7a78e3
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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)

+3 −1
Original line number Diff line number Diff line
@@ -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
+7 −2
Original line number Diff line number Diff line
@@ -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);
}