MFC r204420

When running as a guest operating system, the FreeBSD kernel must assume
  that the virtual machine monitor has enabled machine check exceptions.
  Unfortunately, on AMD Family 10h processors the machine check hardware
  has a bug (Erratum 383) that can result in a false machine check exception
  when a superpage promotion occurs.  Thus, I am disabling superpage
  promotion when the FreeBSD kernel is running as a guest operating system
  on an AMD Family 10h processor.
This commit is contained in:
Alan Cox 2010-03-02 16:29:08 +00:00
parent 69b9452545
commit c288186fe8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/stable/8/; revision=204584
4 changed files with 25 additions and 4 deletions

View File

@ -653,6 +653,15 @@ pmap_init(void)
TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max); TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
pv_entry_high_water = 9 * (pv_entry_max / 10); pv_entry_high_water = 9 * (pv_entry_max / 10);
/*
* Disable large page mappings by default if the kernel is running in
* a virtual machine on an AMD Family 10h processor. This is a work-
* around for Erratum 383.
*/
if (vm_guest == VM_GUEST_VM && cpu_vendor_id == CPU_VENDOR_AMD &&
CPUID_TO_FAMILY(cpu_id) == 0x10)
pg_ps_enabled = 0;
/* /*
* Are large page mappings enabled? * Are large page mappings enabled?
*/ */

View File

@ -677,6 +677,15 @@ pmap_init(void)
pv_entry_max = roundup(pv_entry_max, _NPCPV); pv_entry_max = roundup(pv_entry_max, _NPCPV);
pv_entry_high_water = 9 * (pv_entry_max / 10); pv_entry_high_water = 9 * (pv_entry_max / 10);
/*
* Disable large page mappings by default if the kernel is running in
* a virtual machine on an AMD Family 10h processor. This is a work-
* around for Erratum 383.
*/
if (vm_guest == VM_GUEST_VM && cpu_vendor_id == CPU_VENDOR_AMD &&
CPUID_TO_FAMILY(cpu_id) == 0x10)
pg_ps_enabled = 0;
/* /*
* Are large page mappings enabled? * Are large page mappings enabled?
*/ */

View File

@ -74,10 +74,6 @@ __FBSDID("$FreeBSD$");
#define MAXFILES (maxproc * 2) #define MAXFILES (maxproc * 2)
#endif #endif
/* Values of enum VM_GUEST members are used as indices in
* vm_guest_sysctl_names */
enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM, VM_GUEST_XEN };
static int sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS); static int sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS);
int hz; int hz;
@ -137,6 +133,10 @@ SYSCTL_PROC(_kern, OID_AUTO, vm_guest, CTLFLAG_RD | CTLTYPE_STRING,
*/ */
struct buf *swbuf; struct buf *swbuf;
/*
* The elements of this array are ordered based upon the values of the
* corresponding enum VM_GUEST members.
*/
static const char *const vm_guest_sysctl_names[] = { static const char *const vm_guest_sysctl_names[] = {
"none", "none",
"generic", "generic",

View File

@ -65,6 +65,9 @@ extern int bootverbose; /* nonzero to print verbose messages */
extern int maxusers; /* system tune hint */ extern int maxusers; /* system tune hint */
extern int ngroups_max; /* max # of supplemental groups */ extern int ngroups_max; /* max # of supplemental groups */
extern int vm_guest; /* Running as virtual machine guest? */
enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM, VM_GUEST_XEN };
#ifdef INVARIANTS /* The option is always available */ #ifdef INVARIANTS /* The option is always available */
#define KASSERT(exp,msg) do { \ #define KASSERT(exp,msg) do { \