--- old/usr/src/uts/i86pc/dboot/dboot_elfload.c	Wed Jan 15 08:03:49 2020
+++ new/usr/src/uts/i86pc/dboot/dboot_elfload.c	Wed Jan 15 08:03:49 2020
@@ -24,6 +24,9 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright 2020 Joyent, Inc.
+ */
 
 #include <sys/types.h>
 #include <sys/inttypes.h>
@@ -182,7 +185,7 @@
 		/* zero out bss */
 		if (shdr->sh_type == SHT_NOBITS) {
 			if (prom_debug)
-				dboot_printf("zeroing BSS %lu bytes from "
+				dboot_printf("zeroing BSS %ld bytes from "
 				    "physaddr 0x%" PRIx64
 				    " (end=0x%" PRIx64 ")\n",
 				    (ulong_t)shdr->sh_size,
--- old/usr/src/uts/i86pc/dboot/dboot_startkern.c	Wed Jan 15 08:03:49 2020
+++ new/usr/src/uts/i86pc/dboot/dboot_startkern.c	Wed Jan 15 08:03:49 2020
@@ -23,7 +23,7 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright 2013 Joyent, Inc.  All rights reserved.
+ * Copyright 2020 Joyent, Inc.
  */
 
 
@@ -1759,22 +1759,19 @@
 	}
 
 	/*
-	 * The ACPI RSDP can be found by scanning the BIOS memory areas or
-	 * from the EFI system table. The boot loader may pass in the address
-	 * it found the ACPI tables at.
+	 * The multiboot2 info contains a copy of the RSDP; stash a pointer to
+	 * it (see find_rsdp() in fakebop).
 	 */
 	nacpitagp = (multiboot_tag_new_acpi_t *)
-	    dboot_multiboot2_find_tag(mb2_info,
-	    MULTIBOOT_TAG_TYPE_ACPI_NEW);
+	    dboot_multiboot2_find_tag(mb2_info, MULTIBOOT_TAG_TYPE_ACPI_NEW);
 	oacpitagp = (multiboot_tag_old_acpi_t *)
-	    dboot_multiboot2_find_tag(mb2_info,
-	    MULTIBOOT_TAG_TYPE_ACPI_OLD);
+	    dboot_multiboot2_find_tag(mb2_info, MULTIBOOT_TAG_TYPE_ACPI_OLD);
 
 	if (nacpitagp != NULL) {
-		bi->bi_acpi_rsdp = (native_ptr_t)(uintptr_t)
+		bi->bi_acpi_rsdp_copy = (native_ptr_t)(uintptr_t)
 		    &nacpitagp->mb_rsdp[0];
 	} else if (oacpitagp != NULL) {
-		bi->bi_acpi_rsdp = (native_ptr_t)(uintptr_t)
+		bi->bi_acpi_rsdp_copy = (native_ptr_t)(uintptr_t)
 		    &oacpitagp->mb_rsdp[0];
 	}
 }
@@ -2287,6 +2284,7 @@
 	if (mb2_info != NULL)
 		DBG(mb2_info->mbi_total_size);
 	DBG(bi->bi_acpi_rsdp);
+	DBG(bi->bi_acpi_rsdp_copy);
 	DBG(bi->bi_smbios);
 	DBG(bi->bi_uefi_arch);
 	DBG(bi->bi_uefi_systab);
--- old/usr/src/uts/i86pc/os/fakebop.c	Wed Jan 15 08:03:50 2020
+++ new/usr/src/uts/i86pc/os/fakebop.c	Wed Jan 15 08:03:50 2020
@@ -26,7 +26,7 @@
  * Copyright (c) 2010, Intel Corporation.
  * All rights reserved.
  *
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2020 Joyent, Inc.
  */
 
 /*
@@ -2271,18 +2271,22 @@
  * see ACPI 3.0 Spec, 5.2.5.1
  */
 static ACPI_TABLE_RSDP *
-scan_rsdp(paddr_t start, paddr_t end)
+scan_rsdp(paddr_t *paddrp, size_t len)
 {
-	ssize_t len  = end - start;
+	paddr_t paddr = *paddrp;
 	caddr_t ptr;
 
-	ptr = vmap_phys(len, start);
+	ptr = vmap_phys(len, paddr);
+
 	while (len > 0) {
 		if (strncmp(ptr, ACPI_SIG_RSDP, strlen(ACPI_SIG_RSDP)) == 0 &&
-		    valid_rsdp((ACPI_TABLE_RSDP *)ptr))
+		    valid_rsdp((ACPI_TABLE_RSDP *)ptr)) {
+			*paddrp = paddr;
 			return ((ACPI_TABLE_RSDP *)ptr);
+		}
 
 		ptr += ACPI_RSDP_SCAN_STEP;
+		paddr += ACPI_RSDP_SCAN_STEP;
 		len -= ACPI_RSDP_SCAN_STEP;
 	}
 
@@ -2290,43 +2294,67 @@
 }
 
 /*
- * Refer to ACPI 3.0 Spec, section 5.2.5.1 to understand this function
+ * Locate the ACPI RSDP.  We search in a particular order:
+ *
+ * - If the bootloader told us the location of the RSDP (via the EFI system
+ *   table), try that first.
+ * - Otherwise, look in the EBDA and BIOS memory as per ACPI 5.2.5.1 (legacy
+ *   case).
+ * - Finally, our bootloader may have a copy of the RSDP in its info: this might
+ *   get freed after boot, so we always prefer to find the original RSDP first.
+ *
+ * Once found, we set acpi-root-tab property (a physical address) for the
+ * benefit of acpica, acpidump etc.
  */
