summaryrefslogtreecommitdiff
path: root/usr/src/uts/i86pc/io/pcplusmp
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/i86pc/io/pcplusmp')
-rw-r--r--usr/src/uts/i86pc/io/pcplusmp/apic.c132
-rw-r--r--usr/src/uts/i86pc/io/pcplusmp/apic_common.c43
-rw-r--r--usr/src/uts/i86pc/io/pcplusmp/apic_regops.c201
3 files changed, 37 insertions, 339 deletions
diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic.c b/usr/src/uts/i86pc/io/pcplusmp/apic.c
index cd06f76967..8523112173 100644
--- a/usr/src/uts/i86pc/io/pcplusmp/apic.c
+++ b/usr/src/uts/i86pc/io/pcplusmp/apic.c
@@ -100,7 +100,6 @@ static void apic_picinit(void);
static int apic_post_cpu_start(void);
static int apic_intr_enter(int ipl, int *vect);
static void apic_setspl(int ipl);
-static void x2apic_setspl(int ipl);
static int apic_addspl(int ipl, int vector, int min_ipl, int max_ipl);
static int apic_delspl(int ipl, int vector, int min_ipl, int max_ipl);
static int apic_disable_intr(processorid_t cpun);
@@ -312,22 +311,19 @@ apic_init_intr(void)
apic_reg_ops->apic_write_task_reg(APIC_MASK_ALL);
- if (apic_mode == LOCAL_APIC) {
- /*
- * We are running APIC in MMIO mode.
- */
- if (apic_flat_model) {
- apic_reg_ops->apic_write(APIC_FORMAT_REG,
- APIC_FLAT_MODEL);
- } else {
- apic_reg_ops->apic_write(APIC_FORMAT_REG,
- APIC_CLUSTER_MODEL);
- }
+ ASSERT(apic_mode == LOCAL_APIC);
- apic_reg_ops->apic_write(APIC_DEST_REG,
- AV_HIGH_ORDER >> cpun);
+ /*
+ * We are running APIC in MMIO mode.
+ */
+ if (apic_flat_model) {
+ apic_reg_ops->apic_write(APIC_FORMAT_REG, APIC_FLAT_MODEL);
+ } else {
+ apic_reg_ops->apic_write(APIC_FORMAT_REG, APIC_CLUSTER_MODEL);
}
+ apic_reg_ops->apic_write(APIC_DEST_REG, AV_HIGH_ORDER >> cpun);
+
if (apic_directed_EOI_supported()) {
/*
* Setting the 12th bit in the Spurious Interrupt Vector
@@ -633,24 +629,6 @@ apic_intr_enter(int ipl, int *vectorp)
return (nipl);
}
-/*
- * This macro is a common code used by MMIO local apic and X2APIC
- * local apic.
- */
-#define APIC_INTR_EXIT() \
-{ \
- cpu_infop = &apic_cpus[psm_get_cpu_id()]; \
- if (apic_level_intr[irq]) \
- apic_reg_ops->apic_send_eoi(irq); \
- cpu_infop->aci_curipl = (uchar_t)prev_ipl; \
- /* ISR above current pri could not be in progress */ \
- cpu_infop->aci_ISR_in_progress &= (2 << prev_ipl) - 1; \
-}
-
-/*
- * Any changes made to this function must also change X2APIC
- * version of intr_exit.
- */
void
apic_intr_exit(int prev_ipl, int irq)
{
@@ -658,35 +636,22 @@ apic_intr_exit(int prev_ipl, int irq)
apic_reg_ops->apic_write_task_reg(apic_ipltopri[prev_ipl]);
- APIC_INTR_EXIT();
-}
-
-/*
- * Same as apic_intr_exit() except it uses MSR rather than MMIO
- * to access local apic registers.
- */
-void
-x2apic_intr_exit(int prev_ipl, int irq)
-{
- apic_cpus_info_t *cpu_infop;
-
- X2APIC_WRITE(APIC_TASK_REG, apic_ipltopri[prev_ipl]);
- APIC_INTR_EXIT();
+ cpu_infop = &apic_cpus[psm_get_cpu_id()];
+ if (apic_level_intr[irq])
+ apic_reg_ops->apic_send_eoi(irq);
+ cpu_infop->aci_curipl = (uchar_t)prev_ipl;
+ /* ISR above current pri could not be in progress */
+ cpu_infop->aci_ISR_in_progress &= (2 << prev_ipl) - 1;
}
intr_exit_fn_t
psm_intr_exit_fn(void)
{
- if (apic_mode == LOCAL_X2APIC)
- return (x2apic_intr_exit);
-
return (apic_intr_exit);
}
/*
* Mask all interrupts below or equal to the given IPL.
- * Any changes made to this function must also change X2APIC
- * version of setspl.
*/
static void
apic_setspl(int ipl)
@@ -704,19 +669,6 @@ apic_setspl(int ipl)
(void) apic_reg_ops->apic_get_pri();
}
-/*
- * X2APIC version of setspl.
- * Mask all interrupts below or equal to the given IPL
- */
-static void
-x2apic_setspl(int ipl)
-{
- X2APIC_WRITE(APIC_TASK_REG, apic_ipltopri[ipl]);
-
- /* interrupts at ipl above this cannot be in progress */
- apic_cpus[psm_get_cpu_id()].aci_ISR_in_progress &= (2 << ipl) - 1;
-}
-
/*ARGSUSED*/
static int
apic_addspl(int irqno, int ipl, int min_ipl, int max_ipl)
@@ -739,26 +691,6 @@ apic_post_cpu_start(void)
/* We know this CPU + BSP started successfully. */
cpus_started++;
- /*
- * On BSP we would have enabled X2APIC, if supported by processor,
- * in acpi_probe(), but on AP we do it here.
- *
- * We enable X2APIC mode only if BSP is running in X2APIC & the
- * local APIC mode of the current CPU is MMIO (xAPIC).
- */
- if (apic_mode == LOCAL_X2APIC && apic_detect_x2apic() &&
- apic_local_mode() == LOCAL_APIC) {
- apic_enable_x2apic();
- }
-
- /*
- * Switch back to x2apic IPI sending method for performance when target
- * CPU has entered x2apic mode.
- */
- if (apic_mode == LOCAL_X2APIC) {
- apic_switch_ipi_callback(B_FALSE);
- }
-
splx(ipltospl(LOCK_LEVEL));
apic_init_intr();
@@ -768,12 +700,7 @@ apic_post_cpu_start(void)
*/
setcr0(getcr0() & ~(CR0_CD | CR0_NW));
-#ifdef DEBUG
APIC_AV_PENDING_SET();
-#else
- if (apic_mode == LOCAL_APIC)
- APIC_AV_PENDING_SET();
-#endif /* DEBUG */
/*
* We may be booting, or resuming from suspend; aci_status will
@@ -1330,18 +1257,25 @@ apic_get_apic_type(void)
}
void
-x2apic_update_psm(void)
+apic_switch_ipi_callback(boolean_t enter)
{
- struct psm_ops *pops = &apic_ops;
-
- ASSERT(pops != NULL);
+ ASSERT(enter == B_TRUE);
+}
- pops->psm_intr_exit = x2apic_intr_exit;
- pops->psm_setspl = x2apic_setspl;
+int
+apic_detect_x2apic(void)
+{
+ return (0);
+}
- pops->psm_send_ipi = x2apic_send_ipi;
- send_dirintf = pops->psm_send_ipi;
+void
+apic_enable_x2apic(void)
+{
+ cmn_err(CE_PANIC, "apic_enable_x2apic() called in pcplusmp");
+}
- apic_mode = LOCAL_X2APIC;
- apic_change_ops();
+void
+x2apic_update_psm(void)
+{
+ cmn_err(CE_PANIC, "x2apic_update_psm() called in pcplusmp");
}
diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic_common.c b/usr/src/uts/i86pc/io/pcplusmp/apic_common.c
index 649e5ce950..7498150d49 100644
--- a/usr/src/uts/i86pc/io/pcplusmp/apic_common.c
+++ b/usr/src/uts/i86pc/io/pcplusmp/apic_common.c
@@ -23,7 +23,7 @@
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2017, Joyent, Inc. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
@@ -128,8 +128,6 @@ extern void cmi_cmci_trap(void);
kmutex_t cmci_cpu_setup_lock; /* protects cmci_cpu_setup_registered */
int cmci_cpu_setup_registered;
-/* number of CPUs in power-on transition state */
-static int apic_poweron_cnt = 0;
lock_t apic_mode_switch_lock;
/*
@@ -1456,45 +1454,6 @@ apic_find_cpu(int flag)
return (acid);
}
-/*
- * Switch between safe and x2APIC IPI sending method.
- * CPU may power on in xapic mode or x2apic mode. If CPU needs to send IPI to
- * other CPUs before entering x2APIC mode, it still needs to xAPIC method.
- * Before sending StartIPI to target CPU, psm_send_ipi will be changed to
- * apic_common_send_ipi, which detects current local APIC mode and use right
- * method to send IPI. If some CPUs fail to start up, apic_poweron_cnt
- * won't return to zero, so apic_common_send_ipi will always be used.
- * psm_send_ipi can't be simply changed back to x2apic_send_ipi if some CPUs
- * failed to start up because those failed CPUs may recover itself later at
- * unpredictable time.
- */
-void
-apic_switch_ipi_callback(boolean_t enter)
-{
- ulong_t iflag;
- struct psm_ops *pops = psmops;
-
- iflag = intr_clear();
- lock_set(&apic_mode_switch_lock);
- if (enter) {
- ASSERT(apic_poweron_cnt >= 0);
- if (apic_poweron_cnt == 0) {
- pops->psm_send_ipi = apic_common_send_ipi;
- send_dirintf = pops->psm_send_ipi;
- }
- apic_poweron_cnt++;
- } else {
- ASSERT(apic_poweron_cnt > 0);
- apic_poweron_cnt--;
- if (apic_poweron_cnt == 0) {
- pops->psm_send_ipi = x2apic_send_ipi;
- send_dirintf = pops->psm_send_ipi;
- }
- }
- lock_clear(&apic_mode_switch_lock);
- intr_restore(iflag);
-}
-
void
apic_intrmap_init(int apic_mode)
{
diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic_regops.c b/usr/src/uts/i86pc/io/pcplusmp/apic_regops.c
index 60ce7a3771..e0b647975d 100644
--- a/usr/src/uts/i86pc/io/pcplusmp/apic_regops.c
+++ b/usr/src/uts/i86pc/io/pcplusmp/apic_regops.c
@@ -25,6 +25,7 @@
/*
* Copyright 2014 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
* Copyright (c) 2014 by Delphix. All rights reserved.
+ * Copyright 2017 Joyent, Inc.
*/
#include <sys/cpuvar.h>
@@ -40,17 +41,12 @@
#include <sys/privregs.h>
#include <sys/psm_common.h>
-/* Function prototypes of local apic and X2APIC */
+/* Function prototypes of local apic */
static uint64_t local_apic_read(uint32_t reg);
static void local_apic_write(uint32_t reg, uint64_t value);
static int get_local_apic_pri(void);
static void local_apic_write_task_reg(uint64_t value);
static void local_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1);
-static uint64_t local_x2apic_read(uint32_t msr);
-static void local_x2apic_write(uint32_t msr, uint64_t value);
-static int get_local_x2apic_pri(void);
-static void local_x2apic_write_task_reg(uint64_t value);
-static void local_x2apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1);
/*
* According to the X2APIC specification:
@@ -64,14 +60,13 @@ static void local_x2apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1);
* 1 1 APIC is enabled in X2APIC mode
* -----------------------------------------------------------
*/
-int x2apic_enable = 1;
apic_mode_t apic_mode = LOCAL_APIC; /* Default mode is Local APIC */
/* See apic_directed_EOI_supported(). Currently 3-state variable. */
volatile int apic_directed_eoi_state = 2;
/* Uses MMIO (Memory Mapped IO) */
-static apic_reg_ops_t local_apic_regs_ops = {
+apic_reg_ops_t local_apic_regs_ops = {
local_apic_read,
local_apic_write,
get_local_apic_pri,
@@ -80,16 +75,6 @@ static apic_reg_ops_t local_apic_regs_ops = {
apic_send_EOI,
};
-/* X2APIC : Uses RDMSR/WRMSR instructions to access APIC registers */
-static apic_reg_ops_t x2apic_regs_ops = {
- local_x2apic_read,
- local_x2apic_write,
- get_local_x2apic_pri,
- local_x2apic_write_task_reg,
- local_x2apic_write_int_cmd,
- apic_send_EOI,
-};
-
int apic_have_32bit_cr8 = 0;
/* The default ops is local APIC (Memory Mapped IO) */
@@ -101,8 +86,6 @@ apic_reg_ops_t *apic_reg_ops = &local_apic_regs_ops;
void apic_send_EOI();
void apic_send_directed_EOI(uint32_t irq);
-#define X2APIC_ENABLE_BIT 10
-
/*
* Local APIC Implementation
*/
@@ -150,51 +133,6 @@ local_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1)
apicadr[APIC_INT_CMD1] = cmd1;
}
-/*
- * X2APIC Implementation.
- */
-static uint64_t
-local_x2apic_read(uint32_t msr)
-{
- uint64_t i;
-
- i = (uint64_t)(rdmsr(REG_X2APIC_BASE_MSR + (msr >> 2)) & 0xffffffff);
- return (i);
-}
-
-static void
-local_x2apic_write(uint32_t msr, uint64_t value)
-{
- uint64_t tmp;
-
- if (msr != APIC_EOI_REG) {
- tmp = rdmsr(REG_X2APIC_BASE_MSR + (msr >> 2));
- tmp = (tmp & 0xffffffff00000000) | value;
- } else {
- tmp = 0;
- }
-
- wrmsr((REG_X2APIC_BASE_MSR + (msr >> 2)), tmp);
-}
-
-static int
-get_local_x2apic_pri(void)
-{
- return (rdmsr(REG_X2APIC_BASE_MSR + (APIC_TASK_REG >> 2)));
-}
-
-static void
-local_x2apic_write_task_reg(uint64_t value)
-{
- X2APIC_WRITE(APIC_TASK_REG, value);
-}
-
-static void
-local_x2apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1)
-{
- wrmsr((REG_X2APIC_BASE_MSR + (APIC_INT_CMD1 >> 2)),
- (((uint64_t)cpu_id << 32) | cmd1));
-}
/*ARGSUSED*/
void
@@ -236,38 +174,6 @@ apic_send_directed_EOI(uint32_t irq)
}
}
-int
-apic_detect_x2apic(void)
-{
- if (x2apic_enable == 0)
- return (0);
-
- return (is_x86_feature(x86_featureset, X86FSET_X2APIC));
-}
-
-void
-apic_enable_x2apic(void)
-{
- uint64_t apic_base_msr;
-
- if (apic_local_mode() == LOCAL_X2APIC) {
- /* BIOS apparently has enabled X2APIC */
- if (apic_mode != LOCAL_X2APIC)
- x2apic_update_psm();
- return;
- }
-
- /*
- * This is the first time we are enabling X2APIC on this CPU
- */
- apic_base_msr = rdmsr(REG_APIC_BASE_MSR);
- apic_base_msr = apic_base_msr | (0x1 << X2APIC_ENABLE_BIT);
- wrmsr(REG_APIC_BASE_MSR, apic_base_msr);
-
- if (apic_mode != LOCAL_X2APIC)
- x2apic_update_psm();
-}
-
/*
* Determine which mode the current CPU is in. See the table above.
* (IA32_APIC_BASE[11]) (IA32_APIC_BASE[10])
@@ -339,104 +245,3 @@ apic_directed_EOI_supported()
return (0);
}
-
-/*
- * Change apic_reg_ops depending upon the apic_mode.
- */
-void
-apic_change_ops()
-{
- if (apic_mode == LOCAL_APIC)
- apic_reg_ops = &local_apic_regs_ops;
- else if (apic_mode == LOCAL_X2APIC)
- apic_reg_ops = &x2apic_regs_ops;
-}
-
-/*
- * Generates an interprocessor interrupt to another CPU when X2APIC mode is
- * enabled.
- */
-void
-x2apic_send_ipi(int cpun, int ipl)
-{
- int vector;
- ulong_t flag;
-
- ASSERT(apic_mode == LOCAL_X2APIC);
-
- /*
- * With X2APIC, Intel relaxed the semantics of the
- * WRMSR instruction such that references to the X2APIC
- * MSR registers are no longer serializing instructions.
- * The code that initiates IPIs assumes that some sort
- * of memory serialization occurs. The old APIC code
- * did a write to uncachable memory mapped registers.
- * Any reference to uncached memory is a serializing
- * operation. To mimic those semantics here, we do an
- * atomic operation, which translates to a LOCK OR instruction,
- * which is serializing.
- */
- atomic_or_ulong(&flag, 1);
-
- vector = apic_resv_vector[ipl];
-
- flag = intr_clear();
-
- /*
- * According to X2APIC specification in section '2.3.5.1' of
- * Interrupt Command Register Semantics, the semantics of
- * programming Interrupt Command Register to dispatch an interrupt
- * is simplified. A single MSR write to the 64-bit ICR is required
- * for dispatching an interrupt. Specifically with the 64-bit MSR
- * interface to ICR, system software is not required to check the
- * status of the delivery status bit prior to writing to the ICR
- * to send an IPI. With the removal of the Delivery Status bit,
- * system software no longer has a reason to read the ICR. It remains
- * readable only to aid in debugging.
- */
-#ifdef DEBUG
- APIC_AV_PENDING_SET();
-#endif /* DEBUG */
-
- if ((cpun == psm_get_cpu_id())) {
- X2APIC_WRITE(X2APIC_SELF_IPI, vector);
- } else {
- apic_reg_ops->apic_write_int_cmd(
- apic_cpus[cpun].aci_local_id, vector);
- }
-
- intr_restore(flag);
-}
-
-/*
- * Generates IPI to another CPU depending on the local APIC mode.
- * apic_send_ipi() and x2apic_send_ipi() depends on the configured
- * mode of the local APIC, but that may not match the actual mode
- * early in CPU startup.
- *
- * Any changes made to this routine must be accompanied by similar
- * changes to apic_send_ipi().
- */
-void
-apic_common_send_ipi(int cpun, int ipl)
-{
- int vector;
- ulong_t flag;
- int mode = apic_local_mode();
-
- if (mode == LOCAL_X2APIC) {
- x2apic_send_ipi(cpun, ipl);
- return;
- }
-
- ASSERT(mode == LOCAL_APIC);
-
- vector = apic_resv_vector[ipl];
- ASSERT((vector >= APIC_BASE_VECT) && (vector <= APIC_SPUR_INTR));
- flag = intr_clear();
- while (local_apic_regs_ops.apic_read(APIC_INT_CMD1) & AV_PENDING)
- apic_ret();
- local_apic_regs_ops.apic_write_int_cmd(apic_cpus[cpun].aci_local_id,
- vector);
- intr_restore(flag);
-}