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.
6eedf6a58bb97d935b764a55719f82a486168fbbJosef 'Jeff' Sipek * Copyright 2014 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * Copyright (c) 2014 by Delphix. All rights reserved.
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 * -----------------------------------------------------------
9b1d70f8223c4278acf4ca60eaf5dd285f72eeeeJosef 'Jeff' Sipekapic_mode_t apic_mode = LOCAL_APIC; /* Default mode is Local APIC */
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald/* See apic_directed_EOI_supported(). Currently 3-state variable. */
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);
6eedf6a58bb97d935b764a55719f82a486168fbbJosef 'Jeff' Sipek return (is_x86_feature(x86_featureset, X86FSET_X2APIC));
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;
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * There are some known issues with some versions of Linux KVM and QEMU
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * where by directed EOIs do not properly function and instead get
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * coalesced at the hypervisor, causing the host not to see interrupts.
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * Thus, when the platform is KVM, we would like to disable it by
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * default, but keep it available otherwise.
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * We use a three-state variable (apic_directed_eoi_state) to determine
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * how we handle directed EOI.
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * 0 --> Don't do directed EOI at all.
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * 1 --> Do directed EOI if available, no matter the HW environment.
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * 2 --> Don't do directed EOI on KVM, but do it otherwise if available.
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * If some grinning weirdo put something else in there, treat it as '2'
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * (i.e. the current default).
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * Note, at this time illumos KVM does not identify as KVM. If it does,
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * we'll need to do some work to determine if it should be caught by
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald * this or if it should show up as its own value of platform_type.
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald /* Don't do it at all. */
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald /* Only do it if we aren't on KVM. */
3f745f41d6d087602fbb2f748e1baabc3768f5fbDan McDonald /* FALLTHRU */
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)