diff options
author | Stuart Maybee <Stuart.Maybee@Sun.COM> | 2009-03-09 15:20:14 -0700 |
---|---|---|
committer | Stuart Maybee <Stuart.Maybee@Sun.COM> | 2009-03-09 15:20:14 -0700 |
commit | b9bfdccda8a7c490cc133ece2ab92d914e10b8d7 (patch) | |
tree | 16b0ad37419e3e91d743ed2a902cc6b39db27ee4 /usr/src | |
parent | fcff38ebb7bf8c483f8a0427b4885ef7bbdc0c58 (diff) | |
download | illumos-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.c | 49 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/microcode.c | 22 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/mlsetup.c | 5 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/startup.c | 11 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/timestamp.c | 11 | ||||
-rw-r--r-- | usr/src/uts/intel/io/acpica/acpica.c | 9 | ||||
-rw-r--r-- | usr/src/uts/intel/io/acpica/osl.c | 68 | ||||
-rw-r--r-- | usr/src/uts/intel/sys/x86_archext.h | 11 |
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 |