5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/cpuvar.h>
27 #include <sys/psm.h>
28 #include <sys/archsystm.h>
29 #include <sys/apic.h>
30 #include <sys/sunddi.h>
31 #include <sys/ddi_impldefs.h>
32 #include <sys/mach_intr.h>
33 #include <sys/sysmacros.h>
34 #include <sys/trap.h>
35 #include <sys/x86_archext.h>
36 #include <sys/privregs.h>
37 #include <sys/psm_common.h>
38
39 /* Function prototypes of local apic and X2APIC */
40 static uint64_t local_apic_read(uint32_t reg);
41 static void local_apic_write(uint32_t reg, uint64_t value);
42 static int get_local_apic_pri(void);
43 static void local_apic_write_task_reg(uint64_t value);
44 static void local_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1);
77 static apic_reg_ops_t x2apic_regs_ops = {
78 local_x2apic_read,
79 local_x2apic_write,
80 get_local_x2apic_pri,
81 local_x2apic_write_task_reg,
82 local_x2apic_write_int_cmd,
83 apic_send_EOI,
84 };
85
86 int apic_have_32bit_cr8 = 0;
87
88 /* The default ops is local APIC (Memory Mapped IO) */
89 apic_reg_ops_t *apic_reg_ops = &local_apic_regs_ops;
90
91 /*
92 * APIC register ops related data sturctures and functions.
93 */
94 void apic_send_EOI();
95 void apic_send_directed_EOI(uint32_t irq);
96
97 #define X2APIC_CPUID_BIT 21
98 #define X2APIC_ENABLE_BIT 10
99
100 /*
101 * Local APIC Implementation
102 */
103 static uint64_t
104 local_apic_read(uint32_t reg)
105 {
106 return ((uint32_t)apicadr[reg]);
107 }
108
109 static void
110 local_apic_write(uint32_t reg, uint64_t value)
111 {
112 apicadr[reg] = (uint32_t)value;
113 }
114
115 static int
116 get_local_apic_pri(void)
117 {
216 *
217 * A broadcast EOI is not generated.
218 */
219 apic_reg_ops->apic_write(APIC_EOI_REG, 0);
220
221 apic_irq = apic_irq_table[irq];
222 while (apic_irq) {
223 intr_index = apic_irq->airq_mps_intr_index;
224 if (intr_index == ACPI_INDEX || intr_index >= 0) {
225 ioapicindex = apic_irq->airq_ioapicindex;
226 vector = apic_irq->airq_vector;
227 ioapic_write_eoi(ioapicindex, vector);
228 }
229 apic_irq = apic_irq->airq_next;
230 }
231 }
232
233 int
234 apic_detect_x2apic(void)
235 {
236 struct cpuid_regs cp;
237
238 if (x2apic_enable == 0)
239 return (0);
240
241 cp.cp_eax = 1;
242 (void) __cpuid_insn(&cp);
243
244 return ((cp.cp_ecx & (0x1 << X2APIC_CPUID_BIT)) ? 1 : 0);
245 }
246
247 void
248 apic_enable_x2apic(void)
249 {
250 uint64_t apic_base_msr;
251
252 if (apic_local_mode() == LOCAL_X2APIC) {
253 /* BIOS apparently has enabled X2APIC */
254 if (apic_mode != LOCAL_X2APIC)
255 x2apic_update_psm();
256 return;
257 }
258
259 /*
260 * This is the first time we are enabling X2APIC on this CPU
261 */
262 apic_base_msr = rdmsr(REG_APIC_BASE_MSR);
263 apic_base_msr = apic_base_msr | (0x1 << X2APIC_ENABLE_BIT);
264 wrmsr(REG_APIC_BASE_MSR, apic_base_msr);
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright 2014 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
27 */
28
29 #include <sys/cpuvar.h>
30 #include <sys/psm.h>
31 #include <sys/archsystm.h>
32 #include <sys/apic.h>
33 #include <sys/sunddi.h>
34 #include <sys/ddi_impldefs.h>
35 #include <sys/mach_intr.h>
36 #include <sys/sysmacros.h>
37 #include <sys/trap.h>
38 #include <sys/x86_archext.h>
39 #include <sys/privregs.h>
40 #include <sys/psm_common.h>
41
42 /* Function prototypes of local apic and X2APIC */
43 static uint64_t local_apic_read(uint32_t reg);
44 static void local_apic_write(uint32_t reg, uint64_t value);
45 static int get_local_apic_pri(void);
46 static void local_apic_write_task_reg(uint64_t value);
47 static void local_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1);
80 static apic_reg_ops_t x2apic_regs_ops = {
81 local_x2apic_read,
82 local_x2apic_write,
83 get_local_x2apic_pri,
84 local_x2apic_write_task_reg,
85 local_x2apic_write_int_cmd,
86 apic_send_EOI,
87 };
88
89 int apic_have_32bit_cr8 = 0;
90
91 /* The default ops is local APIC (Memory Mapped IO) */
92 apic_reg_ops_t *apic_reg_ops = &local_apic_regs_ops;
93
94 /*
95 * APIC register ops related data sturctures and functions.
96 */
97 void apic_send_EOI();
98 void apic_send_directed_EOI(uint32_t irq);
99
100 #define X2APIC_ENABLE_BIT 10
101
102 /*
103 * Local APIC Implementation
104 */
105 static uint64_t
106 local_apic_read(uint32_t reg)
107 {
108 return ((uint32_t)apicadr[reg]);
109 }
110
111 static void
112 local_apic_write(uint32_t reg, uint64_t value)
113 {
114 apicadr[reg] = (uint32_t)value;
115 }
116
117 static int
118 get_local_apic_pri(void)
119 {
218 *
219 * A broadcast EOI is not generated.
220 */
221 apic_reg_ops->apic_write(APIC_EOI_REG, 0);
222
223 apic_irq = apic_irq_table[irq];
224 while (apic_irq) {
225 intr_index = apic_irq->airq_mps_intr_index;
226 if (intr_index == ACPI_INDEX || intr_index >= 0) {
227 ioapicindex = apic_irq->airq_ioapicindex;
228 vector = apic_irq->airq_vector;
229 ioapic_write_eoi(ioapicindex, vector);
230 }
231 apic_irq = apic_irq->airq_next;
232 }
233 }
234
235 int
236 apic_detect_x2apic(void)
237 {
238 if (x2apic_enable == 0)
239 return (0);
240
241 return (is_x86_feature(x86_featureset, X86FSET_X2APIC));
242 }
243
244 void
245 apic_enable_x2apic(void)
246 {
247 uint64_t apic_base_msr;
248
249 if (apic_local_mode() == LOCAL_X2APIC) {
250 /* BIOS apparently has enabled X2APIC */
251 if (apic_mode != LOCAL_X2APIC)
252 x2apic_update_psm();
253 return;
254 }
255
256 /*
257 * This is the first time we are enabling X2APIC on this CPU
258 */
259 apic_base_msr = rdmsr(REG_APIC_BASE_MSR);
260 apic_base_msr = apic_base_msr | (0x1 << X2APIC_ENABLE_BIT);
261 wrmsr(REG_APIC_BASE_MSR, apic_base_msr);
|