diff options
author | Tom Cosgrove <tom@cvs.openbsd.org> | 2004-06-26 05:19:38 +0000 |
---|---|---|
committer | Tom Cosgrove <tom@cvs.openbsd.org> | 2004-06-26 05:19:38 +0000 |
commit | 2848f93ab2b2681cd23db65b1134e040761b7d76 (patch) | |
tree | ad72c24cbad3ebcd08f8933d9d3b61e00798a10d | |
parent | 29fe2774e4b657b234b4462fff91c3ba006b7a52 (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/Makefile | 6 | ||||
-rw-r--r-- | sys/arch/i386/stand/libsa/cpuprobe.c | 147 | ||||
-rw-r--r-- | sys/arch/i386/stand/libsa/cpuprobe.h | 24 | ||||
-rw-r--r-- | sys/arch/i386/stand/libsa/libsa.h | 3 |
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(®s[1], cpu_vendor, sizeof(regs[1])); + bcopy(®s[3], cpu_vendor + 4, sizeof(regs[3])); + bcopy(®s[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); |