Use CPUID to see if the current CPU supports long mode when attemping to

boot an amd64 kernel.  If not, then fail the boot request with an error
message.  Otherwise, the boot attempt will fail with a BTX fault when
trying to read the EFER MSR.

MFC after:	3 days
This commit is contained in:
John Baldwin 2008-10-07 14:05:42 +00:00
parent 8c3bc1af40
commit f252d86740

View File

@ -32,6 +32,9 @@ __FBSDID("$FreeBSD$");
#include <sys/reboot.h>
#include <sys/linker.h>
#include <machine/bootinfo.h>
#include <machine/cpufunc.h>
#include <machine/psl.h>
#include <machine/specialreg.h>
#include "bootstrap.h"
#include "libi386.h"
#include "btxv86.h"
@ -124,7 +127,45 @@ bi_copymodules64(vm_offset_t addr)
}
/*
* Load the information expected by an i386 kernel.
* Check to see if this CPU supports long mode.
*/
static int
bi_checkcpu(void)
{
char *cpu_vendor;
int vendor[3];
int eflags, regs[4];
/* Check for presence of "cpuid". */
eflags = read_eflags();
write_eflags(eflags ^ PSL_ID);
if (!((eflags ^ read_eflags()) & PSL_ID))
return (0);
/* Fetch the vendor string. */
do_cpuid(0, regs);
vendor[0] = regs[1];
vendor[1] = regs[3];
vendor[2] = regs[2];
cpu_vendor = (char *)vendor;
/* Check for vendors that support AMD features. */
if (strncmp(cpu_vendor, "GenuineIntel", 12) != 0 &&
strncmp(cpu_vendor, "AuthenticAMD", 12) != 0)
return (0);
/* Has to support AMD features. */
do_cpuid(0x80000000, regs);
if (!(regs[0] >= 0x80000001))
return (0);
/* Check for long mode. */
do_cpuid(0x80000001, regs);
return (regs[3] & AMDID_LM);
}
/*
* Load the information expected by an amd64 kernel.
*
* - The 'boothowto' argument is constructed
* - The 'bootdev' argument is constructed
@ -145,6 +186,11 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
char *rootdevname;
int howto;
if (!bi_checkcpu()) {
printf("CPU doesn't support long mode\n");
return (EINVAL);
}
howto = bi_getboothowto(args);
/*