--- system/cpuinfo.c
+++ system/cpuinfo.c
@@ -848,6 +848,12 @@
       default:
         // Unknown processor - make a guess at the family.
         switch (cpuid_info.version.family) {
+          case 3:
+            cpu_model = "386";
+            break;
+          case 4:
+            cpu_model = "486";
+            break;
           case 5:
             cpu_model = "586";
             break;
--- system/cpuid.c
+++ system/cpuid.c
@@ -8,6 +8,27 @@
 #include <stdint.h>
 
 #include "cpuid.h"
+#include "config.h"
+
+#define AC_BIT		(1<<18)
+#define CPUID_BIT	(1<<21)
+static inline int has_cpuid(int bits)
+{
+	int eax, edx;
+	__asm__ __volatile__(
+		"pushfl\n\t"
+		"popl %0\n\t"
+		"movl %0,%1\n\t"
+		"xorl %2,%0\n\t"
+		"pushl %0\n\t"
+		"popfl\n\t"
+		"pushfl\n\t"
+		"popl %0\n\t"
+		"pushl %1\n\t"
+		"popfl\n\t"
+		"xorl %1,%0":"=a" (eax),"=d" (edx):"c" (bits));
+	return eax;
+}
 
 //------------------------------------------------------------------------------
 // Public Variables
@@ -24,6 +45,15 @@
     uint32_t reg[4];
     char *p, *q;
 
+    switch (has_cpuid(AC_BIT|CPUID_BIT)) {
+    case 0:
+        cpuid_info.version.family = 3;
+        return;
+    case AC_BIT:
+        cpuid_info.version.family = 4;
+        return;
+    }
+
     // Get the max standard cpuid & vendor ID.
     cpuid(0x0, 0,
         &cpuid_info.max_cpuid,
--- boot/setup.S
+++ boot/setup.S
@@ -100,6 +100,29 @@
 	.long	0x10
 
 do_setup:
+
+	# Check cpuid support
+
+	pushfl
+	popw	%dx
+	popw	%ax
+	xorb	$0x20, %al		# toggle CPUID feature bit (21)
+	pushw	%ax
+	pushw	%dx
+	popfl
+	pushfl
+	popw	%dx
+	popw	%ax
+	xorb	%dl, %al
+	and	$0x20, %al
+	jz	1f
+	pushw	$0x1000
+	popw	%ds
+	movb	$0xa8, %al		# testb $imm %al opcode
+	movw	%ax, patch1
+	movw	%ax, patch2
+1:
+
 	# Reload the segment registers, except for the stack.
 
 	movw	%cs, %ax
--- boot/startup32.S
+++ boot/startup32.S
@@ -105,6 +105,8 @@
 
 	# ...and check if the processor supports long mode.
 
+patch1:
+	jmp	1f
 	movl	$0x80000000, %eax	# check if function 0x80000001 is available
 	pushl	%ebx			# ebx is overwritten by cpuid
 	cpuid
@@ -198,6 +200,8 @@
 
 	# Enable PAE if supported.
 
+patch2:
+	jmp	1f
 	pushl	%ebx			# ebx is overwritten by cpuid
 	movl	$0x00000001, %eax	# test the PAE flag
 	cpuid
--- system/cache.h
+++ system/cache.h
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #ifndef CACHE_H
 #define CACHE_H
+#include "cpuid.h"
 /**
  * \file
  *
@@ -26,6 +27,7 @@
         : "rax", "memory"
     );
 #else
+    if (cpuid_info.version.family >= 4)
     __asm__ __volatile__ ("\t"
         "movl   %%cr0, %%eax        \n\t"
         "orl    $0x40000000, %%eax  \n\t"  /* Set CD */
@@ -53,6 +55,7 @@
         : "rax", "memory"
     );
 #else
+    // if (cpuid_info.version.family >= 4)
     __asm__ __volatile__ ("\t"
         "movl   %%cr0, %%eax        \n\t"
         "andl   $0x9fffffff, %%eax  \n\t" /* Clear CD and NW */
@@ -69,6 +72,7 @@
  */
 static inline void cache_flush(void)
 {
+    if (cpuid_info.version.family >= 4)
     __asm__ __volatile__ ("\t"
         "wbinvd\n"
         : /* no outputs */
--- app/main.c
+++ app/main.c
@@ -75,6 +75,7 @@
 
 static volatile int     init_state = 0;
 
+static uintptr_t        low_load_limit = LOW_LOAD_LIMIT;
 static uintptr_t        low_load_addr;
 static uintptr_t        high_load_addr;
 
@@ -205,6 +206,9 @@
 
     cpuid_init();
 
+    if (cpuid_info.version.family <= 4)  // down to 1MB memory size support
+        low_load_limit = SIZE_C(256,KB); // must be a multiple of the page size
+
     // Nothing before this should access the boot parameters, in case they are located above 4GB.
     // This is the first region we map, so it is guaranteed not to fail.
     boot_params_addr = map_region(boot_params_addr, sizeof(boot_params_t), true);
@@ -282,8 +286,8 @@
 
     size_t program_size = (_stacks - _start) + BSP_STACK_SIZE + (num_enabled_cpus - 1) * AP_STACK_SIZE;
 
-    bool load_addr_ok = set_load_addr(& low_load_addr, program_size,         0x1000,  LOW_LOAD_LIMIT)
-                     && set_load_addr(&high_load_addr, program_size, LOW_LOAD_LIMIT, HIGH_LOAD_LIMIT);
+    bool load_addr_ok = set_load_addr(& low_load_addr, program_size,         0x1000,  low_load_limit)
+                     && set_load_addr(&high_load_addr, program_size, low_load_limit, HIGH_LOAD_LIMIT);
 
     trace(0, "program size %ikB", (int)(program_size / 1024));
     trace(0, " low_load_addr %0*x", 2*sizeof(uintptr_t),  low_load_addr);
@@ -420,7 +424,7 @@
                 // Relocation may disrupt the test.
                 window_num = 1;
             }
-            if (window_num == 0 && pm_limit_lower >= LOW_LOAD_LIMIT) {
+            if (window_num == 0 && pm_limit_lower >= low_load_limit) {
                 // Avoid unnecessary relocation.
                 window_num = 1;
             }
@@ -443,10 +447,10 @@
             switch (window_num) {
               case 0:
                 window_start = 0;
-                window_end   = (LOW_LOAD_LIMIT >> PAGE_SHIFT);
+                window_end   = (low_load_limit >> PAGE_SHIFT);
                 break;
               case 1:
-                window_start = (LOW_LOAD_LIMIT >> PAGE_SHIFT);
+                window_start = (low_load_limit >> PAGE_SHIFT);
                 window_end   = VM_WINDOW_SIZE;
                 break;
               default:
--- lib/unistd.c
+++ lib/unistd.c
@@ -5,10 +5,17 @@
 
 #include "cpuinfo.h"
 #include "tsc.h"
+#include "io.h"
 
 #include "unistd.h"
 
 //------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+#define PIT_TICKS_50mS      59659       // PIT clock is 1.193182MHz
+
+//------------------------------------------------------------------------------
 // Public Functions
 //------------------------------------------------------------------------------
 
@@ -22,9 +29,14 @@
             __builtin_ia32_pause();
         } while ((get_tsc() - t0) < cycles);
     } else {
-        // This will be highly inaccurate, but should give at least the requested delay.
-        volatile uint64_t count = (uint64_t)usec * 1000;
+        volatile uint64_t count = (uint64_t)usec / 50000;
         while (count > 0) {
+            // Use PIT Timer
+            outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+            outb(0xb0, 0x43);
+            outb(PIT_TICKS_50mS & 0xff, 0x42);
+            outb(PIT_TICKS_50mS >> 8, 0x42);
+            while ((inb(0x61) & 0x20) == 0);
             count--;
         }
     }
