Print this page
8620 pcplusmp shouldn't support x2APIC mode
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
@@ -23,10 +23,11 @@
* Use is subject to license terms.
*/
/*
* Copyright 2014 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
* Copyright (c) 2014 by Delphix. All rights reserved.
+ * Copyright 2017 Joyent, Inc.
*/
#include <sys/cpuvar.h>
#include <sys/psm.h>
#include <sys/archsystm.h>
@@ -38,21 +39,16 @@
#include <sys/trap.h>
#include <sys/x86_archext.h>
#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:
*
* xAPIC global enable X2APIC enable Description
@@ -62,36 +58,25 @@
* 0 1 Invalid
* 1 0 APIC is enabled in xAPIC mode
* 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,
local_apic_write_task_reg,
local_apic_write_int_cmd,
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) */
apic_reg_ops_t *apic_reg_ops = &local_apic_regs_ops;
@@ -99,12 +84,10 @@
* APIC register ops related data sturctures and functions.
*/
void apic_send_EOI();
void apic_send_directed_EOI(uint32_t irq);
-#define X2APIC_ENABLE_BIT 10
-
/*
* Local APIC Implementation
*/
static uint64_t
local_apic_read(uint32_t reg)
@@ -148,56 +131,11 @@
{
apicadr[APIC_INT_CMD2] = cpu_id << APIC_ICR_ID_BIT_OFFSET;
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
apic_send_EOI(uint32_t irq)
{
apic_reg_ops->apic_write(APIC_EOI_REG, 0);
@@ -234,42 +172,10 @@
}
apic_irq = apic_irq->airq_next;
}
}
-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])
*/
int
@@ -336,107 +242,6 @@
ver = apic_reg_ops->apic_read(APIC_VERS_REG);
if (ver & APIC_DIRECTED_EOI_BIT)
return (1);
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);
}