On Wed, Feb 27, 2019 at 11:07:23AM -0800, Philip Guenther wrote:
> On Mon, 25 Feb 2019, Falk Richter wrote:
> > >Synopsis:  <OpenBSD 6.4 doesn't boot on 486 class processor anymore>
> ...
> > >Description:
> >     <Just after booting the kernel the system stops with:
> > trap: 0(0) invalid opcode fault
> > cn_tab=0x5412c
> > eax 0 ecx 0 edx ff58 ebx ffc8
> > esp fe0c ebp ff40 esi 8 edi ff58
> > eip 4241c eflags 10046 cs 8 ss 10
> > ds 10 es 10 fs 10 gs 10
> > 
> > I tested it with AMD / Cyrix 486DX2-66, AMD 486DX4-100 and Cyrix 
> > 5x86-100GP processors on different mainboards with chipsets of UMC, SiS 
> > and Winbond. I found one exception which works yet (see dmesg): AMD 5x86 
> > P75 (marketing name) which was a AMD 486DX4-133 with write-back cache.
> 
> The problem is that ucode_load() in sys/arch/i386/stand/libsa/exec_i386.c 
> uses CPUID() without checking whether the cpuid instruction is supported.  
> There are currently three places in sys/arch/i386/stand/libsa which make 
> that check: cpuprobe.c, machdep.c, and random_i386.S. ucode_load() could 
> copy the chunk from machdep.c...or someone could add a global and do the 
> check once, early...

Index: boot/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/stand/boot/conf.c,v
retrieving revision 1.65
diff -u -p -r1.65 conf.c
--- boot/conf.c 23 Aug 2018 14:47:52 -0000      1.65
+++ boot/conf.c 28 Feb 2019 01:19:19 -0000
@@ -41,7 +41,7 @@
 #include <dev/cons.h>
 #include "debug.h"
 
-const char version[] = "3.34";
+const char version[] = "3.35";
 int    debug = 1;
 
 
Index: cdboot/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/stand/cdboot/conf.c,v
retrieving revision 1.33
diff -u -p -r1.33 conf.c
--- cdboot/conf.c       23 Aug 2018 14:47:52 -0000      1.33
+++ cdboot/conf.c       28 Feb 2019 01:19:31 -0000
@@ -42,7 +42,7 @@
 #include <dev/cons.h>
 #include "debug.h"
 
-const char version[] = "3.30";
+const char version[] = "3.31";
 int    debug = 1;
 
 void (*sa_cleanup)(void) = NULL;
Index: libsa/exec_i386.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/stand/libsa/exec_i386.c,v
retrieving revision 1.47
diff -u -p -r1.47 exec_i386.c
--- libsa/exec_i386.c   10 Dec 2018 16:52:02 -0000      1.47
+++ libsa/exec_i386.c   28 Feb 2019 00:55:07 -0000
@@ -34,6 +34,7 @@
 #include <lib/libsa/loadfile.h>
 #include <machine/biosvar.h>
 #include <machine/specialreg.h>
+#include <machine/psl.h>
 #include <stand/boot/bootarg.h>
 
 #include "cmd.h"
@@ -163,7 +164,40 @@ ucode_load(void)
        char path[128];
        size_t buflen;
        char *buf;
-       int fd;
+       int fd, psl_check;
+
+       /*
+        * The following is a simple check to see if cpuid is supported.
+        * We try to toggle bit 21 (PSL_ID) in eflags.  If it works, then
+        * cpuid is supported.  If not, there's no cpuid, and we don't
+        * try it (don't want /boot to get an invalid opcode exception).
+        *
+        * XXX The NexGen Nx586 does not support this bit, so this is not
+        *     a good method to detect the presence of cpuid on this
+        *     processor.  That's fine: the purpose here is to detect the
+        *     absence of cpuid.  We don't mind if the instruction's not
+        *     there - this is not intended to determine exactly what
+        *     processor is there, just whether it's i386 or amd64.
+        *
+        *     The only thing that would cause us grief is a processor which
+        *     does not support cpuid but which does allow the PSL_ID bit
+        *     in eflags to be toggled.
+        */
+       __asm volatile(
+           "pushfl\n\t"
+           "popl       %2\n\t"
+           "xorl       %2, %0\n\t"
+           "pushl      %0\n\t"
+           "popfl\n\t"
+           "pushfl\n\t"
+           "popl       %0\n\t"
+           "xorl       %2, %0\n\t"             /* If %2 == %0, no cpuid */
+           : "=r" (psl_check)
+           : "0" (PSL_ID), "r" (0)
+           : "cc");
+
+       if (psl_check != PSL_ID)
+               return;
 
        CPUID(0, dummy, vendor[0], vendor[2], vendor[1]);
        vendor[3] = 0; /* NULL-terminate */
Index: pxeboot/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/stand/pxeboot/conf.c,v
retrieving revision 1.38
diff -u -p -r1.38 conf.c
--- pxeboot/conf.c      23 Aug 2018 14:47:52 -0000      1.38
+++ pxeboot/conf.c      28 Feb 2019 01:19:44 -0000
@@ -44,7 +44,7 @@
 #include "pxeboot.h"
 #include "pxe_net.h"
 
-const char version[] = "3.30";
+const char version[] = "3.31";
 int    debug = 1;
 
 void (*sa_cleanup)(void) = pxe_shutdown;

Reply via email to