summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/amd64/lapic.c78
1 files changed, 38 insertions, 40 deletions
diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c
index ad5ebb6f900..740347cf0bc 100644
--- a/sys/arch/amd64/amd64/lapic.c
+++ b/sys/arch/amd64/amd64/lapic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lapic.c,v 1.44 2016/06/22 01:12:38 mikeb Exp $ */
+/* $OpenBSD: lapic.c,v 1.45 2016/11/01 01:13:19 yasuoka Exp $ */
/* $NetBSD: lapic.c,v 1.2 2003/05/08 01:04:35 fvdl Exp $ */
/*-
@@ -170,59 +170,57 @@ lapic_map(paddr_t lapic_base)
int s;
pt_entry_t *pte;
vaddr_t va;
+ u_int64_t msr;
- /*
- * On real hardware, x2apic must only be enabled if interrupt remapping
- * is also enabled. See 10.12.7 of the SDM vol 3.
- * On hypervisors, this is not necessary. Hypervisors can implement
- * x2apic support even if the host CPU does not support it.
- * Until we support interrupt remapping, use x2apic only if the
- * hypervisor flag is also set.
- */
- if ((cpu_ecxfeature&CPUIDECX_X2APIC) && (cpu_ecxfeature&CPUIDECX_HV)) {
- u_int64_t msr;
-
- disable_intr();
- s = lapic_tpr;
-
- msr = rdmsr(MSR_APICBASE);
- msr |= APICBASE_ENABLE_X2APIC;
- wrmsr(MSR_APICBASE, msr);
+ disable_intr();
+ s = lapic_tpr;
+ msr = rdmsr(MSR_APICBASE);
+
+ if (ISSET(msr, APICBASE_ENABLE_X2APIC) ||
+ (ISSET(cpu_ecxfeature, CPUIDECX_HV) &&
+ ISSET(cpu_ecxfeature, CPUIDECX_X2APIC))) {
+ /*
+ * On real hardware, x2apic must only be enabled if interrupt
+ * remapping is also enabled. See 10.12.7 of the SDM vol 3.
+ * On hypervisors, this is not necessary. Hypervisors can
+ * implement x2apic support even if the host CPU does not
+ * support it. Until we support interrupt remapping, use
+ * x2apic only if the hypervisor flag is also set or it is
+ * enabled by BIOS.
+ */
+ if (!ISSET(msr, APICBASE_ENABLE_X2APIC)) {
+ msr |= APICBASE_ENABLE_X2APIC;
+ wrmsr(MSR_APICBASE, msr);
+ }
lapic_readreg = x2apic_readreg;
lapic_writereg = x2apic_writereg;
#ifdef MULTIPROCESSOR
x86_ipi = x2apic_ipi;
#endif
x2apic_enabled = 1;
-
codepatch_call(CPTAG_EOI, &x2apic_eoi);
lapic_writereg(LAPIC_TPRI, s);
- enable_intr();
+ } else {
+ /*
+ * Map local apic. If we have a local apic, it's safe to
+ * assume we're on a 486 or better and can use invlpg and
+ * non-cacheable PTE's
+ *
+ * Whap the PTE "by hand" rather than calling pmap_kenter_pa
+ * because the latter will attempt to invoke TLB shootdown
+ * code just as we might have changed the value of
+ * cpu_number()..
+ */
+ va = (vaddr_t)&local_apic;
+ pte = kvtopte(va);
+ *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
+ invlpg(va);
- return;
+ lapic_tpr = s;
}
- va = (vaddr_t)&local_apic;
-
- disable_intr();
- s = lapic_tpr;
-
- /*
- * Map local apic. If we have a local apic, it's safe to assume
- * we're on a 486 or better and can use invlpg and non-cacheable PTE's
- *
- * Whap the PTE "by hand" rather than calling pmap_kenter_pa because
- * the latter will attempt to invoke TLB shootdown code just as we
- * might have changed the value of cpu_number()..
- */
-
- pte = kvtopte(va);
- *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
- invlpg(va);
-
- lapic_tpr = s;
enable_intr();
}