[PATCH 7/7] x86: simplify 32-bit instruction set selection
H. Peter Anvin
hpa at zytor.com
Thu Nov 5 12:17:19 PST 2026
On November 5, 2026 8:34:38 AM PST, Arnd Bergmann <arnd at kernel.org> wrote:
>From: Arnd Bergmann <arnd at arndb.de>
>
>The -march= compiler flags select both instruction set and tuning for
>a particular CPU, which works well when building a kernel that can only
>run on this one type, but has some counterintuitive effects because it
>is not always clear which models are compatible.
>
>E.g. building for Geode LX results in a kernel that can work on all on
>all 686-class CPUs but crashes on CPUs without the CMOV instructions.
>Building a kernel for 686 could work on Geode LX and Crusoe but fails
>because of the CPU generation check that detects these as 585-class.
>Similarly, building for Intel Atom produces a 32-bit kernel that uses
>the MOVBE instructions and does not work on any other 32-bit CPU or
>even 64-bit CPUs before Haswell/Excavator.
>
>Change the CPU selection to build everything with either -march=i586
>or -march=i686 and make the specific options only change the -mtune=
>parameter where this was previously handled by -march=. Note that
>the only -mtune= options that gcc or clang understand for x86-32
>are i486, pentium, pentiumpro, pentium4, atom, geode, k6 and athlon,
>the other ten are just aliases for one of them.
>
>Selecting any 586-class configuration option now produces a kernel that
>works on every supported CPU, while selecting a 686-class configuration
>works on all 686-class CPUs but no 586-class ones.
>
>Consequently, the vermagic.h logic can be simplified to just these
>two cases.
>
>Signed-off-by: Arnd Bergmann <arnd at arndb.de>
>---
> arch/x86/Kconfig.cpu | 13 +++++-------
> arch/x86/Makefile_32.cpu | 16 +++++++--------
> arch/x86/include/asm/vermagic.h | 36 ++-------------------------------
> 3 files changed, 15 insertions(+), 50 deletions(-)
>
>diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
>index 21026e0cb569..121881c4d076 100644
>--- a/arch/x86/Kconfig.cpu
>+++ b/arch/x86/Kconfig.cpu
>@@ -6,9 +6,9 @@ choice
> default M686
> help
> This is the processor type of your CPU. This information is
>- used for optimizing purposes. In order to compile a kernel
>- that can run on all supported x86 CPU types (albeit not
>- optimally fast), you can specify "586" here.
>+ used to pick between i586-class and i686-class processors,
>+ as well as to optimize for a particular microarchitecture
>+ within the two classes.
>
> Note that the 386 and 486 is no longer supported, this includes
> AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI 486DLC/DLC2,
>@@ -164,16 +164,13 @@ config MCYRIXIII
> treat this chip as a generic 586. Whilst the CPU is 686 class,
> it lacks the cmov extension which gcc assumes is present when
> generating 686 code.
>- Note that Nehemiah (Model 9) and above will not boot with this
>- kernel due to them lacking the 3DNow! instructions used in earlier
>- incarnations of the CPU.
>
> config MVIAC3_2
> bool "VIA C3-2 (Nehemiah)"
> depends on X86_32
> help
>- Select this for a VIA C3 "Nehemiah". Selecting this enables usage
>- of SSE and tells gcc to treat the CPU as a 686.
>+ Select this for a VIA C3 "Nehemiah". Selecting tells gcc to treat
>+ the CPU as a 686.
> Note, this kernel will not boot on older (pre model 9) C3s.
>
> config MVIAC7
>diff --git a/arch/x86/Makefile_32.cpu b/arch/x86/Makefile_32.cpu
>index c5aa169b596d..1735a5f95d33 100644
>--- a/arch/x86/Makefile_32.cpu
>+++ b/arch/x86/Makefile_32.cpu
>@@ -11,26 +11,26 @@ align := -falign-functions=0 -falign-jumps=0 -falign-loops=0
> endif
>
> cflags-$(CONFIG_M586TSC) += -march=i586
>-cflags-$(CONFIG_M586MMX) += -march=pentium-mmx
>+cflags-$(CONFIG_M586MMX) += -march=i586
> cflags-$(CONFIG_M686) += -march=i686
> cflags-$(CONFIG_MPENTIUMII) += -march=i686 $(call tune,pentium2)
> cflags-$(CONFIG_MPENTIUMIII) += -march=i686 $(call tune,pentium3)
> cflags-$(CONFIG_MPENTIUMM) += -march=i686 $(call tune,pentium3)
> cflags-$(CONFIG_MPENTIUM4) += -march=i686 $(call tune,pentium4)
>-cflags-$(CONFIG_MK6) += -march=k6
>+cflags-$(CONFIG_MK6) += -march=i586 $(call tune,k6)
> # Please note, that patches that add -march=athlon-xp and friends are pointless.
> # They make zero difference whatsosever to performance at this time.
>-cflags-$(CONFIG_MK7) += -march=athlon
>+cflags-$(CONFIG_MK7) += -march=i686 $(call tune,athlon)
> cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)
> cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align)
>-cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)
>-cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686)
>+cflags-$(CONFIG_MCYRIXIII) += -march=i586 $(call tune,i486) $(align)
>+cflags-$(CONFIG_MVIAC3_2) += -march=i686
> cflags-$(CONFIG_MVIAC7) += -march=i686
>-cflags-$(CONFIG_MATOM) += -march=atom
>+cflags-$(CONFIG_MATOM) += -march=i686 $(call tune,atom)
>
> # Geode GX1 support
>-cflags-$(CONFIG_MGEODEGX1) += -march=pentium-mmx
>-cflags-$(CONFIG_MGEODE_LX) += $(call cc-option,-march=geode,-march=pentium-mmx)
>+cflags-$(CONFIG_MGEODEGX1) += -march=i586 $(call tune,geode)
>+cflags-$(CONFIG_MGEODE_LX) += -march=i586 $(call tune,geode)
> # add at the end to overwrite eventual tuning options from earlier
> # cpu entries
> cflags-$(CONFIG_X86_GENERIC) += $(call tune,generic,$(call tune,i686))
>diff --git a/arch/x86/include/asm/vermagic.h b/arch/x86/include/asm/vermagic.h
>index e26061df0c9b..5323ed585bc9 100644
>--- a/arch/x86/include/asm/vermagic.h
>+++ b/arch/x86/include/asm/vermagic.h
>@@ -5,42 +5,10 @@
>
> #ifdef CONFIG_X86_64
> /* X86_64 does not define MODULE_PROC_FAMILY */
>-#elif defined CONFIG_M586TSC
>-#define MODULE_PROC_FAMILY "586TSC "
>-#elif defined CONFIG_M586MMX
>-#define MODULE_PROC_FAMILY "586MMX "
>-#elif defined CONFIG_MATOM
>-#define MODULE_PROC_FAMILY "ATOM "
>-#elif defined CONFIG_M686
>+#elif CONFIG_X86_MINIMUM_CPU_FAMILY == 6
> #define MODULE_PROC_FAMILY "686 "
>-#elif defined CONFIG_MPENTIUMII
>-#define MODULE_PROC_FAMILY "PENTIUMII "
>-#elif defined CONFIG_MPENTIUMIII
>-#define MODULE_PROC_FAMILY "PENTIUMIII "
>-#elif defined CONFIG_MPENTIUMM
>-#define MODULE_PROC_FAMILY "PENTIUMM "
>-#elif defined CONFIG_MPENTIUM4
>-#define MODULE_PROC_FAMILY "PENTIUM4 "
>-#elif defined CONFIG_MK6
>-#define MODULE_PROC_FAMILY "K6 "
>-#elif defined CONFIG_MK7
>-#define MODULE_PROC_FAMILY "K7 "
>-#elif defined CONFIG_MCRUSOE
>-#define MODULE_PROC_FAMILY "CRUSOE "
>-#elif defined CONFIG_MEFFICEON
>-#define MODULE_PROC_FAMILY "EFFICEON "
>-#elif defined CONFIG_MCYRIXIII
>-#define MODULE_PROC_FAMILY "CYRIXIII "
>-#elif defined CONFIG_MVIAC3_2
>-#define MODULE_PROC_FAMILY "VIAC3-2 "
>-#elif defined CONFIG_MVIAC7
>-#define MODULE_PROC_FAMILY "VIAC7 "
>-#elif defined CONFIG_MGEODEGX1
>-#define MODULE_PROC_FAMILY "GEODEGX1 "
>-#elif defined CONFIG_MGEODE_LX
>-#define MODULE_PROC_FAMILY "GEODE "
> #else
>-#error unknown processor family
>+#define MODULE_PROC_FAMILY "586 "
> #endif
>
> #ifdef CONFIG_X86_32
Crusoe (TM3xxx/TM5xxx) do have a handful of compiler/user space visible items that are missing from i686, as I recall notably the long nop instructions and *possibly* fcomi (I *think* we caught that one, but I'm not 100% sure.)
As a result, it reports correctly as family 5.
More information about the linux-um
mailing list