1 7282 mishra /* 2 7282 mishra * CDDL HEADER START 3 7282 mishra * 4 7282 mishra * The contents of this file are subject to the terms of the 5 7282 mishra * Common Development and Distribution License (the "License"). 6 7282 mishra * You may not use this file except in compliance with the License. 7 7282 mishra * 8 7282 mishra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 7282 mishra * or http://www.opensolaris.org/os/licensing. 10 7282 mishra * See the License for the specific language governing permissions 11 7282 mishra * and limitations under the License. 12 7282 mishra * 13 7282 mishra * When distributing Covered Code, include this CDDL HEADER in each 14 7282 mishra * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 7282 mishra * If applicable, add the following below this CDDL HEADER, with the 16 7282 mishra * fields enclosed by brackets "[]" replaced with your own identifying 17 7282 mishra * information: Portions Copyright [yyyy] [name of copyright owner] 18 7282 mishra * 19 7282 mishra * CDDL HEADER END 20 7282 mishra */ 21 7282 mishra /* 22 8816 Edward * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 7282 mishra * Use is subject to license terms. 24 7282 mishra */ 25 7282 mishra 26 7282 mishra #include <sys/cpuvar.h> 27 7282 mishra #include <sys/psm.h> 28 7282 mishra #include <sys/archsystm.h> 29 7282 mishra #include <sys/apic.h> 30 7282 mishra #include <sys/sunddi.h> 31 7282 mishra #include <sys/ddi_impldefs.h> 32 7282 mishra #include <sys/mach_intr.h> 33 7282 mishra #include <sys/sysmacros.h> 34 7282 mishra #include <sys/trap.h> 35 7282 mishra #include <sys/x86_archext.h> 36 7282 mishra #include <sys/privregs.h> 37 7282 mishra #include <sys/psm_common.h> 38 7282 mishra 39 7986 Saurabh /* Function prototypes of local apic and X2APIC */ 40 7282 mishra static uint64_t local_apic_read(uint32_t reg); 41 7282 mishra static void local_apic_write(uint32_t reg, uint64_t value); 42 7282 mishra static int get_local_apic_pri(void); 43 7282 mishra static void local_apic_write_task_reg(uint64_t value); 44 7282 mishra static void local_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1); 45 7282 mishra static uint64_t local_x2apic_read(uint32_t msr); 46 7282 mishra static void local_x2apic_write(uint32_t msr, uint64_t value); 47 7282 mishra static int get_local_x2apic_pri(void); 48 7282 mishra static void local_x2apic_write_task_reg(uint64_t value); 49 7282 mishra static void local_x2apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1); 50 7282 mishra 51 7282 mishra /* 52 7986 Saurabh * According to the X2APIC specification: 53 7282 mishra * 54 7986 Saurabh * xAPIC global enable X2APIC enable Description 55 7282 mishra * (IA32_APIC_BASE[11]) (IA32_APIC_BASE[10]) 56 7282 mishra * ----------------------------------------------------------- 57 7282 mishra * 0 0 APIC is disabled 58 7282 mishra * 0 1 Invalid 59 7282 mishra * 1 0 APIC is enabled in xAPIC mode 60 7986 Saurabh * 1 1 APIC is enabled in X2APIC mode 61 7282 mishra * ----------------------------------------------------------- 62 7282 mishra */ 63 7282 mishra int x2apic_enable = 1; 64 7282 mishra int apic_mode = LOCAL_APIC; /* Default mode is Local APIC */ 65 7282 mishra 66 7282 mishra /* Uses MMIO (Memory Mapped IO) */ 67 7282 mishra static apic_reg_ops_t local_apic_regs_ops = { 68 7282 mishra local_apic_read, 69 7282 mishra local_apic_write, 70 7282 mishra get_local_apic_pri, 71 7282 mishra local_apic_write_task_reg, 72 7282 mishra local_apic_write_int_cmd, 73 7282 mishra apic_send_EOI, 74 7282 mishra }; 75 7282 mishra 76 7986 Saurabh /* X2APIC : Uses RDMSR/WRMSR instructions to access APIC registers */ 77 7282 mishra static apic_reg_ops_t x2apic_regs_ops = { 78 7282 mishra local_x2apic_read, 79 7282 mishra local_x2apic_write, 80 7282 mishra get_local_x2apic_pri, 81 7282 mishra local_x2apic_write_task_reg, 82 7282 mishra local_x2apic_write_int_cmd, 83 7282 mishra apic_send_EOI, 84 7282 mishra }; 85 7282 mishra 86 10252 Joe int apic_have_32bit_cr8 = 0; 87 7282 mishra 88 7282 mishra /* The default ops is local APIC (Memory Mapped IO) */ 89 7282 mishra apic_reg_ops_t *apic_reg_ops = &local_apic_regs_ops; 90 7282 mishra 91 7282 mishra /* 92 7282 mishra * APIC register ops related data sturctures and functions. 93 7282 mishra */ 94 7282 mishra void apic_send_EOI(); 95 7282 mishra void apic_send_directed_EOI(uint32_t irq); 96 7282 mishra 97 7282 mishra #define X2APIC_CPUID_BIT 21 98 7282 mishra #define X2APIC_ENABLE_BIT 10 99 7282 mishra 100 7282 mishra /* 101 7282 mishra * Local APIC Implementation 102 7282 mishra */ 103 7282 mishra static uint64_t 104 7282 mishra local_apic_read(uint32_t reg) 105 7282 mishra { 106 7282 mishra return ((uint32_t)apicadr[reg]); 107 7282 mishra } 108 7282 mishra 109 7282 mishra static void 110 7282 mishra local_apic_write(uint32_t reg, uint64_t value) 111 7282 mishra { 112 7282 mishra apicadr[reg] = (uint32_t)value; 113 7282 mishra } 114 7282 mishra 115 7282 mishra static int 116 7282 mishra get_local_apic_pri(void) 117 7282 mishra { 118 7282 mishra #if defined(__amd64) 119 7282 mishra return ((int)getcr8()); 120 7282 mishra #else 121 10080 Joe if (apic_have_32bit_cr8) 122 10080 Joe return ((int)getcr8()); 123 7282 mishra return (apicadr[APIC_TASK_REG]); 124 7282 mishra #endif 125 7282 mishra } 126 7282 mishra 127 7282 mishra static void 128 7282 mishra local_apic_write_task_reg(uint64_t value) 129 7282 mishra { 130 7282 mishra #if defined(__amd64) 131 7282 mishra setcr8((ulong_t)(value >> APIC_IPL_SHIFT)); 132 7282 mishra #else 133 10080 Joe if (apic_have_32bit_cr8) 134 10080 Joe setcr8((ulong_t)(value >> APIC_IPL_SHIFT)); 135 10080 Joe else 136 10080 Joe apicadr[APIC_TASK_REG] = (uint32_t)value; 137 7282 mishra #endif 138 7282 mishra } 139 7282 mishra 140 7282 mishra static void 141 7282 mishra local_apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1) 142 7282 mishra { 143 7282 mishra apicadr[APIC_INT_CMD2] = cpu_id << APIC_ICR_ID_BIT_OFFSET; 144 7282 mishra apicadr[APIC_INT_CMD1] = cmd1; 145 7282 mishra } 146 7282 mishra 147 7282 mishra /* 148 7986 Saurabh * X2APIC Implementation. 149 7282 mishra */ 150 7282 mishra static uint64_t 151 7282 mishra local_x2apic_read(uint32_t msr) 152 7282 mishra { 153 7282 mishra uint64_t i; 154 7282 mishra 155 7282 mishra i = (uint64_t)(rdmsr(REG_X2APIC_BASE_MSR + (msr >> 2)) & 0xffffffff); 156 7282 mishra return (i); 157 7282 mishra } 158 7282 mishra 159 7282 mishra static void 160 7282 mishra local_x2apic_write(uint32_t msr, uint64_t value) 161 7282 mishra { 162 7282 mishra uint64_t tmp; 163 7282 mishra 164 7282 mishra if (msr != APIC_EOI_REG) { 165 7282 mishra tmp = rdmsr(REG_X2APIC_BASE_MSR + (msr >> 2)); 166 7282 mishra tmp = (tmp & 0xffffffff00000000) | value; 167 7445 Saurabh } else { 168 7445 Saurabh tmp = 0; 169 7282 mishra } 170 7282 mishra 171 7282 mishra wrmsr((REG_X2APIC_BASE_MSR + (msr >> 2)), tmp); 172 7282 mishra } 173 7282 mishra 174 7282 mishra static int 175 7282 mishra get_local_x2apic_pri(void) 176 7282 mishra { 177 7798 Saurabh return (rdmsr(REG_X2APIC_BASE_MSR + (APIC_TASK_REG >> 2))); 178 7282 mishra } 179 7282 mishra 180 7282 mishra static void 181 7282 mishra local_x2apic_write_task_reg(uint64_t value) 182 7282 mishra { 183 7282 mishra X2APIC_WRITE(APIC_TASK_REG, value); 184 7282 mishra } 185 7282 mishra 186 7282 mishra static void 187 7282 mishra local_x2apic_write_int_cmd(uint32_t cpu_id, uint32_t cmd1) 188 7282 mishra { 189 7282 mishra wrmsr((REG_X2APIC_BASE_MSR + (APIC_INT_CMD1 >> 2)), 190 7282 mishra (((uint64_t)cpu_id << 32) | cmd1)); 191 7282 mishra } 192 7282 mishra 193 7282 mishra /*ARGSUSED*/ 194 7282 mishra void 195 7282 mishra apic_send_EOI(uint32_t irq) 196 7282 mishra { 197 7282 mishra apic_reg_ops->apic_write(APIC_EOI_REG, 0); 198 7282 mishra } 199 7282 mishra 200 8816 Edward /* 201 8816 Edward * Support for Directed EOI capability is available in both the xAPIC 202 8816 Edward * and x2APIC mode. 203 8816 Edward */ 204 7282 mishra void 205 7282 mishra apic_send_directed_EOI(uint32_t irq) 206 7282 mishra { 207 7282 mishra uchar_t ioapicindex; 208 7282 mishra uchar_t vector; 209 7282 mishra apic_irq_t *apic_irq; 210 7282 mishra short intr_index; 211 7282 mishra 212 8816 Edward /* 213 8816 Edward * Following the EOI to the local APIC unit, perform a directed 214 8816 Edward * EOI to the IOxAPIC generating the interrupt by writing to its 215 8816 Edward * EOI register. 216 8816 Edward * 217 8816 Edward * A broadcast EOI is not generated. 218 8816 Edward */ 219 8816 Edward apic_reg_ops->apic_write(APIC_EOI_REG, 0); 220 7282 mishra 221 7282 mishra apic_irq = apic_irq_table[irq]; 222 7282 mishra while (apic_irq) { 223 7282 mishra intr_index = apic_irq->airq_mps_intr_index; 224 7282 mishra if (intr_index == ACPI_INDEX || intr_index >= 0) { 225 7282 mishra ioapicindex = apic_irq->airq_ioapicindex; 226 7282 mishra vector = apic_irq->airq_vector; 227 7282 mishra ioapic_write_eoi(ioapicindex, vector); 228 7282 mishra } 229 7282 mishra apic_irq = apic_irq->airq_next; 230 7282 mishra } 231 7282 mishra } 232 7282 mishra 233 7282 mishra int 234 7282 mishra apic_detect_x2apic(void) 235 7282 mishra { 236 7282 mishra struct cpuid_regs cp; 237 7282 mishra 238 7282 mishra if (x2apic_enable == 0) 239 7282 mishra return (0); 240 7282 mishra 241 7282 mishra cp.cp_eax = 1; 242 7282 mishra (void) __cpuid_insn(&cp); 243 7282 mishra 244 7282 mishra return ((cp.cp_ecx & (0x1 << X2APIC_CPUID_BIT)) ? 1 : 0); 245 7282 mishra } 246 7282 mishra 247 7282 mishra void 248 7282 mishra apic_enable_x2apic(void) 249 7282 mishra { 250 7282 mishra uint64_t apic_base_msr; 251 7282 mishra 252 7986 Saurabh if (apic_local_mode() == LOCAL_X2APIC) { 253 7986 Saurabh /* BIOS apparently has enabled X2APIC */ 254 7986 Saurabh if (apic_mode != LOCAL_X2APIC) 255 7986 Saurabh x2apic_update_psm(); 256 7986 Saurabh return; 257 7986 Saurabh } 258 7986 Saurabh 259 7986 Saurabh /* 260 7986 Saurabh * This is the first time we are enabling X2APIC on this CPU 261 7986 Saurabh */ 262 7282 mishra apic_base_msr = rdmsr(REG_APIC_BASE_MSR); 263 7282 mishra apic_base_msr = apic_base_msr | (0x1 << X2APIC_ENABLE_BIT); 264 7282 mishra wrmsr(REG_APIC_BASE_MSR, apic_base_msr); 265 7282 mishra 266 7986 Saurabh if (apic_mode != LOCAL_X2APIC) 267 7282 mishra x2apic_update_psm(); 268 7282 mishra } 269 7282 mishra 270 7282 mishra /* 271 7986 Saurabh * Determine which mode the current CPU is in. See the table above. 272 7986 Saurabh * (IA32_APIC_BASE[11]) (IA32_APIC_BASE[10]) 273 7986 Saurabh */ 274 7986 Saurabh int 275 7986 Saurabh apic_local_mode(void) 276 7986 Saurabh { 277 7986 Saurabh uint64_t apic_base_msr; 278 7986 Saurabh int bit = ((0x1 << (X2APIC_ENABLE_BIT + 1)) | 279 7986 Saurabh (0x1 << X2APIC_ENABLE_BIT)); 280 7986 Saurabh 281 7986 Saurabh apic_base_msr = rdmsr(REG_APIC_BASE_MSR); 282 7986 Saurabh 283 7986 Saurabh if ((apic_base_msr & bit) == bit) 284 7986 Saurabh return (LOCAL_X2APIC); 285 7986 Saurabh else 286 7986 Saurabh return (LOCAL_APIC); 287 7986 Saurabh } 288 7986 Saurabh 289 7986 Saurabh void 290 10345 Saurabh apic_set_directed_EOI_handler() 291 7986 Saurabh { 292 7986 Saurabh apic_reg_ops->apic_send_eoi = apic_send_directed_EOI; 293 10345 Saurabh } 294 10345 Saurabh 295 10345 Saurabh int 296 10345 Saurabh apic_directed_EOI_supported() 297 10345 Saurabh { 298 10345 Saurabh uint32_t ver; 299 10345 Saurabh 300 10345 Saurabh ver = apic_reg_ops->apic_read(APIC_VERS_REG); 301 10345 Saurabh if (ver & APIC_DIRECTED_EOI_BIT) 302 10345 Saurabh return (1); 303 10345 Saurabh 304 10345 Saurabh return (0); 305 7986 Saurabh } 306 7986 Saurabh 307 7986 Saurabh /* 308 7986 Saurabh * Change apic_reg_ops depending upon the apic_mode. 309 7986 Saurabh */ 310 7986 Saurabh void 311 7986 Saurabh apic_change_ops() 312 7986 Saurabh { 313 7986 Saurabh if (apic_mode == LOCAL_APIC) 314 7986 Saurabh apic_reg_ops = &local_apic_regs_ops; 315 7986 Saurabh else if (apic_mode == LOCAL_X2APIC) 316 7986 Saurabh apic_reg_ops = &x2apic_regs_ops; 317 7986 Saurabh } 318 7986 Saurabh 319 7986 Saurabh /* 320 7986 Saurabh * Generates an interprocessor interrupt to another CPU when X2APIC mode is 321 7282 mishra * enabled. 322 7282 mishra */ 323 7282 mishra void 324 7282 mishra x2apic_send_ipi(int cpun, int ipl) 325 7282 mishra { 326 7282 mishra int vector; 327 7282 mishra ulong_t flag; 328 7798 Saurabh 329 8918 Saurabh ASSERT(apic_mode == LOCAL_X2APIC); 330 8918 Saurabh 331 7798 Saurabh /* 332 7798 Saurabh * With X2APIC, Intel relaxed the semantics of the 333 7798 Saurabh * WRMSR instruction such that references to the X2APIC 334 7798 Saurabh * MSR registers are no longer serializing instructions. 335 7798 Saurabh * The code that initiates IPIs assumes that some sort 336 7798 Saurabh * of memory serialization occurs. The old APIC code 337 7798 Saurabh * did a write to uncachable memory mapped registers. 338 7798 Saurabh * Any reference to uncached memory is a serializing 339 7798 Saurabh * operation. To mimic those semantics here, we do an 340 7798 Saurabh * atomic operation, which translates to a LOCK OR instruction, 341 7798 Saurabh * which is serializing. 342 7798 Saurabh */ 343 7798 Saurabh atomic_or_ulong(&flag, 1); 344 7282 mishra 345 7282 mishra vector = apic_resv_vector[ipl]; 346 7282 mishra 347 7282 mishra flag = intr_clear(); 348 7282 mishra 349 7798 Saurabh /* 350 7986 Saurabh * According to X2APIC specification in section '2.3.5.1' of 351 7798 Saurabh * Interrupt Command Register Semantics, the semantics of 352 7798 Saurabh * programming Interrupt Command Register to dispatch an interrupt 353 7798 Saurabh * is simplified. A single MSR write to the 64-bit ICR is required 354 7798 Saurabh * for dispatching an interrupt. Specifically with the 64-bit MSR 355 7798 Saurabh * interface to ICR, system software is not required to check the 356 7798 Saurabh * status of the delivery status bit prior to writing to the ICR 357 7798 Saurabh * to send an IPI. With the removal of the Delivery Status bit, 358 7798 Saurabh * system software no longer has a reason to read the ICR. It remains 359 7798 Saurabh * readable only to aid in debugging. 360 7798 Saurabh */ 361 7798 Saurabh #ifdef DEBUG 362 7798 Saurabh APIC_AV_PENDING_SET(); 363 7798 Saurabh #endif /* DEBUG */ 364 7282 mishra 365 8918 Saurabh if ((cpun == psm_get_cpu_id())) { 366 8918 Saurabh X2APIC_WRITE(X2APIC_SELF_IPI, vector); 367 8918 Saurabh } else { 368 7282 mishra apic_reg_ops->apic_write_int_cmd( 369 7282 mishra apic_cpus[cpun].aci_local_id, vector); 370 8918 Saurabh } 371 7282 mishra 372 7282 mishra intr_restore(flag); 373 7282 mishra } 374 7282 mishra 375 7986 Saurabh /* 376 7986 Saurabh * Generates IPI to another CPU depending on the local APIC mode. 377 7986 Saurabh * apic_send_ipi() and x2apic_send_ipi() depends on the configured 378 7986 Saurabh * mode of the local APIC, but that may not match the actual mode 379 7986 Saurabh * early in CPU startup. 380 7986 Saurabh * 381 7986 Saurabh * Any changes made to this routine must be accompanied by similar 382 7986 Saurabh * changes to apic_send_ipi(). 383 7986 Saurabh */ 384 7986 Saurabh void 385 7986 Saurabh apic_common_send_ipi(int cpun, int ipl) 386 7986 Saurabh { 387 7986 Saurabh int vector; 388 7986 Saurabh ulong_t flag; 389 7986 Saurabh int mode = apic_local_mode(); 390 7282 mishra 391 7986 Saurabh if (mode == LOCAL_X2APIC) { 392 7986 Saurabh x2apic_send_ipi(cpun, ipl); 393 7986 Saurabh return; 394 7986 Saurabh } 395 7986 Saurabh 396 7986 Saurabh ASSERT(mode == LOCAL_APIC); 397 7986 Saurabh 398 7986 Saurabh vector = apic_resv_vector[ipl]; 399 7986 Saurabh ASSERT((vector >= APIC_BASE_VECT) && (vector <= APIC_SPUR_INTR)); 400 7986 Saurabh flag = intr_clear(); 401 7986 Saurabh while (local_apic_regs_ops.apic_read(APIC_INT_CMD1) & AV_PENDING) 402 7986 Saurabh apic_ret(); 403 7986 Saurabh local_apic_regs_ops.apic_write_int_cmd(apic_cpus[cpun].aci_local_id, 404 7986 Saurabh vector); 405 7986 Saurabh intr_restore(flag); 406 7282 mishra } 407