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 /*
23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 /*
26 * Copyright (c) 2010, Intel Corporation.
27 * All rights reserved.
28 */
29 /*
30 * Copyright 2015 Joyent, Inc.
31 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
32 */
33
34 #include <sys/types.h>
35 #include <sys/thread.h>
36 #include <sys/cpuvar.h>
37 #include <sys/cpu.h>
38 #include <sys/t_lock.h>
39 #include <sys/param.h>
40 #include <sys/proc.h>
41 #include <sys/disp.h>
42 #include <sys/class.h>
43 #include <sys/cmn_err.h>
44 #include <sys/debug.h>
45 #include <sys/note.h>
46 #include <sys/asm_linkage.h>
47 #include <sys/x_call.h>
48 #include <sys/systm.h>
49 #include <sys/var.h>
50 #include <sys/vtrace.h>
230 ASSERT32(UCS_SEL == ((KCS_SEL + 16) | 3));
231 ASSERT32(UDS_SEL == UCS_SEL + 8);
232
233 ASSERT64(U32CS_SEL == ((KCS_SEL + 16) | 3));
234 ASSERT64(UDS_SEL == U32CS_SEL + 8);
235 #endif
236
237 cpu_sep_enable();
238
239 /*
240 * resume() sets this value to the base of the threads stack
241 * via a context handler.
242 */
243 wrmsr(MSR_INTC_SEP_ESP, 0);
244 wrmsr(MSR_INTC_SEP_EIP, (uint64_t)(uintptr_t)sys_sysenter);
245 }
246
247 kpreempt_enable();
248 }
249
250 /*
251 * Multiprocessor initialization.
252 *
253 * Allocate and initialize the cpu structure, TRAPTRACE buffer, and the
254 * startup and idle threads for the specified CPU.
255 * Parameter boot is true for boot time operations and is false for CPU
256 * DR operations.
257 */
258 static struct cpu *
259 mp_cpu_configure_common(int cpun, boolean_t boot)
260 {
261 struct cpu *cp;
262 kthread_id_t tp;
263 caddr_t sp;
264 proc_t *procp;
265 #if !defined(__xpv)
266 extern int idle_cpu_prefer_mwait;
267 extern void cpu_idle_mwait();
268 #endif
269 extern void idle();
270 extern void cpu_idle();
413 bcopy(CPU->cpu_idt, cp->cpu_idt, PAGESIZE);
414 } else {
415 cp->cpu_idt = CPU->cpu_idt;
416 }
417
418 /*
419 * alloc space for cpuid info
420 */
421 cpuid_alloc_space(cp);
422 #if !defined(__xpv)
423 if (is_x86_feature(x86_featureset, X86FSET_MWAIT) &&
424 idle_cpu_prefer_mwait) {
425 cp->cpu_m.mcpu_mwait = cpuid_mwait_alloc(cp);
426 cp->cpu_m.mcpu_idle_cpu = cpu_idle_mwait;
427 } else
428 #endif
429 cp->cpu_m.mcpu_idle_cpu = cpu_idle;
430
431 init_cpu_info(cp);
432
433 /*
434 * alloc space for ucode_info
435 */
436 ucode_alloc_space(cp);
437 xc_init_cpu(cp);
438 hat_cpu_online(cp);
439
440 #ifdef TRAPTRACE
441 /*
442 * If this is a TRAPTRACE kernel, allocate TRAPTRACE buffers
443 */
444 ttc->ttc_first = (uintptr_t)kmem_zalloc(trap_trace_bufsize, KM_SLEEP);
445 ttc->ttc_next = ttc->ttc_first;
446 ttc->ttc_limit = ttc->ttc_first + trap_trace_bufsize;
447 #endif
448
449 /*
450 * Record that we have another CPU.
451 */
452 /*
1469 tempset = *((volatile cpuset_t *)&cpu_ready_set);
1470 }
1471 mutex_enter(&cpu_lock);
1472
1473 return (0);
1474 }
1475
1476 void
1477 start_other_cpus(int cprboot)
1478 {
1479 _NOTE(ARGUNUSED(cprboot));
1480
1481 uint_t who;
1482 uint_t bootcpuid = 0;
1483
1484 /*
1485 * Initialize our own cpu_info.
1486 */
1487 init_cpu_info(CPU);
1488
1489 cmn_err(CE_CONT, "?cpu%d: %s\n", CPU->cpu_id, CPU->cpu_idstr);
1490 cmn_err(CE_CONT, "?cpu%d: %s\n", CPU->cpu_id, CPU->cpu_brandstr);
1491
1492 /*
1493 * Initialize our syscall handlers
1494 */
1495 init_cpu_syscall(CPU);
1496
1497 /*
1498 * Take the boot cpu out of the mp_cpus set because we know
1499 * it's already running. Add it to the cpu_ready_set for
1500 * precisely the same reason.
1501 */
1502 CPUSET_DEL(mp_cpus, bootcpuid);
1503 CPUSET_ADD(cpu_ready_set, bootcpuid);
1504
1505 /*
1506 * skip the rest of this if
1507 * . only 1 cpu dectected and system isn't hotplug-capable
1508 * . not using MP
|
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 /*
23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 /*
26 * Copyright (c) 2010, Intel Corporation.
27 * All rights reserved.
28 */
29 /*
30 * Copyright 2016 Joyent, Inc.
31 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
32 */
33
34 #include <sys/types.h>
35 #include <sys/thread.h>
36 #include <sys/cpuvar.h>
37 #include <sys/cpu.h>
38 #include <sys/t_lock.h>
39 #include <sys/param.h>
40 #include <sys/proc.h>
41 #include <sys/disp.h>
42 #include <sys/class.h>
43 #include <sys/cmn_err.h>
44 #include <sys/debug.h>
45 #include <sys/note.h>
46 #include <sys/asm_linkage.h>
47 #include <sys/x_call.h>
48 #include <sys/systm.h>
49 #include <sys/var.h>
50 #include <sys/vtrace.h>
230 ASSERT32(UCS_SEL == ((KCS_SEL + 16) | 3));
231 ASSERT32(UDS_SEL == UCS_SEL + 8);
232
233 ASSERT64(U32CS_SEL == ((KCS_SEL + 16) | 3));
234 ASSERT64(UDS_SEL == U32CS_SEL + 8);
235 #endif
236
237 cpu_sep_enable();
238
239 /*
240 * resume() sets this value to the base of the threads stack
241 * via a context handler.
242 */
243 wrmsr(MSR_INTC_SEP_ESP, 0);
244 wrmsr(MSR_INTC_SEP_EIP, (uint64_t)(uintptr_t)sys_sysenter);
245 }
246
247 kpreempt_enable();
248 }
249
250 #if !defined(__xpv)
251 /*
252 * Configure per-cpu ID GDT
253 */
254 static void
255 init_cpu_id_gdt(struct cpu *cp)
256 {
257 /* Write cpu_id into limit field of GDT for usermode retrieval */
258 #if defined(__amd64)
259 set_usegd(&cp->cpu_gdt[GDT_CPUID], SDP_SHORT, NULL, cp->cpu_id,
260 SDT_MEMRODA, SEL_UPL, SDP_BYTES, SDP_OP32);
261 #elif defined(__i386)
262 set_usegd(&cp->cpu_gdt[GDT_CPUID], NULL, cp->cpu_id, SDT_MEMRODA,
263 SEL_UPL, SDP_BYTES, SDP_OP32);
264 #endif
265 }
266 #endif /* !defined(__xpv) */
267
268 /*
269 * Multiprocessor initialization.
270 *
271 * Allocate and initialize the cpu structure, TRAPTRACE buffer, and the
272 * startup and idle threads for the specified CPU.
273 * Parameter boot is true for boot time operations and is false for CPU
274 * DR operations.
275 */
276 static struct cpu *
277 mp_cpu_configure_common(int cpun, boolean_t boot)
278 {
279 struct cpu *cp;
280 kthread_id_t tp;
281 caddr_t sp;
282 proc_t *procp;
283 #if !defined(__xpv)
284 extern int idle_cpu_prefer_mwait;
285 extern void cpu_idle_mwait();
286 #endif
287 extern void idle();
288 extern void cpu_idle();
431 bcopy(CPU->cpu_idt, cp->cpu_idt, PAGESIZE);
432 } else {
433 cp->cpu_idt = CPU->cpu_idt;
434 }
435
436 /*
437 * alloc space for cpuid info
438 */
439 cpuid_alloc_space(cp);
440 #if !defined(__xpv)
441 if (is_x86_feature(x86_featureset, X86FSET_MWAIT) &&
442 idle_cpu_prefer_mwait) {
443 cp->cpu_m.mcpu_mwait = cpuid_mwait_alloc(cp);
444 cp->cpu_m.mcpu_idle_cpu = cpu_idle_mwait;
445 } else
446 #endif
447 cp->cpu_m.mcpu_idle_cpu = cpu_idle;
448
449 init_cpu_info(cp);
450
451 #if !defined(__xpv)
452 init_cpu_id_gdt(cp);
453 #endif
454
455 /*
456 * alloc space for ucode_info
457 */
458 ucode_alloc_space(cp);
459 xc_init_cpu(cp);
460 hat_cpu_online(cp);
461
462 #ifdef TRAPTRACE
463 /*
464 * If this is a TRAPTRACE kernel, allocate TRAPTRACE buffers
465 */
466 ttc->ttc_first = (uintptr_t)kmem_zalloc(trap_trace_bufsize, KM_SLEEP);
467 ttc->ttc_next = ttc->ttc_first;
468 ttc->ttc_limit = ttc->ttc_first + trap_trace_bufsize;
469 #endif
470
471 /*
472 * Record that we have another CPU.
473 */
474 /*
1491 tempset = *((volatile cpuset_t *)&cpu_ready_set);
1492 }
1493 mutex_enter(&cpu_lock);
1494
1495 return (0);
1496 }
1497
1498 void
1499 start_other_cpus(int cprboot)
1500 {
1501 _NOTE(ARGUNUSED(cprboot));
1502
1503 uint_t who;
1504 uint_t bootcpuid = 0;
1505
1506 /*
1507 * Initialize our own cpu_info.
1508 */
1509 init_cpu_info(CPU);
1510
1511 #if !defined(__xpv)
1512 init_cpu_id_gdt(CPU);
1513 #endif
1514
1515 cmn_err(CE_CONT, "?cpu%d: %s\n", CPU->cpu_id, CPU->cpu_idstr);
1516 cmn_err(CE_CONT, "?cpu%d: %s\n", CPU->cpu_id, CPU->cpu_brandstr);
1517
1518 /*
1519 * Initialize our syscall handlers
1520 */
1521 init_cpu_syscall(CPU);
1522
1523 /*
1524 * Take the boot cpu out of the mp_cpus set because we know
1525 * it's already running. Add it to the cpu_ready_set for
1526 * precisely the same reason.
1527 */
1528 CPUSET_DEL(mp_cpus, bootcpuid);
1529 CPUSET_ADD(cpu_ready_set, bootcpuid);
1530
1531 /*
1532 * skip the rest of this if
1533 * . only 1 cpu dectected and system isn't hotplug-capable
1534 * . not using MP
|