+
 static ACPI_TABLE_RSDP *
-find_rsdp()
+find_rsdp(struct xboot_info *xbp)
 {
-	ACPI_TABLE_RSDP *rsdp;
-	uint64_t rsdp_val = 0;
-	uint16_t *ebda_seg;
-	paddr_t  ebda_addr;
+	ACPI_TABLE_RSDP *rsdp = NULL;
+	paddr_t paddr = 0;
 
-	/* check for "acpi-root-tab" property */
 	if (do_bsys_getproplen(NULL, "acpi-root-tab") == sizeof (uint64_t)) {
-		(void) do_bsys_getprop(NULL, "acpi-root-tab", &rsdp_val);
-		if (rsdp_val != 0) {
-			rsdp = scan_rsdp(rsdp_val, rsdp_val + sizeof (*rsdp));
-			if (rsdp != NULL) {
-				if (kbm_debug) {
-					bop_printf(NULL,
-					    "Using RSDP from bootloader: "
-					    "0x%p\n", (void *)rsdp);
-				}
-				return (rsdp);
-			}
-		}
+		(void) do_bsys_getprop(NULL, "acpi-root-tab", &paddr);
+		rsdp = scan_rsdp(&paddr, sizeof (*rsdp));
 	}
 
-	/*
-	 * Get the EBDA segment and scan the first 1K
-	 */
-	ebda_seg = (uint16_t *)vmap_phys(sizeof (uint16_t),
-	    ACPI_EBDA_PTR_LOCATION);
-	ebda_addr = *ebda_seg << 4;
-	rsdp = scan_rsdp(ebda_addr, ebda_addr + ACPI_EBDA_WINDOW_SIZE);
-	if (rsdp == NULL)
-		/* if EBDA doesn't contain RSDP, look in BIOS memory */
-		rsdp = scan_rsdp(ACPI_HI_RSDP_WINDOW_BASE,
-		    ACPI_HI_RSDP_WINDOW_BASE + ACPI_HI_RSDP_WINDOW_SIZE);
+#ifndef __xpv
+	if (rsdp == NULL && xbp->bi_acpi_rsdp != NULL) {
+		paddr = (uintptr_t)xbp->bi_acpi_rsdp;
+		rsdp = scan_rsdp(&paddr, sizeof (*rsdp));
+	}
+#endif
+
+	if (rsdp == NULL) {
+		uint16_t *ebda_seg = (uint16_t *)vmap_phys(sizeof (uint16_t),
+		    ACPI_EBDA_PTR_LOCATION);
+		paddr = *ebda_seg << 4;
+		rsdp = scan_rsdp(&paddr, ACPI_EBDA_WINDOW_SIZE);
+	}
+
+	if (rsdp == NULL) {
+		paddr = ACPI_HI_RSDP_WINDOW_BASE;
+		rsdp = scan_rsdp(&paddr, ACPI_HI_RSDP_WINDOW_SIZE);
+	}
+
+#ifndef __xpv
+	if (rsdp == NULL && xbp->bi_acpi_rsdp_copy != NULL) {
+		paddr = (uintptr_t)xbp->bi_acpi_rsdp_copy;
+		rsdp = scan_rsdp(&paddr, sizeof (*rsdp));
+	}
+#endif
+
+	if (rsdp == NULL) {
+		bop_printf(NULL, "no RSDP found!\n");
+		return (NULL);
+	}
+
+	if (kbm_debug)
+		bop_printf(NULL, "RSDP found at physical 0x%lx\n", paddr);
+
+	if (do_bsys_getproplen(NULL, "acpi-root-tab") != sizeof (uint64_t))
+		bsetprop64("acpi-root-tab", paddr);
+
 	return (rsdp);
 }
 
