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 {
118 #if defined(__amd64)
119 return ((int)getcr8());
120 #else
121 if (apic_have_32bit_cr8)
122 return ((int)getcr8());
123 return (apicadr[APIC_TASK_REG]);
124 #endif
125 }
126
127 static void
128 local_apic_write_task_reg(uint64_t value)
129 {
130 #if defined(__amd64)
131 setcr8((ulong_t)(value >> APIC_IPL_SHIFT));
132 #else
133 if (apic_have_32bit_cr8)
134 setcr8((ulong_t)(value >> APIC_IPL_SHIFT));
135 else
136 apicadr[APIC_TASK_REG] = (uint32_t)value;
137 #endif
138 }
139
140 static void
141 local_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1)
142 {
143 apicadr[APIC_INT_CMD2] = cpu_id << APIC_ICR_ID_BIT_OFFSET;
144 apicadr[APIC_INT_CMD1] = cmd1;
145 }
146
147 /*
148 * X2APIC Implementation.
149 */
150 static uint64_t
151 local_x2apic_read(uint32_t msr)
152 {
153 uint64_t i;
154
155 i = (uint64_t)(rdmsr(REG_X2APIC_BASE_MSR + (msr >> 2)) & 0xffffffff);
156 return (i);
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);
|
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_ENABLE_BIT 10
98
99 /*
100 * Local APIC Implementation
101 */
102 static uint64_t
103 local_apic_read(uint32_t reg)
104 {
105 return ((uint32_t)apicadr[reg]);
106 }
107
108 static void
109 local_apic_write(uint32_t reg, uint64_t value)
110 {
111 LOCAL_APIC_WRITE_REG(reg, (uint32_t)value);
112 }
113
114 static int
115 get_local_apic_pri(void)
116 {
117 #if defined(__amd64)
118 return ((int)getcr8());
119 #else
120 if (apic_have_32bit_cr8)
121 return ((int)getcr8());
122 return (apicadr[APIC_TASK_REG]);
123 #endif
124 }
125
126 static void
127 local_apic_write_task_reg(uint64_t value)
128 {
129 #if defined(__amd64)
130 setcr8((ulong_t)(value >> APIC_IPL_SHIFT));
131 #else
132 if (apic_have_32bit_cr8)
133 setcr8((ulong_t)(value >> APIC_IPL_SHIFT));
134 else
135 LOCAL_APIC_WRITE_REG(APIC_TASK_REG, (uint32_t)value);
136 #endif
137 }
138
139 static void
140 local_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1)
141 {
142 apicadr[APIC_INT_CMD2] = cpu_id << APIC_ICR_ID_BIT_OFFSET;
143 apicadr[APIC_INT_CMD1] = cmd1;
144 }
145
146 /*
147 * X2APIC Implementation.
148 */
149 static uint64_t
150 local_x2apic_read(uint32_t msr)
151 {
152 uint64_t i;
153
154 i = (uint64_t)(rdmsr(REG_X2APIC_BASE_MSR + (msr >> 2)) & 0xffffffff);
155 return (i);
215 *
216 * A broadcast EOI is not generated.
217 */
218 apic_reg_ops->apic_write(APIC_EOI_REG, 0);
219
220 apic_irq = apic_irq_table[irq];
221 while (apic_irq) {
222 intr_index = apic_irq->airq_mps_intr_index;
223 if (intr_index == ACPI_INDEX || intr_index >= 0) {
224 ioapicindex = apic_irq->airq_ioapicindex;
225 vector = apic_irq->airq_vector;
226 ioapic_write_eoi(ioapicindex, vector);
227 }
228 apic_irq = apic_irq->airq_next;
229 }
230 }
231
232 int
233 apic_detect_x2apic(void)
234 {
235 if (x2apic_enable == 0)
236 return (0);
237
238 return is_x86_feature(x86_featureset, X86FSET_X2APIC);
239 }
240
241 void
242 apic_enable_x2apic(void)
243 {
244 uint64_t apic_base_msr;
245
246 if (apic_local_mode() == LOCAL_X2APIC) {
247 /* BIOS apparently has enabled X2APIC */
248 if (apic_mode != LOCAL_X2APIC)
249 x2apic_update_psm();
250 return;
251 }
252
253 /*
254 * This is the first time we are enabling X2APIC on this CPU
255 */
256 apic_base_msr = rdmsr(REG_APIC_BASE_MSR);
257 apic_base_msr = apic_base_msr | (0x1 << X2APIC_ENABLE_BIT);
258 wrmsr(REG_APIC_BASE_MSR, apic_base_msr);
|