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;