1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 /* 25 * Copyright (c) 2010, Intel Corporation. 26 * All rights reserved. 27 */ 28 /* 29 * Copyright 2019 Joyent, Inc. 30 */ 31 32 /* 33 * Welcome to the world of the "real mode platter". 34 * See also startup.c, mpcore.s and apic.c for related routines. 35 */ 36 37 #include <sys/types.h> 38 #include <sys/systm.h> 39 #include <sys/cpuvar.h> 40 #include <sys/cpu_module.h> 41 #include <sys/kmem.h> 42 #include <sys/archsystm.h> 43 #include <sys/machsystm.h> 44 #include <sys/controlregs.h> 45 #include <sys/x86_archext.h> 46 #include <sys/smp_impldefs.h> 47 #include <sys/sysmacros.h> 48 #include <sys/mach_mmu.h> 49 #include <sys/promif.h> 50 #include <sys/cpu.h> 51 #include <sys/cpu_event.h> 52 #include <sys/sunndi.h> 53 #include <sys/fs/dv_node.h> 54 #include <vm/hat_i86.h> 55 #include <vm/as.h> 56 57 extern cpuset_t cpu_ready_set; 58 59 extern int mp_start_cpu_common(cpu_t *cp, boolean_t boot); 60 extern void real_mode_start_cpu(void); 61 extern void real_mode_start_cpu_end(void); 62 extern void real_mode_stop_cpu_stage1(void); 63 extern void real_mode_stop_cpu_stage1_end(void); 64 extern void real_mode_stop_cpu_stage2(void); 65 extern void real_mode_stop_cpu_stage2_end(void); 66 67 void rmp_gdt_init(rm_platter_t *); 68 69 /* 70 * Fill up the real mode platter to make it easy for real mode code to 71 * kick it off. This area should really be one passed by boot to kernel 72 * and guaranteed to be below 1MB and aligned to 16 bytes. Should also 73 * have identical physical and virtual address in paged mode. 74 */ 75 static ushort_t *warm_reset_vector = NULL; 76 77 int 78 mach_cpucontext_init(void) 79 { 80 ushort_t *vec; 81 ulong_t addr; 82 struct rm_platter *rm = (struct rm_platter *)rm_platter_va; 83 84 if (!(vec = (ushort_t *)psm_map_phys(WARM_RESET_VECTOR, 85 sizeof (vec), PROT_READ | PROT_WRITE))) 86 return (-1); 87 88 /* 89 * setup secondary cpu bios boot up vector 90 * Write page offset to 0x467 and page frame number to 0x469. 91 */ 92 addr = (ulong_t)((caddr_t)rm->rm_code - (caddr_t)rm) + rm_platter_pa; 93 vec[0] = (ushort_t)(addr & PAGEOFFSET); 94 vec[1] = (ushort_t)((addr & (0xfffff & PAGEMASK)) >> 4); 95 warm_reset_vector = vec; 96 97 /* Map real mode platter into kas so kernel can access it. */ 98 hat_devload(kas.a_hat, 99 (caddr_t)(uintptr_t)rm_platter_pa, MMU_PAGESIZE, 100 btop(rm_platter_pa), PROT_READ | PROT_WRITE | PROT_EXEC, 101 HAT_LOAD_NOCONSIST); 102 103 /* Copy CPU startup code to rm_platter if it's still during boot. */ 104 if (!plat_dr_enabled()) { 105 ASSERT((size_t)real_mode_start_cpu_end - 106 (size_t)real_mode_start_cpu <= RM_PLATTER_CODE_SIZE); 107 bcopy((caddr_t)real_mode_start_cpu, (caddr_t)rm->rm_code, 108 (size_t)real_mode_start_cpu_end - 109 (size_t)real_mode_start_cpu); 110 } 111 112 return (0); 113 } 114 115 void 116 mach_cpucontext_fini(void) 117 { 118 if (warm_reset_vector) 119 psm_unmap_phys((caddr_t)warm_reset_vector, 120 sizeof (warm_reset_vector)); 121 hat_unload(kas.a_hat, (caddr_t)(uintptr_t)rm_platter_pa, MMU_PAGESIZE, 122 HAT_UNLOAD); 123 } 124 125 #if defined(__amd64) 126 extern void *long_mode_64(void); 127 #endif /* __amd64 */ 128 129 /*ARGSUSED*/ 130 void 131 rmp_gdt_init(rm_platter_t *rm) 132 { 133 134 #if defined(__amd64) 135 /* Use the kas address space for the CPU startup thread. */ 136 if (mmu_ptob(kas.a_hat->hat_htable->ht_pfn) > 0xffffffffUL) { 137 panic("Cannot initialize CPUs; kernel's 64-bit page tables\n" 138 "located above 4G in physical memory (@ 0x%lx)", 139 mmu_ptob(kas.a_hat->hat_htable->ht_pfn)); 140 } 141 142 /* 143 * Setup pseudo-descriptors for temporary GDT and IDT for use ONLY 144 * by code in real_mode_start_cpu(): 145 * 146 * GDT[0]: NULL selector 147 * GDT[1]: 64-bit CS: Long = 1, Present = 1, bits 12, 11 = 1 148 * 149 * Clear the IDT as interrupts will be off and a limit of 0 will cause 150 * the CPU to triple fault and reset on an NMI, seemingly as reasonable 151 * a course of action as any other, though it may cause the entire 152 * platform to reset in some cases... 153 */ 154 rm->rm_temp_gdt[0] = 0; 155 rm->rm_temp_gdt[TEMPGDT_KCODE64] = 0x20980000000000ULL; 156 157 rm->rm_temp_gdt_lim = (ushort_t)(sizeof (rm->rm_temp_gdt) - 1); 158 rm->rm_temp_gdt_base = rm_platter_pa + 159 (uint32_t)offsetof(rm_platter_t, rm_temp_gdt); 160 rm->rm_temp_idt_lim = 0; 161 rm->rm_temp_idt_base = 0; 162 163 /* 164 * Since the CPU needs to jump to protected mode using an identity 165 * mapped address, we need to calculate it here. 166 */ 167 rm->rm_longmode64_addr = rm_platter_pa + 168 (uint32_t)((uintptr_t)long_mode_64 - 169 (uintptr_t)real_mode_start_cpu); 170 #endif /* __amd64 */ 171 } 172 173 static void * 174 mach_cpucontext_alloc_tables(struct cpu *cp) 175 { 176 tss_t *ntss; 177 struct cpu_tables *ct; 178 size_t ctsize; 179 180 /* 181 * Allocate space for stack, tss, gdt and idt. We round the size 182 * allotted for cpu_tables up, so that the TSS is on a unique page. 183 * This is more efficient when running in virtual machines. 184 */ 185 ctsize = P2ROUNDUP(sizeof (*ct), PAGESIZE); 186 ct = kmem_zalloc(ctsize, KM_SLEEP); 187 if ((uintptr_t)ct & PAGEOFFSET) 188 panic("mach_cpucontext_alloc_tables: cpu%d misaligned tables", 189 cp->cpu_id); 190 191 ntss = cp->cpu_tss = &ct->ct_tss; 192 193 #if defined(__amd64) 194 uintptr_t va; 195 size_t len; 196 197 /* 198 * #DF (double fault). 199 */ 200 ntss->tss_ist1 = (uintptr_t)&ct->ct_stack1[sizeof (ct->ct_stack1)]; 201 202 /* 203 * #NM (non-maskable interrupt) 204 */ 205 ntss->tss_ist2 = (uintptr_t)&ct->ct_stack2[sizeof (ct->ct_stack2)]; 206 207 /* 208 * #MC (machine check exception / hardware error) 209 */ 210 ntss->tss_ist3 = (uintptr_t)&ct->ct_stack3[sizeof (ct->ct_stack3)]; 211 212 /* 213 * #DB, #BP debug interrupts and KDI/kmdb 214 */ 215 ntss->tss_ist4 = (uintptr_t)&cp->cpu_m.mcpu_kpti_dbg.kf_tr_rsp; 216 217 if (kpti_enable == 1) { 218 /* 219 * #GP, #PF, #SS fault interrupts 220 */ 221 ntss->tss_ist5 = (uintptr_t)&cp->cpu_m.mcpu_kpti_flt.kf_tr_rsp; 222 223 /* 224 * Used by all other interrupts 225 */ 226 ntss->tss_ist6 = (uint64_t)&cp->cpu_m.mcpu_kpti.kf_tr_rsp; 227 228 /* 229 * On AMD64 we need to make sure that all of the pages of the 230 * struct cpu_tables are punched through onto the user CPU for 231 * kpti. 232 * 233 * The final page will always be the TSS, so treat that 234 * separately. 235 */ 236 for (va = (uintptr_t)ct, len = ctsize - MMU_PAGESIZE; 237 len >= MMU_PAGESIZE; 238 len -= MMU_PAGESIZE, va += MMU_PAGESIZE) { 239 /* The doublefault stack must be RW */ 240 hati_cpu_punchin(cp, va, PROT_READ | PROT_WRITE); 241 } 242 ASSERT3U((uintptr_t)ntss, ==, va); 243 hati_cpu_punchin(cp, (uintptr_t)ntss, PROT_READ); 244 } 245 246 #elif defined(__i386) 247 248 ntss->tss_esp0 = ntss->tss_esp1 = ntss->tss_esp2 = ntss->tss_esp = 249 (uint32_t)&ct->ct_stack1[sizeof (ct->ct_stack1)]; 250 251 ntss->tss_ss0 = ntss->tss_ss1 = ntss->tss_ss2 = ntss->tss_ss = KDS_SEL; 252 253 ntss->tss_eip = (uint32_t)cp->cpu_thread->t_pc; 254 255 ntss->tss_cs = KCS_SEL; 256 ntss->tss_ds = ntss->tss_es = KDS_SEL; 257 ntss->tss_fs = KFS_SEL; 258 ntss->tss_gs = KGS_SEL; 259 260 #endif /* __i386 */ 261 262 /* 263 * Set I/O bit map offset equal to size of TSS segment limit 264 * for no I/O permission map. This will cause all user I/O 265 * instructions to generate #gp fault. 266 */ 267 ntss->tss_bitmapbase = sizeof (*ntss); 268 269 /* 270 * Setup kernel tss. 271 */ 272 set_syssegd((system_desc_t *)&cp->cpu_gdt[GDT_KTSS], cp->cpu_tss, 273 sizeof (*cp->cpu_tss) - 1, SDT_SYSTSS, SEL_KPL); 274 275 return (ct); 276 } 277 278 void * 279 mach_cpucontext_xalloc(struct cpu *cp, int optype) 280 { 281 size_t len; 282 struct cpu_tables *ct; 283 rm_platter_t *rm = (rm_platter_t *)rm_platter_va; 284 static int cpu_halt_code_ready; 285 286 if (optype == MACH_CPUCONTEXT_OP_STOP) { 287 ASSERT(plat_dr_enabled()); 288 289 /* 290 * The WARM_RESET_VECTOR has a limitation that the physical 291 * address written to it must be page-aligned. To work around 292 * this limitation, the CPU stop code has been splitted into 293 * two stages. 294 * The stage 2 code, which implements the real logic to halt 295 * CPUs, is copied to the rm_cpu_halt_code field in the real 296 * mode platter. The stage 1 code, which simply jumps to the 297 * stage 2 code in the rm_cpu_halt_code field, is copied to 298 * rm_code field in the real mode platter and it may be 299 * overwritten after the CPU has been stopped. 300 */ 301 if (!cpu_halt_code_ready) { 302 /* 303 * The rm_cpu_halt_code field in the real mode platter 304 * is used by the CPU stop code only. So only copy the 305 * CPU stop stage 2 code into the rm_cpu_halt_code 306 * field on the first call. 307 */ 308 len = (size_t)real_mode_stop_cpu_stage2_end - 309 (size_t)real_mode_stop_cpu_stage2; 310 ASSERT(len <= RM_PLATTER_CPU_HALT_CODE_SIZE); 311 bcopy((caddr_t)real_mode_stop_cpu_stage2, 312 (caddr_t)rm->rm_cpu_halt_code, len); 313 cpu_halt_code_ready = 1; 314 } 315 316 /* 317 * The rm_code field in the real mode platter is shared by 318 * the CPU start, CPU stop, CPR and fast reboot code. So copy 319 * the CPU stop stage 1 code into the rm_code field every time. 320 */ 321 len = (size_t)real_mode_stop_cpu_stage1_end - 322 (size_t)real_mode_stop_cpu_stage1; 323 ASSERT(len <= RM_PLATTER_CODE_SIZE); 324 bcopy((caddr_t)real_mode_stop_cpu_stage1, 325 (caddr_t)rm->rm_code, len); 326 rm->rm_cpu_halted = 0; 327 328 return (cp->cpu_m.mcpu_mach_ctx_ptr); 329 } else if (optype != MACH_CPUCONTEXT_OP_START) { 330 return (NULL); 331 } 332 333 /* 334 * Only need to allocate tables when starting CPU. 335 * Tables allocated when starting CPU will be reused when stopping CPU. 336 */ 337 ct = mach_cpucontext_alloc_tables(cp); 338 if (ct == NULL) { 339 return (NULL); 340 } 341 342 /* Copy CPU startup code to rm_platter for CPU hot-add operations. */ 343 if (plat_dr_enabled()) { 344 bcopy((caddr_t)real_mode_start_cpu, (caddr_t)rm->rm_code, 345 (size_t)real_mode_start_cpu_end - 346 (size_t)real_mode_start_cpu); 347 } 348 349 /* 350 * Now copy all that we've set up onto the real mode platter 351 * for the real mode code to digest as part of starting the cpu. 352 */ 353 rm->rm_idt_base = cp->cpu_idt; 354 rm->rm_idt_lim = sizeof (*cp->cpu_idt) * NIDT - 1; 355 rm->rm_gdt_base = cp->cpu_gdt; 356 rm->rm_gdt_lim = sizeof (*cp->cpu_gdt) * NGDT - 1; 357 358 /* 359 * CPU needs to access kernel address space after powering on. 360 */ 361 rm->rm_pdbr = MAKECR3(kas.a_hat->hat_htable->ht_pfn, PCID_NONE); 362 rm->rm_cpu = cp->cpu_id; 363 364 /* 365 * We need to mask off any bits set on our boot CPU that can't apply 366 * while the subject CPU is initializing. If appropriate, they are 367 * enabled later on. 368 */ 369 rm->rm_cr4 = getcr4(); 370 rm->rm_cr4 &= ~(CR4_MCE | CR4_PCE | CR4_PCIDE); 371 372 rmp_gdt_init(rm); 373 374 return (ct); 375 } 376 377 void 378 mach_cpucontext_xfree(struct cpu *cp, void *arg, int err, int optype) 379 { 380 struct cpu_tables *ct = arg; 381 382 ASSERT(&ct->ct_tss == cp->cpu_tss); 383 if (optype == MACH_CPUCONTEXT_OP_START) { 384 switch (err) { 385 case 0: 386 /* 387 * Save pointer for reuse when stopping CPU. 388 */ 389 cp->cpu_m.mcpu_mach_ctx_ptr = arg; 390 break; 391 case ETIMEDOUT: 392 /* 393 * The processor was poked, but failed to start before 394 * we gave up waiting for it. In case it starts later, 395 * don't free anything. 396 */ 397 cp->cpu_m.mcpu_mach_ctx_ptr = arg; 398 break; 399 default: 400 /* 401 * Some other, passive, error occurred. 402 */ 403 kmem_free(ct, P2ROUNDUP(sizeof (*ct), PAGESIZE)); 404 cp->cpu_tss = NULL; 405 break; 406 } 407 } else if (optype == MACH_CPUCONTEXT_OP_STOP) { 408 switch (err) { 409 case 0: 410 /* 411 * Free resources allocated when starting CPU. 412 */ 413 kmem_free(ct, P2ROUNDUP(sizeof (*ct), PAGESIZE)); 414 cp->cpu_tss = NULL; 415 cp->cpu_m.mcpu_mach_ctx_ptr = NULL; 416 break; 417 default: 418 /* 419 * Don't touch table pointer in case of failure. 420 */ 421 break; 422 } 423 } else { 424 ASSERT(0); 425 } 426 } 427 428 void * 429 mach_cpucontext_alloc(struct cpu *cp) 430 { 431 return (mach_cpucontext_xalloc(cp, MACH_CPUCONTEXT_OP_START)); 432 } 433 434 void 435 mach_cpucontext_free(struct cpu *cp, void *arg, int err) 436 { 437 mach_cpucontext_xfree(cp, arg, err, MACH_CPUCONTEXT_OP_START); 438 } 439 440 /* 441 * "Enter monitor." Called via cross-call from stop_other_cpus(). 442 */ 443 void 444 mach_cpu_halt(char *msg) 445 { 446 if (msg) 447 prom_printf("%s\n", msg); 448 449 /*CONSTANTCONDITION*/ 450 while (1) 451 ; 452 } 453 454 void 455 mach_cpu_idle(void) 456 { 457 x86_md_clear(); 458 i86_halt(); 459 } 460 461 void 462 mach_cpu_pause(volatile char *safe) 463 { 464 /* 465 * This cpu is now safe. 466 */ 467 *safe = PAUSE_WAIT; 468 membar_enter(); /* make sure stores are flushed */ 469 470 /* 471 * Now we wait. When we are allowed to continue, safe 472 * will be set to PAUSE_IDLE. 473 */ 474 while (*safe != PAUSE_IDLE) 475 SMT_PAUSE(); 476 } 477 478 /* 479 * Power on the target CPU. 480 */ 481 int 482 mp_cpu_poweron(struct cpu *cp) 483 { 484 int error; 485 cpuset_t tempset; 486 processorid_t cpuid; 487 488 ASSERT(cp != NULL); 489 cpuid = cp->cpu_id; 490 if (use_mp == 0 || plat_dr_support_cpu() == 0) { 491 return (ENOTSUP); 492 } else if (cpuid < 0 || cpuid >= max_ncpus) { 493 return (EINVAL); 494 } 495 496 /* 497 * The currrent x86 implementaiton of mp_cpu_configure() and 498 * mp_cpu_poweron() have a limitation that mp_cpu_poweron() could only 499 * be called once after calling mp_cpu_configure() for a specific CPU. 500 * It's because mp_cpu_poweron() will destroy data structure created 501 * by mp_cpu_configure(). So reject the request if the CPU has already 502 * been powered on once after calling mp_cpu_configure(). 503 * This limitaiton only affects the p_online syscall and the DR driver 504 * won't be affected because the DR driver always invoke public CPU 505 * management interfaces in the predefined order: 506 * cpu_configure()->cpu_poweron()...->cpu_poweroff()->cpu_unconfigure() 507 */ 508 if (cpuid_checkpass(cp, 4) || cp->cpu_thread == cp->cpu_idle_thread) { 509 return (ENOTSUP); 510 } 511 512 /* 513 * Check if there's at least a Mbyte of kmem available 514 * before attempting to start the cpu. 515 */ 516 if (kmem_avail() < 1024 * 1024) { 517 /* 518 * Kick off a reap in case that helps us with 519 * later attempts .. 520 */ 521 kmem_reap(); 522 return (ENOMEM); 523 } 524 525 affinity_set(CPU->cpu_id); 526 527 /* 528 * Start the target CPU. No need to call mach_cpucontext_fini() 529 * if mach_cpucontext_init() fails. 530 */ 531 if ((error = mach_cpucontext_init()) == 0) { 532 error = mp_start_cpu_common(cp, B_FALSE); 533 mach_cpucontext_fini(); 534 } 535 if (error != 0) { 536 affinity_clear(); 537 return (error); 538 } 539 540 /* Wait for the target cpu to reach READY state. */ 541 tempset = cpu_ready_set; 542 while (!CPU_IN_SET(tempset, cpuid)) { 543 delay(1); 544 tempset = *((volatile cpuset_t *)&cpu_ready_set); 545 } 546 547 /* Mark the target CPU as available for mp operation. */ 548 CPUSET_ATOMIC_ADD(mp_cpus, cpuid); 549 550 /* Free the space allocated to hold the microcode file */ 551 ucode_cleanup(); 552 553 affinity_clear(); 554 555 return (0); 556 } 557 558 #define MP_CPU_DETACH_MAX_TRIES 5 559 #define MP_CPU_DETACH_DELAY 100 560 561 static int 562 mp_cpu_detach_driver(dev_info_t *dip) 563 { 564 int i; 565 int rv = EBUSY; 566 dev_info_t *pdip; 567 568 pdip = ddi_get_parent(dip); 569 ASSERT(pdip != NULL); 570 /* 571 * Check if caller holds pdip busy - can cause deadlocks in 572 * e_ddi_branch_unconfigure(), which calls devfs_clean(). 573 */ 574 if (DEVI_BUSY_OWNED(pdip)) { 575 return (EDEADLOCK); 576 } 577 578 for (i = 0; i < MP_CPU_DETACH_MAX_TRIES; i++) { 579 if (e_ddi_branch_unconfigure(dip, NULL, 0) == 0) { 580 rv = 0; 581 break; 582 } 583 DELAY(MP_CPU_DETACH_DELAY); 584 } 585 586 return (rv); 587 } 588 589 /* 590 * Power off the target CPU. 591 * Note: cpu_lock will be released and then reacquired. 592 */ 593 int 594 mp_cpu_poweroff(struct cpu *cp) 595 { 596 int rv = 0; 597 void *ctx; 598 dev_info_t *dip = NULL; 599 rm_platter_t *rm = (rm_platter_t *)rm_platter_va; 600 extern void cpupm_start(cpu_t *); 601 extern void cpupm_stop(cpu_t *); 602 603 ASSERT(cp != NULL); 604 ASSERT((cp->cpu_flags & CPU_OFFLINE) != 0); 605 ASSERT((cp->cpu_flags & CPU_QUIESCED) != 0); 606 607 if (use_mp == 0 || plat_dr_support_cpu() == 0) { 608 return (ENOTSUP); 609 } 610 /* 611 * There is no support for powering off cpu0 yet. 612 * There are many pieces of code which have a hard dependency on cpu0. 613 */ 614 if (cp->cpu_id == 0) { 615 return (ENOTSUP); 616 }; 617 618 if (mach_cpu_get_device_node(cp, &dip) != PSM_SUCCESS) { 619 return (ENXIO); 620 } 621 ASSERT(dip != NULL); 622 if (mp_cpu_detach_driver(dip) != 0) { 623 rv = EBUSY; 624 goto out_online; 625 } 626 627 /* Allocate CPU context for stopping */ 628 if (mach_cpucontext_init() != 0) { 629 rv = ENXIO; 630 goto out_online; 631 } 632 ctx = mach_cpucontext_xalloc(cp, MACH_CPUCONTEXT_OP_STOP); 633 if (ctx == NULL) { 634 rv = ENXIO; 635 goto out_context_fini; 636 } 637 638 cpupm_stop(cp); 639 cpu_event_fini_cpu(cp); 640 641 if (cp->cpu_m.mcpu_cmi_hdl != NULL) { 642 cmi_fini(cp->cpu_m.mcpu_cmi_hdl); 643 cp->cpu_m.mcpu_cmi_hdl = NULL; 644 } 645 646 rv = mach_cpu_stop(cp, ctx); 647 if (rv != 0) { 648 goto out_enable_cmi; 649 } 650 651 /* Wait until the target CPU has been halted. */ 652 while (*(volatile ushort_t *)&(rm->rm_cpu_halted) != 0xdead) { 653 delay(1); 654 } 655 rm->rm_cpu_halted = 0xffff; 656 657 /* CPU_READY has been cleared by mach_cpu_stop. */ 658 ASSERT((cp->cpu_flags & CPU_READY) == 0); 659 ASSERT((cp->cpu_flags & CPU_RUNNING) == 0); 660 cp->cpu_flags = CPU_OFFLINE | CPU_QUIESCED | CPU_POWEROFF; 661 CPUSET_ATOMIC_DEL(mp_cpus, cp->cpu_id); 662 663 mach_cpucontext_xfree(cp, ctx, 0, MACH_CPUCONTEXT_OP_STOP); 664 mach_cpucontext_fini(); 665 666 return (0); 667 668 out_enable_cmi: 669 { 670 cmi_hdl_t hdl; 671 672 if ((hdl = cmi_init(CMI_HDL_NATIVE, cmi_ntv_hwchipid(cp), 673 cmi_ntv_hwcoreid(cp), cmi_ntv_hwstrandid(cp))) != NULL) { 674 if (is_x86_feature(x86_featureset, X86FSET_MCA)) 675 cmi_mca_init(hdl); 676 cp->cpu_m.mcpu_cmi_hdl = hdl; 677 } 678 } 679 cpu_event_init_cpu(cp); 680 cpupm_start(cp); 681 mach_cpucontext_xfree(cp, ctx, rv, MACH_CPUCONTEXT_OP_STOP); 682 683 out_context_fini: 684 mach_cpucontext_fini(); 685 686 out_online: 687 (void) e_ddi_branch_configure(dip, NULL, 0); 688 689 if (rv != EAGAIN && rv != ETIME) { 690 rv = ENXIO; 691 } 692 693 return (rv); 694 } 695 696 /* 697 * Return vcpu state, since this could be a virtual environment that we 698 * are unaware of, return "unknown". 699 */ 700 /* ARGSUSED */ 701 int 702 vcpu_on_pcpu(processorid_t cpu) 703 { 704 return (VCPU_STATE_UNKNOWN); 705 } 706