2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
59 * File: kern/machine.c
60 * Author: Avadis Tevanian, Jr.
63 * Support for machine independent machine abstraction.
68 #include <mach/mach_types.h>
69 #include <mach/boolean.h>
70 #include <mach/kern_return.h>
71 #include <mach/machine.h>
72 #include <mach/host_info.h>
73 #include <mach/host_reboot.h>
74 #include <mach/host_priv_server.h>
75 #include <mach/processor_server.h>
77 #include <kern/kern_types.h>
78 #include <kern/cpu_data.h>
79 #include <kern/cpu_quiesce.h>
80 #include <kern/ipc_host.h>
81 #include <kern/host.h>
82 #include <kern/machine.h>
83 #include <kern/misc_protos.h>
84 #include <kern/processor.h>
85 #include <kern/queue.h>
86 #include <kern/sched.h>
87 #include <kern/startup.h>
88 #include <kern/task.h>
89 #include <kern/thread.h>
91 #include <machine/commpage.h>
92 #include <machine/machine_routines.h>
95 #include <IOKit/IOHibernatePrivate.h>
97 #include <IOKit/IOPlatformExpert.h>
100 extern void (*dtrace_cpu_state_changed_hook
)(int, boolean_t
);
103 #if defined(__x86_64__)
104 #include <i386/panic_notify.h>
105 #include <libkern/OSDebug.h>
109 * Exported variables:
112 struct machine_info machine_info
;
116 processor_doshutdown(processor_t processor
);
119 processor_offline(void * parameter
, __unused wait_result_t result
);
122 processor_offline_intstack(processor_t processor
) __dead2
;
127 * Flag processor as up and running, and available
132 processor_t processor
)
134 processor_set_t pset
;
138 init_ast_check(processor
);
139 pset
= processor
->processor_set
;
142 ++pset
->online_processor_count
;
143 pset_update_processor_state(pset
, processor
, PROCESSOR_RUNNING
);
144 os_atomic_inc(&processor_avail_count
, relaxed
);
145 if (processor
->is_recommended
) {
146 os_atomic_inc(&processor_avail_count_user
, relaxed
);
147 SCHED(pset_made_schedulable
)(processor
, pset
, false);
149 if (processor
->processor_primary
== processor
) {
150 os_atomic_inc(&primary_processor_avail_count
, relaxed
);
151 if (processor
->is_recommended
) {
152 os_atomic_inc(&primary_processor_avail_count_user
, relaxed
);
155 commpage_update_active_cpus();
161 if (dtrace_cpu_state_changed_hook
) {
162 (*dtrace_cpu_state_changed_hook
)(processor
->cpu_id
, TRUE
);
166 #include <atm/atm_internal.h>
170 host_priv_t host_priv
,
173 if (host_priv
== HOST_PRIV_NULL
) {
174 return KERN_INVALID_HOST
;
177 #if DEVELOPMENT || DEBUG
178 if (options
& HOST_REBOOT_DEBUGGER
) {
179 Debugger("Debugger");
184 if (options
& HOST_REBOOT_UPSDELAY
) {
185 // UPS power cutoff path
186 PEHaltRestart( kPEUPSDelayHaltCPU
);
188 halt_all_cpus(!(options
& HOST_REBOOT_HALT
));
196 __unused processor_t processor
,
197 __unused processor_set_t new_pset
,
198 __unused boolean_t wait
)
205 processor_t processor
)
207 processor_set_t pset
;
210 ml_cpu_begin_state_transition(processor
->cpu_id
);
212 pset
= processor
->processor_set
;
214 if (processor
->state
== PROCESSOR_OFF_LINE
) {
216 * Success if already shutdown.
220 ml_cpu_end_state_transition(processor
->cpu_id
);
225 if (!ml_cpu_can_exit(processor
->cpu_id
)) {
227 * Failure if disallowed by arch code.
231 ml_cpu_end_state_transition(processor
->cpu_id
);
236 if (processor
->state
== PROCESSOR_START
) {
238 * Failure if currently being started.
247 * If the processor is dispatching, let it finish.
249 while (processor
->state
== PROCESSOR_DISPATCHING
) {
258 * Success if already being shutdown.
260 if (processor
->state
== PROCESSOR_SHUTDOWN
) {
263 ml_cpu_end_state_transition(processor
->cpu_id
);
268 ml_broadcast_cpu_event(CPU_EXIT_REQUESTED
, processor
->cpu_id
);
269 pset_update_processor_state(pset
, processor
, PROCESSOR_SHUTDOWN
);
272 processor_doshutdown(processor
);
275 cpu_exit_wait(processor
->cpu_id
);
276 ml_cpu_end_state_transition(processor
->cpu_id
);
277 ml_broadcast_cpu_event(CPU_EXITED
, processor
->cpu_id
);
283 * Called with interrupts disabled.
286 processor_doshutdown(
287 processor_t processor
)
289 thread_t self
= current_thread();
292 * Get onto the processor to shutdown
294 processor_t prev
= thread_bind(processor
);
295 thread_block(THREAD_CONTINUE_NULL
);
297 /* interrupts still disabled */
298 assert(ml_get_interrupts_enabled() == FALSE
);
300 assert(processor
== current_processor());
301 assert(processor
->state
== PROCESSOR_SHUTDOWN
);
304 if (dtrace_cpu_state_changed_hook
) {
305 (*dtrace_cpu_state_changed_hook
)(processor
->cpu_id
, FALSE
);
312 if (processor_avail_count
< 2) {
314 hibernate_vm_unlock();
318 processor_set_t pset
= processor
->processor_set
;
321 pset_update_processor_state(pset
, processor
, PROCESSOR_OFF_LINE
);
322 --pset
->online_processor_count
;
323 os_atomic_dec(&processor_avail_count
, relaxed
);
324 if (processor
->is_recommended
) {
325 os_atomic_dec(&processor_avail_count_user
, relaxed
);
327 if (processor
->processor_primary
== processor
) {
328 os_atomic_dec(&primary_processor_avail_count
, relaxed
);
329 if (processor
->is_recommended
) {
330 os_atomic_dec(&primary_processor_avail_count_user
, relaxed
);
333 commpage_update_active_cpus();
334 SCHED(processor_queue_shutdown
)(processor
);
335 /* pset lock dropped */
336 SCHED(rt_queue_shutdown
)(processor
);
340 /* interrupts still disabled */
343 * Continue processor shutdown on the processor's idle thread.
344 * The handoff won't fail because the idle thread has a reserved stack.
345 * Switching to the idle thread leaves interrupts disabled,
346 * so we can't accidentally take an interrupt after the context switch.
348 thread_t shutdown_thread
= processor
->idle_thread
;
349 shutdown_thread
->continuation
= processor_offline
;
350 shutdown_thread
->parameter
= processor
;
352 thread_run(self
, NULL
, NULL
, shutdown_thread
);
356 * Called in the context of the idle thread to shut down the processor
358 * A shut-down processor looks like it's 'running' the idle thread parked
359 * in this routine, but it's actually been powered off and has no hardware state.
364 __unused wait_result_t result
)
366 processor_t processor
= (processor_t
) parameter
;
367 thread_t self
= current_thread();
368 __assert_only thread_t old_thread
= THREAD_NULL
;
370 assert(processor
== current_processor());
371 assert(self
->state
& TH_IDLE
);
372 assert(processor
->idle_thread
== self
);
373 assert(ml_get_interrupts_enabled() == FALSE
);
374 assert(self
->continuation
== NULL
);
375 assert(processor
->processor_offlined
== false);
376 assert(processor
->running_timers_active
== false);
378 bool enforce_quiesce_safety
= gEnforceQuiesceSafety
;
381 * Scheduling is now disabled for this processor.
382 * Ensure that primitives that need scheduling (like mutexes) know this.
384 if (enforce_quiesce_safety
) {
385 disable_preemption();
388 /* convince slave_main to come back here */
389 processor
->processor_offlined
= true;
392 * Switch to the interrupt stack and shut down the processor.
394 * When the processor comes back, it will eventually call load_context which
395 * restores the context saved by machine_processor_shutdown, returning here.
397 old_thread
= machine_processor_shutdown(self
, processor_offline_intstack
, processor
);
399 /* old_thread should be NULL because we got here through Load_context */
400 assert(old_thread
== THREAD_NULL
);
402 assert(processor
== current_processor());
403 assert(processor
->idle_thread
== current_thread());
405 assert(ml_get_interrupts_enabled() == FALSE
);
406 assert(self
->continuation
== NULL
);
408 /* Extract the machine_param value stashed by slave_main */
409 void * machine_param
= self
->parameter
;
410 self
->parameter
= NULL
;
412 /* Re-initialize the processor */
413 slave_machine_init(machine_param
);
415 assert(processor
->processor_offlined
== true);
416 processor
->processor_offlined
= false;
418 if (enforce_quiesce_safety
) {
423 * Now that the processor is back, invoke the idle thread to find out what to do next.
424 * idle_thread will enable interrupts.
426 thread_block(idle_thread
);
431 * Complete the shutdown and place the processor offline.
433 * Called at splsched in the shutdown context
434 * (i.e. on the idle thread, on the interrupt stack)
436 * The onlining half of this is done in load_context().
439 processor_offline_intstack(
440 processor_t processor
)
442 assert(processor
== current_processor());
443 assert(processor
->active_thread
== current_thread());
445 timer_stop(processor
->current_state
, processor
->last_dispatch
);
447 cpu_quiescent_counter_leave(processor
->last_dispatch
);
449 PMAP_DEACTIVATE_KERNEL(processor
->cpu_id
);
452 panic("zombie processor");
458 host_priv_t host_priv
,
459 kernel_boot_info_t boot_info
)
461 const char *src
= "";
462 if (host_priv
== HOST_PRIV_NULL
) {
463 return KERN_INVALID_HOST
;
467 * Copy first operator string terminated by '\0' followed by
468 * standardized strings generated from boot string.
470 src
= machine_boot_info(boot_info
, KERNEL_BOOT_INFO_MAX
);
471 if (src
!= boot_info
) {
472 (void) strncpy(boot_info
, src
, KERNEL_BOOT_INFO_MAX
);
479 #include <mach/sdt.h>
483 ml_io_read(uintptr_t vaddr
, int size
)
485 unsigned long long result
= 0;
489 #if defined(__x86_64__)
491 boolean_t istate
, timeread
= FALSE
;
492 #if DEVELOPMENT || DEBUG
493 extern uint64_t simulate_stretched_io
;
494 uintptr_t paddr
= pmap_verify_noncacheable(vaddr
);
495 #endif /* x86_64 DEVELOPMENT || DEBUG */
496 if (__improbable(reportphyreaddelayabs
!= 0)) {
497 istate
= ml_set_interrupts_enabled(FALSE
);
498 sabs
= mach_absolute_time();
502 #if DEVELOPMENT || DEBUG
503 if (__improbable(timeread
&& simulate_stretched_io
)) {
504 sabs
-= simulate_stretched_io
;
506 #endif /* x86_64 DEVELOPMENT || DEBUG */
512 s1
= *(volatile unsigned char *)vaddr
;
516 s2
= *(volatile unsigned short *)vaddr
;
520 result
= *(volatile unsigned int *)vaddr
;
523 result
= *(volatile unsigned long long *)vaddr
;
526 panic("Invalid size %d for ml_io_read(%p)", size
, (void *)vaddr
);
530 #if defined(__x86_64__)
531 if (__improbable(timeread
== TRUE
)) {
532 eabs
= mach_absolute_time();
534 #if DEVELOPMENT || DEBUG
535 iotrace(IOTRACE_IO_READ
, vaddr
, paddr
, size
, result
, sabs
, eabs
- sabs
);
538 if (__improbable((eabs
- sabs
) > reportphyreaddelayabs
)) {
539 #if !(DEVELOPMENT || DEBUG)
540 uintptr_t paddr
= kvtophys(vaddr
);
543 (void)ml_set_interrupts_enabled(istate
);
545 if (phyreadpanic
&& (machine_timeout_suspended() == FALSE
)) {
547 panic("Read from IO vaddr 0x%lx paddr 0x%lx took %llu ns, "
548 "result: 0x%llx (start: %llu, end: %llu), ceiling: %llu",
549 vaddr
, paddr
, (eabs
- sabs
), result
, sabs
, eabs
,
550 reportphyreaddelayabs
);
553 if (reportphyreadosbt
) {
554 OSReportWithBacktrace("ml_io_read(v=%p, p=%p) size %d result 0x%llx "
556 (void *)vaddr
, (void *)paddr
, size
, result
,
557 (eabs
- sabs
) / NSEC_PER_USEC
);
560 DTRACE_PHYSLAT5(physioread
, uint64_t, (eabs
- sabs
),
561 uint64_t, vaddr
, uint32_t, size
, uint64_t, paddr
, uint64_t, result
);
562 #endif /* CONFIG_DTRACE */
563 } else if (__improbable(tracephyreaddelayabs
> 0 && (eabs
- sabs
) > tracephyreaddelayabs
)) {
564 #if !(DEVELOPMENT || DEBUG)
565 uintptr_t paddr
= kvtophys(vaddr
);
568 KDBG(MACHDBG_CODE(DBG_MACH_IO
, DBC_MACH_IO_MMIO_READ
),
569 (eabs
- sabs
), VM_KERNEL_UNSLIDE_OR_PERM(vaddr
), paddr
, result
);
571 (void)ml_set_interrupts_enabled(istate
);
573 (void)ml_set_interrupts_enabled(istate
);
581 ml_io_read8(uintptr_t vaddr
)
583 return (unsigned) ml_io_read(vaddr
, 1);
587 ml_io_read16(uintptr_t vaddr
)
589 return (unsigned) ml_io_read(vaddr
, 2);
593 ml_io_read32(uintptr_t vaddr
)
595 return (unsigned) ml_io_read(vaddr
, 4);
599 ml_io_read64(uintptr_t vaddr
)
601 return ml_io_read(vaddr
, 8);
607 ml_io_write(uintptr_t vaddr
, uint64_t val
, int size
)
609 #if defined(__x86_64__)
611 boolean_t istate
, timewrite
= FALSE
;
612 #if DEVELOPMENT || DEBUG
613 extern uint64_t simulate_stretched_io
;
614 uintptr_t paddr
= pmap_verify_noncacheable(vaddr
);
615 #endif /* x86_64 DEVELOPMENT || DEBUG */
616 if (__improbable(reportphywritedelayabs
!= 0)) {
617 istate
= ml_set_interrupts_enabled(FALSE
);
618 sabs
= mach_absolute_time();
622 #if DEVELOPMENT || DEBUG
623 if (__improbable(timewrite
&& simulate_stretched_io
)) {
624 sabs
-= simulate_stretched_io
;
626 #endif /* x86_64 DEVELOPMENT || DEBUG */
631 *(volatile uint8_t *)vaddr
= (uint8_t)val
;
634 *(volatile uint16_t *)vaddr
= (uint16_t)val
;
637 *(volatile uint32_t *)vaddr
= (uint32_t)val
;
640 *(volatile uint64_t *)vaddr
= (uint64_t)val
;
643 panic("Invalid size %d for ml_io_write(%p, 0x%llx)", size
, (void *)vaddr
, val
);
647 #if defined(__x86_64__)
648 if (__improbable(timewrite
== TRUE
)) {
649 eabs
= mach_absolute_time();
651 #if DEVELOPMENT || DEBUG
652 iotrace(IOTRACE_IO_WRITE
, vaddr
, paddr
, size
, val
, sabs
, eabs
- sabs
);
655 if (__improbable((eabs
- sabs
) > reportphywritedelayabs
)) {
656 #if !(DEVELOPMENT || DEBUG)
657 uintptr_t paddr
= kvtophys(vaddr
);
660 (void)ml_set_interrupts_enabled(istate
);
662 if (phywritepanic
&& (machine_timeout_suspended() == FALSE
)) {
664 panic("Write to IO vaddr %p paddr %p val 0x%llx took %llu ns,"
665 " (start: %llu, end: %llu), ceiling: %llu",
666 (void *)vaddr
, (void *)paddr
, val
, (eabs
- sabs
), sabs
, eabs
,
667 reportphywritedelayabs
);
670 if (reportphywriteosbt
) {
671 OSReportWithBacktrace("ml_io_write size %d (v=%p, p=%p, 0x%llx) "
673 size
, (void *)vaddr
, (void *)paddr
, val
, (eabs
- sabs
) / NSEC_PER_USEC
);
676 DTRACE_PHYSLAT5(physiowrite
, uint64_t, (eabs
- sabs
),
677 uint64_t, vaddr
, uint32_t, size
, uint64_t, paddr
, uint64_t, val
);
678 #endif /* CONFIG_DTRACE */
679 } else if (__improbable(tracephywritedelayabs
> 0 && (eabs
- sabs
) > tracephywritedelayabs
)) {
680 #if !(DEVELOPMENT || DEBUG)
681 uintptr_t paddr
= kvtophys(vaddr
);
684 KDBG(MACHDBG_CODE(DBG_MACH_IO
, DBC_MACH_IO_MMIO_WRITE
),
685 (eabs
- sabs
), VM_KERNEL_UNSLIDE_OR_PERM(vaddr
), paddr
, val
);
687 (void)ml_set_interrupts_enabled(istate
);
689 (void)ml_set_interrupts_enabled(istate
);
696 ml_io_write8(uintptr_t vaddr
, uint8_t val
)
698 ml_io_write(vaddr
, val
, 1);
702 ml_io_write16(uintptr_t vaddr
, uint16_t val
)
704 ml_io_write(vaddr
, val
, 2);
708 ml_io_write32(uintptr_t vaddr
, uint32_t val
)
710 ml_io_write(vaddr
, val
, 4);
714 ml_io_write64(uintptr_t vaddr
, uint64_t val
)
716 ml_io_write(vaddr
, val
, 8);
719 struct cpu_callback_chain_elem
{
722 struct cpu_callback_chain_elem
*next
;
725 static struct cpu_callback_chain_elem
*cpu_callback_chain
;
726 static LCK_GRP_DECLARE(cpu_callback_chain_lock_grp
, "cpu_callback_chain");
727 static LCK_SPIN_DECLARE(cpu_callback_chain_lock
, &cpu_callback_chain_lock_grp
);
730 cpu_event_register_callback(cpu_callback_t fn
, void *param
)
732 struct cpu_callback_chain_elem
*new_elem
;
734 new_elem
= zalloc_permanent_type(struct cpu_callback_chain_elem
);
736 panic("can't allocate cpu_callback_chain_elem");
739 lck_spin_lock(&cpu_callback_chain_lock
);
740 new_elem
->next
= cpu_callback_chain
;
742 new_elem
->param
= param
;
743 os_atomic_store(&cpu_callback_chain
, new_elem
, release
);
744 lck_spin_unlock(&cpu_callback_chain_lock
);
747 __attribute__((noreturn
))
749 cpu_event_unregister_callback(__unused cpu_callback_t fn
)
751 panic("Unfortunately, cpu_event_unregister_callback is unimplemented.");
755 ml_broadcast_cpu_event(enum cpu_event event
, unsigned int cpu_or_cluster
)
757 struct cpu_callback_chain_elem
*cursor
;
759 cursor
= os_atomic_load(&cpu_callback_chain
, dependency
);
760 for (; cursor
!= NULL
; cursor
= cursor
->next
) {
761 cursor
->fn(cursor
->param
, event
, cpu_or_cluster
);