--- old/usr/src/uts/i86pc/os/biosdisk.c	Mon Mar 27 00:11:46 2017
+++ new/usr/src/uts/i86pc/os/biosdisk.c	Mon Mar 27 00:11:46 2017
@@ -37,6 +37,7 @@
 #include <sys/sunndi.h>
 #include <sys/biosdisk.h>
 #include <sys/psw.h>
+#include <sys/machsystm.h>
 #if defined(__xpv)
 #include <sys/hypervisor.h>
 #endif
@@ -82,8 +83,13 @@
 	dev_info_t	*devi;
 	int extensions;
 
-	if (dobiosdev == 0)
+	if (dobiosdev == 0 || !bios_calls_available) {
+		/*
+		 * If BIOS calls have been disabled, or are not supported on
+		 * this system, we cannot probe for the startup disk.
+		 */
 		return;
+	}
 
 	for (drivenum = 0x80; drivenum < (0x80 + BIOSDEV_NUM); drivenum++) {
 
--- old/usr/src/uts/i86pc/os/fakebop.c	Mon Mar 27 00:11:47 2017
+++ new/usr/src/uts/i86pc/os/fakebop.c	Mon Mar 27 00:11:47 2017
@@ -141,8 +141,10 @@
 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
 
 /*
@@ -2509,6 +2511,48 @@
 	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()
@@ -2542,6 +2586,9 @@
 	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
--- old/usr/src/uts/i86pc/os/mlsetup.c	Mon Mar 27 00:11:48 2017
+++ new/usr/src/uts/i86pc/os/mlsetup.c	Mon Mar 27 00:11:48 2017
@@ -87,6 +87,9 @@
 {
 	struct bop_regs rp = {0};
 
+	if (!bios_calls_available)
+		return;
+
 	rp.eax.byte.ah = 0x0;
 	rp.eax.byte.al = val;
 	rp.ebx.word.bx = 0x0;
--- old/usr/src/uts/i86pc/os/pci_bios.c	Mon Mar 27 00:11:48 2017
+++ new/usr/src/uts/i86pc/os/pci_bios.c	Mon Mar 27 00:11:48 2017
@@ -32,6 +32,7 @@
 #include <sys/memlist.h>
 #include <sys/bootconf.h>
 #include <sys/psw.h>
+#include <sys/machsystm.h>
 
 /*
  * pci irq routing information table
@@ -77,6 +78,13 @@
 		*nneededp = 0;
 
 	/*
+	 * If this system does not support BIOS calls, we can't use this
+	 * mechanism.
+	 */
+	if (!bios_calls_available)
+		return (0);
+
+	/*
 	 * Set up irq routing header with the size and address
 	 * of some useable low-memory data addresses.  Initalize
 	 * data area to zero, avoiding memcpy/bzero.
--- old/usr/src/uts/i86pc/os/pci_cfgspace.c	Mon Mar 27 00:11:49 2017
+++ new/usr/src/uts/i86pc/os/pci_cfgspace.c	Mon Mar 27 00:11:49 2017
@@ -35,13 +35,12 @@
 #include <sys/pci_cfgspace.h>
 #include <sys/pci_cfgspace_impl.h>
 #include <sys/pci_cfgacc.h>
+#include <sys/machsystm.h>
 #if defined(__xpv)
 #include <sys/hypervisor.h>
 #endif
 
-#if defined(__xpv)
 int pci_max_nbus = 0xFE;
-#endif
 int pci_bios_cfg_type = PCI_MECHANISM_UNKNOWN;
 int pci_bios_maxbus;
 int pci_bios_mech;
@@ -253,6 +252,18 @@
 	uint32_t	carryflag;
 	uint16_t	ax, dx;
 
+	if (!bios_calls_available) {
+		/*
+		 * If this system does not support BIOS calls, we must fall
+		 * back to default values and a search of all of the possible
+		 * PCI buses.
+		 */
+		pci_bios_mech = 1;
+		pci_bios_vers = 0;
+		pci_bios_maxbus = pci_max_nbus;
+		return (PCI_MECHANISM_1);
+	}
+
 	bzero(&regs, sizeof (regs));
 	regs.eax.word.ax = (PCI_FUNCTION_ID << 8) | PCI_BIOS_PRESENT;
 
--- old/usr/src/uts/i86pc/sys/machsystm.h	Mon Mar 27 00:11:49 2017
+++ new/usr/src/uts/i86pc/sys/machsystm.h	Mon Mar 27 00:11:49 2017
@@ -36,7 +36,6 @@
  *
  * This file should not be included by code that purports to be
  * platform-independent.
- *
  */
 
 #include <sys/machparam.h>
@@ -232,6 +231,8 @@
 
 extern hrtime_t tsc_gethrtime_tick_delta(void);
 
+extern boolean_t bios_calls_available;
+
 #endif /* _KERNEL */
 
 #ifdef __cplusplus
