+unsigned int
+ml_io_read16(uintptr_t vaddr)
+{
+ return (unsigned) ml_io_read(vaddr, 2);
+}
+
+unsigned int
+ml_io_read32(uintptr_t vaddr)
+{
+ return (unsigned) ml_io_read(vaddr, 4);
+}
+
+unsigned long long
+ml_io_read64(uintptr_t vaddr)
+{
+ return ml_io_read(vaddr, 8);
+}
+
+/* ml_io_write* */
+
+void
+ml_io_write(uintptr_t vaddr, uint64_t val, int size)
+{
+#if defined(__x86_64__)
+ uint64_t sabs, eabs;
+ boolean_t istate, timewrite = FALSE;
+#if DEVELOPMENT || DEBUG
+ extern uint64_t simulate_stretched_io;
+ uintptr_t paddr = pmap_verify_noncacheable(vaddr);
+#endif /* x86_64 DEVELOPMENT || DEBUG */
+ if (__improbable(reportphywritedelayabs != 0)) {
+ istate = ml_set_interrupts_enabled(FALSE);
+ sabs = mach_absolute_time();
+ timewrite = TRUE;
+ }
+
+#if DEVELOPMENT || DEBUG
+ if (__improbable(timewrite && simulate_stretched_io)) {
+ sabs -= simulate_stretched_io;
+ }
+#endif /* x86_64 DEVELOPMENT || DEBUG */
+#endif /* x86_64 */
+
+ switch (size) {
+ case 1:
+ *(volatile uint8_t *)vaddr = (uint8_t)val;
+ break;
+ case 2:
+ *(volatile uint16_t *)vaddr = (uint16_t)val;
+ break;
+ case 4:
+ *(volatile uint32_t *)vaddr = (uint32_t)val;
+ break;
+ case 8:
+ *(volatile uint64_t *)vaddr = (uint64_t)val;
+ break;
+ default:
+ panic("Invalid size %d for ml_io_write(%p, 0x%llx)", size, (void *)vaddr, val);
+ break;
+ }
+
+#if defined(__x86_64__)
+ if (__improbable(timewrite == TRUE)) {
+ eabs = mach_absolute_time();
+
+#if DEVELOPMENT || DEBUG
+ iotrace(IOTRACE_IO_WRITE, vaddr, paddr, size, val, sabs, eabs - sabs);
+#endif
+
+ if (__improbable((eabs - sabs) > reportphywritedelayabs)) {
+#if !(DEVELOPMENT || DEBUG)
+ uintptr_t paddr = kvtophys(vaddr);
+#endif
+
+ (void)ml_set_interrupts_enabled(istate);
+
+ if (phywritepanic && (machine_timeout_suspended() == FALSE)) {
+ panic_io_port_read();
+ panic("Write to IO vaddr %p paddr %p val 0x%llx took %llu ns,"
+ " (start: %llu, end: %llu), ceiling: %llu",
+ (void *)vaddr, (void *)paddr, val, (eabs - sabs), sabs, eabs,
+ reportphywritedelayabs);
+ }
+
+ if (reportphywriteosbt) {
+ OSReportWithBacktrace("ml_io_write size %d (v=%p, p=%p, 0x%llx) "
+ "took %lluus",
+ size, (void *)vaddr, (void *)paddr, val, (eabs - sabs) / NSEC_PER_USEC);
+ }
+#if CONFIG_DTRACE
+ DTRACE_PHYSLAT5(physiowrite, uint64_t, (eabs - sabs),
+ uint64_t, vaddr, uint32_t, size, uint64_t, paddr, uint64_t, val);
+#endif /* CONFIG_DTRACE */
+ } else if (__improbable(tracephywritedelayabs > 0 && (eabs - sabs) > tracephywritedelayabs)) {
+#if !(DEVELOPMENT || DEBUG)
+ uintptr_t paddr = kvtophys(vaddr);
+#endif
+
+ KDBG(MACHDBG_CODE(DBG_MACH_IO, DBC_MACH_IO_MMIO_WRITE),
+ (eabs - sabs), VM_KERNEL_UNSLIDE_OR_PERM(vaddr), paddr, val);
+
+ (void)ml_set_interrupts_enabled(istate);
+ } else {
+ (void)ml_set_interrupts_enabled(istate);
+ }
+ }
+#endif /* x86_64 */
+}
+
+void
+ml_io_write8(uintptr_t vaddr, uint8_t val)
+{
+ ml_io_write(vaddr, val, 1);
+}
+
+void
+ml_io_write16(uintptr_t vaddr, uint16_t val)
+{
+ ml_io_write(vaddr, val, 2);
+}
+
+void
+ml_io_write32(uintptr_t vaddr, uint32_t val)
+{
+ ml_io_write(vaddr, val, 4);
+}
+
+void
+ml_io_write64(uintptr_t vaddr, uint64_t val)
+{
+ ml_io_write(vaddr, val, 8);