@@ -2346,13 +2374,12 @@
 }
 
 static ACPI_TABLE_HEADER *
-find_fw_table(char *signature)
+find_fw_table(ACPI_TABLE_RSDP *rsdp, char *signature)
 {
 	static int revision = 0;
 	static ACPI_TABLE_XSDT *xsdt;
 	static int len;
 	paddr_t xsdt_addr;
-	ACPI_TABLE_RSDP *rsdp;
 	ACPI_TABLE_HEADER *tp;
 	paddr_t table_addr;
 	int	n;
@@ -2370,40 +2397,42 @@
 	 * revision 1 and use the RSDT.
 	 */
 	if (revision == 0) {
-		if ((rsdp = find_rsdp()) != NULL) {
-			revision = rsdp->Revision;
+		if (rsdp == NULL)
+			return (NULL);
+
+		revision = rsdp->Revision;
+		/*
+		 * ACPI 6.0 states that current revision is 2
+		 * from acpi_table_rsdp definition:
+		 * Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+
+		 */
+		if (revision > 2)
+			revision = 2;
+		switch (revision) {
+		case 2:
 			/*
-			 * ACPI 6.0 states that current revision is 2
-			 * from acpi_table_rsdp definition:
-			 * Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+
+			 * Use the XSDT unless BIOS is buggy and
+			 * claims to be rev 2 but has a null XSDT
+			 * address
 			 */
-			if (revision > 2)
-				revision = 2;
-			switch (revision) {
-			case 2:
-				/*
-				 * Use the XSDT unless BIOS is buggy and
-				 * claims to be rev 2 but has a null XSDT
-				 * address
-				 */
-				xsdt_addr = rsdp->XsdtPhysicalAddress;
-				if (xsdt_addr != 0)
-					break;
-				/* FALLTHROUGH */
-			case 0:
-				/* treat RSDP rev 0 as revision 1 internally */
-				revision = 1;
-				/* FALLTHROUGH */
-			case 1:
-				/* use the RSDT for rev 0/1 */
-				xsdt_addr = rsdp->RsdtPhysicalAddress;
+			xsdt_addr = rsdp->XsdtPhysicalAddress;
+			if (xsdt_addr != 0)
 				break;
-			default:
-				/* unknown revision */
-				revision = 0;
-				break;
-			}
+			/* FALLTHROUGH */
+		case 0:
+			/* treat RSDP rev 0 as revision 1 internally */
+			revision = 1;
+			/* FALLTHROUGH */
+		case 1:
+			/* use the RSDT for rev 0/1 */
+			xsdt_addr = rsdp->RsdtPhysicalAddress;
+			break;
+		default:
+			/* unknown revision */
+			revision = 0;
+			break;
 		}
+
 		if (revision == 0)
 			return (NULL);
 
@@ -2840,6 +2869,7 @@
 build_firmware_properties(struct xboot_info *xbp)
 {
 	ACPI_TABLE_HEADER *tp = NULL;
+	ACPI_TABLE_RSDP *rsdp;
 
 #ifndef __xpv
 	if (xbp->bi_uefi_arch == XBI_UEFI_ARCH_64) {
@@ -2856,36 +2886,33 @@
 			bop_printf(NULL, "32-bit UEFI detected.\n");
 	}
 
-	if (xbp->bi_acpi_rsdp != NULL) {
-		bsetprop64("acpi-root-tab",
-		    (uint64_t)(uintptr_t)xbp->bi_acpi_rsdp);
-	}
-
 	if (xbp->bi_smbios != NULL) {
 		bsetprop64("smbios-address",
 		    (uint64_t)(uintptr_t)xbp->bi_smbios);
 	}
 
-	if ((tp = find_fw_table(ACPI_SIG_MSCT)) != NULL)
+	rsdp = find_rsdp(xbp);
+
+	if ((tp = find_fw_table(rsdp, ACPI_SIG_MSCT)) != NULL)
 		msct_ptr = process_msct((ACPI_TABLE_MSCT *)tp);
 	else
 		msct_ptr = NULL;
 
-	if ((tp = find_fw_table(ACPI_SIG_MADT)) != NULL)
+	if ((tp = find_fw_table(rsdp, ACPI_SIG_MADT)) != NULL)
 		process_madt((ACPI_TABLE_MADT *)tp);
 
 	if ((srat_ptr = (ACPI_TABLE_SRAT *)
-	    find_fw_table(ACPI_SIG_SRAT)) != NULL)
+	    find_fw_table(rsdp, ACPI_SIG_SRAT)) != NULL)
 		process_srat(srat_ptr);
 
-	if (slit_ptr = (ACPI_TABLE_SLIT *)find_fw_table(ACPI_SIG_SLIT))
+	if (slit_ptr = (ACPI_TABLE_SLIT *)find_fw_table(rsdp, ACPI_SIG_SLIT))
 		process_slit(slit_ptr);
 
-	tp = find_fw_table(ACPI_SIG_MCFG);
+	tp = find_fw_table(rsdp, ACPI_SIG_MCFG);
 #else /* __xpv */
 	enumerate_xen_cpus();
 	if (DOMAIN_IS_INITDOMAIN(xen_info))
-		tp = find_fw_table(ACPI_SIG_MCFG);
+		tp = find_fw_table(rsdp, ACPI_SIG_MCFG);
 #endif /* __xpv */
 	if (tp != NULL)
 		process_mcfg((ACPI_TABLE_MCFG *)tp);
--- old/usr/src/uts/intel/sys/bootinfo.h	Wed Jan 15 08:03:50 2020
+++ new/usr/src/uts/intel/sys/bootinfo.h	Wed Jan 15 08:03:50 2020
@@ -24,6 +24,10 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright 2020 Joyent, Inc.
+ */
+
 #ifndef	_SYS_BOOTINFO_H
 #define	_SYS_BOOTINFO_H
 
@@ -118,6 +122,7 @@
 	native_ptr_t	bi_mb_info;		/* multiboot 1 or 2 info */
 	int		bi_mb_version;		/* multiboot version */
 	native_ptr_t	bi_acpi_rsdp;
+	native_ptr_t	bi_acpi_rsdp_copy;
 	native_ptr_t	bi_smbios;
 	native_ptr_t	bi_uefi_systab;
 	uefi_arch_type_t bi_uefi_arch;
