summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorStuart Maybee <Stuart.Maybee@Sun.COM>2009-03-09 15:20:14 -0700
committerStuart Maybee <Stuart.Maybee@Sun.COM>2009-03-09 15:20:14 -0700
commitb9bfdccda8a7c490cc133ece2ab92d914e10b8d7 (patch)
tree16b0ad37419e3e91d743ed2a902cc6b39db27ee4 /usr/src
parentfcff38ebb7bf8c483f8a0427b4885ef7bbdc0c58 (diff)
downloadillumos-gate-b9bfdccda8a7c490cc133ece2ab92d914e10b8d7.tar.gz
6775011 bad trap page fault while starting dom0
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/i86pc/os/cpuid.c49
-rw-r--r--usr/src/uts/i86pc/os/microcode.c22
-rw-r--r--usr/src/uts/i86pc/os/mlsetup.c5
-rw-r--r--usr/src/uts/i86pc/os/startup.c11
-rw-r--r--usr/src/uts/i86pc/os/timestamp.c11
-rw-r--r--usr/src/uts/intel/io/acpica/acpica.c9
-rw-r--r--usr/src/uts/intel/io/acpica/osl.c68
-rw-r--r--usr/src/uts/intel/sys/x86_archext.h11
8 files changed, 141 insertions, 45 deletions
diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c
index a82d6d70e5..15969b2c02 100644
--- a/usr/src/uts/i86pc/os/cpuid.c
+++ b/usr/src/uts/i86pc/os/cpuid.c
@@ -114,13 +114,9 @@ uint_t pentiumpro_bug4064495;
uint_t enable486;
/*
- * This is set if Solaris is booted in a fully virtualized mode:
- * - as HVM guest under xVM
- * - as guest under VMware
- * check_for_hvm() has the logic to detect these 2 cases.
- * This is not applicable if Solaris is booted as a para virtual guest.
+ * This is set to platform type Solaris is running on.
*/
-int platform_is_virt = 0;
+static int platform_type = HW_NATIVE;
/*
* monitor/mwait info.
@@ -429,12 +425,11 @@ cpuid_free_space(cpu_t *cpu)
#if !defined(__xpv)
static void
-check_for_hvm()
+determine_platform()
{
struct cpuid_regs cp;
char *xen_str;
uint32_t xen_signature[4];
- extern int xpv_is_hvm;
/*
* In a fully virtualized domain, Xen's pseudo-cpuid function
@@ -449,13 +444,39 @@ check_for_hvm()
xen_signature[2] = cp.cp_edx;
xen_signature[3] = 0;
xen_str = (char *)xen_signature;
- if (strcmp("XenVMMXenVMM", xen_str) == 0 && cp.cp_eax <= 0x40000002)
- xpv_is_hvm = 1;
+ if (strcmp("XenVMMXenVMM", xen_str) == 0 && cp.cp_eax <= 0x40000002) {
+ platform_type = HW_XEN_HVM;
+ } else if (vmware_platform()) { /* running under vmware hypervisor? */
+ platform_type = HW_VMWARE;
+ }
+}
+
+int
+get_hwenv(void)
+{
+ return (platform_type);
+}
+
+int
+is_controldom(void)
+{
+ return (0);
+}
+
+#else
+
+int
+get_hwenv(void)
+{
+ return (HW_XEN_PV);
+}
- /* could we be running under vmware hypervisor */
- if (xpv_is_hvm || vmware_platform())
- platform_is_virt = 1;
+int
+is_controldom(void)
+{
+ return (DOMAIN_IS_INITDOMAIN(xen_info));
}
+
#endif /* __xpv */
uint_t
@@ -1200,7 +1221,7 @@ cpuid_pass1(cpu_t *cpu)
pass1_done:
#if !defined(__xpv)
- check_for_hvm();
+ determine_platform();
#endif
cpi->cpi_pass = 1;
return (feature);
diff --git a/usr/src/uts/i86pc/os/microcode.c b/usr/src/uts/i86pc/os/microcode.c
index 8cf5d99d24..c69c8c0500 100644
--- a/usr/src/uts/i86pc/os/microcode.c
+++ b/usr/src/uts/i86pc/os/microcode.c
@@ -203,32 +203,22 @@ ucode_free(processorid_t id, void* buf, size_t size)
static int
ucode_capable_amd(cpu_t *cp)
{
-#ifndef __xpv
- extern int xpv_is_hvm;
- if (xpv_is_hvm) {
- return (0);
- }
-#else
- if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
+ int hwenv = get_hwenv();
+
+ if (hwenv == HW_XEN_HVM || (hwenv == HW_XEN_PV && !is_controldom())) {
return (0);
}
-#endif
return (cpuid_getfamily(cp) >= 0x10);
}
static int
ucode_capable_intel(cpu_t *cp)
{
-#ifndef __xpv
- extern int xpv_is_hvm;
- if (xpv_is_hvm) {
- return (0);
- }
-#else
- if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
+ int hwenv = get_hwenv();
+
+ if (hwenv == HW_XEN_HVM || (hwenv == HW_XEN_PV && !is_controldom())) {
return (0);
}
-#endif
return (cpuid_getfamily(cp) >= 6);
}
diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c
index 001bd0537f..c3aa711f13 100644
--- a/usr/src/uts/i86pc/os/mlsetup.c
+++ b/usr/src/uts/i86pc/os/mlsetup.c
@@ -102,9 +102,6 @@ mlsetup(struct regs *rp)
extern struct classfuncs sys_classfuncs;
extern disp_t cpu0_disp;
extern char t0stack[];
-#if !defined(__xpv)
- extern int xpv_is_hvm;
-#endif
ASSERT_STACK_ALIGNED();
@@ -180,7 +177,7 @@ mlsetup(struct regs *rp)
* The Xen hypervisor does not correctly report whether rdtscp is
* supported or not, so we must assume that it is not.
*/
- if (xpv_is_hvm == 0 && (x86_feature & X86_TSCP))
+ if (get_hwenv() != HW_XEN_HVM && (x86_feature & X86_TSCP))
patch_tsc_read(X86_HAVE_TSCP);
else if (cpuid_getvendor(CPU) == X86_VENDOR_AMD &&
cpuid_getfamily(CPU) <= 0xf && (x86_feature & X86_SSE2) != 0)
diff --git a/usr/src/uts/i86pc/os/startup.c b/usr/src/uts/i86pc/os/startup.c
index 6083fb21cd..119bfabf2f 100644
--- a/usr/src/uts/i86pc/os/startup.c
+++ b/usr/src/uts/i86pc/os/startup.c
@@ -541,11 +541,6 @@ static int lower_pages_count = 0;
struct system_hardware system_hardware;
/*
- * Is this Solaris instance running in a fully virtualized xVM domain?
- */
-int xpv_is_hvm = 0;
-
-/*
* Enable some debugging messages concerning memory usage...
*/
static void
@@ -1431,7 +1426,7 @@ startup_modules(void)
*/
microfind();
- if (xpv_is_hvm)
+ if (get_hwenv() == HW_XEN_HVM)
update_default_path();
#endif
@@ -1542,7 +1537,7 @@ startup_modules(void)
* Initialize a handle for the boot cpu - others will initialize
* as they startup. Do not do this if we know we are in an HVM domU.
*/
- if (!xpv_is_hvm &&
+ if ((get_hwenv() != HW_XEN_HVM) &&
(hdl = cmi_init(CMI_HDL_NATIVE, cmi_ntv_hwchipid(CPU),
cmi_ntv_hwcoreid(CPU), cmi_ntv_hwstrandid(CPU))) != NULL &&
(x86_feature & X86_MCA))
@@ -2155,7 +2150,7 @@ post_startup(void)
* Startup the memory scrubber.
* XXPV This should be running somewhere ..
*/
- if (!xpv_is_hvm)
+ if (get_hwenv() != HW_XEN_HVM)
memscrub_init();
#endif
}
diff --git a/usr/src/uts/i86pc/os/timestamp.c b/usr/src/uts/i86pc/os/timestamp.c
index e93f9de2c8..02b4cb529c 100644
--- a/usr/src/uts/i86pc/os/timestamp.c
+++ b/usr/src/uts/i86pc/os/timestamp.c
@@ -134,7 +134,6 @@ static volatile int tsc_sync_go;
}
int tsc_master_slave_sync_needed = 1;
-extern int platform_is_virt;
static int tsc_max_delta;
static hrtime_t tsc_sync_tick_delta[NCPU];
@@ -415,8 +414,11 @@ tsc_sync_master(processorid_t slave)
hrtime_t write_time, x, mtsc_after, tdelta;
tsc_sync_t *tsc = tscp;
int cnt;
+ int hwtype;
- if (!tsc_master_slave_sync_needed || platform_is_virt)
+ hwtype = get_hwenv();
+ if (!tsc_master_slave_sync_needed || hwtype == HW_XEN_HVM ||
+ hwtype == HW_VMWARE)
return;
flags = clear_int_flag();
@@ -492,8 +494,11 @@ tsc_sync_slave(void)
hrtime_t s1;
tsc_sync_t *tsc = tscp;
int cnt;
+ int hwtype;
- if (!tsc_master_slave_sync_needed || platform_is_virt)
+ hwtype = get_hwenv();
+ if (!tsc_master_slave_sync_needed || hwtype == HW_XEN_HVM ||
+ hwtype == HW_VMWARE)
return;
flags = clear_int_flag();
diff --git a/usr/src/uts/intel/io/acpica/acpica.c b/usr/src/uts/intel/io/acpica/acpica.c
index 283e06a164..5889ee845a 100644
--- a/usr/src/uts/intel/io/acpica/acpica.c
+++ b/usr/src/uts/intel/io/acpica/acpica.c
@@ -36,6 +36,7 @@
#include <sys/sunddi.h>
#include <sys/esunddi.h>
#include <sys/kstat.h>
+#include <sys/x86_archext.h>
#include <sys/acpi/acpi.h>
#include <sys/acpica.h>
@@ -370,6 +371,7 @@ acpica_process_user_options()
int
acpica_init()
{
+ extern void acpica_find_ioapics(void);
ACPI_STATUS status;
/*
@@ -406,6 +408,13 @@ acpica_init()
acpica_ec_init();
acpica_init_state = ACPICA_INITIALIZED;
+ /*
+ * If we are running on the Xen hypervisor as dom0 we need to
+ * find the ioapics so we can prevent ACPI from trying to
+ * access them.
+ */
+ if (get_hwenv() == HW_XEN_PV && is_controldom())
+ acpica_find_ioapics();
acpica_init_kstats();
error:
if (acpica_init_state != ACPICA_INITIALIZED) {
diff --git a/usr/src/uts/intel/io/acpica/osl.c b/usr/src/uts/intel/io/acpica/osl.c
index b292fcfa62..b0991d35f7 100644
--- a/usr/src/uts/intel/io/acpica/osl.c
+++ b/usr/src/uts/intel/io/acpica/osl.c
@@ -31,6 +31,7 @@
#include <sys/kmem.h>
#include <sys/psm.h>
#include <sys/pci_cfgspace.h>
+#include <sys/apic.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/sunndi.h>
@@ -518,9 +519,71 @@ AcpiOsFree(void *Memory)
kmem_free(tmp_ptr, size);
}
+static int napics_found; /* number of ioapic addresses in array */
+static ACPI_PHYSICAL_ADDRESS ioapic_paddr[MAX_IO_APIC];
+static ACPI_TABLE_MADT *acpi_mapic_dtp = NULL;
+static void *dummy_ioapicadr;
+
+void
+acpica_find_ioapics(void)
+{
+ int madt_seen, madt_size;
+ ACPI_SUBTABLE_HEADER *ap;
+ ACPI_MADT_IO_APIC *mia;
+
+ if (acpi_mapic_dtp != NULL)
+ return; /* already parsed table */
+ if (AcpiGetTable(ACPI_SIG_MADT, 1,
+ (ACPI_TABLE_HEADER **) &acpi_mapic_dtp) != AE_OK)
+ return;
+
+ napics_found = 0;
+
+ /*
+ * Search the MADT for ioapics
+ */
+ ap = (ACPI_SUBTABLE_HEADER *) (acpi_mapic_dtp + 1);
+ madt_size = acpi_mapic_dtp->Header.Length;
+ madt_seen = sizeof (*acpi_mapic_dtp);
+
+ while (madt_seen < madt_size) {
+
+ switch (ap->Type) {
+ case ACPI_MADT_TYPE_IO_APIC:
+ mia = (ACPI_MADT_IO_APIC *) ap;
+ if (napics_found < MAX_IO_APIC) {
+ ioapic_paddr[napics_found++] =
+ (ACPI_PHYSICAL_ADDRESS)
+ (mia->Address & PAGEMASK);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* advance to next entry */
+ madt_seen += ap->Length;
+ ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length);
+ }
+ if (dummy_ioapicadr == NULL)
+ dummy_ioapicadr = kmem_zalloc(PAGESIZE, KM_SLEEP);
+}
+
+
void *
AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Size)
{
+ int i;
+
+ /*
+ * If the iopaic address table is populated, check if trying
+ * to access an ioapic. Instead, return a pointer to a dummy ioapic.
+ */
+ for (i = 0; i < napics_found; i++) {
+ if ((PhysicalAddress & PAGEMASK) == ioapic_paddr[i])
+ return (dummy_ioapicadr);
+ }
/* FUTUREWORK: test PhysicalAddress for > 32 bits */
return (psm_map_new((paddr_t)PhysicalAddress,
(size_t)Size, PSM_PROT_WRITE | PSM_PROT_READ));
@@ -529,6 +592,11 @@ AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Size)
void
AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Size)
{
+ /*
+ * Check if trying to unmap dummy ioapic address.
+ */
+ if (LogicalAddress == dummy_ioapicadr)
+ return;
psm_unmap((caddr_t)LogicalAddress, (size_t)Size);
}
diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h
index 61a93b7556..8a84d0e251 100644
--- a/usr/src/uts/intel/sys/x86_archext.h
+++ b/usr/src/uts/intel/sys/x86_archext.h
@@ -672,6 +672,17 @@ extern int opteron_workaround_6323525;
extern void patch_workaround_6323525(void);
#endif
+extern int get_hwenv(void);
+extern int is_controldom(void);
+
+/*
+ * Defined hardware environments
+ */
+#define HW_NATIVE 0x00 /* Running on bare metal */
+#define HW_XEN_PV 0x01 /* Running on Xen Hypervisor paravirutualized */
+#define HW_XEN_HVM 0x02 /* Running on Xen hypervisor HVM */
+#define HW_VMWARE 0x03 /* Running on VMware hypervisor */
+
#endif /* _KERNEL */
#endif