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,32 ****
--- 23,33 ----
* 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,58 ****
#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 */
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
--- 39,54 ----
#include <sys/trap.h>
#include <sys/x86_archext.h>
#include <sys/privregs.h>
#include <sys/psm_common.h>
! /* 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);
/*
* According to the X2APIC specification:
*
* xAPIC global enable X2APIC enable Description
*** 62,97 ****
* 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 = {
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;
--- 58,82 ----
* 0 1 Invalid
* 1 0 APIC is enabled in xAPIC mode
* 1 1 APIC is enabled in X2APIC mode
* -----------------------------------------------------------
*/
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) */
! 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,
};
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,110 ****
* 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)
--- 84,93 ----
*** 148,203 ****
{
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);
--- 131,141 ----
*** 234,275 ****
}
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
--- 172,181 ----
*** 336,442 ****
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);
}
--- 242,247 ----