summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Cosgrove <tom@cvs.openbsd.org>2004-06-26 05:19:38 +0000
committerTom Cosgrove <tom@cvs.openbsd.org>2004-06-26 05:19:38 +0000
commit2848f93ab2b2681cd23db65b1134e040761b7d76 (patch)
treead72c24cbad3ebcd08f8933d9d3b61e00798a10d
parent29fe2774e4b657b234b4462fff91c3ba006b7a52 (diff)
Initial stab at CPU identification code for i386 boot programs. Added
to i386 libsa, but not yet used by boot etc. ok weingart@
-rw-r--r--sys/arch/i386/stand/libsa/Makefile6
-rw-r--r--sys/arch/i386/stand/libsa/cpuprobe.c147
-rw-r--r--sys/arch/i386/stand/libsa/cpuprobe.h24
-rw-r--r--sys/arch/i386/stand/libsa/libsa.h3
4 files changed, 176 insertions, 4 deletions
diff --git a/sys/arch/i386/stand/libsa/Makefile b/sys/arch/i386/stand/libsa/Makefile
index 1a435b2c74a..3cae2277f8d 100644
--- a/sys/arch/i386/stand/libsa/Makefile
+++ b/sys/arch/i386/stand/libsa/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.43 2004/03/19 13:48:18 tom Exp $
+# $OpenBSD: Makefile,v 1.44 2004/06/26 05:19:37 tom Exp $
.include "${.CURDIR}/../Makefile.inc"
@@ -16,12 +16,12 @@ SRCS+= machdep.c dev_i386.c exec_i386.c cmd_i386.c loadfile.c
SRCS+= unixdev.c unixsys.S nullfs.c memprobe.c
CLEANFILES+= gidt.o debug_i386.o alloca.o \
biosdev.o bioscons.o gateA20.o apmprobe.o \
- memprobe.o diskprobe.o smpprobe.o \
+ cpuprobe.o memprobe.o diskprobe.o smpprobe.o \
time.o biosprobe.o
.else
SRCS+= gidt.S debug_i386.S alloca.S \
biosdev.c bioscons.c gateA20.c apmprobe.c \
- memprobe.c diskprobe.c pciprobe.c smpprobe.c \
+ cpuprobe.c memprobe.c diskprobe.c pciprobe.c smpprobe.c \
time.c biosprobe.c ps2probe.c pxe.c pxe_net.c pxe_call.S
CLEANFILES+= unixdev.o unixsys.o nullfs.o
.endif
diff --git a/sys/arch/i386/stand/libsa/cpuprobe.c b/sys/arch/i386/stand/libsa/cpuprobe.c
new file mode 100644
index 00000000000..286a72cc7d9
--- /dev/null
+++ b/sys/arch/i386/stand/libsa/cpuprobe.c
@@ -0,0 +1,147 @@
+/* $OpenBSD: cpuprobe.c,v 1.1 2004/06/26 05:19:37 tom Exp $ */
+
+/*
+ * Copyright (c) 2004 Tom Cosgrove <tom.cosgrove@arches-consulting.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <machine/psl.h>
+#include <machine/specialreg.h>
+
+#include "libsa.h"
+
+int amd64_supported;
+static int cpu_family, cpu_model, cpu_stepping;
+static int psl_check;
+static u_int32_t feature_ecx, feature_edx, feature_amd;
+static char cpu_brandstr[48]; /* Includes term NUL byte */
+static char cpu_vendor[13]; /* 12 chars plus NUL term */
+
+/*
+ * cpuid instruction. request in eax, result in eax, ebx, ecx, edx.
+ * requires caller to provide u_int32_t regs[4] array.
+ */
+u_int32_t
+cpuid(u_int32_t eax, u_int32_t *regs)
+{
+ __asm __volatile(
+ "cpuid\n\t"
+ "movl %%eax, 0(%2)\n\t"
+ "movl %%ebx, 4(%2)\n\t"
+ "movl %%ecx, 8(%2)\n\t"
+ "movl %%edx, 12(%2)\n\t"
+ : "=a" (eax)
+ : "0" (eax), "S" (regs)
+ : "bx", "cx", "dx");
+
+ return eax;
+}
+
+void
+cpuprobe(void)
+{
+ u_int32_t cpuid_max, extended_max;
+ u_int32_t regs[4];
+
+ /*
+ * 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) { /* cpuid supported */
+ cpuid_max = cpuid(0, regs); /* Highest std call */
+
+ bcopy(&regs[1], cpu_vendor, sizeof(regs[1]));
+ bcopy(&regs[3], cpu_vendor + 4, sizeof(regs[3]));
+ bcopy(&regs[2], cpu_vendor + 8, sizeof(regs[2]));
+ cpu_vendor[sizeof(cpu_vendor) - 1] = '\0';
+
+ if (cpuid_max >= 1) {
+ u_int32_t id;
+
+ id = cpuid(1, regs); /* Get basic info */
+ cpu_stepping = id & 0x000000f;
+ cpu_model = (id >> 4) & 0x0000000f;
+ cpu_family = (id >> 8) & 0x0000000f;
+
+ feature_ecx = regs[2];
+ feature_edx = regs[3];
+ }
+
+ extended_max = cpuid(0x80000000, regs); /* Highest ext */
+
+ if (extended_max >= 0x80000001) {
+ cpuid(0x80000001, regs);
+ feature_amd = regs[3];
+ if (feature_amd & CPUID_LONG)
+ amd64_supported = 1;
+ }
+
+ cpu_brandstr[0] = '\0';
+ if (extended_max >= 0x80000004) {
+ u_int32_t brand_ints[12];
+
+ cpuid(0x80000002, brand_ints);
+ cpuid(0x80000003, brand_ints + 4);
+ cpuid(0x80000004, brand_ints + 8);
+
+ bcopy(brand_ints, cpu_brandstr,
+ sizeof(cpu_brandstr) - 1);
+
+ cpu_brandstr[sizeof(cpu_brandstr) - 1] = '\0';
+ }
+ }
+
+ printf("%s", amd64_supported ? " amd64" : " i386");
+}
+
+void
+dump_cpuinfo(void)
+{
+ printf("\"%s\", family %d, model %d, step %d\n",
+ cpu_vendor, cpu_family, cpu_model, cpu_stepping);
+
+ if (*cpu_brandstr)
+ printf("%s\n", cpu_brandstr);
+
+ printf("features: ecx 0x%x, edx 0x%x, amd 0x%x\n",
+ feature_ecx, feature_edx, feature_amd);
+
+ printf("psl_check: 0x%x\n", psl_check);
+}
diff --git a/sys/arch/i386/stand/libsa/cpuprobe.h b/sys/arch/i386/stand/libsa/cpuprobe.h
new file mode 100644
index 00000000000..6df42b3d4df
--- /dev/null
+++ b/sys/arch/i386/stand/libsa/cpuprobe.h
@@ -0,0 +1,24 @@
+/* $OpenBSD: cpuprobe.h,v 1.1 2004/06/26 05:19:37 tom Exp $ */
+
+/*
+ * Copyright (c) 2004 Tom Cosgrove <tom.cosgrove@arches-consulting.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _CPUPROBE_H
+#define _CPUPROBE_H
+
+void dump_cpuinfo(void);
+
+#endif /* _CPUPROBE_H */
diff --git a/sys/arch/i386/stand/libsa/libsa.h b/sys/arch/i386/stand/libsa/libsa.h
index 2da7e66bd79..d3e599ca382 100644
--- a/sys/arch/i386/stand/libsa/libsa.h
+++ b/sys/arch/i386/stand/libsa/libsa.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: libsa.h,v 1.40 2004/06/23 00:21:49 tom Exp $ */
+/* $OpenBSD: libsa.h,v 1.41 2004/06/26 05:19:37 tom Exp $ */
/*
* Copyright (c) 1996-1999 Michael Shalayeff
@@ -44,6 +44,7 @@ extern void (*sa_cleanup)(void);
void gateA20(int);
void gateA20on(void);
+void cpuprobe(void);
void smpprobe(void);
void ps2probe(void);
void pciprobe(void);