apic_regops.c revision 4c1c9391ff5b1b69f6fc02ce905b96759cc50fc0
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * CDDL HEADER START
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * The contents of this file are subject to the terms of the
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Common Development and Distribution License (the "License").
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * You may not use this file except in compliance with the License.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * See the License for the specific language governing permissions
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * and limitations under the License.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * When distributing Covered Code, include this CDDL HEADER in each
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * If applicable, add the following below this CDDL HEADER, with the
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * fields enclosed by brackets "[]" replaced with your own identifying
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * information: Portions Copyright [yyyy] [name of copyright owner]
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * CDDL HEADER END
d23e508cd51e6b3ec3f10a427259d7dd2592fa94Edward Gillett * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Use is subject to license terms.
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra/* Function prototypes of local apic and X2APIC */
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic void local_apic_write(uint32_t reg, uint64_t value);
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic int get_local_apic_pri(void);
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic void local_apic_write_task_reg(uint64_t value);
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic void local_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1);
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic void local_x2apic_write(uint32_t msr, uint64_t value);
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic int get_local_x2apic_pri(void);
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic void local_x2apic_write_task_reg(uint64_t value);
b6917abefc343244b784f0cc34bc65b01469c3bfmishrastatic void local_x2apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1);
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * According to the X2APIC specification:
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * xAPIC global enable X2APIC enable Description
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * (IA32_APIC_BASE[11]) (IA32_APIC_BASE[10])
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * -----------------------------------------------------------
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 0 0 APIC is disabled
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 0 1 Invalid
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * 1 0 APIC is enabled in xAPIC mode
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * 1 1 APIC is enabled in X2APIC mode
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * -----------------------------------------------------------
b6917abefc343244b784f0cc34bc65b01469c3bfmishraint apic_mode = LOCAL_APIC; /* Default mode is Local APIC */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra/* Uses MMIO (Memory Mapped IO) */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra/* X2APIC : Uses RDMSR/WRMSR instructions to access APIC registers */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra/* The default ops is local APIC (Memory Mapped IO) */
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * APIC register ops related data sturctures and functions.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra * Local APIC Implementation
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return ((int)getcr8());
2ef50f010f7a3a07eb5a9f6001b9843fd868e26bJoe Bonasera return ((int)getcr8());
b6917abefc343244b784f0cc34bc65b01469c3bfmishralocal_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra apicadr[APIC_INT_CMD2] = cpu_id << APIC_ICR_ID_BIT_OFFSET;
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * X2APIC Implementation.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra i = (uint64_t)(rdmsr(REG_X2APIC_BASE_MSR + (msr >> 2)) & 0xffffffff);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return (i);
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra return (rdmsr(REG_X2APIC_BASE_MSR + (APIC_TASK_REG >> 2)));
b6917abefc343244b784f0cc34bc65b01469c3bfmishralocal_x2apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1)
b6917abefc343244b784f0cc34bc65b01469c3bfmishra/*ARGSUSED*/
d23e508cd51e6b3ec3f10a427259d7dd2592fa94Edward Gillett * Support for Directed EOI capability is available in both the xAPIC
d23e508cd51e6b3ec3f10a427259d7dd2592fa94Edward Gillett * and x2APIC mode.
d23e508cd51e6b3ec3f10a427259d7dd2592fa94Edward Gillett * Following the EOI to the local APIC unit, perform a directed
d23e508cd51e6b3ec3f10a427259d7dd2592fa94Edward Gillett * EOI to the IOxAPIC generating the interrupt by writing to its
d23e508cd51e6b3ec3f10a427259d7dd2592fa94Edward Gillett * EOI register.
d23e508cd51e6b3ec3f10a427259d7dd2592fa94Edward Gillett * A broadcast EOI is not generated.
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return (0);
b6917abefc343244b784f0cc34bc65b01469c3bfmishra return ((cp.cp_ecx & (0x1 << X2APIC_CPUID_BIT)) ? 1 : 0);
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra /* BIOS apparently has enabled X2APIC */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * This is the first time we are enabling X2APIC on this CPU
b6917abefc343244b784f0cc34bc65b01469c3bfmishra apic_base_msr = apic_base_msr | (0x1 << X2APIC_ENABLE_BIT);
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * Determine which mode the current CPU is in. See the table above.
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * (IA32_APIC_BASE[11]) (IA32_APIC_BASE[10])
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra apic_reg_ops->apic_send_eoi = apic_send_directed_EOI;
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * Change apic_reg_ops depending upon the apic_mode.
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * Generates an interprocessor interrupt to another CPU when X2APIC mode is
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * With X2APIC, Intel relaxed the semantics of the
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * WRMSR instruction such that references to the X2APIC
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * MSR registers are no longer serializing instructions.
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * The code that initiates IPIs assumes that some sort
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * of memory serialization occurs. The old APIC code
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * did a write to uncachable memory mapped registers.
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * Any reference to uncached memory is a serializing
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * operation. To mimic those semantics here, we do an
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * atomic operation, which translates to a LOCK OR instruction,
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * which is serializing.
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * According to X2APIC specification in section '2.3.5.1' of
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * Interrupt Command Register Semantics, the semantics of
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * programming Interrupt Command Register to dispatch an interrupt
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * is simplified. A single MSR write to the 64-bit ICR is required
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * for dispatching an interrupt. Specifically with the 64-bit MSR
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * interface to ICR, system software is not required to check the
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * status of the delivery status bit prior to writing to the ICR
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * to send an IPI. With the removal of the Delivery Status bit,
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * system software no longer has a reason to read the ICR. It remains
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra * readable only to aid in debugging.
5d8efbbc545e36559256557618fcd256b7da72e4Saurabh Misra#endif /* DEBUG */
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * Generates IPI to another CPU depending on the local APIC mode.
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * apic_send_ipi() and x2apic_send_ipi() depends on the configured
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * mode of the local APIC, but that may not match the actual mode
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * early in CPU startup.
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * Any changes made to this routine must be accompanied by similar
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra * changes to apic_send_ipi().
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra ASSERT((vector >= APIC_BASE_VECT) && (vector <= APIC_SPUR_INTR));
325e77f4fc68ea7eea21f5e705d3cf89fd3a7e3dSaurabh Misra while (local_apic_regs_ops.apic_read(APIC_INT_CMD1) & AV_PENDING)