Page MenuHomeFreeBSD

D35799.id108381.diff
No OneTemporary

D35799.id108381.diff

Index: sys/conf/options.amd64
===================================================================
--- sys/conf/options.amd64
+++ sys/conf/options.amd64
@@ -64,3 +64,6 @@
# Don't create a "legacy" PCI bridge if none is found.
NO_LEGACY_PCIB opt_cpu.h
+
+# Compatibility with Linux MP table bugs.
+MPTABLE_LINUX_BUG_COMPAT
Index: sys/conf/options.i386
===================================================================
--- sys/conf/options.i386
+++ sys/conf/options.i386
@@ -108,3 +108,6 @@
# Don't create a "legacy" PCI bridge if none is found.
NO_LEGACY_PCIB opt_cpu.h
+
+# Compatibility with Linux MP table bugs.
+MPTABLE_LINUX_BUG_COMPAT
Index: sys/x86/x86/mptable.c
===================================================================
--- sys/x86/x86/mptable.c
+++ sys/x86/x86/mptable.c
@@ -30,6 +30,7 @@
__FBSDID("$FreeBSD$");
#include "opt_mptable_force_htt.h"
+#include "opt_mptable_linux_bug_compat.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -245,6 +246,34 @@
return (UNKNOWN_BUSTYPE);
}
+#ifdef MPTABLE_LINUX_BUG_COMPAT
+/* Compute the correct entry_count value. */
+static void
+compute_entry_count(void)
+{
+ u_char *end = (u_char *)(mpct) + mpct->base_table_length;
+ u_char *entry = (u_char *)(mpct + 1);
+ size_t nentries = 0;
+
+ while (entry < end) {
+ switch (*entry) {
+ case MPCT_ENTRY_PROCESSOR:
+ case MPCT_ENTRY_IOAPIC:
+ case MPCT_ENTRY_BUS:
+ case MPCT_ENTRY_INT:
+ case MPCT_ENTRY_LOCAL_INT:
+ break;
+ default:
+ panic("%s: Unknown MP Config Entry %d\n", __func__,
+ (int)*entry);
+ }
+ entry += basetable_entry_types[*entry].length;
+ nentries++;
+ }
+ mpct->entry_count = (uint16_t)(nentries);
+}
+#endif
+
/*
* Look for an Intel MP spec table (ie, SMP capable hardware).
*/
@@ -273,6 +302,17 @@
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
+#ifdef MPTABLE_LINUX_BUG_COMPAT
+ /*
+ * Linux assumes that it always has 640 kB of base memory and
+ * searches for the MP table at 639k regardless of whether that
+ * address is present in the system memory map. Some VM systems
+ * rely on this buggy behaviour.
+ */
+ if ((x = search_for_sig(639 * 1024, 1024 / 4)) >= 0)
+ goto found;
+#endif
+
/* nothing found */
return (ENXIO);
@@ -321,6 +361,16 @@
printf(
"MP Configuration Table version 1.%d found at %p\n",
mpct->spec_rev, mpct);
+#ifdef MPTABLE_LINUX_BUG_COMPAT
+ /*
+ * Linux ignores entry_count and instead scans the MP table
+ * until it runs out of bytes of table (as specified by the
+ * base_table_length field). Some VM systems rely on this
+ * buggy behaviour and record an entry_count of zero.
+ */
+ if (mpct->entry_count == 0)
+ compute_entry_count();
+#endif
}
return (-100);

File Metadata

Mime Type
text/plain
Expires
Fri, Dec 27, 1:31 PM (55 m, 43 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15614814
Default Alt Text
D35799.id108381.diff (2 KB)

Event Timeline