Print this page
XXX nobios
@@ -139,12 +139,14 @@
int force_fastreboot = 0;
volatile int fastreboot_onpanic = 0;
int post_fastreboot = 0;
#ifdef __xpv
volatile int fastreboot_capable = 0;
+boolean_t bios_calls_available = B_FALSE;
#else
volatile int fastreboot_capable = 1;
+boolean_t bios_calls_available = B_TRUE;
#endif
/*
* Information saved from current boot for fast reboot.
* If the information size exceeds what we have allocated, fast reboot
@@ -2507,10 +2509,52 @@
plat_dr_options |= PLAT_DR_FEATURE_MEMORY;
return (tp);
}
+/*
+ * If this system has a PC-compatible BIOS, it will have handlers for
+ * various well-known BIOS calls. These calls take the form of INT
+ * instructions, revectoring to the nominated entry in the real mode
+ * Interrupt Vector Table (IVT). If all of the commonly used entries (from
+ * INT 10h up to INT 1Ah) are zero, we almost certainly don't want to make
+ * use of BOP_DOINT() later.
+ *
+ * The IVT begins at linear address 0 on the 8086. Though later CPUs
+ * allowed it to be moved, it seems that most BIOS implementations choose
+ * not to do so for compatibility reasons. Our BIOS call trampoline (see
+ * "idt_info" in "uts/i86pc/ml/bios_call_src.s") also assumes this address.
+ */
+static int
+system_has_bios(void)
+{
+ uint32_t all_ivts = 0;
+
+ DBG_MSG("\nBIOS IVT Entries:\n");
+ for (uint32_t intnum = 0x10; intnum <= 0x1a; intnum++) {
+ /*
+ * The first software interrupt number (i.e. INT 0h) maps to
+ * vector number 32 in the IVT. Each entry in the IVT is
+ * four bytes, describing a 16 bit far call address.
+ */
+ uintptr_t slot = 4 * (32 + intnum);
+ uint32_t ivte = *((uint32_t *)slot);
+
+ if (ivte != 0) {
+ DBG(intnum);
+ DBG(ivte);
+ }
+ all_ivts |= ivte;
+ }
+ if (all_ivts == 0) {
+ DBG_MSG("System has no BIOS IVT entries\n");
+ }
+ DBG_MSG("\n");
+
+ return (all_ivts != 0);
+}
+
#else /* __xpv */
static void
enumerate_xen_cpus()
{
processorid_t id, max_id;
@@ -2540,10 +2584,13 @@
build_firmware_properties(void)
{
ACPI_TABLE_HEADER *tp = NULL;
#ifndef __xpv
+ if (do_bsys_getproplen(NULL, "no-bios") > 0 || !system_has_bios())
+ bios_calls_available = B_FALSE;
+
if ((tp = find_fw_table(ACPI_SIG_MSCT)) != NULL)
msct_ptr = process_msct((ACPI_TABLE_MSCT *)tp);
else
msct_ptr = NULL;