]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/machine.c
xnu-6153.11.26.tar.gz
[apple/xnu.git] / osfmk / kern / machine.c
CommitLineData
1c79356b 1/*
0a7de745 2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
0a7de745 31/*
1c79356b
A
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
0a7de745 35 *
1c79356b
A
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.
0a7de745 41 *
1c79356b
A
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.
0a7de745 45 *
1c79356b 46 * Carnegie Mellon requests users of this software to return to
0a7de745 47 *
1c79356b
A
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
0a7de745 52 *
1c79356b
A
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56/*
57 */
58/*
59 * File: kern/machine.c
60 * Author: Avadis Tevanian, Jr.
61 * Date: 1987
62 *
63 * Support for machine independent machine abstraction.
64 */
65
1c79356b 66#include <string.h>
91447636
A
67
68#include <mach/mach_types.h>
1c79356b
A
69#include <mach/boolean.h>
70#include <mach/kern_return.h>
1c79356b
A
71#include <mach/machine.h>
72#include <mach/host_info.h>
73#include <mach/host_reboot.h>
91447636
A
74#include <mach/host_priv_server.h>
75#include <mach/processor_server.h>
76
77#include <kern/kern_types.h>
1c79356b
A
78#include <kern/counters.h>
79#include <kern/cpu_data.h>
d9a64523 80#include <kern/cpu_quiesce.h>
1c79356b
A
81#include <kern/ipc_host.h>
82#include <kern/host.h>
1c79356b 83#include <kern/machine.h>
91447636 84#include <kern/misc_protos.h>
1c79356b
A
85#include <kern/processor.h>
86#include <kern/queue.h>
87#include <kern/sched.h>
cb323159 88#include <kern/startup.h>
1c79356b
A
89#include <kern/task.h>
90#include <kern/thread.h>
1c79356b 91
6d2010ae
A
92#include <machine/commpage.h>
93
2d21ac55 94#if HIBERNATION
3a60a9f5 95#include <IOKit/IOHibernatePrivate.h>
2d21ac55 96#endif
0c530ab8 97#include <IOKit/IOPlatformExpert.h>
1c79356b 98
fe8ab488
A
99#if CONFIG_DTRACE
100extern void (*dtrace_cpu_state_changed_hook)(int, boolean_t);
101#endif
102
0a7de745
A
103#if defined(__x86_64__)
104#include <i386/misc_protos.h>
105#include <libkern/OSDebug.h>
106#endif
107
1c79356b
A
108/*
109 * Exported variables:
110 */
111
0a7de745 112struct machine_info machine_info;
1c79356b
A
113
114/* Forwards */
cb323159
A
115static void
116processor_doshutdown(processor_t processor);
117
118static void
119processor_offline(void * parameter, __unused wait_result_t result);
120
121static void
122processor_offline_intstack(processor_t processor) __dead2;
1c79356b
A
123
124/*
91447636 125 * processor_up:
1c79356b 126 *
91447636
A
127 * Flag processor as up and running, and available
128 * for scheduling.
1c79356b
A
129 */
130void
91447636 131processor_up(
0a7de745 132 processor_t processor)
1c79356b 133{
0a7de745
A
134 processor_set_t pset;
135 spl_t s;
cb323159 136 boolean_t pset_online = false;
1c79356b
A
137
138 s = splsched();
1c79356b 139 init_ast_check(processor);
2d21ac55
A
140 pset = processor->processor_set;
141 pset_lock(pset);
cb323159
A
142 if (pset->online_processor_count == 0) {
143 /* About to bring the first processor of a pset online */
144 pset_online = true;
145 }
fe8ab488 146 ++pset->online_processor_count;
d9a64523 147 pset_update_processor_state(pset, processor, PROCESSOR_RUNNING);
cb323159 148 os_atomic_inc(&processor_avail_count, relaxed);
0a7de745 149 if (processor->is_recommended) {
cb323159 150 os_atomic_inc(&processor_avail_count_user, relaxed);
0a7de745 151 }
6d2010ae 152 commpage_update_active_cpus();
cb323159
A
153 if (pset_online) {
154 /* New pset is coming up online; callout to the
155 * scheduler in case it wants to adjust runqs.
156 */
157 SCHED(pset_made_schedulable)(processor, pset, true);
158 /* pset lock dropped */
159 } else {
160 pset_unlock(pset);
161 }
91447636 162 ml_cpu_up();
1c79356b 163 splx(s);
fe8ab488
A
164
165#if CONFIG_DTRACE
0a7de745 166 if (dtrace_cpu_state_changed_hook) {
fe8ab488 167 (*dtrace_cpu_state_changed_hook)(processor->cpu_id, TRUE);
0a7de745 168 }
fe8ab488 169#endif
1c79356b 170}
fe8ab488 171#include <atm/atm_internal.h>
1c79356b
A
172
173kern_return_t
174host_reboot(
0a7de745
A
175 host_priv_t host_priv,
176 int options)
1c79356b 177{
0a7de745
A
178 if (host_priv == HOST_PRIV_NULL) {
179 return KERN_INVALID_HOST;
180 }
1c79356b
A
181
182 assert(host_priv == &realhost);
183
4bd07ac2 184#if DEVELOPMENT || DEBUG
1c79356b
A
185 if (options & HOST_REBOOT_DEBUGGER) {
186 Debugger("Debugger");
0a7de745 187 return KERN_SUCCESS;
1c79356b 188 }
4bd07ac2 189#endif
1c79356b 190
0a7de745
A
191 if (options & HOST_REBOOT_UPSDELAY) {
192 // UPS power cutoff path
193 PEHaltRestart( kPEUPSDelayHaltCPU );
194 } else {
195 halt_all_cpus(!(options & HOST_REBOOT_HALT));
196 }
9bccf70c 197
0a7de745 198 return KERN_SUCCESS;
1c79356b
A
199}
200
201kern_return_t
202processor_assign(
0a7de745
A
203 __unused processor_t processor,
204 __unused processor_set_t new_pset,
205 __unused boolean_t wait)
1c79356b 206{
0a7de745 207 return KERN_FAILURE;
1c79356b
A
208}
209
1c79356b
A
210kern_return_t
211processor_shutdown(
0a7de745 212 processor_t processor)
1c79356b 213{
0a7de745
A
214 processor_set_t pset;
215 spl_t s;
1c79356b
A
216
217 s = splsched();
2d21ac55
A
218 pset = processor->processor_set;
219 pset_lock(pset);
91447636 220 if (processor->state == PROCESSOR_OFF_LINE) {
1c79356b 221 /*
91447636 222 * Success if already shutdown.
1c79356b 223 */
2d21ac55 224 pset_unlock(pset);
1c79356b
A
225 splx(s);
226
0a7de745 227 return KERN_SUCCESS;
1c79356b
A
228 }
229
55e303ae
A
230 if (processor->state == PROCESSOR_START) {
231 /*
232 * Failure if currently being started.
233 */
2d21ac55 234 pset_unlock(pset);
55e303ae 235 splx(s);
1c79356b 236
0a7de745 237 return KERN_FAILURE;
55e303ae 238 }
1c79356b 239
55e303ae 240 /*
2d21ac55 241 * If the processor is dispatching, let it finish.
55e303ae 242 */
2d21ac55
A
243 while (processor->state == PROCESSOR_DISPATCHING) {
244 pset_unlock(pset);
fe8ab488 245 splx(s);
2d21ac55 246 delay(1);
fe8ab488 247 s = splsched();
2d21ac55 248 pset_lock(pset);
91447636 249 }
2d21ac55
A
250
251 /*
252 * Success if already being shutdown.
253 */
254 if (processor->state == PROCESSOR_SHUTDOWN) {
255 pset_unlock(pset);
91447636
A
256 splx(s);
257
0a7de745 258 return KERN_SUCCESS;
55e303ae 259 }
1c79356b 260
d9a64523 261 pset_update_processor_state(pset, processor, PROCESSOR_SHUTDOWN);
2d21ac55 262 pset_unlock(pset);
1c79356b 263
55e303ae 264 processor_doshutdown(processor);
1c79356b 265 splx(s);
1c79356b 266
b0d623f7 267 cpu_exit_wait(processor->cpu_id);
5353443c 268
0a7de745 269 return KERN_SUCCESS;
1c79356b
A
270}
271
272/*
bd504ef0 273 * Called with interrupts disabled.
1c79356b 274 */
cb323159 275static void
55e303ae 276processor_doshutdown(
cb323159 277 processor_t processor)
1c79356b 278{
cb323159 279 thread_t self = current_thread();
1c79356b
A
280
281 /*
282 * Get onto the processor to shutdown
283 */
cb323159 284 processor_t prev = thread_bind(processor);
9bccf70c 285 thread_block(THREAD_CONTINUE_NULL);
1c79356b 286
cb323159
A
287 /* interrupts still disabled */
288 assert(ml_get_interrupts_enabled() == FALSE);
289
290 assert(processor == current_processor());
55e303ae 291 assert(processor->state == PROCESSOR_SHUTDOWN);
1c79356b 292
fe8ab488 293#if CONFIG_DTRACE
0a7de745 294 if (dtrace_cpu_state_changed_hook) {
fe8ab488 295 (*dtrace_cpu_state_changed_hook)(processor->cpu_id, FALSE);
0a7de745 296 }
fe8ab488
A
297#endif
298
bd504ef0
A
299 ml_cpu_down();
300
2d21ac55 301#if HIBERNATION
bd504ef0
A
302 if (processor_avail_count < 2) {
303 hibernate_vm_lock();
3a60a9f5 304 hibernate_vm_unlock();
bd504ef0 305 }
2d21ac55 306#endif
91447636 307
cb323159
A
308 processor_set_t pset = processor->processor_set;
309
bd504ef0 310 pset_lock(pset);
d9a64523 311 pset_update_processor_state(pset, processor, PROCESSOR_OFF_LINE);
fe8ab488 312 --pset->online_processor_count;
cb323159 313 os_atomic_dec(&processor_avail_count, relaxed);
0a7de745 314 if (processor->is_recommended) {
cb323159 315 os_atomic_dec(&processor_avail_count_user, relaxed);
0a7de745 316 }
bd504ef0
A
317 commpage_update_active_cpus();
318 SCHED(processor_queue_shutdown)(processor);
319 /* pset lock dropped */
5ba3f43e 320 SCHED(rt_queue_shutdown)(processor);
bd504ef0 321
cb323159
A
322 thread_bind(prev);
323
324 /* interrupts still disabled */
325
1c79356b 326 /*
cb323159
A
327 * Continue processor shutdown on the processor's idle thread.
328 * The handoff won't fail because the idle thread has a reserved stack.
329 * Switching to the idle thread leaves interrupts disabled,
330 * so we can't accidentally take an interrupt after the context switch.
1c79356b 331 */
cb323159
A
332 thread_t shutdown_thread = processor->idle_thread;
333 shutdown_thread->continuation = processor_offline;
334 shutdown_thread->parameter = processor;
a3d08fcd 335
cb323159 336 thread_run(self, NULL, NULL, shutdown_thread);
1c79356b
A
337}
338
339/*
cb323159 340 * Called in the context of the idle thread to shut down the processor
490019cf 341 *
cb323159
A
342 * A shut-down processor looks like it's 'running' the idle thread parked
343 * in this routine, but it's actually been powered off and has no hardware state.
1c79356b 344 */
cb323159 345static void
55e303ae 346processor_offline(
cb323159
A
347 void * parameter,
348 __unused wait_result_t result)
1c79356b 349{
cb323159
A
350 processor_t processor = (processor_t) parameter;
351 thread_t self = current_thread();
352 __assert_only thread_t old_thread = THREAD_NULL;
353
490019cf 354 assert(processor == current_processor());
cb323159
A
355 assert(self->state & TH_IDLE);
356 assert(processor->idle_thread == self);
357 assert(ml_get_interrupts_enabled() == FALSE);
358 assert(self->continuation == NULL);
359 assert(processor->processor_offlined == false);
490019cf 360
cb323159 361 bool enforce_quiesce_safety = gEnforceQuiesceSafety;
91447636 362
cb323159
A
363 /*
364 * Scheduling is now disabled for this processor.
365 * Ensure that primitives that need scheduling (like mutexes) know this.
366 */
367 if (enforce_quiesce_safety) {
368 disable_preemption();
d9a64523
A
369 }
370
cb323159
A
371 /* convince slave_main to come back here */
372 processor->processor_offlined = true;
91447636 373
cb323159
A
374 /*
375 * Switch to the interrupt stack and shut down the processor.
376 *
377 * When the processor comes back, it will eventually call load_context which
378 * restores the context saved by machine_processor_shutdown, returning here.
379 */
380 old_thread = machine_processor_shutdown(self, processor_offline_intstack, processor);
490019cf 381
cb323159
A
382 /* old_thread should be NULL because we got here through Load_context */
383 assert(old_thread == THREAD_NULL);
490019cf 384
cb323159
A
385 assert(processor == current_processor());
386 assert(processor->idle_thread == current_thread());
387
388 assert(ml_get_interrupts_enabled() == FALSE);
389 assert(self->continuation == NULL);
390
391 /* Extract the machine_param value stashed by slave_main */
392 void * machine_param = self->parameter;
393 self->parameter = NULL;
394
395 /* Re-initialize the processor */
396 slave_machine_init(machine_param);
397
398 assert(processor->processor_offlined == true);
399 processor->processor_offlined = false;
400
401 if (enforce_quiesce_safety) {
402 enable_preemption();
403 }
490019cf 404
cb323159
A
405 /*
406 * Now that the processor is back, invoke the idle thread to find out what to do next.
407 * idle_thread will enable interrupts.
408 */
409 thread_block(idle_thread);
410 /*NOTREACHED*/
411}
91447636 412
cb323159
A
413/*
414 * Complete the shutdown and place the processor offline.
415 *
416 * Called at splsched in the shutdown context
417 * (i.e. on the idle thread, on the interrupt stack)
418 *
419 * The onlining half of this is done in load_context().
420 */
421static void
422processor_offline_intstack(
423 processor_t processor)
424{
425 assert(processor == current_processor());
426 assert(processor->active_thread == current_thread());
91447636 427
cb323159 428 timer_stop(PROCESSOR_DATA(processor, current_state), processor->last_dispatch);
1c79356b 429
d9a64523
A
430 cpu_quiescent_counter_leave(processor->last_dispatch);
431
b0d623f7 432 PMAP_DEACTIVATE_KERNEL(processor->cpu_id);
91447636 433
1c79356b
A
434 cpu_sleep();
435 panic("zombie processor");
436 /*NOTREACHED*/
437}
438
439kern_return_t
440host_get_boot_info(
0a7de745
A
441 host_priv_t host_priv,
442 kernel_boot_info_t boot_info)
1c79356b 443{
91447636 444 const char *src = "";
0a7de745
A
445 if (host_priv == HOST_PRIV_NULL) {
446 return KERN_INVALID_HOST;
447 }
1c79356b
A
448
449 assert(host_priv == &realhost);
450
451 /*
452 * Copy first operator string terminated by '\0' followed by
453 * standardized strings generated from boot string.
454 */
455 src = machine_boot_info(boot_info, KERNEL_BOOT_INFO_MAX);
0a7de745 456 if (src != boot_info) {
1c79356b 457 (void) strncpy(boot_info, src, KERNEL_BOOT_INFO_MAX);
0a7de745 458 }
1c79356b 459
0a7de745 460 return KERN_SUCCESS;
1c79356b 461}
813fb2f6
A
462
463#if CONFIG_DTRACE
464#include <mach/sdt.h>
465#endif
466
0a7de745
A
467unsigned long long
468ml_io_read(uintptr_t vaddr, int size)
469{
813fb2f6
A
470 unsigned long long result = 0;
471 unsigned char s1;
472 unsigned short s2;
473
474#if defined(__x86_64__)
475 uint64_t sabs, eabs;
476 boolean_t istate, timeread = FALSE;
477#if DEVELOPMENT || DEBUG
0a7de745
A
478 extern uint64_t simulate_stretched_io;
479 uintptr_t paddr = pmap_verify_noncacheable(vaddr);
813fb2f6
A
480#endif /* x86_64 DEVELOPMENT || DEBUG */
481 if (__improbable(reportphyreaddelayabs != 0)) {
482 istate = ml_set_interrupts_enabled(FALSE);
483 sabs = mach_absolute_time();
484 timeread = TRUE;
485 }
0a7de745
A
486
487#if DEVELOPMENT || DEBUG
488 if (__improbable(timeread && simulate_stretched_io)) {
489 sabs -= simulate_stretched_io;
490 }
491#endif /* x86_64 DEVELOPMENT || DEBUG */
492
813fb2f6
A
493#endif /* x86_64 */
494
495 switch (size) {
0a7de745 496 case 1:
813fb2f6
A
497 s1 = *(volatile unsigned char *)vaddr;
498 result = s1;
499 break;
0a7de745 500 case 2:
813fb2f6
A
501 s2 = *(volatile unsigned short *)vaddr;
502 result = s2;
503 break;
0a7de745 504 case 4:
813fb2f6
A
505 result = *(volatile unsigned int *)vaddr;
506 break;
507 case 8:
508 result = *(volatile unsigned long long *)vaddr;
509 break;
510 default:
0a7de745 511 panic("Invalid size %d for ml_io_read(%p)", size, (void *)vaddr);
813fb2f6 512 break;
0a7de745 513 }
813fb2f6
A
514
515#if defined(__x86_64__)
516 if (__improbable(timeread == TRUE)) {
517 eabs = mach_absolute_time();
0a7de745
A
518
519#if DEVELOPMENT || DEBUG
520 iotrace(IOTRACE_IO_READ, vaddr, paddr, size, result, sabs, eabs - sabs);
521#endif
813fb2f6
A
522
523 if (__improbable((eabs - sabs) > reportphyreaddelayabs)) {
0a7de745
A
524#if !(DEVELOPMENT || DEBUG)
525 uintptr_t paddr = kvtophys(vaddr);
526#endif
527
528 (void)ml_set_interrupts_enabled(istate);
529
5ba3f43e 530 if (phyreadpanic && (machine_timeout_suspended() == FALSE)) {
0a7de745
A
531 panic_io_port_read();
532 panic("Read from IO vaddr 0x%lx paddr 0x%lx took %llu ns, "
533 "result: 0x%llx (start: %llu, end: %llu), ceiling: %llu",
534 vaddr, paddr, (eabs - sabs), result, sabs, eabs,
535 reportphyreaddelayabs);
536 }
537
538 if (reportphyreadosbt) {
539 OSReportWithBacktrace("ml_io_read(v=%p, p=%p) size %d result 0x%llx "
540 "took %lluus",
541 (void *)vaddr, (void *)paddr, size, result,
542 (eabs - sabs) / NSEC_PER_USEC);
813fb2f6
A
543 }
544#if CONFIG_DTRACE
0a7de745
A
545 DTRACE_PHYSLAT5(physioread, uint64_t, (eabs - sabs),
546 uint64_t, vaddr, uint32_t, size, uint64_t, paddr, uint64_t, result);
813fb2f6 547#endif /* CONFIG_DTRACE */
0a7de745
A
548 } else if (__improbable(tracephyreaddelayabs > 0 && (eabs - sabs) > tracephyreaddelayabs)) {
549#if !(DEVELOPMENT || DEBUG)
550 uintptr_t paddr = kvtophys(vaddr);
551#endif
552
553 KDBG(MACHDBG_CODE(DBG_MACH_IO, DBC_MACH_IO_MMIO_READ),
554 (eabs - sabs), VM_KERNEL_UNSLIDE_OR_PERM(vaddr), paddr, result);
555
556 (void)ml_set_interrupts_enabled(istate);
557 } else {
558 (void)ml_set_interrupts_enabled(istate);
813fb2f6
A
559 }
560 }
561#endif /* x86_64 */
562 return result;
563}
564
0a7de745
A
565unsigned int
566ml_io_read8(uintptr_t vaddr)
567{
813fb2f6
A
568 return (unsigned) ml_io_read(vaddr, 1);
569}
570
0a7de745
A
571unsigned int
572ml_io_read16(uintptr_t vaddr)
573{
813fb2f6
A
574 return (unsigned) ml_io_read(vaddr, 2);
575}
576
0a7de745
A
577unsigned int
578ml_io_read32(uintptr_t vaddr)
579{
813fb2f6
A
580 return (unsigned) ml_io_read(vaddr, 4);
581}
582
0a7de745
A
583unsigned long long
584ml_io_read64(uintptr_t vaddr)
585{
813fb2f6
A
586 return ml_io_read(vaddr, 8);
587}
0a7de745
A
588
589/* ml_io_write* */
590
591void
592ml_io_write(uintptr_t vaddr, uint64_t val, int size)
593{
594#if defined(__x86_64__)
595 uint64_t sabs, eabs;
596 boolean_t istate, timewrite = FALSE;
597#if DEVELOPMENT || DEBUG
598 extern uint64_t simulate_stretched_io;
599 uintptr_t paddr = pmap_verify_noncacheable(vaddr);
600#endif /* x86_64 DEVELOPMENT || DEBUG */
601 if (__improbable(reportphywritedelayabs != 0)) {
602 istate = ml_set_interrupts_enabled(FALSE);
603 sabs = mach_absolute_time();
604 timewrite = TRUE;
605 }
606
607#if DEVELOPMENT || DEBUG
608 if (__improbable(timewrite && simulate_stretched_io)) {
609 sabs -= simulate_stretched_io;
610 }
611#endif /* x86_64 DEVELOPMENT || DEBUG */
612#endif /* x86_64 */
613
614 switch (size) {
615 case 1:
616 *(volatile uint8_t *)vaddr = (uint8_t)val;
617 break;
618 case 2:
619 *(volatile uint16_t *)vaddr = (uint16_t)val;
620 break;
621 case 4:
622 *(volatile uint32_t *)vaddr = (uint32_t)val;
623 break;
624 case 8:
625 *(volatile uint64_t *)vaddr = (uint64_t)val;
626 break;
627 default:
628 panic("Invalid size %d for ml_io_write(%p, 0x%llx)", size, (void *)vaddr, val);
629 break;
630 }
631
632#if defined(__x86_64__)
633 if (__improbable(timewrite == TRUE)) {
634 eabs = mach_absolute_time();
635
636#if DEVELOPMENT || DEBUG
637 iotrace(IOTRACE_IO_WRITE, vaddr, paddr, size, val, sabs, eabs - sabs);
638#endif
639
640 if (__improbable((eabs - sabs) > reportphywritedelayabs)) {
641#if !(DEVELOPMENT || DEBUG)
642 uintptr_t paddr = kvtophys(vaddr);
643#endif
644
645 (void)ml_set_interrupts_enabled(istate);
646
647 if (phywritepanic && (machine_timeout_suspended() == FALSE)) {
648 panic_io_port_read();
649 panic("Write to IO vaddr %p paddr %p val 0x%llx took %llu ns,"
650 " (start: %llu, end: %llu), ceiling: %llu",
651 (void *)vaddr, (void *)paddr, val, (eabs - sabs), sabs, eabs,
652 reportphywritedelayabs);
653 }
654
655 if (reportphywriteosbt) {
656 OSReportWithBacktrace("ml_io_write size %d (v=%p, p=%p, 0x%llx) "
657 "took %lluus",
658 size, (void *)vaddr, (void *)paddr, val, (eabs - sabs) / NSEC_PER_USEC);
659 }
660#if CONFIG_DTRACE
661 DTRACE_PHYSLAT5(physiowrite, uint64_t, (eabs - sabs),
662 uint64_t, vaddr, uint32_t, size, uint64_t, paddr, uint64_t, val);
663#endif /* CONFIG_DTRACE */
664 } else if (__improbable(tracephywritedelayabs > 0 && (eabs - sabs) > tracephywritedelayabs)) {
665#if !(DEVELOPMENT || DEBUG)
666 uintptr_t paddr = kvtophys(vaddr);
667#endif
668
669 KDBG(MACHDBG_CODE(DBG_MACH_IO, DBC_MACH_IO_MMIO_WRITE),
670 (eabs - sabs), VM_KERNEL_UNSLIDE_OR_PERM(vaddr), paddr, val);
671
672 (void)ml_set_interrupts_enabled(istate);
673 } else {
674 (void)ml_set_interrupts_enabled(istate);
675 }
676 }
677#endif /* x86_64 */
678}
679
680void
681ml_io_write8(uintptr_t vaddr, uint8_t val)
682{
683 ml_io_write(vaddr, val, 1);
684}
685
686void
687ml_io_write16(uintptr_t vaddr, uint16_t val)
688{
689 ml_io_write(vaddr, val, 2);
690}
691
692void
693ml_io_write32(uintptr_t vaddr, uint32_t val)
694{
695 ml_io_write(vaddr, val, 4);
696}
697
698void
699ml_io_write64(uintptr_t vaddr, uint64_t val)
700{
701 ml_io_write(vaddr, val, 8);
702}