summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2016-09-21 15:06:57 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2016-09-21 15:07:54 +0000
commit5cf554af1079ca06b1b977788f9c0fb796f68945 (patch)
tree8a710a5a1335d11a8c0bd8528ce8eb822b4e06bc
parent6a41e7224f5dce21547e07eced881016dac9e18a (diff)
downloadillumos-joyent-5cf554af1079ca06b1b977788f9c0fb796f68945.tar.gz
OS-5614 acpidump cannot find RSDP on some machines
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Approved by: Patrick Mooney <patrick.mooney@joyent.com>
-rw-r--r--usr/src/cmd/acpi/acpidump/osillumostbl.c88
-rw-r--r--usr/src/uts/i86pc/io/xsvc/xsvc.c17
2 files changed, 80 insertions, 25 deletions
diff --git a/usr/src/cmd/acpi/acpidump/osillumostbl.c b/usr/src/cmd/acpi/acpidump/osillumostbl.c
index d4f38b2604..8e8375f9a2 100644
--- a/usr/src/cmd/acpi/acpidump/osillumostbl.c
+++ b/usr/src/cmd/acpi/acpidump/osillumostbl.c
@@ -357,44 +357,84 @@ AcpiOsGetTableByIndex(UINT32 Index, ACPI_TABLE_HEADER **Table,
* RETURN: Status
*
* DESCRIPTION: Scan and load RSDP.
- *
+ * See the find_rsdp() function in usr/src/uts/i86pc/os/fakebop.c, which is how
+ * the kernel finds the RSDP. That algorithm matches AcpiFindRootPointer().
+ * The code here is derived from AcpiFindRootPointer, except that we will try
+ * the BIOS if the EBDA fails, and we will copy the table if found.
*/
static ACPI_STATUS
OslLoadRsdp(void)
{
- ACPI_TABLE_HEADER *MappedTable;
- UINT8 *RsdpAddress;
- ACPI_PHYSICAL_ADDRESS RsdpBase;
- ACPI_SIZE RsdpSize;
+ UINT8 *mapp;
+ ACPI_TABLE_HEADER *tblp;
+ ACPI_SIZE mapsize;
+ ACPI_PHYSICAL_ADDRESS physaddr;
- /* Get RSDP from memory */
+ /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
+ mapp = AcpiOsMapMemory((ACPI_PHYSICAL_ADDRESS)ACPI_EBDA_PTR_LOCATION,
+ ACPI_EBDA_PTR_LENGTH);
+ if (mapp == NULL)
+ goto try_bios;
+
+ ACPI_MOVE_16_TO_32(&physaddr, mapp);
+
+ /* Convert segment part to physical address */
+ physaddr <<= 4;
+ AcpiOsUnmapMemory(mapp, ACPI_EBDA_PTR_LENGTH);
+
+ /* EBDA present? */
+ if (physaddr <= 0x400)
+ goto try_bios;
+
+ /*
+ * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of 1K
+ * length)
+ */
+ mapp = AcpiOsMapMemory(physaddr, ACPI_EBDA_WINDOW_SIZE);
+ if (mapp == NULL) {
+ (void) fprintf(stderr, "EBDA (0x%p) found, but is not "
+ "mappable\n", physaddr);
+ goto try_bios;
+ }
+
+ tblp = ACPI_CAST_PTR(ACPI_TABLE_HEADER,
+ AcpiTbScanMemoryForRsdp(mapp, ACPI_EBDA_WINDOW_SIZE));
+ if (tblp != NULL) {
+ physaddr += (ACPI_PHYSICAL_ADDRESS) ACPI_PTR_DIFF(tblp, mapp);
+ Gbl_RsdpAddress = physaddr;
+ memcpy(&Gbl_Rsdp, tblp, sizeof (ACPI_TABLE_RSDP));
+ AcpiOsUnmapMemory(mapp, ACPI_EBDA_WINDOW_SIZE);
+
+ return (AE_OK);
+ }
+ AcpiOsUnmapMemory(mapp, ACPI_EBDA_WINDOW_SIZE);
- RsdpSize = sizeof (ACPI_TABLE_RSDP);
- if (Gbl_RsdpBase) {
- RsdpBase = Gbl_RsdpBase;
+try_bios:
+ /* Try to get RSDP from BIOS memory */
+ if (Gbl_RsdpBase != NULL) {
+ physaddr = Gbl_RsdpBase;
+ mapsize = sizeof (ACPI_TABLE_RSDP);
} else {
- RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
- RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
+ physaddr = ACPI_HI_RSDP_WINDOW_BASE;
+ mapsize = ACPI_HI_RSDP_WINDOW_SIZE;
}
- RsdpAddress = AcpiOsMapMemory(RsdpBase, RsdpSize);
- if (RsdpAddress == NULL) {
+ mapp = AcpiOsMapMemory(physaddr, mapsize);
+ if (mapp == NULL)
return (OslGetLastStatus(AE_BAD_ADDRESS));
- }
/* Search low memory for the RSDP */
-
- MappedTable = ACPI_CAST_PTR(ACPI_TABLE_HEADER,
- AcpiTbScanMemoryForRsdp(RsdpAddress, RsdpSize));
- if (MappedTable == NULL) {
- AcpiOsUnmapMemory(RsdpAddress, RsdpSize);
+ tblp = ACPI_CAST_PTR(ACPI_TABLE_HEADER,
+ AcpiTbScanMemoryForRsdp(mapp, mapsize));
+ if (tblp == NULL) {
+ AcpiOsUnmapMemory(mapp, mapsize);
return (AE_NOT_FOUND);
}
- Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8(MappedTable) - RsdpAddress);
-
- memcpy(&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP));
- AcpiOsUnmapMemory(RsdpAddress, RsdpSize);
+ physaddr += (ACPI_PHYSICAL_ADDRESS) ACPI_PTR_DIFF(tblp, mapp);
+ Gbl_RsdpAddress = physaddr;
+ memcpy(&Gbl_Rsdp, tblp, sizeof (ACPI_TABLE_RSDP));
+ AcpiOsUnmapMemory(mapp, mapsize);
return (AE_OK);
}
@@ -1013,5 +1053,5 @@ AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size)
offset = (ulong_t)LogicalAddress % pagesize;
- (void)munmap(LogicalAddress - offset, Size + offset);
+ (void) munmap(LogicalAddress - offset, Size + offset);
}
diff --git a/usr/src/uts/i86pc/io/xsvc/xsvc.c b/usr/src/uts/i86pc/io/xsvc/xsvc.c
index 1d0b9741b0..de3b727544 100644
--- a/usr/src/uts/i86pc/io/xsvc/xsvc.c
+++ b/usr/src/uts/i86pc/io/xsvc/xsvc.c
@@ -22,6 +22,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2016 Joyent, Inc.
*/
#include <sys/errno.h>
@@ -807,7 +809,7 @@ xsvc_mnode_key_compare(const void *q, const void *e)
/*ARGSUSED*/
static int
xsvc_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
- size_t *maplen, uint_t model)
+ size_t *maplen, uint_t model)
{
ddi_umem_cookie_t cookie;
xsvc_state_t *state;
@@ -874,6 +876,19 @@ xsvc_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
kvai = kva;
for (i = 0; i < npages; i++) {
+ page_t *pp = page_numtopp_nolock(pfn);
+
+ /*
+ * Preemptively check for panic conditions from
+ * hat_devload and error out instead.
+ */
+ if (pp != NULL && (PP_ISFREE(pp) ||
+ (!PAGE_LOCKED(pp) && !PP_ISNORELOC(pp)))) {
+ err = DDI_FAILURE;
+ npages = i;
+ goto devmapfail_cookie_alloc;
+ }
+
hat_devload(kas.a_hat, kvai, PAGESIZE, pfn,
PROT_READ | PROT_WRITE, HAT_LOAD_LOCK);
pfn++;