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; }