diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/Makefile.objs b/xnu-qemu-arm64-5.1.0/hw/arm/Makefile.objs
index 534a6a1..3cd9b77 100644
--- a/xnu-qemu-arm64-5.1.0/hw/arm/Makefile.objs
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/Makefile.objs
@@ -1,4 +1,4 @@
-obj-y += boot.o
+obj-y += boot.o xnu_fb_cfg.o xnu_trampoline_hook.o xnu_pagetable.o xnu_cpacr.o xnu_dtb.o xnu_file_mmio_dev.o xnu_mem.o xnu.o j273_macos11.o guest-services.o guest-socket.o guest-fds.o guest-file.o
 obj-$(CONFIG_PLATFORM_BUS) += sysbus-fdt.o
 obj-$(CONFIG_ARM_VIRT) += virt.o
 obj-$(CONFIG_ACPI) += virt-acpi-build.o
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/guest-fds.c b/xnu-qemu-arm64-5.1.0/hw/arm/guest-fds.c
new file mode 100644
index 0000000..f109443
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/guest-fds.c
@@ -0,0 +1,72 @@
+/*
+ * QEMU TCP Tunnelling
+ *
+ * Copyright (c) 2019 Lev Aronsky <aronsky@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdarg.h>
+
+#include "hw/arm/guest-services/fds.h"
+#include "cpu.h"
+
+int32_t guest_svcs_fds[MAX_FD_COUNT] = { [0 ... MAX_FD_COUNT-1] = -1 };
+
+int32_t qc_handle_close(CPUState *cpu, int32_t fd)
+{
+    VERIFY_FD(fd);
+
+    int retval = -1;
+
+    if ((retval = close(guest_svcs_fds[fd])) < 0) {
+        guest_svcs_errno = errno;
+    } else {
+        // TODO: should this be in the "else" clause, or performed regardless?
+        guest_svcs_fds[fd] = -1;
+    }
+
+    return retval;
+}
+
+int32_t qc_handle_fcntl_getfl(CPUState *cpu, int32_t fd)
+{
+    VERIFY_FD(fd);
+
+    int retval = -1;
+
+    if ((retval = fcntl(guest_svcs_fds[fd], F_GETFL)) < 0) {
+        guest_svcs_errno = errno;
+    }
+
+    return retval;
+}
+
+int32_t qc_handle_fcntl_setfl(CPUState *cpu, int32_t fd, int32_t flags)
+{
+    VERIFY_FD(fd);
+
+    int retval = -1;
+
+    if ((retval = fcntl(guest_svcs_fds[fd], F_SETFL, flags)) < 0) {
+        guest_svcs_errno = errno;
+    }
+
+    return retval;
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/guest-file.c b/xnu-qemu-arm64-5.1.0/hw/arm/guest-file.c
new file mode 100644
index 0000000..f9f4709
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/guest-file.c
@@ -0,0 +1,111 @@
+/*
+ * QEMU Host file guest access
+ *
+ * Copyright (c) 2020 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/arm/guest-services/file.h"
+#include "cpu.h"
+
+static int32_t file_fds[MAX_FILE_FDS] = { [0 ... MAX_FILE_FDS-1] = -1 };
+
+void qc_file_open(uint64_t index, const char *filename)
+{
+    if (index >= MAX_FILE_FDS) {
+        abort();
+    }
+    if (-1 != file_fds[index]) {
+        abort();
+    }
+    file_fds[index] = open(filename, O_RDWR);
+    if (-1 == file_fds[index]) {
+        abort();
+    }
+}
+
+int64_t qc_handle_write_file(CPUState *cpu, uint64_t buffer_guest_ptr,
+                             uint64_t length, uint64_t offset, uint64_t index)
+{
+    uint8_t buf[MAX_FILE_TRANSACTION_LEN];
+
+    if (index >= MAX_FILE_FDS) {
+        abort();
+    }
+    int fd = file_fds[index];
+    if (-1 == fd) {
+        abort();
+    }
+    if (offset != lseek(fd, offset, SEEK_SET)) {
+        abort();
+    }
+    if (length > MAX_FILE_TRANSACTION_LEN) {
+        abort();
+    }
+    cpu_memory_rw_debug(cpu, buffer_guest_ptr, &buf[0], length, 0);
+    if (length != write(fd, &buf[0], length)) {
+        abort();
+    }
+
+    return 0;
+}
+
+int64_t qc_handle_read_file(CPUState *cpu, uint64_t buffer_guest_ptr,
+                            uint64_t length, uint64_t offset, uint64_t index)
+{
+    uint8_t buf[MAX_FILE_TRANSACTION_LEN];
+    if (index >= MAX_FILE_FDS) {
+        abort();
+    }
+    int fd = file_fds[index];
+    if (-1 == fd) {
+        abort();
+    }
+    if (offset != lseek(fd, offset, SEEK_SET)) {
+        abort();
+    }
+    if (length > MAX_FILE_TRANSACTION_LEN) {
+        abort();
+    }
+    if (length != read(fd, &buf[0], length)) {
+        abort();
+    }
+    cpu_memory_rw_debug(cpu, buffer_guest_ptr, &buf[0], length, 1);
+
+    return 0;
+}
+
+int64_t qc_handle_size_file(uint64_t index)
+{
+    struct stat st;
+
+    if (index >= MAX_FILE_FDS) {
+        abort();
+    }
+    int fd = file_fds[index];
+    if (-1 == fd) {
+        abort();
+    }
+    if (-1 == fstat(fd, &st)) {
+        abort();
+    }
+
+    return st.st_size;
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/guest-services.c b/xnu-qemu-arm64-5.1.0/hw/arm/guest-services.c
new file mode 100644
index 0000000..fed1a7e
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/guest-services.c
@@ -0,0 +1,185 @@
+/*
+ * QEMU TCP Tunnelling
+ *
+ * Copyright (c) 2019 Lev Aronsky <aronsky@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "exec/address-spaces.h"
+#include "hw/misc/unimp.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/platform-bus.h"
+
+#include "hw/arm/j273_macos11.h"
+#include "hw/arm/guest-services/general.h"
+#include "hw/arm/xnu_trampoline_hook.h"
+
+int32_t guest_svcs_errno = 0;
+
+uint64_t qemu_call_status(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    // NOT USED FOR NOW
+    return 0;
+}
+
+void qemu_call(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+    CPUState *cpu = qemu_get_cpu(0);
+    qemu_call_t qcall;
+    uint64_t i = 0;
+
+    static uint8_t hooks_installed = false;
+
+    if (!value) {
+        // Special case: not a regular QEMU call. This is used by our
+        // kernel task port patch to notify of the readiness for the
+        // hook installation.
+
+        J273MachineState *nms = J273_MACHINE(qdev_get_machine());
+        KernelTrHookParams *hook = &nms->hook;
+
+        if (0 != hook->va) {
+            //install the hook here because we need the MMU to be already
+            //configured and all the memory mapped before installing the hook
+            xnu_hook_tr_copy_install(hook->va, hook->pa, hook->buf_va,
+                                     hook->buf_pa, hook->code, hook->code_size,
+                                     hook->buf_size, hook->scratch_reg);
+
+        }
+
+        if (!hooks_installed) {
+            for (i = 0; i < nms->hook_funcs_count; i++) {
+                xnu_hook_tr_copy_install(nms->hook_funcs[i].va,
+                                         nms->hook_funcs[i].pa,
+                                         nms->hook_funcs[i].buf_va,
+                                         nms->hook_funcs[i].buf_pa,
+                                         nms->hook_funcs[i].code,
+                                         nms->hook_funcs[i].code_size,
+                                         nms->hook_funcs[i].buf_size,
+                                         nms->hook_funcs[i].scratch_reg);
+            }
+            hooks_installed = true;
+        }
+
+        //emulate original opcode: str x19, [x20]
+        value = env->xregs[19];
+        cpu_memory_rw_debug(cpu, env->xregs[20], (uint8_t*) &value,
+                            sizeof(value), 1);
+        ////emulate original opcode: str x20, [x23]
+        //value = env->xregs[20];
+        //cpu_memory_rw_debug(cpu, env->xregs[23], (uint8_t*) &value,
+        //                    sizeof(value), 1);
+
+        return;
+    }
+
+    // Read the request
+    cpu_memory_rw_debug(cpu, value, (uint8_t*) &qcall, sizeof(qcall), 0);
+
+    switch (qcall.call_number) {
+        // File Descriptors
+        case QC_CLOSE:
+            qcall.retval = qc_handle_close(cpu, qcall.args.close.fd);
+            break;
+        case QC_FCNTL:
+            switch (qcall.args.fcntl.cmd) {
+                case F_GETFL:
+                    qcall.retval = qc_handle_fcntl_getfl(
+                        cpu, qcall.args.fcntl.fd);
+                    break;
+                case F_SETFL:
+                    qcall.retval = qc_handle_fcntl_setfl(
+                        cpu, qcall.args.fcntl.fd, qcall.args.fcntl.flags);
+                    break;
+                default:
+                    guest_svcs_errno = EINVAL;
+                    qcall.retval = -1;
+            }
+            break;
+
+        // Socket API
+        case QC_SOCKET:
+            qcall.retval = qc_handle_socket(cpu, qcall.args.socket.domain,
+                                            qcall.args.socket.type,
+                                            qcall.args.socket.protocol);
+            break;
+        case QC_ACCEPT:
+            qcall.retval = qc_handle_accept(cpu, qcall.args.accept.socket,
+                                            qcall.args.accept.addr,
+                                            qcall.args.accept.addrlen);
+            break;
+        case QC_BIND:
+            qcall.retval = qc_handle_bind(cpu, qcall.args.bind.socket,
+                                          qcall.args.bind.addr,
+                                          qcall.args.bind.addrlen);
+            break;
+        case QC_CONNECT:
+            qcall.retval = qc_handle_connect(cpu, qcall.args.connect.socket,
+                                             qcall.args.connect.addr,
+                                             qcall.args.connect.addrlen);
+            break;
+        case QC_LISTEN:
+            qcall.retval = qc_handle_listen(cpu, qcall.args.listen.socket,
+                                            qcall.args.listen.backlog);
+            break;
+        case QC_RECV:
+            qcall.retval = qc_handle_recv(cpu, qcall.args.recv.socket,
+                                          qcall.args.recv.buffer,
+                                          qcall.args.recv.length,
+                                          qcall.args.recv.flags);
+            break;
+        case QC_SEND:
+            qcall.retval = qc_handle_send(cpu, qcall.args.send.socket,
+                                          qcall.args.send.buffer,
+                                          qcall.args.send.length,
+                                          qcall.args.send.flags);
+            break;
+        case QC_WRITE_FILE:
+            qcall.retval = qc_handle_write_file(cpu,
+                                       qcall.args.write_file.buffer_guest_ptr,
+                                       qcall.args.write_file.length,
+                                       qcall.args.write_file.offset,
+                                       qcall.args.write_file.index);
+            break;
+        case QC_READ_FILE:
+            qcall.retval = qc_handle_read_file(cpu,
+                                       qcall.args.read_file.buffer_guest_ptr,
+                                       qcall.args.read_file.length,
+                                       qcall.args.read_file.offset,
+                                       qcall.args.read_file.index);
+            break;
+        case QC_SIZE_FILE:
+            qcall.retval = qc_handle_size_file(qcall.args.size_file.index);
+            break;
+        default:
+            // TODO: handle unknown call numbers
+            break;
+    }
+
+    qcall.error = guest_svcs_errno;
+
+    // Write the response
+    cpu_memory_rw_debug(cpu, value, (uint8_t*) &qcall, sizeof(qcall), 1);
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/guest-socket.c b/xnu-qemu-arm64-5.1.0/hw/arm/guest-socket.c
new file mode 100644
index 0000000..fdf9d1e
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/guest-socket.c
@@ -0,0 +1,192 @@
+/*
+ * QEMU TCP Tunnelling
+ *
+ * Copyright (c) 2019 Lev Aronsky <aronsky@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/arm/guest-services/socket.h"
+#include "hw/arm/guest-services/fds.h"
+#include "sys/socket.h"
+#include "cpu.h"
+
+#define SOCKET_TIMEOUT_USECS (10)
+
+static int32_t find_free_socket(void) {
+    for (int i = 0; i < MAX_FD_COUNT; ++i) {
+        if (-1 == guest_svcs_fds[i]) {
+            return i;
+        }
+    }
+
+    guest_svcs_errno = ENOMEM;
+    return -1;
+}
+
+int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type,
+                         int32_t protocol)
+{
+    int retval = find_free_socket();
+
+    if (retval < 0) {
+        guest_svcs_errno = ENOTSOCK;
+    } else if ((guest_svcs_fds[retval] = socket(domain, type, protocol)) < 0) {
+        retval = -1;
+        guest_svcs_errno = errno;
+    }
+
+    return retval;
+}
+
+int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr,
+                         socklen_t *g_addrlen)
+{
+    struct sockaddr_in addr;
+    socklen_t addrlen;
+
+    VERIFY_FD(sckt);
+
+    int retval = find_free_socket();
+
+    // TODO: timeout
+    if (retval < 0) {
+        guest_svcs_errno = ENOTSOCK;
+    } else if ((guest_svcs_fds[retval] = accept(guest_svcs_fds[sckt],
+                                         (struct sockaddr *) &addr,
+                                         &addrlen)) < 0) {
+        retval = -1;
+        guest_svcs_errno = errno;
+    } else {
+        cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr,
+                            sizeof(addr), 1);
+        cpu_memory_rw_debug(cpu, (target_ulong) g_addrlen,
+                            (uint8_t*) &addrlen, sizeof(addrlen), 1);
+    }
+
+    return retval;
+}
+
+int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr,
+                       socklen_t addrlen)
+{
+    struct sockaddr_in addr;
+
+    VERIFY_FD(sckt);
+
+    int retval = 0;
+
+    if (addrlen > sizeof(addr)) {
+        guest_svcs_errno = ENOMEM;
+    } else {
+        cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr,
+                            sizeof(addr), 0);
+
+        if ((retval = bind(guest_svcs_fds[sckt], (struct sockaddr *) &addr,
+                           addrlen)) < 0) {
+            guest_svcs_errno = errno;
+        } else {
+            cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr,
+                                sizeof(addr), 1);
+        }
+    }
+
+    return retval;
+}
+
+int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr,
+                          socklen_t addrlen)
+{
+    struct sockaddr_in addr;
+
+    VERIFY_FD(sckt);
+
+    int retval = 0;
+
+    if (addrlen > sizeof(addr)) {
+        guest_svcs_errno = ENOMEM;
+    } else {
+        cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr,
+                            sizeof(addr), 0);
+
+        if ((retval = connect(guest_svcs_fds[sckt], (struct sockaddr *) &addr,
+                            addrlen)) < 0) {
+            guest_svcs_errno = errno;
+        } else {
+            cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr,
+                                sizeof(addr), 1);
+        }
+    }
+
+    return retval;
+}
+
+int32_t qc_handle_listen(CPUState *cpu, int32_t sckt, int32_t backlog)
+{
+    VERIFY_FD(sckt);
+
+    int retval = 0;
+
+    if ((retval = listen(guest_svcs_fds[sckt], backlog)) < 0) {
+        guest_svcs_errno = errno;
+    }
+
+    return retval;
+}
+
+int32_t qc_handle_recv(CPUState *cpu, int32_t sckt, void *g_buffer,
+                       size_t length, int32_t flags)
+{
+    VERIFY_FD(sckt);
+    uint8_t buffer[MAX_BUF_SIZE];
+
+    int retval = -1;
+
+    // TODO: timeout
+    if (length > MAX_BUF_SIZE) {
+        guest_svcs_errno = ENOMEM;
+    } else if ((retval = recv(guest_svcs_fds[sckt], buffer, length, flags)) <= 0) {
+        guest_svcs_errno = errno;
+    } else {
+        cpu_memory_rw_debug(cpu, (target_ulong) g_buffer, buffer, retval, 1);
+    }
+
+    return retval;
+}
+
+int32_t qc_handle_send(CPUState *cpu, int32_t sckt, void *g_buffer,
+                       size_t length, int32_t flags)
+{
+    VERIFY_FD(sckt);
+    uint8_t buffer[MAX_BUF_SIZE];
+
+    int retval = -1;
+
+    if (length > MAX_BUF_SIZE) {
+        guest_svcs_errno = ENOMEM;
+    } else {
+        cpu_memory_rw_debug(cpu, (target_ulong) g_buffer, buffer, length, 0);
+
+        if ((retval = send(guest_svcs_fds[sckt], buffer, length, flags)) < 0) {
+            guest_svcs_errno = errno;
+        }
+    }
+
+    return retval;
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/j273_macos11.c b/xnu-qemu-arm64-5.1.0/hw/arm/j273_macos11.c
new file mode 100644
index 0000000..6cda40a
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/j273_macos11.c
@@ -0,0 +1,997 @@
+/*
+ * macOS 11 Big Sur - j273 - A12Z
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "exec/address-spaces.h"
+#include "hw/misc/unimp.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/reset.h"
+#include "qemu/error-report.h"
+#include "hw/platform-bus.h"
+
+#include "hw/arm/j273_macos11.h"
+
+#include "hw/arm/exynos4210.h"
+#include "hw/arm/guest-services/general.h"
+
+#define J273_SECURE_RAM_SIZE (0x100000)
+#define J273_PHYS_BASE (0x40000000)
+
+//compiled nop instruction: mov x0, x0
+#define NOP_INST (0xaa0003e0)
+#define RET_INST (0xd65f03c0) // *NEW*
+#define MOV_W0_01_INST (0x52800020)
+#define CMP_X9_x9_INST (0xeb09013f)
+//compiled  instruction: mov w7, #0
+#define W7_ZERO_INST (0x52800007)
+#define W10_ZERO_INST (0x5280000a)
+#define W23_ZERO_INST (0x52800017)
+#define ORR_X0_2_INST (0xb27f0000) // *NEW*
+
+//hook the kernel to execute our "driver" code in this function
+//after things are already running in the kernel but the root mount is not
+//yet mounted.
+//We chose this place in the beginning of ubc_init() inlined in bsd_init()
+//because enough things are up and running for our driver to properly setup,
+//This means that global IOKIT locks and dictionaries are already initialized
+//and in general, the IOKIT system is already initialized.
+//We are now able to initialize our driver and attach it to an existing
+//IOReg object.
+//On the other hand, no mounting of any FS happened yet so we have a chance
+//for our block device driver to present a new block device that will be
+//mounted on the root mount.
+//We need to choose the hook location carefully.
+//We need 3 instructions in a row that we overwrite that are not location
+//dependant (such as adr, adrp and branching) as we are going to execute
+//them elsewhere.
+//We also need a register to use as a scratch register that its value is
+//disregarded right after the hook and does not affect anything.
+#define UBC_INIT_VADDR_16B92 (0xfffffff0073dec10)
+
+#define J273_CPREG_FUNCS(name) \
+static uint64_t j273_cpreg_read_##name(CPUARMState *env, \
+                                      const ARMCPRegInfo *ri) \
+{ \
+    J273MachineState *nms = (J273MachineState *)ri->opaque; \
+    return nms->J273_CPREG_VAR_NAME(name); \
+} \
+static void j273_cpreg_write_##name(CPUARMState *env, const ARMCPRegInfo *ri, \
+                                   uint64_t value) \
+{ \
+    J273MachineState *nms = (J273MachineState *)ri->opaque; \
+    nms->J273_CPREG_VAR_NAME(name) = value; \
+}
+
+#define J273_CPREG_DEF(p_name, p_op0, p_op1, p_crn, p_crm, p_op2, p_access) \
+    { .cp = CP_REG_ARM64_SYSREG_CP, \
+      .name = #p_name, .opc0 = p_op0, .crn = p_crn, .crm = p_crm, \
+      .opc1 = p_op1, .opc2 = p_op2, .access = p_access, .type = ARM_CP_IO, \
+      .state = ARM_CP_STATE_AA64, .readfn = j273_cpreg_read_##p_name, \
+      .writefn = j273_cpreg_write_##p_name }
+
+#define ENABLE_EL2_REGS
+
+J273_CPREG_FUNCS(ARM64_REG_EHID1)
+J273_CPREG_FUNCS(ARM64_REG_EHID10)
+J273_CPREG_FUNCS(ARM64_REG_EHID4)
+J273_CPREG_FUNCS(ARM64_REG_HID11)
+J273_CPREG_FUNCS(ARM64_REG_HID3)
+J273_CPREG_FUNCS(ARM64_REG_HID5)
+J273_CPREG_FUNCS(ARM64_REG_HID4)
+J273_CPREG_FUNCS(ARM64_REG_HID8)
+J273_CPREG_FUNCS(ARM64_REG_HID7)
+J273_CPREG_FUNCS(ARM64_REG_LSU_ERR_STS)
+J273_CPREG_FUNCS(PMC0)
+J273_CPREG_FUNCS(PMC1)
+J273_CPREG_FUNCS(PMCR1)
+J273_CPREG_FUNCS(PMSR)
+J273_CPREG_FUNCS(L2ACTLR_EL1)
+#ifdef ENABLE_EL2_REGS
+J273_CPREG_FUNCS(ARM64_REG_MIGSTS_EL1);
+J273_CPREG_FUNCS(ARM64_REG_KERNELKEYLO_EL1);
+J273_CPREG_FUNCS(ARM64_REG_KERNELKEYHI_EL1);
+J273_CPREG_FUNCS(ARM64_REG_VMSA_LOCK_EL1);
+J273_CPREG_FUNCS(APRR_EL0);
+J273_CPREG_FUNCS(APRR_EL1);
+J273_CPREG_FUNCS(CTRR_LOCK);
+J273_CPREG_FUNCS(CTRR_A_LWR_EL1);
+J273_CPREG_FUNCS(CTRR_A_UPR_EL1);
+J273_CPREG_FUNCS(CTRR_CTL_EL1);
+J273_CPREG_FUNCS(APRR_MASK_EN_EL1);
+J273_CPREG_FUNCS(APRR_MASK_EL0);
+J273_CPREG_FUNCS(ACC_CTRR_A_LWR_EL2);
+J273_CPREG_FUNCS(ACC_CTRR_A_UPR_EL2);
+J273_CPREG_FUNCS(ACC_CTRR_CTL_EL2);
+J273_CPREG_FUNCS(ACC_CTRR_LOCK_EL2);
+J273_CPREG_FUNCS(ARM64_REG_CYC_CFG);
+J273_CPREG_FUNCS(ARM64_REG_CYC_OVRD);
+J273_CPREG_FUNCS(IPI_SR);
+J273_CPREG_FUNCS(UPMCR0);
+J273_CPREG_FUNCS(UPMPCM);
+#endif
+
+static const ARMCPRegInfo j273_cp_reginfo_kvm[] = {
+    // Apple-specific registers
+    J273_CPREG_DEF(ARM64_REG_EHID1, 3, 0, 15, 3, 1, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_EHID10, 3, 0, 15, 10, 1, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_EHID4, 3, 0, 15, 4, 1, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID11, 3, 0, 15, 13, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID3, 3, 0, 15, 3, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID4, 3, 0, 15, 4, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID5, 3, 0, 15, 5, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID7, 3, 0, 15, 7, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID8, 3, 0, 15, 8, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_LSU_ERR_STS, 3, 3, 15, 0, 0, PL1_RW),
+    J273_CPREG_DEF(PMC0, 3, 2, 15, 0, 0, PL1_RW),
+    J273_CPREG_DEF(PMC1, 3, 2, 15, 1, 0, PL1_RW),
+    J273_CPREG_DEF(PMCR1, 3, 1, 15, 1, 0, PL1_RW),
+    J273_CPREG_DEF(PMSR, 3, 1, 15, 13, 0, PL1_RW),
+    J273_CPREG_DEF(L2ACTLR_EL1, 3, 1, 15, 0, 0, PL1_RW),
+#ifdef ENABLE_EL2_REGS
+    J273_CPREG_DEF(ARM64_REG_MIGSTS_EL1, 3, 4, 15, 0, 4, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_KERNELKEYLO_EL1, 3, 4, 15, 1, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_KERNELKEYHI_EL1, 3, 4, 15, 1, 1, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_VMSA_LOCK_EL1, 3, 4, 15, 1, 2, PL1_RW),
+    J273_CPREG_DEF(APRR_EL0, 3, 4, 15, 2, 0, PL1_RW),
+    J273_CPREG_DEF(APRR_EL1, 3, 4, 15, 2, 1, PL1_RW),
+    J273_CPREG_DEF(CTRR_LOCK, 3, 4, 15, 2, 2, PL1_RW),
+    J273_CPREG_DEF(CTRR_A_LWR_EL1, 3, 4, 15, 2, 3, PL1_RW),
+    J273_CPREG_DEF(CTRR_A_UPR_EL1, 3, 4, 15, 2, 4, PL1_RW),
+    J273_CPREG_DEF(CTRR_CTL_EL1, 3, 4, 15, 2, 5, PL1_RW),
+    J273_CPREG_DEF(APRR_MASK_EN_EL1, 3, 4, 15, 2, 6, PL1_RW),
+    J273_CPREG_DEF(APRR_MASK_EL0, 3, 4, 15, 2, 7, PL1_RW),
+    J273_CPREG_DEF(ACC_CTRR_A_LWR_EL2, 3, 4, 15, 11, 0, PL1_RW),
+    J273_CPREG_DEF(ACC_CTRR_A_UPR_EL2, 3, 4, 15, 11, 1, PL1_RW),
+    J273_CPREG_DEF(ACC_CTRR_CTL_EL2, 3, 4, 15, 11, 4, PL1_RW),
+    J273_CPREG_DEF(ACC_CTRR_LOCK_EL2, 3, 4, 15, 11, 5, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_CYC_CFG, 3, 5, 15, 4, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_CYC_OVRD, 3, 5, 15, 5, 0, PL1_RW),
+    J273_CPREG_DEF(IPI_SR, 3, 5, 15, 1, 1, PL1_RW),
+    J273_CPREG_DEF(UPMCR0, 3, 7, 15, 0, 4, PL1_RW),
+    J273_CPREG_DEF(UPMPCM, 3, 7, 15, 5, 4, PL1_RW),
+#endif
+
+    // Aleph-specific registers for communicating with QEMU
+
+    // REG_QEMU_CALL:
+    { .cp = CP_REG_ARM64_SYSREG_CP, .name = "REG_QEMU_CALL",
+      .opc0 = 3, .opc1 = 3, .crn = 15, .crm = 15, .opc2 = 0,
+      .access = PL0_RW, .type = ARM_CP_IO, .state = ARM_CP_STATE_AA64,
+      .readfn = qemu_call_status,
+      .writefn = qemu_call },
+
+    REGINFO_SENTINEL,
+};
+
+// This is the same as the array for kvm, but without
+// the L2ACTLR_EL1, which is already defined in TCG.
+// Duplicating this list isn't a perfect solution,
+// but it's quick and reliable.
+static const ARMCPRegInfo j273_cp_reginfo_tcg[] = {
+    // Apple-specific registers
+    J273_CPREG_DEF(ARM64_REG_EHID1, 3, 0, 15, 3, 1, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_EHID10, 3, 0, 15, 10, 1, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_EHID4, 3, 0, 15, 4, 1, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID11, 3, 0, 15, 13, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID3, 3, 0, 15, 3, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID5, 3, 0, 15, 5, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID4, 3, 0, 15, 4, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID8, 3, 0, 15, 8, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_HID7, 3, 0, 15, 7, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_LSU_ERR_STS, 3, 3, 15, 0, 0, PL1_RW),
+    J273_CPREG_DEF(PMC0, 3, 2, 15, 0, 0, PL1_RW),
+    J273_CPREG_DEF(PMC1, 3, 2, 15, 1, 0, PL1_RW),
+    J273_CPREG_DEF(PMCR1, 3, 1, 15, 1, 0, PL1_RW),
+    J273_CPREG_DEF(PMSR, 3, 1, 15, 13, 0, PL1_RW),
+#ifdef ENABLE_EL2_REGS
+    J273_CPREG_DEF(ARM64_REG_MIGSTS_EL1, 3, 4, 15, 0, 4, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_KERNELKEYLO_EL1, 3, 4, 15, 1, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_KERNELKEYHI_EL1, 3, 4, 15, 1, 1, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_VMSA_LOCK_EL1, 3, 4, 15, 1, 2, PL1_RW),
+    J273_CPREG_DEF(APRR_EL0, 3, 4, 15, 2, 0, PL1_RW),
+    J273_CPREG_DEF(APRR_EL1, 3, 4, 15, 2, 1, PL1_RW),
+    J273_CPREG_DEF(CTRR_LOCK, 3, 4, 15, 2, 2, PL1_RW),
+    J273_CPREG_DEF(CTRR_A_LWR_EL1, 3, 4, 15, 2, 3, PL1_RW),
+    J273_CPREG_DEF(CTRR_A_UPR_EL1, 3, 4, 15, 2, 4, PL1_RW),
+    J273_CPREG_DEF(CTRR_CTL_EL1, 3, 4, 15, 2, 5, PL1_RW),
+    J273_CPREG_DEF(APRR_MASK_EN_EL1, 3, 4, 15, 2, 6, PL1_RW),
+    J273_CPREG_DEF(APRR_MASK_EL0, 3, 4, 15, 2, 7, PL1_RW),
+    J273_CPREG_DEF(ACC_CTRR_A_LWR_EL2, 3, 4, 15, 11, 0, PL1_RW),
+    J273_CPREG_DEF(ACC_CTRR_A_UPR_EL2, 3, 4, 15, 11, 1, PL1_RW),
+    J273_CPREG_DEF(ACC_CTRR_CTL_EL2, 3, 4, 15, 11, 4, PL1_RW),
+    J273_CPREG_DEF(ACC_CTRR_LOCK_EL2, 3, 4, 15, 11, 5, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_CYC_CFG, 3, 5, 15, 4, 0, PL1_RW),
+    J273_CPREG_DEF(ARM64_REG_CYC_OVRD, 3, 5, 15, 5, 0, PL1_RW),
+    J273_CPREG_DEF(IPI_SR, 3, 5, 15, 1, 1, PL1_RW),
+    J273_CPREG_DEF(UPMCR0, 3, 7, 15, 0, 4, PL1_RW),
+    J273_CPREG_DEF(UPMPCM, 3, 7, 15, 5, 4, PL1_RW),
+#endif
+
+    // Aleph-specific registers for communicating with QEMU
+
+    // REG_QEMU_CALL:
+    { .cp = CP_REG_ARM64_SYSREG_CP, .name = "REG_QEMU_CALL",
+      .opc0 = 3, .opc1 = 3, .crn = 15, .crm = 15, .opc2 = 0,
+      .access = PL0_RW, .type = ARM_CP_IO, .state = ARM_CP_STATE_AA64,
+      .readfn = qemu_call_status,
+      .writefn = qemu_call },
+
+    REGINFO_SENTINEL,
+};
+
+static uint32_t g_nop_inst = NOP_INST;
+static uint32_t g_ret_inst = RET_INST;
+static uint32_t g_mov_w0_01_inst = MOV_W0_01_INST;
+static uint32_t g_compare_true_inst = CMP_X9_x9_INST;
+static uint32_t g_w7_zero_inst = W7_ZERO_INST;
+static uint32_t g_w10_zero_inst = W10_ZERO_INST;
+static uint32_t g_w23_zero_inst = W23_ZERO_INST;
+static uint32_t g_orr_x0_2_inst = ORR_X0_2_INST;
+static uint32_t g_set_cpacr_and_branch_inst[] = {
+    //  91400c21       add x1, x1, 3, lsl 12    # x1 = x1 + 0x3000
+    //  d378dc21       lsl x1, x1, 8            # x1 = x1 * 0x100 (x1 = 0x300000)
+    //  d5181041       msr cpacr_el1, x1        # cpacr_el1 = x1 (enable FP)
+    //  d2800041       mov x1, #2
+    //  d51cf081       mov apctl_el1, x1
+    //  aa1f03e1       mov x1, xzr              # x1 = 0
+    //  14000eb5       b 0x1fc0                 # branch to regular start
+    0x91400c21, 0xd378dc21, 0xd5181041,
+    0xd2800041, 0xd51cf081, 0xaa1f03e1,
+    0x14000eb5
+};
+static uint32_t g_bzero_branch_unconditionally_inst = 0x14000039;
+static uint32_t g_qemu_call = 0xd51bff1f;
+
+typedef struct darwin_patch {
+    uint64_t addr;
+    uint32_t *inst;
+    uint32_t len;
+} darwin_patch;
+
+typedef struct darwin_kernel_patch {
+    const char *darwin_str;
+    uint32_t num_patches;
+    struct darwin_patch patches[];
+} darwin_kernel_patch;
+
+// Patch is a single instruction
+#define DARWIN_PATCH(offset, instruction) \
+{ .addr = offset, .inst = &instruction, .len = sizeof(instruction) }
+
+// Patch is an array of instructions
+#define DARWIN_PATCH_A(offset, instruction) \
+{ .addr = offset, .inst = instruction, .len = sizeof(instruction) }
+
+struct darwin_kernel_patch darwin_patches_20A5364e = {
+    .darwin_str =
+        "Darwin Kernel Version 20.0.0: Sun Jun 14 21:36:36 PDT 2020; "
+        "root:Bridge_xnu-7090.111.5.2~1/RELEASE_ARM64_T8020",
+    .num_patches = 6, .patches = {
+        DARWIN_PATCH_A(0xfffffe00079f0580, g_set_cpacr_and_branch_inst), // initial branch
+        DARWIN_PATCH(0xfffffe00079e49fc, g_bzero_branch_unconditionally_inst), // bzero conditional branch
+        DARWIN_PATCH(0xfffffe0007f8330c, g_w23_zero_inst), // parse_machfile slide set instruction
+        DARWIN_PATCH(0xfffffe0007a5b47c, g_qemu_call), // notify kernel task pointer
+        DARWIN_PATCH(0xfffffe0008af5e3c, g_mov_w0_01_inst), // core trust check
+        DARWIN_PATCH(0xfffffe0007f83108, g_nop_inst), // load_machfile: disable IMGPF_NOJOP
+    }
+};
+
+struct darwin_kernel_patch darwin_patches_20B5012d = {
+    .darwin_str =
+        "Darwin Kernel Version 20.1.0: Sat Oct 24 21:20:41 PDT 2020; "
+        "root:xnu-7195.50.3.201.1~1/RELEASE_ARM64_T8020",
+    .num_patches = 6, .patches = {
+        DARWIN_PATCH_A(0xfffffe0007ab0580, g_set_cpacr_and_branch_inst), // initial branch
+        DARWIN_PATCH(0xfffffe0007aa49fc, g_bzero_branch_unconditionally_inst), // bzero conditional branch
+        DARWIN_PATCH(0xfffffe0008056168, g_w10_zero_inst), // parse_machfile slide set instruction
+        DARWIN_PATCH(0xfffffe0007b1f4d8, g_qemu_call), // notify kernel task pointer
+        DARWIN_PATCH(0xfffffe0008c96538, g_mov_w0_01_inst), // core trust check
+        DARWIN_PATCH(0xfffffe0008055f64, g_nop_inst), // load_machfile: disable IMGPF_NOJOP
+    }
+};
+
+struct darwin_kernel_patch darwin_patches_20C69 = {
+    .darwin_str =
+        "Darwin Kernel Version 20.2.0: Wed Dec  2 20:40:22 PST 2020; "
+        "root:xnu-7195.60.75~1/RELEASE_ARM64_T8020",
+    .num_patches = 5, .patches = {
+        DARWIN_PATCH_A(0xfffffe0007ac4580, g_set_cpacr_and_branch_inst), // initial branch
+        DARWIN_PATCH(0xfffffe0007ab8a3c, g_bzero_branch_unconditionally_inst), // bzero conditional branch
+        DARWIN_PATCH(0xfffffe000806b438, g_w10_zero_inst), // parse_machfile slide set instruction
+        DARWIN_PATCH(0xfffffe0008cb6538, g_mov_w0_01_inst), // core trust check
+        DARWIN_PATCH(0xfffffe000806b234, g_nop_inst), // load_machfile: disable IMGPF_NOJOP
+    }
+};
+
+struct darwin_kernel_patch *darwin_patches[] = {
+    &darwin_patches_20A5364e,
+    &darwin_patches_20B5012d,
+    &darwin_patches_20C69,
+};
+
+static void j273_add_cpregs(J273MachineState *nms)
+{
+    ARMCPU *cpu = nms->cpu;
+
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_EHID1) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_EHID10) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_EHID4) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_HID11) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_HID3) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_HID5) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_HID8) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_HID7) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_LSU_ERR_STS) = 0;
+    nms->J273_CPREG_VAR_NAME(PMC0) = 0;
+    nms->J273_CPREG_VAR_NAME(PMC1) = 0;
+    nms->J273_CPREG_VAR_NAME(PMCR1) = 0;
+    nms->J273_CPREG_VAR_NAME(PMSR) = 0;
+    nms->J273_CPREG_VAR_NAME(L2ACTLR_EL1) = 0;
+#ifdef ENABLE_EL2_REGS
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_MIGSTS_EL1) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_KERNELKEYLO_EL1) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_KERNELKEYHI_EL1) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_VMSA_LOCK_EL1) = 0;
+    nms->J273_CPREG_VAR_NAME(APRR_EL0) = 0;
+    nms->J273_CPREG_VAR_NAME(APRR_EL1) = 0;
+    nms->J273_CPREG_VAR_NAME(CTRR_LOCK) = 0;
+    nms->J273_CPREG_VAR_NAME(CTRR_A_LWR_EL1) = 0;
+    nms->J273_CPREG_VAR_NAME(CTRR_A_UPR_EL1) = 0;
+    nms->J273_CPREG_VAR_NAME(CTRR_CTL_EL1) = 0;
+    nms->J273_CPREG_VAR_NAME(APRR_MASK_EN_EL1) = 0;
+    nms->J273_CPREG_VAR_NAME(APRR_MASK_EL0) = 0;
+    nms->J273_CPREG_VAR_NAME(ACC_CTRR_A_LWR_EL2) = 0;
+    nms->J273_CPREG_VAR_NAME(ACC_CTRR_A_UPR_EL2) = 0;
+    nms->J273_CPREG_VAR_NAME(ACC_CTRR_CTL_EL2) = 0;
+    nms->J273_CPREG_VAR_NAME(ACC_CTRR_LOCK_EL2) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_CYC_CFG) = 0;
+    nms->J273_CPREG_VAR_NAME(ARM64_REG_CYC_OVRD) = 0;
+    nms->J273_CPREG_VAR_NAME(UPMCR0) = 0;
+    nms->J273_CPREG_VAR_NAME(UPMPCM) = 0;
+#endif
+
+    if (kvm_enabled()) {
+        define_arm_cp_regs_with_opaque(cpu, j273_cp_reginfo_kvm, nms);
+    } else {
+        define_arm_cp_regs_with_opaque(cpu, j273_cp_reginfo_tcg, nms);
+    }
+}
+
+static void j273_create_s3c_uart(const J273MachineState *nms, Chardev *chr)
+{
+    qemu_irq irq;
+    DeviceState *d;
+    SysBusDevice *s;
+    hwaddr base = nms->uart_mmio_pa;
+
+    //hack for now. create a device that is not used just to have a dummy
+    //unused interrupt
+    d = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
+    s = SYS_BUS_DEVICE(d);
+    sysbus_init_irq(s, &irq);
+    //pass a dummy irq as we don't need nor want interrupts for this UART
+    DeviceState *dev = exynos4210_uart_create(base, 256, 0, chr, irq);
+    if (!dev) {
+        abort();
+    }
+}
+
+static void j273_patch_kernel(AddressSpace *nsas, char *darwin_ver)
+{
+    bool found = false;
+    darwin_patch *patch;
+    darwin_kernel_patch *kernel_patch;
+    for (int i = 0; i < sizeof(darwin_patches) / sizeof(uint64_t); i++) {
+        kernel_patch = darwin_patches[i];
+        if (!strncmp(darwin_ver, kernel_patch->darwin_str, 1024)) {
+            for (int a = 0; a < kernel_patch->num_patches; a++) {
+                patch = &kernel_patch->patches[a];
+                address_space_rw(nsas, vtop_static(patch->addr),
+                        MEMTXATTRS_UNSPECIFIED, (uint8_t *)patch->inst,
+                        patch->len, 1);
+            }
+            found = true;
+        }
+    }
+    if (found == false) {
+        printf("No support for %s\n", darwin_ver);
+        abort();
+    }
+}
+
+static void j273_ns_memory_setup(MachineState *machine, MemoryRegion *sysmem,
+                                AddressSpace *nsas)
+{
+    uint64_t used_ram_for_blobs = 0;
+    hwaddr kernel_low;
+    hwaddr kernel_high;
+    hwaddr virt_base;
+    hwaddr dtb_va;
+    uint64_t dtb_size;
+    hwaddr kbootargs_pa;
+    hwaddr top_of_kernel_data_pa;
+    hwaddr mem_size;
+    hwaddr remaining_mem_size;
+    hwaddr allocated_ram_pa;
+    hwaddr phys_ptr;
+    hwaddr phys_pc;
+    hwaddr ramfb_pa = 0;
+    video_boot_args v_bootargs = {0};
+    J273MachineState *nms = J273_MACHINE(machine);
+    char darwin_ver[1024];
+
+    //setup the memory layout:
+
+    //At the beginning of the non-secure ram we have the raw kernel file.
+    //After that we have the static trust cache.
+    //After that we have all the kernel sections.
+    //After that we have ramdosk
+    //After that we have the device tree
+    //After that we have the kernel boot args
+    //After that we have the rest of the RAM
+
+    macho_file_highest_lowest_base(nms->kernel_filename, J273_PHYS_BASE,
+                                   &virt_base, &kernel_low, &kernel_high);
+
+    g_virt_base = virt_base;
+    g_phys_base = J273_PHYS_BASE;
+    phys_ptr = J273_PHYS_BASE;
+
+    //now account for the loaded kernel
+    arm_load_macho(nms->kernel_filename, nsas, sysmem, "kernel.j273",
+                    J273_PHYS_BASE, virt_base, kernel_low,
+                    kernel_high, &phys_pc, darwin_ver);
+    nms->kpc_pa = phys_pc;
+    used_ram_for_blobs += (align_64k_high(kernel_high) - kernel_low);
+
+    j273_patch_kernel(nsas, darwin_ver);
+
+    phys_ptr = align_64k_high(vtop_static(kernel_high));
+
+    //now account for the ramdisk
+    nms->ramdisk_file_dev.pa = 0;
+    hwaddr ramdisk_size = 0;
+    if (0 != nms->ramdisk_filename[0]) {
+        nms->ramdisk_file_dev.pa = phys_ptr;
+        macho_map_raw_file(nms->ramdisk_filename, nsas, sysmem,
+                           "ramdisk_raw_file.j273", nms->ramdisk_file_dev.pa,
+                           &nms->ramdisk_file_dev.size);
+        ramdisk_size = nms->ramdisk_file_dev.size;
+        phys_ptr += align_64k_high(nms->ramdisk_file_dev.size);
+    }
+
+    //now account for device tree
+    macho_load_dtb(nms->dtb_filename, nsas, sysmem, "dtb.j273", phys_ptr,
+                   &dtb_size, nms->ramdisk_file_dev.pa,
+                   ramdisk_size, &nms->uart_mmio_pa);
+    dtb_va = ptov_static(phys_ptr);
+    phys_ptr += align_64k_high(dtb_size);
+    used_ram_for_blobs += align_64k_high(dtb_size);
+
+    //now account for kernel boot args
+    used_ram_for_blobs += align_64k_high(sizeof(struct xnu_arm64_boot_args));
+    kbootargs_pa = phys_ptr;
+    nms->kbootargs_pa = kbootargs_pa;
+    phys_ptr += align_64k_high(sizeof(struct xnu_arm64_boot_args));
+    nms->extra_data_pa = phys_ptr;
+    allocated_ram_pa = phys_ptr;
+
+    if (nms->use_ramfb){
+        ramfb_pa = ((hwaddr)&((AllocatedData *)nms->extra_data_pa)->ramfb[0]);
+        xnu_define_ramfb_device(nsas,ramfb_pa);
+        xnu_get_video_bootargs(&v_bootargs, ramfb_pa);
+    }
+
+    phys_ptr += align_64k_high(sizeof(AllocatedData));
+    top_of_kernel_data_pa = phys_ptr;
+    remaining_mem_size = machine->ram_size - used_ram_for_blobs;
+    mem_size = allocated_ram_pa - J273_PHYS_BASE + remaining_mem_size;
+    macho_setup_bootargs("k_bootargs.j273", nsas, sysmem, kbootargs_pa,
+                         virt_base, J273_PHYS_BASE, mem_size,
+                         top_of_kernel_data_pa, dtb_va, dtb_size,
+                         v_bootargs, nms->kern_args);
+
+    allocate_ram(sysmem, "j273.ram", allocated_ram_pa, remaining_mem_size);
+}
+
+static void j273_memory_setup(MachineState *machine,
+                             MemoryRegion *sysmem,
+                             MemoryRegion *secure_sysmem,
+                             AddressSpace *nsas)
+{
+    j273_ns_memory_setup(machine, sysmem, nsas);
+}
+
+static void j273_cpu_setup(MachineState *machine, MemoryRegion **sysmem,
+                          MemoryRegion **secure_sysmem, ARMCPU **cpu,
+                          AddressSpace **nsas)
+{
+    Object *cpuobj = object_new(machine->cpu_type);
+    *cpu = ARM_CPU(cpuobj);
+    CPUState *cs = CPU(*cpu);
+
+    *sysmem = get_system_memory();
+
+    object_property_set_link(cpuobj, "memory",
+                             OBJECT(*sysmem), &error_abort);
+
+    //set secure monitor to false
+    object_property_set_bool(cpuobj, "has_el3", false, NULL);
+
+    object_property_set_bool(cpuobj, "has_el2", false, NULL);
+
+    object_property_set_bool(cpuobj, "realized", true, &error_fatal);
+
+    *nsas = cpu_get_address_space(cs, ARMASIdx_NS);
+
+    object_unref(cpuobj);
+    //currently support only a single CPU and thus
+    //use no interrupt controller and wire IRQs from devices directly to the CPU
+}
+
+static void j273_bootargs_setup(MachineState *machine)
+{
+    J273MachineState *nms = J273_MACHINE(machine);
+    nms->bootinfo.firmware_loaded = true;
+}
+
+static void j273_cpu_reset(void *opaque)
+{
+    J273MachineState *nms = J273_MACHINE((MachineState *)opaque);
+    ARMCPU *cpu = nms->cpu;
+    CPUState *cs = CPU(cpu);
+    CPUARMState *env = &cpu->env;
+
+    cpu_reset(cs);
+
+    env->xregs[0] = nms->kbootargs_pa;
+    env->pc = nms->kpc_pa;
+}
+
+//hooks arg is expected like this:
+//"hookfilepath@va@scratch_reg#hookfilepath@va@scratch_reg#..."
+
+static void j273_machine_init_hook_funcs(J273MachineState *nms,
+                                        AddressSpace *nsas)
+{
+    AllocatedData *allocated_data = (AllocatedData *)nms->extra_data_pa;
+    uint64_t i = 0;
+    char *orig_pos = NULL;
+    size_t orig_len = 0;
+    char *pos = NULL;
+    char *next_pos = NULL;
+    size_t len = 0;
+    char *elem = NULL;
+    char *next_elem = NULL;
+    size_t elem_len = 0;
+    char *end;
+
+    //ugly solution but a simple one for now, use this memory which is fixed at
+    //(pa: 0x0000000049BF4C00 va: 0xFFFFFFF009BF4C00) for globals to be common
+    //between drivers/hooks. Please adjust address if anything changes in
+    //the layout of the memory the "boot loader" sets up
+    uint64_t zero_var = 0;
+    address_space_rw(nsas, (hwaddr)&allocated_data->hook_globals[0],
+                     MEMTXATTRS_UNSPECIFIED, (uint8_t *)&zero_var,
+                     sizeof(zero_var), 1);
+
+    nms->hook_funcs_count = 0;
+
+    pos = &nms->hook_funcs_cfg[0];
+    if ((NULL == pos) || (0 == strlen(pos))) {
+        //fprintf(stderr, "no function hooks configured\n");
+        return;
+    }
+
+    orig_pos = pos;
+    orig_len = strlen(pos);
+
+    do {
+        next_pos = memchr(pos, '#', strlen(pos));
+        if (NULL != next_pos) {
+            len = next_pos - pos;
+        } else {
+            len = strlen(pos);
+        }
+
+        elem = pos;
+        next_elem = memchr(elem, '@', len);
+        if (NULL == next_elem) {
+            fprintf(stderr, "hook[%lu] failed to find '@' in %s\n", i, elem);
+            abort();
+        }
+        elem_len = next_elem - elem;
+        elem[elem_len] = 0;
+
+        uint8_t *code = NULL;
+        size_t size = 0;
+        if (!g_file_get_contents(elem, (char **)&code, &size, NULL)) {
+            fprintf(stderr, "hook[%lu] failed to read filepath: %s\n",
+                    i, elem);
+            abort();
+        }
+
+        elem += elem_len + 1;
+        next_elem = memchr(elem, '@', len);
+        if (NULL == next_elem) {
+            fprintf(stderr, "hook[%lu] failed to find '@' in %s\n", i, elem);
+            abort();
+        }
+        elem_len = next_elem - elem;
+        elem[elem_len] = 0;
+
+        nms->hook_funcs[i].va = strtoull(elem, &end, 16);
+        nms->hook_funcs[i].pa = vtop_static(nms->hook_funcs[i].va);
+        nms->hook_funcs[i].buf_va =
+                   ptov_static((hwaddr)&allocated_data->hook_funcs_code[i][0]);
+        nms->hook_funcs[i].buf_pa =
+                                (hwaddr)&allocated_data->hook_funcs_code[i][0];
+        nms->hook_funcs[i].buf_size = HOOK_CODE_ALLOC_SIZE;
+        nms->hook_funcs[i].code = (uint8_t *)code;
+        nms->hook_funcs[i].code_size = size;
+
+        elem += elem_len + 1;
+        if (NULL != next_pos) {
+            elem_len = next_pos - elem;
+        } else {
+            elem_len = strlen(elem);
+        }
+        elem[elem_len] = 0;
+
+        nms->hook_funcs[i].scratch_reg = (uint8_t)strtoul(elem, &end, 10);
+
+        i++;
+        pos += len + 1;
+    } while ((NULL != pos) && (pos < (orig_pos + orig_len)));
+
+    nms->hook_funcs_count = i;
+}
+
+static void j273_machine_init(MachineState *machine)
+{
+    J273MachineState *nms = J273_MACHINE(machine);
+    MemoryRegion *sysmem;
+    MemoryRegion *secure_sysmem;
+    AddressSpace *nsas;
+    ARMCPU *cpu;
+    CPUState *cs;
+    DeviceState *cpudev;
+
+    j273_cpu_setup(machine, &sysmem, &secure_sysmem, &cpu, &nsas);
+
+    nms->cpu = cpu;
+
+    j273_memory_setup(machine, sysmem, secure_sysmem, nsas);
+
+    cpudev = DEVICE(cpu);
+    cs = CPU(cpu);
+    AllocatedData *allocated_data = (AllocatedData *)nms->extra_data_pa;
+
+    if (0 != nms->driver_filename[0]) {
+        xnu_hook_tr_setup(nsas, cpu);
+        uint8_t *code = NULL;
+        unsigned long size;
+        if (!g_file_get_contents(nms->driver_filename, (char **)&code,
+                                 &size, NULL)) {
+            abort();
+        }
+        nms->hook.va = UBC_INIT_VADDR_16B92;
+        nms->hook.pa = vtop_static(UBC_INIT_VADDR_16B92);
+        nms->hook.buf_va =
+                        ptov_static((hwaddr)&allocated_data->hook_code[0]);
+        nms->hook.buf_pa = (hwaddr)&allocated_data->hook_code[0];
+        nms->hook.buf_size = HOOK_CODE_ALLOC_SIZE;
+        nms->hook.code = (uint8_t *)code;
+        nms->hook.code_size = size;
+        nms->hook.scratch_reg = 2;
+    }
+
+    if (0 != nms->qc_file_0_filename[0]) {
+        qc_file_open(0, &nms->qc_file_0_filename[0]);
+    }
+
+    if (0 != nms->qc_file_1_filename[0]) {
+        qc_file_open(1, &nms->qc_file_1_filename[0]);
+    }
+
+    if (0 != nms->qc_file_log_filename[0]) {
+        qc_file_open(2, &nms->qc_file_log_filename[0]);
+    }
+
+    j273_machine_init_hook_funcs(nms, nsas);
+
+    j273_add_cpregs(nms);
+
+    j273_create_s3c_uart(nms, serial_hd(0));
+
+    //wire timer to FIQ as expected by Apple's SoCs
+    qdev_connect_gpio_out(cpudev, GTIMER_VIRT,
+                          qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+
+    j273_bootargs_setup(machine);
+
+    qemu_register_reset(j273_cpu_reset, nms);
+}
+
+static void j273_set_ramdisk_filename(Object *obj, const char *value,
+                                     Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+
+    g_strlcpy(nms->ramdisk_filename, value, sizeof(nms->ramdisk_filename));
+}
+
+static char *j273_get_ramdisk_filename(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    return g_strdup(nms->ramdisk_filename);
+}
+
+static void j273_set_kernel_filename(Object *obj, const char *value,
+                                     Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+
+    g_strlcpy(nms->kernel_filename, value, sizeof(nms->kernel_filename));
+}
+
+static char *j273_get_kernel_filename(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    return g_strdup(nms->kernel_filename);
+}
+
+static void j273_set_dtb_filename(Object *obj, const char *value,
+                                     Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+
+    g_strlcpy(nms->dtb_filename, value, sizeof(nms->dtb_filename));
+}
+
+static char *j273_get_dtb_filename(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    return g_strdup(nms->dtb_filename);
+}
+
+static void j273_set_kern_args(Object *obj, const char *value,
+                                     Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+
+    g_strlcpy(nms->kern_args, value, sizeof(nms->kern_args));
+}
+
+static char *j273_get_kern_args(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    return g_strdup(nms->kern_args);
+}
+
+static void j273_set_tunnel_port(Object *obj, const char *value,
+                                     Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    nms->tunnel_port = atoi(value);
+}
+
+static char *j273_get_tunnel_port(Object *obj, Error **errp)
+{
+    char buf[128];
+    J273MachineState *nms = J273_MACHINE(obj);
+    snprintf(buf, 128, "%d", nms->tunnel_port);
+    return g_strdup(buf);
+}
+
+static void j273_set_hook_funcs(Object *obj, const char *value, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+
+    g_strlcpy(nms->hook_funcs_cfg, value, sizeof(nms->hook_funcs_cfg));
+}
+
+static char *j273_get_hook_funcs(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    return g_strdup(nms->hook_funcs_cfg);
+}
+
+static void j273_set_driver_filename(Object *obj, const char *value,
+                                    Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+
+    g_strlcpy(nms->driver_filename, value, sizeof(nms->driver_filename));
+}
+
+static char *j273_get_driver_filename(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    return g_strdup(nms->driver_filename);
+}
+
+static void j273_set_qc_file_0_filename(Object *obj, const char *value,
+                                       Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+
+    g_strlcpy(nms->qc_file_0_filename, value, sizeof(nms->qc_file_0_filename));
+}
+
+static char *j273_get_qc_file_0_filename(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    return g_strdup(nms->qc_file_0_filename);
+}
+
+static void j273_set_qc_file_1_filename(Object *obj, const char *value,
+                                       Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+
+    g_strlcpy(nms->qc_file_1_filename, value, sizeof(nms->qc_file_1_filename));
+}
+
+static char *j273_get_qc_file_1_filename(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    return g_strdup(nms->qc_file_1_filename);
+}
+
+static void j273_set_qc_file_log_filename(Object *obj, const char *value,
+                                       Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+
+    g_strlcpy(nms->qc_file_log_filename, value,
+              sizeof(nms->qc_file_log_filename));
+}
+
+static char *j273_get_qc_file_log_filename(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    return g_strdup(nms->qc_file_log_filename);
+}
+
+static void j273_set_xnu_ramfb(Object *obj, const char *value,
+                                       Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    if (strcmp(value,"on") == 0)
+        nms->use_ramfb = true;
+    else {
+        if (strcmp(value,"off") != 0)
+            fprintf(stderr,"NOTE: the value of xnu-ramfb is not valid,\
+the framebuffer will be disabled.\n");
+        nms->use_ramfb = false;
+    }
+}
+
+static char* j273_get_xnu_ramfb(Object *obj, Error **errp)
+{
+    J273MachineState *nms = J273_MACHINE(obj);
+    if (nms->use_ramfb)
+        return g_strdup("on");
+    else
+        return g_strdup("off");
+}
+
+static void j273_instance_init(Object *obj)
+{
+    object_property_add_str(obj, "ramdisk-filename", j273_get_ramdisk_filename,
+                            j273_set_ramdisk_filename);
+    object_property_set_description(obj, "ramdisk-filename",
+                                    "Set the ramdisk filename to be loaded");
+
+    object_property_add_str(obj, "kernel-filename", j273_get_kernel_filename,
+                            j273_set_kernel_filename);
+    object_property_set_description(obj, "kernel-filename",
+                                    "Set the kernel filename to be loaded");
+
+    object_property_add_str(obj, "dtb-filename", j273_get_dtb_filename,
+                            j273_set_dtb_filename);
+    object_property_set_description(obj, "dtb-filename",
+                                    "Set the dev tree filename to be loaded");
+
+    object_property_add_str(obj, "kern-cmd-args", j273_get_kern_args,
+                            j273_set_kern_args);
+    object_property_set_description(obj, "kern-cmd-args",
+                                    "Set the XNU kernel cmd args");
+
+    object_property_add_str(obj, "tunnel-port", j273_get_tunnel_port,
+                            j273_set_tunnel_port);
+    object_property_set_description(obj, "tunnel-port",
+                                    "Set the port for the tunnel connection");
+
+    object_property_add_str(obj, "hook-funcs", j273_get_hook_funcs,
+                            j273_set_hook_funcs);
+    object_property_set_description(obj, "hook-funcs",
+                                    "Set the hook funcs to be loaded");
+
+    object_property_add_str(obj, "driver-filename", j273_get_driver_filename,
+                            j273_set_driver_filename);
+    object_property_set_description(obj, "driver-filename",
+                                    "Set the driver filename to be loaded");
+
+    object_property_add_str(obj, "qc-file-0-filename",
+                            j273_get_qc_file_0_filename,
+                            j273_set_qc_file_0_filename);
+    object_property_set_description(obj, "qc-file-0-filename",
+                                    "Set the qc file 0 filename to be loaded");
+
+    object_property_add_str(obj, "qc-file-1-filename",
+                            j273_get_qc_file_1_filename,
+                            j273_set_qc_file_1_filename);
+    object_property_set_description(obj, "qc-file-1-filename",
+                                    "Set the qc file 1 filename to be loaded");
+
+    object_property_add_str(obj, "qc-file-log-filename",
+                            j273_get_qc_file_log_filename,
+                            j273_set_qc_file_log_filename);
+    object_property_set_description(obj, "qc-file-log-filename",
+                                   "Set the qc file log filename to be loaded");
+
+    object_property_add_str(obj, "xnu-ramfb",
+                            j273_get_xnu_ramfb,
+                            j273_set_xnu_ramfb);
+    object_property_set_description(obj, "xnu-ramfb",
+                                    "Turn on the display framebuffer");
+
+}
+
+static void j273_machine_class_init(ObjectClass *klass, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(klass);
+    mc->desc = "macOS Big Sur Beta 6 (j273 - A12Z)";
+    mc->init = j273_machine_init;
+    mc->max_cpus = 1;
+    //this disables the error message "Failed to query for block devices!"
+    //when starting qemu - must keep at least one device
+    //mc->no_sdcard = 1;
+    mc->no_floppy = 1;
+    mc->no_cdrom = 1;
+    mc->no_parallel = 1;
+    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");
+    mc->minimum_page_bits = 12;
+}
+
+static const TypeInfo j273_machine_info = {
+    .name          = TYPE_J273_MACHINE,
+    .parent        = TYPE_MACHINE,
+    .instance_size = sizeof(J273MachineState),
+    .class_size    = sizeof(J273MachineClass),
+    .class_init    = j273_machine_class_init,
+    .instance_init = j273_instance_init,
+};
+
+static void j273_machine_types(void)
+{
+    type_register_static(&j273_machine_info);
+}
+
+type_init(j273_machine_types)
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/xnu.c b/xnu-qemu-arm64-5.1.0/hw/arm/xnu.c
new file mode 100644
index 0000000..70ffeaf
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/xnu.c
@@ -0,0 +1,343 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/arm/xnu.h"
+#include "hw/loader.h"
+
+static void allocate_and_copy(MemoryRegion *mem, AddressSpace *as,
+                              const char *name, hwaddr pa, hwaddr size,
+                              void *buf)
+{
+    if (mem) {
+        allocate_ram(mem, name, pa, align_64k_high(size));
+    }
+    address_space_rw(as, pa, MEMTXATTRS_UNSPECIFIED, (uint8_t *)buf, size, 1);
+}
+
+void macho_load_dtb(char *filename, AddressSpace *as, MemoryRegion *mem,
+                    const char *name, hwaddr dtb_pa, uint64_t *size,
+                    hwaddr ramdisk_addr, hwaddr ramdisk_size,
+                    hwaddr *uart_mmio_pa)
+{
+    uint8_t *file_data = NULL;
+    unsigned long fsize;
+
+    if (g_file_get_contents(filename, (char **)&file_data, &fsize, NULL)) {
+        DTBNode *root = load_dtb(file_data);
+
+        //first fetch the uart mmio address
+        DTBNode *child = get_dtb_child_node_by_name(root, "arm-io");
+        if (NULL == child) {
+            abort();
+        }
+        DTBProp *prop = get_dtb_prop(child, "ranges");
+        if (NULL == prop) {
+            abort();
+        }
+        hwaddr *ranges = (hwaddr *)prop->value;
+        hwaddr soc_base_pa = ranges[1];
+        child = get_dtb_child_node_by_name(child, "uart0");
+        if (NULL == child) {
+            abort();
+        }
+        //make sure this node has the boot-console prop
+        prop = get_dtb_prop(child, "boot-console");
+        if (NULL == prop) {
+            abort();
+        }
+        prop = get_dtb_prop(child, "reg");
+        if (NULL == prop) {
+            abort();
+        }
+        hwaddr *uart_offset = (hwaddr *)prop->value;
+        if (NULL != uart_mmio_pa) {
+            *uart_mmio_pa = soc_base_pa + uart_offset[0];
+        }
+
+        child = get_dtb_child_node_by_name(root, "chosen");
+        child = get_dtb_child_node_by_name(child, "memory-map");
+        if (NULL == child) {
+            abort();
+        }
+
+        uint64_t memmap[2] = {0};
+
+        if ((0 != ramdisk_addr) && (0 != ramdisk_size)) {
+            memmap[0] = ramdisk_addr;
+            memmap[1] = ramdisk_size;
+            add_dtb_prop(child, "RAMDisk", sizeof(memmap),
+                    (uint8_t *)&memmap[0]);
+        }
+
+        uint64_t size_n = get_dtb_node_buffer_size(root);
+
+        uint8_t *buf = g_malloc0(size_n);
+        save_dtb(buf, root);
+
+        allocate_and_copy(mem, as, name, dtb_pa, size_n, buf);
+        g_free(file_data);
+        delete_dtb_node(root);
+        g_free(buf);
+        *size = size_n;
+    } else {
+        abort();
+    }
+}
+
+void macho_map_raw_file(const char *filename, AddressSpace *as, MemoryRegion *mem,
+                        const char *name, hwaddr file_pa, uint64_t *size)
+{
+    Error *err = NULL;
+    MemoryRegion *mr = NULL;
+    struct stat file_info;
+
+    if (stat(filename, &file_info)) {
+        fprintf(stderr, "Couldn't get file size for mmapping. Loading into RAM.\n");
+        goto load_fallback;
+    }
+
+    mr = g_new(MemoryRegion, 1);
+    *size = file_info.st_size;
+
+    memory_region_init_ram_from_file(mr, NULL, name, *size & (~0xffffUL), 0, 0, filename, &err);
+    if (err) {
+        error_report_err(err);
+        fprintf(stderr, "Couldn't mmap file. Loading into RAM.\n");
+        goto load_fallback;
+    }
+    memory_region_add_subregion(mem, file_pa, mr);
+    return;
+
+load_fallback:
+    if (mr) {
+        g_free(mr);
+    }
+    macho_load_raw_file(filename, as, mem, name, file_pa, size);
+}
+
+void macho_load_raw_file(const char *filename, AddressSpace *as, MemoryRegion *mem,
+                         const char *name, hwaddr file_pa, uint64_t *size)
+{
+    uint8_t* file_data = NULL;
+    unsigned long sizef;
+    if (g_file_get_contents(filename, (char **)&file_data, &sizef, NULL)) {
+        *size = sizef;
+        allocate_and_copy(mem, as, name, file_pa, *size, file_data);
+        g_free(file_data);
+    } else {
+        abort();
+    }
+}
+
+void macho_tz_setup_bootargs(const char *name, AddressSpace *as,
+                             MemoryRegion *mem, hwaddr bootargs_addr,
+                             hwaddr virt_base, hwaddr phys_base,
+                             hwaddr mem_size, hwaddr kern_args,
+                             hwaddr kern_entry, hwaddr kern_phys_base)
+{
+    struct xnu_arm64_monitor_boot_args boot_args;
+    memset(&boot_args, 0, sizeof(boot_args));
+    boot_args.version = xnu_arm64_kBootArgsVersion2;
+    boot_args.virtBase = virt_base;
+    boot_args.physBase = phys_base;
+    boot_args.memSize = mem_size;
+    boot_args.kernArgs = kern_args;
+    boot_args.kernEntry = kern_entry;
+    boot_args.kernPhysBase = kern_phys_base;
+
+    boot_args.kernPhysSlide = 0;
+    boot_args.kernVirtSlide = 0;
+
+    allocate_and_copy(mem, as, name, bootargs_addr, sizeof(boot_args),
+                      &boot_args);
+}
+
+void macho_setup_bootargs(const char *name, AddressSpace *as,
+                          MemoryRegion *mem, hwaddr bootargs_pa,
+                          hwaddr virt_base, hwaddr phys_base, hwaddr mem_size,
+                          hwaddr top_of_kernel_data_pa, hwaddr dtb_va,
+                          hwaddr dtb_size, video_boot_args v_bootargs,
+                          char *kern_args)
+{
+    struct xnu_arm64_boot_args boot_args;
+    memset(&boot_args, 0, sizeof(boot_args));
+    boot_args.Revision = xnu_arm64_kBootArgsRevision2;
+    boot_args.Version = xnu_arm64_kBootArgsVersion2;
+    boot_args.virtBase = virt_base;
+    boot_args.physBase = phys_base;
+    boot_args.memSize = mem_size;
+
+    boot_args.Video.v_baseAddr = v_bootargs.v_baseAddr;
+    boot_args.Video.v_depth = v_bootargs.v_depth;
+    boot_args.Video.v_display = v_bootargs.v_display;
+    boot_args.Video.v_height = v_bootargs.v_height;
+    boot_args.Video.v_rowBytes = v_bootargs.v_rowBytes;
+    boot_args.Video.v_width = v_bootargs.v_width;
+
+    boot_args.topOfKernelData = top_of_kernel_data_pa;
+    boot_args.deviceTreeP = dtb_va;
+    boot_args.deviceTreeLength = dtb_size;
+    boot_args.memSizeActual = 0;
+    if (kern_args) {
+        g_strlcpy(boot_args.CommandLine, kern_args,
+                  sizeof(boot_args.CommandLine));
+    }
+
+    allocate_and_copy(mem, as, name, bootargs_pa, sizeof(boot_args),
+                      &boot_args);
+}
+
+static void macho_highest_lowest(struct mach_header_64* mh, uint64_t *lowaddr,
+                                 uint64_t *highaddr)
+{
+    struct load_command* cmd = (struct load_command*)((uint8_t*)mh +
+                                                sizeof(struct mach_header_64));
+    // iterate all the segments once to find highest and lowest addresses
+    uint64_t low_addr_temp = ~0;
+    uint64_t high_addr_temp = 0;
+    for (unsigned int index = 0; index < mh->ncmds; index++) {
+        switch (cmd->cmd) {
+            case LC_SEGMENT_64: {
+                struct segment_command_64 *segCmd =
+                                        (struct segment_command_64 *)cmd;
+                if (segCmd->vmaddr < low_addr_temp) {
+                    low_addr_temp = segCmd->vmaddr;
+                }
+                if (segCmd->vmaddr + segCmd->vmsize > high_addr_temp) {
+                    high_addr_temp = segCmd->vmaddr + segCmd->vmsize;
+                }
+                break;
+            }
+        }
+        cmd = (struct load_command*)((char*)cmd + cmd->cmdsize);
+    }
+    *lowaddr = low_addr_temp;
+    *highaddr = high_addr_temp;
+}
+
+static void macho_file_highest_lowest(const char *filename, hwaddr *lowest,
+                                      hwaddr *highest)
+{
+    gsize len;
+    uint8_t *data = NULL;
+    if (!g_file_get_contents(filename, (char **)&data, &len, NULL)) {
+        abort();
+    }
+    struct mach_header_64* mh = (struct mach_header_64*)data;
+    macho_highest_lowest(mh, lowest, highest);
+    g_free(data);
+}
+
+void macho_file_highest_lowest_base(const char *filename, hwaddr phys_base,
+                                    hwaddr *virt_base, hwaddr *lowest,
+                                    hwaddr *highest)
+{
+    uint8_t high_Low_dif_bit_index;
+    uint8_t phys_base_non_zero_bit_index;
+    hwaddr bit_mask_for_index;
+
+    macho_file_highest_lowest(filename, lowest, highest);
+    high_Low_dif_bit_index =
+        get_highest_different_bit_index(align_64k_high(*highest),
+                                        align_64k_low(*lowest));
+    if (phys_base) {
+        phys_base_non_zero_bit_index =
+            get_lowest_non_zero_bit_index(phys_base);
+
+        //make sure we have enough zero bits to have all the diffrent kernel
+        //image addresses have the same non static bits in physical and in
+        //virtual memory.
+        if (high_Low_dif_bit_index > phys_base_non_zero_bit_index) {
+            abort();
+        }
+        bit_mask_for_index =
+            get_low_bits_mask_for_bit_index(phys_base_non_zero_bit_index);
+
+        *virt_base = align_64k_low(*lowest) & (~bit_mask_for_index);
+    }
+
+}
+
+void arm_load_macho(char *filename, AddressSpace *as, MemoryRegion *mem,
+                    const char *name, hwaddr phys_base, hwaddr virt_base,
+                    hwaddr low_virt_addr, hwaddr high_virt_addr, hwaddr *pc,
+                    char *darwin_ver)
+{
+    uint8_t *data = NULL;
+    gsize len;
+    uint8_t* rom_buf = NULL;
+
+    if (!g_file_get_contents(filename, (char **)&data, &len, NULL)) {
+        abort();
+    }
+
+    const char *darwin_str = "Darwin Kernel Version";
+    if (darwin_ver) {
+        char *res = memmem((char *)data, len, darwin_str,
+                sizeof(darwin_str));
+        if (!res)
+            abort();
+        strncpy(darwin_ver, res, strnlen(res, 1024) + 1);
+    }
+
+    struct mach_header_64* mh = (struct mach_header_64*)data;
+    struct load_command* cmd = (struct load_command*)(data +
+                                                sizeof(struct mach_header_64));
+
+    uint64_t rom_buf_size = align_64k_high(high_virt_addr) - low_virt_addr;
+    rom_buf = g_malloc0(rom_buf_size);
+    for (unsigned int index = 0; index < mh->ncmds; index++) {
+        switch (cmd->cmd) {
+            case LC_SEGMENT_64: {
+                struct segment_command_64 *segCmd =
+                                            (struct segment_command_64 *)cmd;
+                memcpy(rom_buf + (segCmd->vmaddr - low_virt_addr),
+                       data + segCmd->fileoff, segCmd->filesize);
+                break;
+            }
+            case LC_UNIXTHREAD: {
+                // grab just the entry point PC
+                uint64_t* ptrPc = (uint64_t*)((char*)cmd + 0x110);
+                // 0x110 for arm64 only.
+                *pc = vtop_bases(*ptrPc, phys_base, virt_base);
+                break;
+            }
+        }
+        cmd = (struct load_command*)((char*)cmd + cmd->cmdsize);
+    }
+    hwaddr low_phys_addr = vtop_bases(low_virt_addr, phys_base, virt_base);
+    allocate_and_copy(mem, as, name, low_phys_addr, rom_buf_size, rom_buf);
+
+    if (data) {
+        g_free(data);
+    }
+    if (rom_buf) {
+        g_free(rom_buf);
+    }
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/xnu_cpacr.c b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_cpacr.c
new file mode 100644
index 0000000..18a85b3
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_cpacr.c
@@ -0,0 +1,86 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/arm/xnu_cpacr.h"
+#include "hw/loader.h"
+
+static CpacrIntCtx ctx = {0};
+
+static void cpacr_a32_s_int_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                  uint64_t value)
+{
+    ctx.wfn_a32_s(env, ri, ctx.val);
+}
+
+static void cpacr_a32_s_int_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    cpacr_a32_s_int_write(env, ri, ctx.val);
+}
+
+static void cpacr_a32_ns_int_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                   uint64_t value)
+{
+    ctx.wfn_a32_ns(env, ri, ctx.val);
+}
+
+static void cpacr_a32_ns_int_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    cpacr_a32_ns_int_write(env, ri, ctx.val);
+}
+
+static void cpacr_a64_intercept_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                      uint64_t value)
+{
+    ctx.wfn_a64(env, ri, ctx.val);
+}
+
+static void cpacr_a64_intercept_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    cpacr_a64_intercept_write(env, ri, ctx.val);
+}
+
+void xnu_cpacr_intercept_write_const_val(ARMCPU *cpu, uint64_t val)
+{
+    ctx.val = val;
+    uint32_t key = ENCODE_AA64_CP_REG(19, 1, 0, 3, 0, 2);
+    ARMCPRegInfo *ri = (ARMCPRegInfo *)get_arm_cp_reginfo(cpu->cp_regs, key);
+    ctx.wfn_a64 = ri->writefn;
+    ri->writefn = cpacr_a64_intercept_write;
+    ri->resetfn = cpacr_a64_intercept_reset;
+    key = ENCODE_CP_REG(15, 0, 1, 1, 0, 0, 2);
+    ri = (ARMCPRegInfo *)get_arm_cp_reginfo(cpu->cp_regs, key);
+    ctx.wfn_a32_ns = ri->writefn;
+    ri->writefn = cpacr_a32_ns_int_write;
+    ri->resetfn = cpacr_a32_ns_int_reset;
+    key = ENCODE_CP_REG(15, 0, 0, 1, 0, 0, 2);
+    ri = (ARMCPRegInfo *)get_arm_cp_reginfo(cpu->cp_regs, key);
+    ctx.wfn_a32_s = ri->writefn;
+    ri->writefn = cpacr_a32_s_int_write;
+    ri->resetfn = cpacr_a32_s_int_reset;
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/xnu_dtb.c b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_dtb.c
new file mode 100644
index 0000000..e539a24
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_dtb.c
@@ -0,0 +1,335 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/arm/xnu.h"
+#include "hw/loader.h"
+#include "hw/arm/xnu_dtb.h"
+
+static uint64_t align_4_high_num(uint64_t num)
+{
+    return (num + (4 - 1)) & ~(4 - 1);
+}
+
+static void *align_4_high_ptr(void *ptr)
+{
+    uint64_t num = align_4_high_num((uint64_t)ptr);
+    return (void *)num;
+}
+
+
+static DTBProp *read_dtb_prop(uint8_t **dtb_blob)
+{
+    if ((NULL == dtb_blob) || (NULL == *dtb_blob)) {
+        abort();
+    }
+    *dtb_blob = align_4_high_ptr(*dtb_blob);
+    DTBProp *prop = g_new0(DTBProp, 1);
+    memcpy(&prop->name[0], *dtb_blob, DTB_PROP_NAME_LEN);
+    *dtb_blob += DTB_PROP_NAME_LEN;
+    //zero out this flag which sometimes appears in the DT
+    //normally done by iboot
+    prop->length = *(uint32_t *)*dtb_blob & ~DT_PROP_FLAG_PLACEHOLDER;
+    *dtb_blob += sizeof(uint32_t);
+    if (0 != prop->length) {
+        prop->value = g_malloc0(prop->length);
+        if (NULL == prop->value) {
+            abort();
+        }
+        memcpy(&prop->value[0], *dtb_blob, prop->length);
+        *dtb_blob += prop->length;
+    }
+
+    return prop;
+}
+
+static void delete_prop(DTBProp *prop)
+{
+    if (NULL == prop) {
+        return;
+    }
+
+    if (NULL != prop->value) {
+        g_free(prop->value);
+    }
+
+    g_free(prop);
+}
+
+static DTBNode *read_dtb_node(uint8_t **dtb_blob)
+{
+    if ((NULL == dtb_blob) || (NULL == *dtb_blob)) {
+        abort();
+    }
+
+    uint32_t i = 0;
+
+    *dtb_blob = align_4_high_ptr(*dtb_blob);
+    DTBNode *node = g_new0(DTBNode, 1);
+    node->prop_count = *(uint32_t *)*dtb_blob;
+    *dtb_blob += sizeof(uint32_t);
+    node->child_node_count = *(uint32_t *)*dtb_blob;
+    *dtb_blob += sizeof(uint32_t);
+
+    if (0 == node->prop_count) {
+        abort();
+    }
+    for (i = 0; i < node->prop_count; i++) {
+        DTBProp *prop = read_dtb_prop(dtb_blob);
+        node->props = g_list_append(node->props, prop);
+    }
+    for (i = 0; i < node->child_node_count; i++) {
+        DTBNode *child = read_dtb_node(dtb_blob);
+        node->child_nodes = g_list_append(node->child_nodes, child);
+    }
+    return node;
+}
+
+void delete_dtb_node(DTBNode *node)
+{
+    if (NULL == node) {
+        return;
+    }
+    if (NULL != node->props) {
+        g_list_free_full(node->props, (GDestroyNotify)delete_prop);
+    }
+    if (NULL != node->child_nodes) {
+        g_list_free_full(node->child_nodes, (GDestroyNotify)delete_dtb_node);
+    }
+    g_free(node);
+}
+
+DTBNode *load_dtb(uint8_t *dtb_blob)
+{
+    DTBNode *root = read_dtb_node(&dtb_blob);
+    return root;
+}
+
+static void save_prop(DTBProp *prop, uint8_t **buf)
+{
+    if ((NULL == prop) || (NULL == buf) || (NULL ==*buf)) {
+        abort();
+    }
+
+    *buf = align_4_high_ptr(*buf);
+    memcpy(*buf, &prop->name[0], DTB_PROP_NAME_LEN);
+    *buf += DTB_PROP_NAME_LEN;
+    memcpy(*buf, &prop->length, sizeof(uint32_t));
+    *buf += sizeof(uint32_t);
+    memcpy(*buf, prop->value, prop->length);
+    *buf += prop->length;
+}
+
+static void save_node(DTBNode *node, uint8_t **buf)
+{
+    if ((NULL == node) || (NULL == buf) || (NULL ==*buf)) {
+        abort();
+    }
+
+    *buf = align_4_high_ptr(*buf);
+
+    memcpy(*buf, &node->prop_count, sizeof(uint32_t));
+    *buf += sizeof(uint32_t);
+    memcpy(*buf, &node->child_node_count, sizeof(uint32_t));
+    *buf += sizeof(uint32_t);
+    g_list_foreach(node->props, (GFunc)save_prop, buf);
+    g_list_foreach(node->child_nodes, (GFunc)save_node, buf);
+}
+
+void remove_dtb_prop(DTBNode *node, DTBProp *prop)
+{
+    if ((NULL == node) || (NULL == prop)) {
+        abort();
+    }
+    GList *iter;
+    bool found = false;
+    for (iter = node->props; iter != NULL; iter = iter->next) {
+        if (prop == iter->data) {
+            found = true;
+            break;
+        }
+    }
+    if (!found) {
+        abort();
+        return;
+    }
+    delete_prop(prop);
+    node->props = g_list_delete_link(node->props, iter);
+
+    //sanity
+    if (0 == node->prop_count) {
+        abort();
+    }
+
+    node->prop_count--;
+}
+
+void add_dtb_prop(DTBNode *n, const char *name, uint32_t size, uint8_t *val)
+{
+    if ((NULL == n) || (NULL == name) || (NULL == val)) {
+        abort();
+    }
+    DTBProp *prop = g_new0(DTBProp, 1);
+    memcpy(&prop->name[0], name, DTB_PROP_NAME_LEN);
+    prop->length = size;
+    prop->value = g_malloc0(size);
+    memcpy(&prop->value[0], val, size);
+    n->props = g_list_append(n->props, prop);
+    n->prop_count++;
+}
+
+void save_dtb(uint8_t *buf, DTBNode *root)
+{
+    if ((NULL == root) || (NULL == buf)) {
+        abort();
+    }
+
+    //TODO: handle cases where the buffer is not 4 bytes aligned
+    //though this is never expected to happen and the code is simpler this
+    //way
+    if (align_4_high_ptr(buf) != buf) {
+        abort();
+    }
+
+    save_node(root, &buf);
+}
+
+static uint64_t get_dtb_prop_size(DTBProp *prop)
+{
+    uint64_t size = 0;
+
+    if (NULL == prop) {
+        abort();
+    }
+
+    size = align_4_high_num(sizeof(prop->name) + sizeof(prop->length) +
+                            prop->length);
+    return size;
+}
+
+uint64_t get_dtb_node_buffer_size(DTBNode *node)
+{
+    uint64_t size = 0;
+    DTBProp *prop = NULL;
+    DTBNode *child = NULL;
+    GList *iter = NULL;
+
+    if (NULL == node) {
+        abort();
+    }
+
+    size += sizeof(node->prop_count) + sizeof(node->child_node_count);
+
+    for (iter = node->props; iter != NULL; iter = iter->next) {
+        prop = (DTBProp *)iter->data;
+        if (NULL == prop) {
+            abort();
+        }
+        size += get_dtb_prop_size(prop);
+    }
+    for (iter = node->child_nodes; iter != NULL; iter = iter->next) {
+        child = (DTBNode *)iter->data;
+        if (NULL == child) {
+            abort();
+        }
+        size += get_dtb_node_buffer_size(child);
+    }
+    return size;
+}
+
+DTBProp *get_dtb_prop(DTBNode *node, const char *name)
+{
+    if ((NULL == node) || (NULL == name)) {
+        abort();
+    }
+
+    GList *iter = NULL;
+    DTBProp *prop = NULL;
+
+    for (iter = node->props; iter != NULL; iter = iter->next) {
+        prop = (DTBProp *)iter->data;
+
+        if (NULL == prop) {
+            abort();
+        }
+
+        if (0 == strncmp((const char *)&prop->name[0], name,
+                         DTB_PROP_NAME_LEN)) {
+            return prop;
+        }
+    }
+    return NULL;
+}
+
+DTBNode *get_dtb_child_node_by_name(DTBNode *node, const char *name)
+{
+    if ((NULL == node) || (NULL == name)) {
+        abort();
+    }
+
+    GList *iter = NULL;
+    DTBProp *prop = NULL;
+    DTBNode *child = NULL;
+
+    for (iter = node->child_nodes; iter != NULL; iter = iter->next) {
+        child = (DTBNode *)iter->data;
+
+        if (NULL == child) {
+            abort();
+        }
+
+        prop = get_dtb_prop(child, "name");
+
+        if (NULL == prop) {
+            abort();
+        }
+
+        if (0 == strncmp((const char *)prop->value, name, prop->length)) {
+            return child;
+        }
+    }
+    return NULL;
+}
+
+void overwrite_dtb_prop_val(DTBProp *prop, uint8_t chr)
+{
+    uint64_t i = 0;
+    uint8_t *ptr = prop->value;
+    for (i = 0; i < prop->length - 1; i++) {
+        ptr[i] = chr;
+    }
+}
+
+void overwrite_dtb_prop_name(DTBProp *prop, uint8_t chr)
+{
+    uint64_t i = 0;
+    uint8_t *ptr = &prop->name[0];
+    for (i = 0; i < DTB_PROP_NAME_LEN; i++) {
+        ptr[i] = chr;
+    }
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/xnu_fb_cfg.c b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_fb_cfg.c
new file mode 100644
index 0000000..eabe984
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_fb_cfg.c
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/arm/xnu.h"
+#include "hw/loader.h"
+#include "hw/arm/xnu_file_mmio_dev.h"
+#include "hw/display/xnu_ramfb.h"
+#include "include/hw/qdev-properties.h"
+
+void xnu_define_ramfb_device(AddressSpace* as, hwaddr ramfb_pa)
+{
+
+    DeviceState *fb_dev;
+    fb_dev = qdev_new(TYPE_XNU_RAMFB_DEVICE);
+    qdev_prop_set_uint64(fb_dev, "as", (hwaddr)as);
+    qdev_prop_set_uint64(fb_dev, "fb_pa", ramfb_pa);
+    qdev_prop_set_uint32(fb_dev, "fb_size", RAMFB_SIZE);
+    qdev_prop_set_uint32(fb_dev, "display_cfg.height", V_HEIGHT);
+    qdev_prop_set_uint32(fb_dev, "display_cfg.width", V_WIDTH);
+    qdev_prop_set_uint32(fb_dev, "display_cfg.linesize", V_LINESIZE);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(fb_dev), &error_fatal);
+}
+
+void  xnu_get_video_bootargs(void *opaque, hwaddr ramfb_pa)
+{
+
+    video_boot_args* v_bootargs = (video_boot_args*)opaque;
+    v_bootargs->v_baseAddr = ramfb_pa;
+    v_bootargs->v_depth = V_DEPTH;
+    v_bootargs->v_display = V_DISPLAY;
+    v_bootargs->v_height = V_HEIGHT;
+    v_bootargs->v_width = V_WIDTH;
+    v_bootargs->v_rowBytes = V_LINESIZE;
+
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/xnu_file_mmio_dev.c b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_file_mmio_dev.c
new file mode 100644
index 0000000..5d025c3
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_file_mmio_dev.c
@@ -0,0 +1,106 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/arm/xnu.h"
+#include "hw/loader.h"
+#include "hw/arm/xnu_file_mmio_dev.h"
+
+static uint64_t xnu_file_mmio_dev_read(void *opaque,
+                                       hwaddr addr, unsigned size)
+{
+    FileMmioDev *file_dev = opaque;
+    uint64_t ret = 0;
+
+    if (addr + size > file_dev->size) {
+        abort();
+    }
+
+    if (size > sizeof(ret)) {
+        abort();
+    }
+
+    if (addr != lseek(file_dev->fd, addr, SEEK_SET)) {
+        abort();
+    }
+
+    if (size != read(file_dev->fd, &ret, size)) {
+        abort();
+    }
+
+    return ret;
+}
+
+static void xnu_file_mmio_dev_write(void *opaque, hwaddr addr,
+                                    uint64_t val, unsigned size)
+{
+    FileMmioDev *file_dev = opaque;
+
+    if (addr + size > file_dev->size) {
+        abort();
+    }
+
+    if (addr != lseek(file_dev->fd, addr, SEEK_SET)) {
+        abort();
+    }
+
+    if (size != write(file_dev->fd, &val, size)) {
+        abort();
+    }
+
+}
+
+const MemoryRegionOps xnu_file_mmio_dev_ops = {
+    .read = xnu_file_mmio_dev_read,
+    .write = xnu_file_mmio_dev_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+void xnu_file_mmio_dev_create(MemoryRegion *sysmem, FileMmioDev *file_dev,
+                              const char *name, const char *filename)
+{
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+    struct stat st;
+
+    if (-1 == lstat(filename, &st)) {
+        abort();
+    }
+
+    file_dev->size = st.st_size;
+
+    memory_region_init_io(iomem, NULL, &xnu_file_mmio_dev_ops, file_dev,
+                          name, file_dev->size);
+    memory_region_add_subregion(sysmem, file_dev->pa, iomem);
+
+    //TODO; think about using O_SYNC
+    //or maybe use fsync() from time to time
+    file_dev->fd = open(filename, O_RDWR);
+    if (-1 == file_dev->fd) {
+        abort();
+    }
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/xnu_mem.c b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_mem.c
new file mode 100644
index 0000000..5e4a62f
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_mem.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "exec/address-spaces.h"
+#include "hw/misc/unimp.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/platform-bus.h"
+#include "exec/memory.h"
+#include "qemu-common.h"
+#include "exec/hwaddr.h"
+#include "hw/boards.h"
+#include "hw/arm/boot.h"
+#include "cpu.h"
+#include "hw/arm/xnu_mem.h"
+
+hwaddr g_virt_base = 0;
+hwaddr g_phys_base = 0;
+
+hwaddr vtop_bases(hwaddr va, hwaddr phys_base, hwaddr virt_base)
+{
+    if ((0 == virt_base) || (0 == phys_base)) {
+        abort();
+    }
+    return va - virt_base + phys_base;
+}
+
+hwaddr ptov_bases(hwaddr pa, hwaddr phys_base, hwaddr virt_base)
+{
+    if ((0 == virt_base) || (0 == phys_base)) {
+        abort();
+    }
+    return pa - phys_base + virt_base;
+}
+
+hwaddr vtop_static(hwaddr va)
+{
+    return vtop_bases(va, g_phys_base, g_virt_base);
+}
+
+hwaddr ptov_static(hwaddr pa)
+{
+    return ptov_bases(pa, g_phys_base, g_virt_base);
+}
+
+hwaddr vtop_mmu(hwaddr va, CPUState *cs)
+{
+    hwaddr phys_addr;
+    MemTxAttrs attrs = {};
+
+    phys_addr = arm_cpu_get_phys_page_attrs_debug(cs, va, &attrs);
+    if (-1 == phys_addr) {
+        abort();
+    }
+
+    return phys_addr;
+}
+
+uint8_t get_highest_different_bit_index(hwaddr addr1, hwaddr addr2)
+{
+    if ((addr1 == addr2) || (0 == addr1) || (0 == addr2)) {
+        abort();
+    }
+    return (64 - __builtin_clzll(addr1 ^ addr2));
+}
+
+hwaddr align_64k_low(hwaddr addr)
+{
+    return addr & ~0xffffull;
+}
+
+hwaddr align_64k_high(hwaddr addr)
+{
+    return (addr + 0xffffull) & ~0xffffull;
+}
+
+uint8_t get_lowest_non_zero_bit_index(hwaddr addr)
+{
+    if (0 == addr) {
+        abort();
+    }
+    return __builtin_ctzll(addr);
+}
+
+hwaddr get_low_bits_mask_for_bit_index(uint8_t bit_index)
+{
+    if (bit_index >= 64) {
+        abort();
+    }
+    return (1 << bit_index) - 1;
+}
+
+void allocate_ram(MemoryRegion *top, const char *name, hwaddr addr,
+                  hwaddr size)
+{
+        MemoryRegion *sec = g_new(MemoryRegion, 1);
+        memory_region_init_ram(sec, NULL, name, size, &error_fatal);
+        memory_region_add_subregion(top, addr, sec);
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/xnu_pagetable.c b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_pagetable.c
new file mode 100644
index 0000000..cfce447
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_pagetable.c
@@ -0,0 +1,230 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/arm/xnu_pagetable.h"
+#include "hw/loader.h"
+#include "qemu/osdep.h"
+#include "target/arm/idau.h"
+#include "trace.h"
+#include "cpu.h"
+#include "internals.h"
+#include "exec/gdbstub.h"
+#include "exec/helper-proto.h"
+#include "qemu/host-utils.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/sysemu.h"
+#include "qemu/bitops.h"
+#include "qemu/crc32c.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "arm_ldst.h"
+#include "hw/semihosting/semihost.h"
+
+#define PHYS_ADDR_SIZE (40)
+#define TG_16K_SIZE (14)
+#define PAGE_MASK_16K (~(((uint64_t)1 << TG_16K_SIZE) - 1))
+#define TE_PHYS_ADDR_MASK ((((uint64_t)1 << PHYS_ADDR_SIZE) - 1) & \
+                           PAGE_MASK_16K)
+
+#define TG_16KB (1)
+#define TG_16KB_LEVEL0_INDEX (47)
+#define TG_16KB_LEVEL0_SIZE (1)
+#define TG_16KB_LEVEL1_INDEX (36)
+#define TG_16KB_LEVEL1_SIZE (11)
+#define TG_16KB_LEVEL2_INDEX (25)
+#define TG_16KB_LEVEL2_SIZE (11)
+#define TG_16KB_LEVEL3_INDEX (14)
+#define TG_16KB_LEVEL3_SIZE (11)
+
+#define TCR_IPS_INDEX (32)
+#define TCR_IPS_SIZE (3)
+#define TCR_IPS_40_ADDR_SIZE (2)
+#define TCR_TG1_INDEX (30)
+#define TCR_TG1_SIZE (2)
+#define TCR_T1SZ_INDEX (16)
+#define TCR_T1SZ_SIZE (6)
+#define TCR_TG0_INDEX (14)
+#define TCR_TG0_SIZE (2)
+#define TCR_T0SZ_INDEX (0)
+#define TCR_T0SZ_SIZE (6)
+
+#define TE_ACCESS_PERMS_INDEX (6)
+#define TE_ACCESS_PERMS_SIZE (2)
+#define TE_ACCESS_PERMS_MASK ((((uint64_t)1 << TE_ACCESS_PERMS_SIZE) - 1) << \
+                              TE_ACCESS_PERMS_INDEX)
+#define TE_ACCESS_PERMS_ZERO_MASK (~TE_ACCESS_PERMS_MASK)
+#define TE_ACCESS_PERMS_KERN_RW (0)
+#define TE_XN_INDEX (53)
+#define TE_XN_SIZE (2)
+#define TE_XN_MASK ((((uint64_t)1 << TE_XN_SIZE) - 1) << TE_XN_INDEX)
+#define TE_XN_ZERO_MASK (~TE_XN_MASK)
+#define TE_XN_KERN_EXE ((uint64_t)2 << TE_XN_INDEX)
+#define TE_TYPE_INDEX (0)
+#define TE_TYPE_SIZE (2)
+#define TE_TYPE_TABLE_DESC (3)
+#define TE_TYPE_L3_BLOCK (3)
+
+hwaddr pt_tte_el1(ARMCPU *cpu, AddressSpace *as, hwaddr va, bool make_exe)
+{
+    CPUARMState *env = &cpu->env;
+    uint64_t tcr = env->cp15.tcr_el[1].raw_tcr;
+    uint64_t tcr_ips = extract64(tcr, TCR_IPS_INDEX, TCR_IPS_SIZE);
+    uint64_t tcr_tg1 = extract64(tcr, TCR_TG1_INDEX, TCR_TG1_SIZE);
+    uint64_t tcr_t1sz = extract64(tcr, TCR_T1SZ_INDEX, TCR_T1SZ_SIZE);
+    uint64_t tcr_tg0 = extract64(tcr, TCR_TG0_INDEX, TCR_TG0_SIZE);
+    uint64_t tcr_t0sz = extract64(tcr, TCR_T0SZ_INDEX, TCR_T0SZ_SIZE);
+
+    hwaddr tt = 0;
+    hwaddr te = 0;
+    uint64_t tg = 0;
+    uint64_t tsz = 0;
+
+    //currently only support 40bit addresses configuration
+    if (TCR_IPS_40_ADDR_SIZE != tcr_ips) {
+        abort();
+    }
+    //fprintf(stderr, "pt_tte_el1: tcr: 0x%016llx tcr_ips: 0x%016llx tcr_tg1: 0x%016llx tcr_t1sz: 0x%016llx tcr_tg0: %016llx tcr_t0sz: 0x%016llx va: 0x%016llx\n",
+    //        tcr, tcr_ips, tcr_tg1, tcr_t1sz, tcr_tg0, tcr_t0sz, va);
+
+    if (extract64(va, 63, 1) == 1) {
+        uint64_t one_bits = extract64(va, 64 - tcr_t1sz, tcr_t1sz);
+        uint64_t one_bits_verify = (1 << tcr_t1sz) - 1;
+        //fprintf(stderr, "90 pt_tte_el1: te: 0x%016llx\n", te);
+        if ((one_bits & one_bits_verify) != one_bits_verify) {
+            fprintf(stderr, "9 pt_tte_el1: te: 0x%016llx\n", te);
+            abort();
+        }
+        tt = env->cp15.ttbr1_el[1];
+        tg = tcr_tg1;
+        tsz = tcr_t1sz;
+    } else {
+        uint64_t zero_bits = extract64(va, 64 - tcr_t0sz, tcr_t0sz);
+        //fprintf(stderr, "91 pt_tte_el1: te: 0x%016lx\n", te);
+        if (0 != zero_bits) {
+            fprintf(stderr, "10 pt_tte_el1: te: 0x%016llx\n", te);
+            abort();
+        }
+        tt = env->cp15.ttbr0_el[1];
+        tg = tcr_tg0;
+        tsz = tcr_t0sz;
+    }
+
+    //currently only support parsing 16kg granule page tables
+    if (TG_16KB != tg) {
+        fprintf(stderr, "8 pt_tte_el1: te: 0x%016llx\n", te);
+        abort();
+    }
+
+    //currently only support level 1 base entries
+    if ((tsz < (64 - TG_16KB_LEVEL0_INDEX)) ||
+        (tsz >= (64 - TG_16KB_LEVEL1_INDEX))) {
+        fprintf(stderr, "7 pt_tte_el1: te: 0x%016llx\n", te);
+        abort();
+    }
+
+    uint64_t l1_index_size = 64 - tsz - TG_16KB_LEVEL1_INDEX;
+    uint64_t l1_idx = extract64(va, TG_16KB_LEVEL1_INDEX, l1_index_size);
+    uint64_t l2_idx = extract64(va, TG_16KB_LEVEL2_INDEX, TG_16KB_LEVEL2_SIZE);
+    uint64_t l3_idx = extract64(va, TG_16KB_LEVEL3_INDEX, TG_16KB_LEVEL3_SIZE);
+
+    address_space_rw(as, (tt + (sizeof(hwaddr) * l1_idx)),
+                     MEMTXATTRS_UNSPECIFIED, (uint8_t *)&te, sizeof(te), 0);
+    if (0 == te) {
+        fprintf(stderr, "6 pt_tte_el1: te: 0x%016llx\n", te);
+        abort();
+    }
+
+    uint64_t te_type = extract64(te, TE_TYPE_INDEX, TE_TYPE_SIZE);
+    //currently only support table description level1 entries
+    if (TE_TYPE_TABLE_DESC != te_type) {
+        fprintf(stderr, "5 pt_tte_el1: te: 0x%016llx\n", te);
+        abort();
+    }
+
+    //layer 2
+    tt = te & TE_PHYS_ADDR_MASK;
+    address_space_rw(as, (tt + (sizeof(hwaddr) * l2_idx)),
+                     MEMTXATTRS_UNSPECIFIED, (uint8_t *)&te, sizeof(te), 0);
+    if (0 == te) {
+        fprintf(stderr, "4 pt_tte_el1: te: 0x%016llx\n", te);
+        abort();
+    }
+
+    te_type = extract64(te, TE_TYPE_INDEX, TE_TYPE_SIZE);
+    //currently only support table description level2 entries
+    if (TE_TYPE_TABLE_DESC != te_type) {
+        fprintf(stderr, "3 pt_tte_el1: te: 0x%016llx\n", te);
+        abort();
+    }
+
+    //layer 3
+    tt = te & TE_PHYS_ADDR_MASK;
+    hwaddr l3_te_addr = tt + (sizeof(hwaddr) * l3_idx);
+    address_space_rw(as, l3_te_addr, MEMTXATTRS_UNSPECIFIED, (uint8_t *)&te,
+                     sizeof(te), 0);
+    if (0 == te) {
+        fprintf(stderr, "2 pt_tte_el1: te: 0x%016llx\n", te);
+        abort();
+    }
+
+    te_type = extract64(te, TE_TYPE_INDEX, TE_TYPE_SIZE);
+    //sanity - l3 entries can only be block entries or invalid entries
+    if (TE_TYPE_L3_BLOCK != te_type) {
+        fprintf(stderr, "1 pt_tte_el1: te: 0x%016llx\n", te);
+        abort();
+    }
+
+    //fprintf(stderr, "pt_tte_el1: te: 0x%016llx\n", te);
+
+    if (make_exe) {
+        //fprintf(stderr, "pt_tte_el1: TE_ACCESS_PERMS_ZERO_MASK: 0x%016llx\n", TE_ACCESS_PERMS_ZERO_MASK);
+        //fprintf(stderr, "pt_tte_el1: TE_XN_ZERO_MASK: 0x%016llx\n", TE_XN_ZERO_MASK);
+        //fprintf(stderr, "pt_tte_el1: TE_ACCESS_PERMS_KERN_RW: 0x%016llx\n", TE_ACCESS_PERMS_KERN_RW);
+        //fprintf(stderr, "pt_tte_el1: TE_XN_KERN_EXE: 0x%016llx\n", TE_XN_KERN_EXE);
+        te &= TE_ACCESS_PERMS_ZERO_MASK & TE_XN_ZERO_MASK;
+        te |= TE_ACCESS_PERMS_KERN_RW | TE_XN_KERN_EXE;
+        address_space_rw(as, l3_te_addr, MEMTXATTRS_UNSPECIFIED,
+                         (uint8_t *)&te, sizeof(te), 1);
+        tlb_flush(CPU(cpu));
+    }
+
+    //fprintf(stderr, "pt_tte_el1: te: 0x%016llx\n", te);
+
+    uint64_t page_offset = extract64(va, 0, TG_16K_SIZE);
+    return (te & TE_PHYS_ADDR_MASK) + page_offset;
+}
+
+void va_make_exec(ARMCPU *cpu, AddressSpace *as, hwaddr va, hwaddr size)
+{
+    hwaddr curr_va = va & PAGE_MASK_16K;
+    while (curr_va < va + size) {
+        pt_tte_el1(cpu, as, curr_va, true);
+        curr_va += ((uint64_t)1 << TG_16K_SIZE);
+    }
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/arm/xnu_trampoline_hook.c b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_trampoline_hook.c
new file mode 100644
index 0000000..2975543
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/arm/xnu_trampoline_hook.c
@@ -0,0 +1,521 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/arm/xnu_trampoline_hook.h"
+#include "hw/arm/xnu_mem.h"
+#include "hw/arm/xnu_pagetable.h"
+#include "hw/loader.h"
+#include "qemu/osdep.h"
+#include "target/arm/idau.h"
+#include "trace.h"
+#include "cpu.h"
+#include "internals.h"
+#include "exec/gdbstub.h"
+#include "exec/helper-proto.h"
+#include "qemu/host-utils.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/sysemu.h"
+#include "qemu/bitops.h"
+#include "qemu/crc32c.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "arm_ldst.h"
+#include "hw/semihosting/semihost.h"
+#include "sysemu/hw_accel.h"
+
+#define TRAMPOLINE_CODE_INSTS (1024)
+#define TRAMPOLINE_CODE_SIZE (TRAMPOLINE_CODE_INSTS * 4)
+
+#define PAGE_4K_BITS (12)
+#define PAGE_4K_MASK (((uint64_t)1 << PAGE_4K_BITS) - 1)
+#define PAGE_4K_ALIGN_MASK (~(PAGE_4K_MASK))
+
+#define ADRP_IMMLO_SIZE (2)
+#define ADRP_IMMLO_MASK (((uint32_t)1 << ADRP_IMMLO_SIZE) - 1)
+#define ADRP_IMMLO_SHIFT (29)
+
+#define ADRP_IMMHI_SIZE (19)
+#define ADRP_IMMHI_MASK (((uint32_t)1 << ADRP_IMMHI_SIZE) - 1)
+#define ADRP_IMMHI_SHIFT (5)
+
+#define ADRP_RD_SIZE (5)
+#define ADRP_RD_MASK (((uint32_t)1 << ADRP_RD_SIZE) - 1)
+#define ADRP_RD_SHIFT (0)
+
+#define ADD_RN_SIZE (5)
+#define ADD_RN_MASK (((uint32_t)1 << ADD_RN_SIZE) - 1)
+#define ADD_RN_SHIFT (5)
+
+#define ADD_RD_SIZE (5)
+#define ADD_RD_MASK (((uint32_t)1 << ADD_RD_SIZE) - 1)
+#define ADD_RD_SHIFT (0)
+
+#define ADD_IMM_SIZE (12)
+#define ADD_IMM_MASK (((uint32_t)1 << ADD_IMM_SIZE) - 1)
+#define ADD_IMM_SHIFT (10)
+
+#define SUB_RN_SIZE (5)
+#define SUB_RN_MASK (((uint32_t)1 << SUB_RN_SIZE) - 1)
+#define SUB_RN_SHIFT (5)
+
+#define SUB_RD_SIZE (5)
+#define SUB_RD_MASK (((uint32_t)1 << SUB_RD_SIZE) - 1)
+#define SUB_RD_SHIFT (0)
+
+#define SUB_IMM_SIZE (12)
+#define SUB_IMM_MASK (((uint32_t)1 << SUB_IMM_SIZE) - 1)
+#define SUB_IMM_SHIFT (10)
+
+#define STR_64_FP_RN_SIZE (5)
+#define STR_64_FP_RN_MASK (((uint32_t)1 << STR_64_FP_RN_SIZE) - 1)
+#define STR_64_FP_RN_SHIFT (5)
+
+#define STR_64_FP_RT_SIZE (5)
+#define STR_64_FP_RT_MASK (((uint32_t)1 << STR_64_FP_RT_SIZE) - 1)
+#define STR_64_FP_RT_SHIFT (0)
+
+#define STR_64_FP_IMM_SIZE (12)
+#define STR_64_FP_IMM_MASK (((uint32_t)1 << STR_64_FP_IMM_SIZE) - 1)
+#define STR_64_FP_IMM_SHIFT (10)
+
+#define LDR_64_FP_RN_SIZE (5)
+#define LDR_64_FP_RN_MASK (((uint32_t)1 << LDR_64_FP_RN_SIZE) - 1)
+#define LDR_64_FP_RN_SHIFT (5)
+
+#define LDR_64_FP_RT_SIZE (5)
+#define LDR_64_FP_RT_MASK (((uint32_t)1 << LDR_64_FP_RT_SIZE) - 1)
+#define LDR_64_FP_RT_SHIFT (0)
+
+#define LDR_64_FP_IMM_SIZE (12)
+#define LDR_64_FP_IMM_MASK (((uint32_t)1 << LDR_64_FP_IMM_SIZE) - 1)
+#define LDR_64_FP_IMM_SHIFT (10)
+
+#define STP_XT1_SIZE (5)
+#define STP_XT1_MASK (((uint32_t)1 << STP_XT1_SIZE) - 1)
+#define STP_XT1_SHIFT (0)
+
+#define STP_XT2_SIZE (5)
+#define STP_XT2_MASK (((uint32_t)1 << STP_XT2_SIZE) - 1)
+#define STP_XT2_SHIFT (10)
+
+#define STP_RN_SIZE (5)
+#define STP_RN_MASK (((uint32_t)1 << ADD_RN_SIZE) - 1)
+#define STP_RN_SHIFT (5)
+
+#define STP_IMM_SIZE (7)
+#define STP_IMM_MASK (((uint32_t)1 << STP_IMM_SIZE) - 1)
+#define STP_IMM_SHIFT (15)
+
+#define LDP_XT1_SIZE (5)
+#define LDP_XT1_MASK (((uint32_t)1 << LDP_XT1_SIZE) - 1)
+#define LDP_XT1_SHIFT (0)
+
+#define LDP_XT2_SIZE (5)
+#define LDP_XT2_MASK (((uint32_t)1 << LDP_XT2_SIZE) - 1)
+#define LDP_XT2_SHIFT (10)
+
+#define LDP_RN_SIZE (5)
+#define LDP_RN_MASK (((uint32_t)1 << LDP_RN_SIZE) - 1)
+#define LDP_RN_SHIFT (5)
+
+#define LDP_IMM_SIZE (7)
+#define LDP_IMM_MASK (((uint32_t)1 << LDP_IMM_SIZE) - 1)
+#define LDP_IMM_SHIFT (15)
+
+#define BR_RN_SIZE (5)
+#define BR_RN_MASK (((uint32_t)1 << BR_RN_SIZE) - 1)
+#define BR_RN_SHIFT (5)
+
+#define BLR_RN_SIZE (5)
+#define BLR_RN_MASK (((uint32_t)1 << BLR_RN_SIZE) - 1)
+#define BLR_RN_SHIFT (5)
+
+static AddressSpace *xnu_hook_tr_as = NULL;
+static ARMCPU *xnu_hook_tr_cpu = NULL;
+
+static uint32_t get_adrp_inst(hwaddr source, hwaddr target, uint8_t reg_id)
+{
+    //general adrp inst
+    uint32_t adrp_inst = 0x90000000;
+
+    adrp_inst |= (reg_id & ADRP_RD_MASK) << ADRP_RD_SHIFT;
+
+    hwaddr source_page = source & PAGE_4K_ALIGN_MASK;
+    hwaddr target_page = target & PAGE_4K_ALIGN_MASK;
+
+    hwaddr adrp_inst_diff_imm = ((target_page - source_page) >> PAGE_4K_BITS);
+
+    adrp_inst |= (adrp_inst_diff_imm & ADRP_IMMLO_MASK) << ADRP_IMMLO_SHIFT;
+    adrp_inst |= ((adrp_inst_diff_imm >> ADRP_IMMLO_SIZE) &
+                  ADRP_IMMHI_MASK) << ADRP_IMMHI_SHIFT;
+
+    return adrp_inst;
+}
+
+static uint32_t get_add_inst(uint8_t xd, uint8_t xn, hwaddr imm)
+{
+    //general add inst
+    uint32_t add_inst = 0x91000000;
+
+    add_inst |= (xn & ADD_RN_MASK) << ADD_RN_SHIFT;
+    add_inst |= (xd & ADD_RD_MASK) << ADD_RD_SHIFT;
+    add_inst |= (imm & ADD_IMM_MASK) << ADD_IMM_SHIFT;
+
+    return add_inst;
+}
+
+static uint32_t get_sub_inst(uint8_t xd, uint8_t xn, hwaddr imm)
+{
+    //general sub inst
+    uint32_t sub_inst = 0xD1000000;
+
+    sub_inst |= (xn & SUB_RN_MASK) << SUB_RN_SHIFT;
+    sub_inst |= (xd & SUB_RD_MASK) << SUB_RD_SHIFT;
+    sub_inst |= (imm & SUB_IMM_MASK) << SUB_IMM_SHIFT;
+
+    return sub_inst;
+}
+
+static uint32_t get_str_64_fp_inst(uint8_t dt, uint8_t xn, hwaddr imm)
+{
+    //general str inst
+    uint32_t str_inst = 0xFD000000;
+
+    //has to be devided by 8
+    if (imm % 8 != 0) {
+        abort();
+    }
+
+    imm = imm / 8;
+
+    str_inst |= (xn & STR_64_FP_RN_MASK) << STR_64_FP_RN_SHIFT;
+    str_inst |= (dt & STR_64_FP_RT_MASK) << STR_64_FP_RT_SHIFT;
+    str_inst |= (imm & STR_64_FP_IMM_MASK) << STR_64_FP_IMM_SHIFT;
+
+    return str_inst;
+}
+
+static uint32_t get_ldr_64_fp_inst(uint8_t dt, uint8_t xn, hwaddr imm)
+{
+    //general ldr inst
+    uint32_t ldr_inst = 0xFD400000;
+
+    //has to be devided by 8
+    if (imm % 8 != 0) {
+        abort();
+    }
+
+    imm = imm / 8;
+
+    ldr_inst |= (xn & LDR_64_FP_RN_MASK) << LDR_64_FP_RN_SHIFT;
+    ldr_inst |= (dt & LDR_64_FP_RT_MASK) << LDR_64_FP_RT_SHIFT;
+    ldr_inst |= (imm & LDR_64_FP_IMM_MASK) << LDR_64_FP_IMM_SHIFT;
+
+    return ldr_inst;
+}
+
+static uint32_t get_stp_inst(uint8_t xt1, uint8_t xt2, uint8_t rn, hwaddr imm)
+{
+    //general stp inst
+    uint32_t stp_inst = 0xA9000000;
+
+    //has to be devided by 8
+    if (imm % 8 != 0) {
+        abort();
+    }
+
+    imm = imm / 8;
+
+    if ((imm & STP_IMM_MASK) != imm) {
+        abort();
+    }
+
+    stp_inst |= (xt1 & STP_XT1_MASK) << STP_XT1_SHIFT;
+    stp_inst |= (xt2 & STP_XT2_MASK) << STP_XT2_SHIFT;
+    stp_inst |= (rn & STP_RN_MASK) << STP_RN_SHIFT;
+    stp_inst |= (imm & STP_IMM_MASK) << STP_IMM_SHIFT;
+
+    return stp_inst;
+}
+
+static uint32_t get_ldp_inst(uint8_t xt1, uint8_t xt2, uint8_t rn, hwaddr imm)
+{
+    //general ldp inst
+    uint32_t ldp_inst = 0xA9400000;
+
+    //has to be devided by 8
+    if (imm % 8 != 0) {
+        abort();
+    }
+
+    imm = imm / 8;
+
+    if ((imm & LDP_IMM_MASK) != imm) {
+        abort();
+    }
+
+    ldp_inst |= (xt1 & LDP_XT1_MASK) << LDP_XT1_SHIFT;
+    ldp_inst |= (xt2 & LDP_XT2_MASK) << LDP_XT2_SHIFT;
+    ldp_inst |= (rn & LDP_RN_MASK) << LDP_RN_SHIFT;
+    ldp_inst |= (imm & LDP_IMM_MASK) << LDP_IMM_SHIFT;
+
+    return ldp_inst;
+}
+
+static uint32_t get_br_inst(uint8_t reg_id)
+{
+    //general br inst
+    uint32_t br_inst = 0xD61F0000;
+
+    br_inst |= (reg_id & BR_RN_MASK) << BR_RN_SHIFT;
+
+    return br_inst;
+}
+
+static uint32_t get_blr_inst(uint8_t reg_id)
+{
+    //general blr inst
+    uint32_t blr_inst = 0xD63F0000;
+
+    blr_inst |= (reg_id & BLR_RN_MASK) << BLR_RN_SHIFT;
+
+    return blr_inst;
+}
+
+void xnu_hook_tr_install(hwaddr va, hwaddr pa, hwaddr cb_va, hwaddr tr_buf_va,
+                         hwaddr tr_buf_pa, uint8_t scratch_reg)
+{
+    //must run setup before installing hook
+    if ((NULL == xnu_hook_tr_as) || (NULL == xnu_hook_tr_cpu)) {
+        abort();
+    }
+
+    if ((0 == va) || (0 == pa) || (0 == cb_va) || (0 == tr_buf_va) ||
+        (0 == tr_buf_pa)) {
+        abort();
+    }
+
+    uint32_t backup_insts[3] = {0};
+    uint32_t new_insts[3] = {0};
+    uint32_t tr_insts[TRAMPOLINE_CODE_INSTS] = {0};
+    uint64_t i = 0;
+
+    address_space_rw(xnu_hook_tr_as, pa, MEMTXATTRS_UNSPECIFIED,
+                     (uint8_t *)&backup_insts[0], sizeof(backup_insts), 0);
+
+    new_insts[0] = get_adrp_inst(va, tr_buf_va, scratch_reg);
+    new_insts[1] = get_add_inst(scratch_reg, scratch_reg,
+                                tr_buf_va & PAGE_4K_MASK);
+    new_insts[2] = get_br_inst(scratch_reg);
+
+    address_space_rw(xnu_hook_tr_as, pa, MEMTXATTRS_UNSPECIFIED,
+                     (uint8_t *)&new_insts[0], sizeof(new_insts), 1);
+
+    //31 is treated as sp in aarch64
+    tr_insts[i++] = get_add_inst(scratch_reg, 31, 0);
+    tr_insts[i++] = get_sub_inst(scratch_reg ,scratch_reg, 0x200);
+
+    tr_insts[i++] = get_stp_inst(0, 1, scratch_reg, 0);
+    tr_insts[i++] = get_stp_inst(2, 3, scratch_reg, 0x10);
+    tr_insts[i++] = get_stp_inst(4, 5, scratch_reg, 0x20);
+    tr_insts[i++] = get_stp_inst(6, 7, scratch_reg, 0x30);
+    tr_insts[i++] = get_stp_inst(8, 9, scratch_reg, 0x40);
+    tr_insts[i++] = get_stp_inst(10, 11, scratch_reg, 0x50);
+    tr_insts[i++] = get_stp_inst(12, 13, scratch_reg, 0x60);
+    tr_insts[i++] = get_stp_inst(14, 15, scratch_reg, 0x70);
+    tr_insts[i++] = get_stp_inst(16, 17, scratch_reg, 0x80);
+    tr_insts[i++] = get_stp_inst(18, 19, scratch_reg, 0x90);
+    tr_insts[i++] = get_stp_inst(20, 21, scratch_reg, 0xa0);
+    tr_insts[i++] = get_stp_inst(22, 23, scratch_reg, 0x30);
+    tr_insts[i++] = get_stp_inst(24, 25, scratch_reg, 0xb0);
+    tr_insts[i++] = get_stp_inst(26, 27, scratch_reg, 0xc0);
+    tr_insts[i++] = get_stp_inst(28, 29, scratch_reg, 0xd0);
+    tr_insts[i++] = get_stp_inst(0, 30, scratch_reg, 0xe0);
+
+    tr_insts[i++] = get_str_64_fp_inst(0, scratch_reg, 0xf0);
+    tr_insts[i++] = get_str_64_fp_inst(1, scratch_reg, 0xf8);
+    tr_insts[i++] = get_str_64_fp_inst(2, scratch_reg, 0x100);
+    tr_insts[i++] = get_str_64_fp_inst(3, scratch_reg, 0x108);
+    tr_insts[i++] = get_str_64_fp_inst(4, scratch_reg, 0x110);
+    tr_insts[i++] = get_str_64_fp_inst(5, scratch_reg, 0x118);
+    tr_insts[i++] = get_str_64_fp_inst(6, scratch_reg, 0x120);
+    tr_insts[i++] = get_str_64_fp_inst(7, scratch_reg, 0x128);
+    tr_insts[i++] = get_str_64_fp_inst(8, scratch_reg, 0x130);
+    tr_insts[i++] = get_str_64_fp_inst(9, scratch_reg, 0x138);
+    tr_insts[i++] = get_str_64_fp_inst(10, scratch_reg, 0x140);
+    tr_insts[i++] = get_str_64_fp_inst(11, scratch_reg, 0x148);
+    tr_insts[i++] = get_str_64_fp_inst(12, scratch_reg, 0x150);
+    tr_insts[i++] = get_str_64_fp_inst(13, scratch_reg, 0x158);
+    tr_insts[i++] = get_str_64_fp_inst(14, scratch_reg, 0x160);
+    tr_insts[i++] = get_str_64_fp_inst(15, scratch_reg, 0x168);
+    tr_insts[i++] = get_str_64_fp_inst(16, scratch_reg, 0x170);
+    tr_insts[i++] = get_str_64_fp_inst(17, scratch_reg, 0x178);
+    tr_insts[i++] = get_str_64_fp_inst(18, scratch_reg, 0x180);
+    tr_insts[i++] = get_str_64_fp_inst(19, scratch_reg, 0x188);
+    tr_insts[i++] = get_str_64_fp_inst(20, scratch_reg, 0x190);
+    tr_insts[i++] = get_str_64_fp_inst(21, scratch_reg, 0x198);
+    tr_insts[i++] = get_str_64_fp_inst(22, scratch_reg, 0x1a0);
+    tr_insts[i++] = get_str_64_fp_inst(23, scratch_reg, 0x1a8);
+    tr_insts[i++] = get_str_64_fp_inst(24, scratch_reg, 0x1b0);
+    tr_insts[i++] = get_str_64_fp_inst(25, scratch_reg, 0x1b8);
+    tr_insts[i++] = get_str_64_fp_inst(26, scratch_reg, 0x1c0);
+    tr_insts[i++] = get_str_64_fp_inst(27, scratch_reg, 0x1c8);
+    tr_insts[i++] = get_str_64_fp_inst(28, scratch_reg, 0x1d0);
+    tr_insts[i++] = get_str_64_fp_inst(29, scratch_reg, 0x1d8);
+    tr_insts[i++] = get_str_64_fp_inst(30, scratch_reg, 0x1e0);
+    tr_insts[i++] = get_str_64_fp_inst(31, scratch_reg, 0x1e8);
+
+    tr_insts[i++] = get_sub_inst(31 ,31, 0x200);
+
+    tr_insts[i] = get_adrp_inst(tr_buf_va  + (i * 4), cb_va, scratch_reg);
+    i++;
+    tr_insts[i++] = get_add_inst(scratch_reg, scratch_reg,
+                                 cb_va & PAGE_4K_MASK);
+    tr_insts[i++] = get_blr_inst(scratch_reg);
+
+    tr_insts[i++] = get_add_inst(scratch_reg, 31, 0);
+
+    tr_insts[i++] = get_ldp_inst(0, 1, scratch_reg, 0);
+    tr_insts[i++] = get_ldp_inst(2, 3, scratch_reg, 0x10);
+    tr_insts[i++] = get_ldp_inst(4, 5, scratch_reg, 0x20);
+    tr_insts[i++] = get_ldp_inst(6, 7, scratch_reg, 0x30);
+    tr_insts[i++] = get_ldp_inst(8, 9, scratch_reg, 0x40);
+    tr_insts[i++] = get_ldp_inst(10, 11, scratch_reg, 0x50);
+    tr_insts[i++] = get_ldp_inst(12, 13, scratch_reg, 0x60);
+    tr_insts[i++] = get_ldp_inst(14, 15, scratch_reg, 0x70);
+    tr_insts[i++] = get_ldp_inst(16, 17, scratch_reg, 0x80);
+    tr_insts[i++] = get_ldp_inst(18, 19, scratch_reg, 0x90);
+    tr_insts[i++] = get_ldp_inst(20, 21, scratch_reg, 0xa0);
+    tr_insts[i++] = get_ldp_inst(22, 23, scratch_reg, 0x30);
+    tr_insts[i++] = get_ldp_inst(24, 25, scratch_reg, 0xb0);
+    tr_insts[i++] = get_ldp_inst(26, 27, scratch_reg, 0xc0);
+    tr_insts[i++] = get_ldp_inst(28, 29, scratch_reg, 0xd0);
+    tr_insts[i++] = get_ldp_inst(0, 30, scratch_reg, 0xe0);
+
+    tr_insts[i++] = get_ldr_64_fp_inst(0, scratch_reg, 0xf0);
+    tr_insts[i++] = get_ldr_64_fp_inst(1, scratch_reg, 0xf8);
+    tr_insts[i++] = get_ldr_64_fp_inst(2, scratch_reg, 0x100);
+    tr_insts[i++] = get_ldr_64_fp_inst(3, scratch_reg, 0x108);
+    tr_insts[i++] = get_ldr_64_fp_inst(4, scratch_reg, 0x110);
+    tr_insts[i++] = get_ldr_64_fp_inst(5, scratch_reg, 0x118);
+    tr_insts[i++] = get_ldr_64_fp_inst(6, scratch_reg, 0x120);
+    tr_insts[i++] = get_ldr_64_fp_inst(7, scratch_reg, 0x128);
+    tr_insts[i++] = get_ldr_64_fp_inst(8, scratch_reg, 0x130);
+    tr_insts[i++] = get_ldr_64_fp_inst(9, scratch_reg, 0x138);
+    tr_insts[i++] = get_ldr_64_fp_inst(10, scratch_reg, 0x140);
+    tr_insts[i++] = get_ldr_64_fp_inst(11, scratch_reg, 0x148);
+    tr_insts[i++] = get_ldr_64_fp_inst(12, scratch_reg, 0x150);
+    tr_insts[i++] = get_ldr_64_fp_inst(13, scratch_reg, 0x158);
+    tr_insts[i++] = get_ldr_64_fp_inst(14, scratch_reg, 0x160);
+    tr_insts[i++] = get_ldr_64_fp_inst(15, scratch_reg, 0x168);
+    tr_insts[i++] = get_ldr_64_fp_inst(16, scratch_reg, 0x170);
+    tr_insts[i++] = get_ldr_64_fp_inst(17, scratch_reg, 0x178);
+    tr_insts[i++] = get_ldr_64_fp_inst(18, scratch_reg, 0x180);
+    tr_insts[i++] = get_ldr_64_fp_inst(19, scratch_reg, 0x188);
+    tr_insts[i++] = get_ldr_64_fp_inst(20, scratch_reg, 0x190);
+    tr_insts[i++] = get_ldr_64_fp_inst(21, scratch_reg, 0x198);
+    tr_insts[i++] = get_ldr_64_fp_inst(22, scratch_reg, 0x1a0);
+    tr_insts[i++] = get_ldr_64_fp_inst(23, scratch_reg, 0x1a8);
+    tr_insts[i++] = get_ldr_64_fp_inst(24, scratch_reg, 0x1b0);
+    tr_insts[i++] = get_ldr_64_fp_inst(25, scratch_reg, 0x1b8);
+    tr_insts[i++] = get_ldr_64_fp_inst(26, scratch_reg, 0x1c0);
+    tr_insts[i++] = get_ldr_64_fp_inst(27, scratch_reg, 0x1c8);
+    tr_insts[i++] = get_ldr_64_fp_inst(28, scratch_reg, 0x1d0);
+    tr_insts[i++] = get_ldr_64_fp_inst(29, scratch_reg, 0x1d8);
+    tr_insts[i++] = get_ldr_64_fp_inst(30, scratch_reg, 0x1e0);
+    tr_insts[i++] = get_ldr_64_fp_inst(31, scratch_reg, 0x1e8);
+
+    tr_insts[i++] = get_add_inst(31 ,31, 0x200);
+
+    tr_insts[i] = get_adrp_inst(tr_buf_va + (i * 4),
+                                va + sizeof(backup_insts), scratch_reg);
+    i++;
+    tr_insts[i++] = get_add_inst(scratch_reg, scratch_reg,
+                                 (va + sizeof(backup_insts)) & PAGE_4K_MASK);
+    tr_insts[i++] = backup_insts[0];
+    tr_insts[i++] = backup_insts[1];
+    tr_insts[i++] = backup_insts[2];
+    tr_insts[i++] = get_br_inst(scratch_reg);
+
+    if (i >= TRAMPOLINE_CODE_INSTS) {
+        abort();
+    }
+
+    address_space_rw(xnu_hook_tr_as, tr_buf_pa, MEMTXATTRS_UNSPECIFIED,
+                     (uint8_t *)&tr_insts[0], sizeof(tr_insts), 1);
+
+    va_make_exec(xnu_hook_tr_cpu, xnu_hook_tr_as, tr_buf_va,
+                 TRAMPOLINE_CODE_SIZE);
+}
+
+void xnu_hook_tr_copy_install(hwaddr va, hwaddr pa, hwaddr buf_va,
+                              hwaddr buf_pa, uint8_t *code, uint64_t code_size,
+                              uint64_t buf_size, uint8_t scratch_reg)
+{
+    //must run setup before installing hook
+    if ((NULL == xnu_hook_tr_as) || (NULL == xnu_hook_tr_cpu)) {
+        abort();
+    }
+
+    if ((0 == va) || (0 == pa) || (0 == buf_va) || (0 == buf_pa) ||
+        (NULL == code) || (0 == code_size) || (0 == buf_size)) {
+        abort();
+    }
+
+    if ((code_size + TRAMPOLINE_CODE_SIZE) >= buf_size) {
+        abort();
+    }
+
+    address_space_rw(xnu_hook_tr_as, (buf_pa + TRAMPOLINE_CODE_SIZE),
+                     MEMTXATTRS_UNSPECIFIED, (uint8_t *)code, code_size, 1);
+    va_make_exec(xnu_hook_tr_cpu, xnu_hook_tr_as, buf_va, buf_size);
+    xnu_hook_tr_install(va, pa, buf_va + TRAMPOLINE_CODE_SIZE, buf_va, buf_pa,
+                        scratch_reg);
+}
+
+void xnu_hook_tr_setup(AddressSpace *as, ARMCPU *cpu)
+{
+    //allow setup only once
+    if ((NULL != xnu_hook_tr_as) || (NULL != xnu_hook_tr_cpu)) {
+        abort();
+    }
+
+    //must setup with a non NULL AddressSpace
+    if (NULL == as) {
+        abort();
+    }
+
+    //must setup with a non NULL CPU
+    if (NULL == cpu) {
+        abort();
+    }
+
+    xnu_hook_tr_cpu = cpu;
+    xnu_hook_tr_as = as;
+}
diff --git a/xnu-qemu-arm64-5.1.0/hw/display/xnu_ramfb.c b/xnu-qemu-arm64-5.1.0/hw/display/xnu_ramfb.c
new file mode 100644
index 0000000..b20609f
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/hw/display/xnu_ramfb.c
@@ -0,0 +1,141 @@
+#include "qemu/osdep.h"
+#include "hw/loader.h"
+#include "hw/qdev-properties.h"
+#include "hw/display/xnu_ramfb.h"
+#include "ui/console.h"
+
+#define XNU_RAMFB(obj) \
+    OBJECT_CHECK(xnu_ramfb_state, (obj), TYPE_XNU_RAMFB_DEVICE)
+
+typedef struct display_cfg{
+    uint32_t format;
+    uint32_t width;
+    uint32_t height;
+    uint32_t linesize;
+} xnu_display_cfg;
+
+typedef struct xnu_ramfb_state {
+    SysBusDevice parent_obj;
+    xnu_display_cfg display_cfg;
+    QemuConsole* con;
+    uint8_t* qemu_fb_ptr; //Pointer that will sent to display callbacks
+    hwaddr fb_pa;
+    uint32_t fb_size;
+    hwaddr as;
+} xnu_ramfb_state;
+
+void xnu_ramfb_display_update(void *opaque)
+{
+    DisplaySurface *ds = NULL;
+    xnu_ramfb_state *xnu_ramfb = XNU_RAMFB(opaque);
+    uint32_t format = xnu_ramfb->display_cfg.format;
+    uint32_t width = xnu_ramfb->display_cfg.width;
+    uint32_t height = xnu_ramfb->display_cfg.height;
+    uint32_t linesize = xnu_ramfb->display_cfg.linesize;
+    QemuConsole *con = xnu_ramfb->con;
+    hwaddr as = xnu_ramfb->as;
+    hwaddr fb_pa = xnu_ramfb->fb_pa;
+    uint32_t fb_size = xnu_ramfb->fb_size;
+    uint8_t*  qemu_fb_ptr = xnu_ramfb->qemu_fb_ptr;
+
+    assert(qemu_fb_ptr != 0);
+    assert(fb_pa != 0);
+
+    address_space_rw((AddressSpace*) as, fb_pa, MEMTXATTRS_UNSPECIFIED,
+                qemu_fb_ptr, fb_size, FALSE);
+    ds = qemu_create_displaysurface_from(
+        width, height, format, linesize, qemu_fb_ptr);
+    if (ds) {
+        dpy_gfx_replace_surface(con, ds);
+    }
+    dpy_gfx_update_full(con);
+}
+
+void xnu_display_prolog(xnu_ramfb_state* xnu_fb_state)
+{
+    //currently empty
+    return;
+}
+
+void xnu_ramfb_setup(xnu_ramfb_state* xnu_fb_state)
+{
+    uint8_t* fb_ptr;
+    xnu_fb_state->display_cfg.format = PIXMAN_LE_r8g8b8;
+
+    if (xnu_fb_state->fb_size == 0){
+        fprintf(stderr,
+            "xnu_ram_fb: size for the framebuffer is zero, aborting...\n");
+        abort();
+    }
+    fb_ptr = g_malloc0(xnu_fb_state->fb_size);
+    if (fb_ptr == NULL){
+        fprintf(stderr,
+            "xnu_ram_fb: failed to allocate memory for the framebuffer.\n");
+        abort();
+    }
+    xnu_fb_state->qemu_fb_ptr = fb_ptr;
+
+    xnu_display_prolog(xnu_fb_state);
+}
+
+void xnu_ramfb_free(uint8_t* qemu_fb_ptr)
+{
+    g_free(qemu_fb_ptr);
+}
+
+static const GraphicHwOps wrapper_ops = {
+    .gfx_update = xnu_ramfb_display_update,
+};
+
+static void xnu_ramfb_realizefn(DeviceState *dev, Error **errp)
+{
+    xnu_ramfb_state *xnu_ramfb = XNU_RAMFB(dev);
+    xnu_ramfb->con = graphic_console_init(dev, 0, &wrapper_ops, dev);
+    xnu_ramfb_setup(xnu_ramfb);
+}
+
+static void xnu_ramfb_unrealizefn(DeviceState *dev, Error **errp)
+{
+    xnu_ramfb_state *xnu_ramfb = XNU_RAMFB(dev);
+    graphic_console_close(xnu_ramfb->con);
+    xnu_ramfb_free(xnu_ramfb->qemu_fb_ptr);
+}
+
+static Property xnu_ramfb_properties[] = {
+    DEFINE_PROP_UINT64("as", xnu_ramfb_state, as, 0),
+    DEFINE_PROP_UINT64("fb_pa", xnu_ramfb_state, fb_pa, 0),
+    DEFINE_PROP_UINT32("fb_size", xnu_ramfb_state, fb_size, 0),
+    DEFINE_PROP_UINT32("display_cfg.width", xnu_ramfb_state,
+                display_cfg.width, 0),
+    DEFINE_PROP_UINT32("display_cfg.height", xnu_ramfb_state,
+                display_cfg.height, 0),
+    DEFINE_PROP_UINT32("display_cfg.linesize", xnu_ramfb_state,
+                display_cfg.linesize, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xnu_ramfb_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+    dc->realize = xnu_ramfb_realizefn;
+    dc->unrealize = xnu_ramfb_unrealizefn;
+    dc->props = xnu_ramfb_properties;
+    dc->desc = "xnu ram framebuffer";
+    dc->user_creatable = true;
+}
+
+static const TypeInfo xnu_ramfb_info = {
+    .name          = TYPE_XNU_RAMFB_DEVICE,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(xnu_ramfb_state),
+    .class_init    = xnu_ramfb_class_initfn,
+};
+
+static void xnu_ramfb_register_types(void)
+{
+    type_register_static(&xnu_ramfb_info);
+}
+
+type_init(xnu_ramfb_register_types)
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/fds.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/fds.h
new file mode 100644
index 0000000..83a415c
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/fds.h
@@ -0,0 +1,67 @@
+/*
+ * QEMU TCP Tunnelling
+ *
+ * Copyright (c) 2019 Lev Aronsky <aronsky@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_GUEST_SERVICES_FDS_H
+#define HW_ARM_GUEST_SERVICES_FDS_H
+
+#ifndef OUT_OF_TREE_BUILD
+#include "qemu/osdep.h"
+#else
+#include "sys/types.h"
+#include "sys/socket.h"
+#endif
+
+#define MAX_FD_COUNT (256)
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+extern int32_t guest_svcs_errno;
+#pragma GCC diagnostic pop
+extern int32_t guest_svcs_fds[MAX_FD_COUNT];
+
+#define VERIFY_FD(s) \
+    if ((s < 0) || (s >= MAX_FD_COUNT) || (-1 == guest_svcs_fds[s])) return -1;
+
+typedef struct __attribute__((packed)) {
+    int32_t fd;
+} qc_close_args_t;
+
+typedef struct __attribute__((packed)) {
+    int32_t fd;
+    int32_t cmd;
+    union {
+        int32_t flags;
+    };
+} qc_fcntl_args_t;
+
+#ifndef OUT_OF_TREE_BUILD
+int32_t qc_handle_close(CPUState *cpu, int32_t fd);
+int32_t qc_handle_fcntl_getfl(CPUState *cpu, int32_t fd);
+int32_t qc_handle_fcntl_setfl(CPUState *cpu, int32_t fd, int32_t flags);
+#else
+int qc_close(int fd);
+int qc_fcntl(int fd, int cmd, ...);
+#endif
+
+#endif // HW_ARM_GUEST_SERVICES_FDS_H
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/file.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/file.h
new file mode 100644
index 0000000..bd88591
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/file.h
@@ -0,0 +1,69 @@
+/*
+ * QEMU Host file guest access
+ *
+ * Copyright (c) 2020 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_GUEST_SERVICES_FILE_H
+#define HW_ARM_GUEST_SERVICES_FILE_H
+
+#ifndef OUT_OF_TREE_BUILD
+#include "qemu/osdep.h"
+#else
+#include "sys/types.h"
+#endif
+
+#define MAX_FILE_FDS (8)
+#define MAX_FILE_TRANSACTION_LEN (0x2000)
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+extern int32_t guest_svcs_errno;
+#pragma GCC diagnostic pop
+
+typedef struct __attribute__((packed)) {
+    uint64_t buffer_guest_ptr;
+    uint64_t length;
+    uint64_t offset;
+    uint64_t index;
+} qc_write_file_args_t, qc_read_file_args_t;
+
+typedef struct __attribute__((packed)) {
+    uint64_t index;
+} qc_size_file_args_t;
+
+#ifndef OUT_OF_TREE_BUILD
+void qc_file_open(uint64_t index, const char *filename);
+
+int64_t qc_handle_write_file(CPUState *cpu, uint64_t buffer_guest_ptr,
+                             uint64_t length, uint64_t offset, uint64_t index);
+int64_t qc_handle_read_file(CPUState *cpu, uint64_t buffer_guest_ptr,
+                            uint64_t length, uint64_t offset, uint64_t index);
+int64_t qc_handle_size_file(uint64_t index);
+#else
+int64_t qc_write_file(void *buffer_guest_ptr, uint64_t length,
+                      uint64_t offset, uint64_t index);
+int64_t qc_read_file(void *buffer_guest_ptr, uint64_t length,
+                     uint64_t offset, uint64_t index);
+int64_t qc_size_file(uint64_t index);
+#endif
+
+#endif
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/general.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/general.h
new file mode 100644
index 0000000..3b07d40
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/general.h
@@ -0,0 +1,88 @@
+/*
+ * QEMU TCP Tunnelling
+ *
+ * Copyright (c) 2019 Lev Aronsky <aronsky@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_GUEST_SERVICES_GENERAL_H
+#define HW_ARM_GUEST_SERVICES_GENERAL_H
+
+#include "hw/arm/guest-services/socket.h"
+#include "hw/arm/guest-services/fds.h"
+#include "hw/arm/guest-services/file.h"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+extern int32_t guest_svcs_errno;
+#pragma GCC diagnostic pop
+
+typedef enum {
+    // File Descriptors API
+    QC_CLOSE = 0x100,
+    QC_FCNTL,
+
+    // Socket API
+    QC_SOCKET = 0x110,
+    QC_ACCEPT,
+    QC_BIND,
+    QC_CONNECT,
+    QC_LISTEN,
+    QC_RECV,
+    QC_SEND,
+    QC_WRITE_FILE,
+    QC_READ_FILE,
+    QC_SIZE_FILE,
+} qemu_call_number_t;
+
+typedef struct __attribute__((packed)) {
+    // Request
+    qemu_call_number_t call_number;
+    union {
+        // File Descriptors API
+        qc_close_args_t close;
+        qc_fcntl_args_t fcntl;
+        // Socket API
+        qc_socket_args_t socket;
+        qc_accept_args_t accept;
+        qc_bind_args_t bind;
+        qc_connect_args_t connect;
+        qc_listen_args_t listen;
+        qc_recv_args_t recv;
+        qc_send_args_t send;
+        qc_write_file_args_t write_file;
+        qc_read_file_args_t read_file;
+        qc_size_file_args_t size_file;
+    } args;
+
+    // Response
+    int64_t retval;
+    int64_t error;
+} qemu_call_t;
+
+#ifndef OUT_OF_TREE_BUILD
+uint64_t qemu_call_status(CPUARMState *env, const ARMCPRegInfo *ri);
+void qemu_call(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value);
+#else
+uint64_t qemu_call_status(qemu_call_t *qcall);
+void qemu_call(qemu_call_t *qcall);
+#endif
+
+#endif // HW_ARM_GUEST_SERVICES_GENERAL_H
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/socket.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/socket.h
new file mode 100644
index 0000000..ff98bd8
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/guest-services/socket.h
@@ -0,0 +1,96 @@
+/*
+ * QEMU TCP Tunnelling
+ *
+ * Copyright (c) 2019 Lev Aronsky <aronsky@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_GUEST_SERVICES_SOCKET_H
+#define HW_ARM_GUEST_SERVICES_SOCKET_H
+
+#ifndef OUT_OF_TREE_BUILD
+#include "qemu/osdep.h"
+#else
+#include "sys/types.h"
+#include "sys/socket.h"
+#endif
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+extern int32_t guest_svcs_errno;
+#pragma GCC diagnostic pop
+
+#define MAX_BUF_SIZE (4096)
+
+typedef struct __attribute__((packed)) {
+    int32_t domain;
+    int32_t type;
+    int32_t protocol;
+} qc_socket_args_t;
+
+typedef struct __attribute__((packed)) {
+    int32_t socket;
+    struct sockaddr *addr;
+    socklen_t *addrlen;
+} qc_accept_args_t;
+
+typedef struct __attribute__((packed)) {
+    int32_t socket;
+    struct sockaddr *addr;
+    socklen_t addrlen;
+} qc_bind_args_t, qc_connect_args_t;
+
+typedef struct __attribute__((packed)) {
+    int32_t socket;
+    int32_t backlog;
+} qc_listen_args_t;
+
+typedef struct __attribute__((packed)) {
+    int32_t socket;
+    void *buffer;
+    size_t length;
+    int flags;
+} qc_recv_args_t, qc_send_args_t;
+
+#ifndef OUT_OF_TREE_BUILD
+int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type,
+                         int32_t protocol);
+int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct sockaddr *addr,
+                         socklen_t *addrlen);
+int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, struct sockaddr *addr,
+                       socklen_t addrlen);
+int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, struct sockaddr *addr,
+                          socklen_t addrlen);
+int32_t qc_handle_listen(CPUState *cpu, int32_t sckt, int32_t backlog);
+int32_t qc_handle_recv(CPUState *cpu, int32_t sckt, void *buffer,
+                       size_t length, int32_t flags);
+int32_t qc_handle_send(CPUState *cpu, int32_t sckt, void *buffer,
+                       size_t length, int32_t flags);
+#else
+int qc_socket(int domain, int type, int protocol);
+int qc_accept(int sckt, struct sockaddr *addr, socklen_t *addrlen);
+int qc_bind(int sckt, const struct sockaddr *addr, socklen_t addrlen);
+int qc_connect(int sckt, const struct sockaddr *addr, socklen_t addrlen);
+int qc_listen(int sckt, int backlog);
+ssize_t qc_recv(int sckt, void *buffer, size_t length, int flags);
+ssize_t qc_send(int sckt, const void *buffer, size_t length, int flags);
+#endif
+
+#endif // HW_ARM_GUEST_SERVICES_SOCKET_H
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/j273_macos11.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/j273_macos11.h
new file mode 100644
index 0000000..3b9e07a
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/j273_macos11.h
@@ -0,0 +1,117 @@
+/*
+ * iPhone 6s plus - n66 - S8000
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_J273_H
+#define HW_ARM_J273_H
+
+#include "qemu-common.h"
+#include "exec/hwaddr.h"
+#include "hw/boards.h"
+#include "hw/arm/boot.h"
+#include "hw/arm/xnu.h"
+#include "exec/memory.h"
+#include "cpu.h"
+#include "sysemu/kvm.h"
+
+#define MAX_CUSTOM_HOOKS (30)
+
+#define CUSTOM_HOOKS_GLOBALS_SIZE (0x400)
+
+#define TYPE_J273 "macos11-j273-a12z"
+
+#define TYPE_J273_MACHINE   MACHINE_TYPE_NAME(TYPE_J273)
+
+#define J273_MACHINE(obj) \
+    OBJECT_CHECK(J273MachineState, (obj), TYPE_J273_MACHINE)
+
+#define J273_CPREG_VAR_NAME(name) cpreg_##name
+#define J273_CPREG_VAR_DEF(name) uint64_t J273_CPREG_VAR_NAME(name)
+
+typedef struct {
+    MachineClass parent;
+} J273MachineClass;
+
+typedef struct {
+    MachineState parent;
+    uint64_t hook_funcs_count;
+    hwaddr extra_data_pa;
+    hwaddr kpc_pa;
+    hwaddr kbootargs_pa;
+    hwaddr uart_mmio_pa;
+    ARMCPU *cpu;
+    KernelTrHookParams hook;
+    KernelTrHookParams hook_funcs[MAX_CUSTOM_HOOKS];
+    struct arm_boot_info bootinfo;
+    char ramdisk_filename[1024];
+    char kernel_filename[1024];
+    char dtb_filename[1024];
+    char hook_funcs_cfg[1024 * 1024];
+    char driver_filename[1024];
+    char qc_file_0_filename[1024];
+    char qc_file_1_filename[1024];
+    char qc_file_log_filename[1024];
+    char kern_args[1024];
+    uint16_t tunnel_port;
+    FileMmioDev ramdisk_file_dev;
+    bool use_ramfb;
+    J273_CPREG_VAR_DEF(ARM64_REG_EHID1);
+    J273_CPREG_VAR_DEF(ARM64_REG_EHID10);
+    J273_CPREG_VAR_DEF(ARM64_REG_EHID4);
+    J273_CPREG_VAR_DEF(ARM64_REG_HID11);
+    J273_CPREG_VAR_DEF(ARM64_REG_HID3);
+    J273_CPREG_VAR_DEF(ARM64_REG_HID5);
+    J273_CPREG_VAR_DEF(ARM64_REG_HID4);
+    J273_CPREG_VAR_DEF(ARM64_REG_HID8);
+    J273_CPREG_VAR_DEF(ARM64_REG_HID7);
+    J273_CPREG_VAR_DEF(ARM64_REG_LSU_ERR_STS);
+    J273_CPREG_VAR_DEF(PMC0);
+    J273_CPREG_VAR_DEF(PMC1);
+    J273_CPREG_VAR_DEF(PMCR1);
+    J273_CPREG_VAR_DEF(PMSR);
+    J273_CPREG_VAR_DEF(L2ACTLR_EL1);
+    /* EL2 REGS */
+    J273_CPREG_VAR_DEF(ARM64_REG_MIGSTS_EL1);
+    J273_CPREG_VAR_DEF(ARM64_REG_KERNELKEYLO_EL1);
+    J273_CPREG_VAR_DEF(ARM64_REG_KERNELKEYHI_EL1);
+    J273_CPREG_VAR_DEF(ARM64_REG_VMSA_LOCK_EL1);
+    J273_CPREG_VAR_DEF(APRR_EL0);
+    J273_CPREG_VAR_DEF(APRR_EL1);
+    J273_CPREG_VAR_DEF(CTRR_LOCK);
+    J273_CPREG_VAR_DEF(CTRR_A_LWR_EL1);
+    J273_CPREG_VAR_DEF(CTRR_A_UPR_EL1);
+    J273_CPREG_VAR_DEF(CTRR_CTL_EL1);
+    J273_CPREG_VAR_DEF(APRR_MASK_EN_EL1);
+    J273_CPREG_VAR_DEF(APRR_MASK_EL0);
+    J273_CPREG_VAR_DEF(ACC_CTRR_A_LWR_EL2);
+    J273_CPREG_VAR_DEF(ACC_CTRR_A_UPR_EL2);
+    J273_CPREG_VAR_DEF(ACC_CTRR_CTL_EL2);
+    J273_CPREG_VAR_DEF(ACC_CTRR_LOCK_EL2);
+    J273_CPREG_VAR_DEF(ARM64_REG_CYC_CFG);
+    J273_CPREG_VAR_DEF(ARM64_REG_CYC_OVRD);
+    J273_CPREG_VAR_DEF(IPI_SR);
+    J273_CPREG_VAR_DEF(UPMCR0);
+    J273_CPREG_VAR_DEF(UPMPCM);
+} J273MachineState;
+
+#endif
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu.h
new file mode 100644
index 0000000..b5e696d
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu.h
@@ -0,0 +1,157 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_XNU_H
+#define HW_ARM_XNU_H
+
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "hw/arm/xnu_mem.h"
+#include "hw/arm/xnu_trampoline_hook.h"
+#include "hw/arm/xnu_dtb.h"
+#include "hw/arm/xnu_cpacr.h"
+#include "hw/arm/xnu_pagetable.h"
+#include "hw/arm/xnu_trampoline_hook.h"
+#include "hw/arm/xnu_file_mmio_dev.h"
+#include "hw/arm/xnu_fb_cfg.h"
+
+// pexpert/pexpert/arm64/boot.h
+#define xnu_arm64_kBootArgsRevision2 2 /* added boot_args.bootFlags */
+#define xnu_arm64_kBootArgsVersion2 2
+#define xnu_arm64_BOOT_LINE_LENGTH 256
+
+#define LC_SEGMENT_64   0x19
+#define LC_UNIXTHREAD   0x5
+
+struct segment_command_64
+{
+    uint32_t cmd;
+    uint32_t cmdsize;
+    char segname[16];
+    uint64_t vmaddr;
+    uint64_t vmsize;
+    uint64_t fileoff;
+    uint64_t filesize;
+    uint32_t /*vm_prot_t*/ maxprot;
+    uint32_t /*vm_prot_t*/ initprot;
+    uint32_t nsects;
+    uint32_t flags;
+};
+
+struct mach_header_64 {
+    uint32_t    magic;      /* mach magic number identifier */
+    uint32_t /*cpu_type_t*/  cputype;    /* cpu specifier */
+    uint32_t /*cpu_subtype_t*/   cpusubtype; /* machine specifier */
+    uint32_t    filetype;   /* type of file */
+    uint32_t    ncmds;      /* number of load commands */
+    uint32_t    sizeofcmds; /* the size of all the load commands */
+    uint32_t    flags;      /* flags */
+    uint32_t    reserved;   /* reserved */
+};
+
+struct load_command {
+    uint32_t cmd;       /* type of load command */
+    uint32_t cmdsize;   /* total size of command in bytes */
+};
+
+typedef struct xnu_arm64_video_boot_args {
+    unsigned long v_baseAddr; /* Base address of video memory */
+    unsigned long v_display;  /* Display Code (if Applicable */
+    unsigned long v_rowBytes; /* Number of bytes per pixel row */
+    unsigned long v_width;    /* Width */
+    unsigned long v_height;   /* Height */
+    unsigned long v_depth;    /* Pixel Depth and other parameters */
+} video_boot_args;
+
+typedef struct xnu_arm64_monitor_boot_args {
+	uint64_t	version;                        /* structure version - this is version 2 */
+	uint64_t	virtBase;                       /* virtual base of memory assigned to the monitor */
+	uint64_t	physBase;                       /* physical address corresponding to the virtual base */
+	uint64_t	memSize;                        /* size of memory assigned to the monitor */
+	uint64_t	kernArgs;                       /* physical address of the kernel boot_args structure */
+	uint64_t	kernEntry;                      /* kernel entrypoint */
+	uint64_t	kernPhysBase;                   /* physical base of the kernel's address space */
+	uint64_t	kernPhysSlide;                  /* offset from kernPhysBase to kernel load address */
+	uint64_t	kernVirtSlide;                  /* virtual slide applied to kernel at load time */
+} monitor_boot_args;
+
+struct xnu_arm64_boot_args {
+    uint16_t           Revision;                                   /* Revision of boot_args structure */
+    uint16_t           Version;                                    /* Version of boot_args structure */
+    uint64_t           virtBase;                                   /* Virtual base of memory */
+    uint64_t           physBase;                                   /* Physical base of memory */
+    uint64_t           memSize;                                    /* Size of memory */
+    uint64_t           topOfKernelData;                            /* Highest physical address used in kernel data area */
+    video_boot_args    Video;                                      /* Video Information */
+    uint32_t           machineType;                                /* Machine Type */
+    uint64_t           deviceTreeP;                                /* Base of flattened device tree */
+    uint32_t           deviceTreeLength;                           /* Length of flattened tree */
+    char               CommandLine[xnu_arm64_BOOT_LINE_LENGTH];    /* Passed in command line */
+    uint64_t           bootFlags;                                  /* Additional flags specified by the bootloader */
+    uint64_t           memSizeActual;                              /* Actual size of memory */
+};
+
+void macho_file_highest_lowest_base(const char *filename, hwaddr phys_base,
+                                    hwaddr *virt_base, hwaddr *lowest,
+                                    hwaddr *highest);
+
+void macho_tz_setup_bootargs(const char *name, AddressSpace *as,
+                             MemoryRegion *mem, hwaddr bootargs_addr,
+                             hwaddr virt_base, hwaddr phys_base,
+                             hwaddr mem_size, hwaddr kern_args,
+                             hwaddr kern_entry, hwaddr kern_phys_base);
+
+void macho_setup_bootargs(const char *name, AddressSpace *as,
+                          MemoryRegion *mem, hwaddr bootargs_pa,
+                          hwaddr virt_base, hwaddr phys_base, hwaddr mem_size,
+                          hwaddr top_of_kernel_data_pa, hwaddr dtb_va,
+                          hwaddr dtb_size, video_boot_args v_bootargs,
+                          char *kern_args);
+
+void arm_load_macho(char *filename, AddressSpace *as, MemoryRegion *mem,
+                    const char *name, hwaddr phys_base, hwaddr virt_base,
+                    hwaddr low_virt_addr, hwaddr high_virt_addr, hwaddr *pc,
+                    char *darwin_ver);
+
+void macho_map_raw_file(const char *filename, AddressSpace *as, MemoryRegion *mem,
+                         const char *name, hwaddr file_pa, uint64_t *size);
+
+void macho_load_raw_file(const char *filename, AddressSpace *as, MemoryRegion *mem,
+                         const char *name, hwaddr file_pa, uint64_t *size);
+
+void macho_load_dtb(char *filename, AddressSpace *as, MemoryRegion *mem,
+                    const char *name, hwaddr dtb_pa, uint64_t *size,
+                    hwaddr ramdisk_addr, hwaddr ramdisk_size,
+                    hwaddr *uart_mmio_pa);
+
+#define MAX_CUSTOM_HOOKS (30)
+
+#define CUSTOM_HOOKS_GLOBALS_SIZE (0x400)
+
+typedef struct {
+    uint8_t hook_code[HOOK_CODE_ALLOC_SIZE];
+    uint8_t hook_funcs_code[MAX_CUSTOM_HOOKS][HOOK_CODE_ALLOC_SIZE];
+    uint8_t ramfb[RAMFB_SIZE];
+    uint8_t hook_globals[CUSTOM_HOOKS_GLOBALS_SIZE];
+} __attribute__((packed)) AllocatedData;
+#endif
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_cpacr.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_cpacr.h
new file mode 100644
index 0000000..45220eb
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_cpacr.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_XNU_CPACR_H
+#define HW_ARM_XNU_CPACR_H
+
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "cpu.h"
+
+typedef struct {
+    uint64_t val;
+    CPWriteFn *wfn_a64;
+    CPWriteFn *wfn_a32_ns;
+    CPWriteFn *wfn_a32_s;
+} CpacrIntCtx;
+
+void xnu_cpacr_intercept_write_const_val(ARMCPU *cpu, uint64_t val);
+
+#endif
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_dtb.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_dtb.h
new file mode 100644
index 0000000..5ae6fa1
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_dtb.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_XNU_DTB_H
+#define HW_ARM_XNU_DTB_H
+
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "hw/arm/xnu_mem.h"
+
+#define DT_PROP_FLAG_PLACEHOLDER (0x80000000)
+
+#define DTB_PROP_NAME_LEN (32)
+
+typedef struct {
+    uint8_t name[DTB_PROP_NAME_LEN];
+    uint32_t length;
+    uint8_t *value;
+} DTBProp;
+
+typedef struct {
+    uint32_t prop_count;
+    uint32_t child_node_count;
+    GList *props;
+    GList *child_nodes;
+} DTBNode;
+
+DTBNode *load_dtb(uint8_t *dtb_blob);
+void delete_dtb_node(DTBNode *node);
+void save_dtb(uint8_t *buf, DTBNode *root);
+void remove_dtb_prop(DTBNode *node, DTBProp *prop);
+void add_dtb_prop(DTBNode *n, const char *name, uint32_t size, uint8_t *val);
+uint64_t get_dtb_node_buffer_size(DTBNode *node);
+DTBProp *get_dtb_prop(DTBNode *node, const char *name);
+DTBNode *get_dtb_child_node_by_name(DTBNode *node, const char *name);
+void overwrite_dtb_prop_val(DTBProp *prop, uint8_t chr);
+void overwrite_dtb_prop_name(DTBProp *prop, uint8_t chr);
+
+#endif
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_fb_cfg.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_fb_cfg.h
new file mode 100644
index 0000000..0adb763
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_fb_cfg.h
@@ -0,0 +1,17 @@
+#ifndef HW_ARM_XNU_RAMFB_CFG_H
+#define HW_ARM_XNU_RAMFB_CFG_H
+
+#include "qemu/osdep.h"
+
+#define RAMFB_SIZE 0x2D4C00
+
+#define V_DEPTH     16
+#define V_HEIGHT    800
+#define V_WIDTH     600
+#define V_DISPLAY   0
+#define V_LINESIZE  (V_WIDTH * 3)
+
+void xnu_define_ramfb_device(AddressSpace* as, hwaddr ramfb_pa);
+void xnu_get_video_bootargs(void *opaque, hwaddr ramfb_pa);
+
+#endif
\ No newline at end of file
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_file_mmio_dev.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_file_mmio_dev.h
new file mode 100644
index 0000000..8864b37
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_file_mmio_dev.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_FILE_MMIO_DEV_H
+#define HW_ARM_FILE_MMIO_DEV_H
+
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+
+typedef struct {
+    hwaddr pa;
+    hwaddr size;
+    int fd;
+} FileMmioDev;
+
+void xnu_file_mmio_dev_create(MemoryRegion *sysmem, FileMmioDev *file_dev,
+                              const char *name, const char *filename);
+
+#endif
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_mem.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_mem.h
new file mode 100644
index 0000000..8b2ff6e
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_mem.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_XNU_MEM_H
+#define HW_ARM_XNU_MEM_H
+
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "target/arm/cpu.h"
+
+extern hwaddr g_virt_base;
+extern hwaddr g_phys_base;
+
+hwaddr vtop_static(hwaddr va);
+hwaddr ptov_static(hwaddr pa);
+hwaddr vtop_mmu(hwaddr va, CPUState *cs);
+
+hwaddr align_64k_low(hwaddr addr);
+hwaddr align_64k_high(hwaddr addr);
+
+hwaddr vtop_bases(hwaddr va, hwaddr phys_base, hwaddr virt_base);
+hwaddr ptov_bases(hwaddr pa, hwaddr phys_base, hwaddr virt_base);
+
+uint8_t get_highest_different_bit_index(hwaddr addr1, hwaddr addr2);
+uint8_t get_lowest_non_zero_bit_index(hwaddr addr);
+hwaddr get_low_bits_mask_for_bit_index(uint8_t bit_index);
+
+void allocate_ram(MemoryRegion *top, const char *name, hwaddr addr,
+                  hwaddr size);
+#endif
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_pagetable.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_pagetable.h
new file mode 100644
index 0000000..2bc6fbc
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_pagetable.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_XNU_PAGETABLE_H
+#define HW_ARM_XNU_PAGETABLE_H
+
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "cpu.h"
+
+hwaddr pt_tte_el1(ARMCPU *cpu, AddressSpace *as, hwaddr va, bool make_exe);
+void va_make_exec(ARMCPU *cpu, AddressSpace *as, hwaddr va, hwaddr size);
+
+#endif
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_trampoline_hook.h b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_trampoline_hook.h
new file mode 100644
index 0000000..650af10
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/arm/xnu_trampoline_hook.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright (c) 2019 Jonathan Afek <jonyafek@me.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_XNU_TRAMPOLINE_HOOK_H
+#define HW_ARM_XNU_TRAMPOLINE_HOOK_H
+
+#include "qemu-common.h"
+#include "hw/arm/boot.h"
+#include "cpu.h"
+
+#define HOOK_CODE_ALLOC_SIZE (1 << 20)
+
+typedef struct {
+    hwaddr va;
+    hwaddr pa;
+    hwaddr buf_va;
+    hwaddr buf_pa;
+    uint64_t buf_size;
+    uint8_t *code;
+    uint64_t code_size;
+    uint8_t scratch_reg;
+} KernelTrHookParams;
+
+void xnu_hook_tr_copy_install(hwaddr va, hwaddr pa, hwaddr buf_va,
+                              hwaddr buf_pa, uint8_t *code, uint64_t code_size,
+                              uint64_t buf_size, uint8_t scratch_reg);
+void xnu_hook_tr_install(hwaddr va, hwaddr pa, hwaddr cb_va, hwaddr tr_buf_va,
+                         hwaddr tr_buf_pa, uint8_t scratch_reg);
+void xnu_hook_tr_setup(AddressSpace *as, ARMCPU *cpu);
+
+#endif
diff --git a/xnu-qemu-arm64-5.1.0/include/hw/display/xnu_ramfb.h b/xnu-qemu-arm64-5.1.0/include/hw/display/xnu_ramfb.h
new file mode 100644
index 0000000..3ce5f1a
--- /dev/null
+++ b/xnu-qemu-arm64-5.1.0/include/hw/display/xnu_ramfb.h
@@ -0,0 +1,12 @@
+#ifndef XNU_RAMFB_H
+#define XNU_RAMFB_H
+
+typedef struct xnu_ramfb_state xnu_ramfb_state;
+void xnu_ramfb_display_update(void *opaque);
+void xnu_ramfb_setup(xnu_ramfb_state* xnu_fb_state);
+void xnu_ramfb_free(uint8_t* qemu_fb_ptr);
+void xnu_display_prolog(xnu_ramfb_state* xnu_fb_state);
+
+#define TYPE_XNU_RAMFB_DEVICE "xnu_ramfb"
+
+#endif /* XNU_RAMFB_H */
diff --git a/xnu-qemu-arm64-5.1.0/target/arm/helper.c b/xnu-qemu-arm64-5.1.0/target/arm/helper.c
index 455c92b..6cb6926 100644
--- a/xnu-qemu-arm64-5.1.0/target/arm/helper.c
+++ b/xnu-qemu-arm64-5.1.0/target/arm/helper.c
@@ -8486,7 +8486,7 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
         case 4:
         case 5:
             /* min_EL EL2 */
-            mask = PL2_RW;
+            mask = PL1_RW;
             break;
         case 6:
             /* min_EL EL3 */