I have had great success with Gentoo Linux on the earliest generation of Intel 80486 processors, though I had to patch it (below).
It works on the later ones too (486DX2 and 486DX4, both clock multiplied and having the back-ported Pentium CPUID instruction).
I have it working on a Compaq LTE Elite 4/75CX laptop with a whopping 24MiB of memory.
Bugs have been filed with Gentoo for the following patches.
After you sync up the latest package configs with 'emerge --sync' or 'emerge-webrsync', you need to update the /usr/portage/profiles/arch/x86/make.defaults global configuration file because it assumes i686 as distributed.
So change this:
CHOST="i686-pc-linux-gnu" CFLAGS="-O2 -march=i686 -pipe"
to this:
CHOST="i486-pc-linux-gnu" CFLAGS="-O2 -march=i486 -pipe"
This glibc patch is needed for all i80486 and Pentium cpus because they all return (maxidx < 2) as true and the assert() causes the process to fail with a general protection fault. Unfortunately, that includes causing the init process to die, which makes your system panic.
--- glibc-2.23/sysdeps/x86_64/cacheinfo.c 2016-02-18 17:54:00.000000000 +0000 +++ tmp/cacheinfo.c 2017-07-07 14:58:25.840654116 +0000 @@ -259,7 +259,8 @@ static long int __attribute__ ((noinline)) handle_intel (int name, unsigned int maxidx) { - assert (maxidx >= 2); + if (maxidx < 2) + return -1; /* OK, we can use the CPUID instruction to get all info about the caches. */
This gcc patch is only needed for the first generation i80486, which lacks the CPUID instruction.
--- gcc-5.4.0/gcc/config/i386/cpuid.h 2015-06-18 10:56:43.000000000 +0000 +++ tmp/cpuid.h.newest 2017-07-07 21:54:34.598488154 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2015 Free Software Foundation, Inc. + * Copyright (C) 2007-2017 Free Software Foundation, Inc. * * This file is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -47,7 +47,7 @@ #define bit_SSE (1 << 25) #define bit_SSE2 (1 << 26) -/* Extended Features */ +/* Extended Features (%eax == 0x80000001) */ /* %ecx */ #define bit_LAHF_LM (1 << 0) #define bit_ABM (1 << 5) @@ -63,11 +63,15 @@ #define bit_MMXEXT (1 << 22) #define bit_LM (1 << 29) #define bit_3DNOWP (1 << 30) -#define bit_3DNOW (1 << 31) +#define bit_3DNOW (1u << 31) + +/* %ebx */ +#define bit_CLZERO (1 << 0) /* Extended Features (%eax == 7) */ /* %ebx */ #define bit_FSGSBASE (1 << 0) +#define bit_SGX (1 << 2) #define bit_BMI (1 << 3) #define bit_HLE (1 << 4) #define bit_AVX2 (1 << 5) @@ -87,11 +91,19 @@ #define bit_AVX512CD (1 << 28) #define bit_SHA (1 << 29) #define bit_AVX512BW (1 << 30) -#define bit_AVX512VL (1 << 31) +#define bit_AVX512VL (1u << 31) /* %ecx */ #define bit_PREFETCHWT1 (1 << 0) #define bit_AVX512VBMI (1 << 1) +#define bit_PKU (1 << 3) +#define bit_OSPKE (1 << 4) +#define bit_AVX512VPOPCNTDQ (1 << 14) +#define bit_RDPID (1 << 22) + +/* %edx */ +#define bit_AVX5124VNNIW (1 << 2) +#define bit_AVX5124FMAPS (1 << 3) /* XFEATURE_ENABLED_MASK register bits (%eax == 13, %ecx == 0) */ #define bit_BNDREGS (1 << 3) @@ -168,7 +180,7 @@ /* Return highest supported input value for cpuid instruction. ext can - be either 0x0 or 0x8000000 to return highest supported value for + be either 0x0 or 0x80000000 to return highest supported value for basic or extended cpuid information. Function returns 0 if cpuid is not supported or whatever cpuid returns in eax register. If sig pointer is non-null, then first four bytes of the signature @@ -224,21 +236,39 @@ return __eax; } -/* Return cpuid data for requested cpuid level, as found in returned +/* Return cpuid data for requested cpuid leaf, as found in returned eax, ebx, ecx and edx registers. The function checks if cpuid is supported and returns 1 for valid cpuid information or 0 for - unsupported cpuid level. All pointers are required to be non-null. */ + unsupported cpuid leaf. All pointers are required to be non-null. */ static __inline int -__get_cpuid (unsigned int __level, +__get_cpuid (unsigned int __leaf, unsigned int *__eax, unsigned int *__ebx, unsigned int *__ecx, unsigned int *__edx) { - unsigned int __ext = __level & 0x80000000; + unsigned int __ext = __leaf & 0x80000000; + unsigned int __maxlevel = __get_cpuid_max (__ext, 0); + + if (__maxlevel == 0 || __maxlevel < __leaf) + return 0; + + __cpuid (__leaf, *__eax, *__ebx, *__ecx, *__edx); + return 1; +} + +/* Same as above, but sub-leaf can be specified. */ + +static __inline int +__get_cpuid_count (unsigned int __leaf, unsigned int __subleaf, + unsigned int *__eax, unsigned int *__ebx, + unsigned int *__ecx, unsigned int *__edx) +{ + unsigned int __ext = __leaf & 0x80000000; + unsigned int __maxlevel = __get_cpuid_max (__ext, 0); - if (__get_cpuid_max (__ext, 0) < __level) + if (__maxlevel == 0 || __maxlevel < __leaf) return 0; - __cpuid (__level, *__eax, *__ebx, *__ecx, *__edx); + __cpuid_count (__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx); return 1; }