//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.
//hack for now. create a device that is not used just to have a dummy
//unused interrupt
d = qdev_create(NULL, 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 n66_patch_kernel(AddressSpace nsas)
{
//patch the initial branch with instructions that set up CPACR
address_space_rw(nsas, vtop_static(INITIAL_BRANCH_VADDR_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t )&g_set_cpacr_and_branch_inst,
sizeof(g_set_cpacr_and_branch_inst), 1);
//patch bzero to avoid "dc zva", which zeroes out different amount of bytes
//under different CPUs
address_space_rw(nsas, vtop_static(BZERO_COND_BRANCH_VADDR_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_bzero_branch_unconditionally_inst,
sizeof(g_bzero_branch_unconditionally_inst), 1);
//patch the smc instruction to nop since we no longer use a secure
//monitor because we disabled KPP this way
address_space_rw(nsas, vtop_static(SMC_INST_VADDR_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_nop_inst,
sizeof(g_nop_inst), 1);
//patch the slide set instruction when creating a new process
//in parse_machfile() in order to disable aslr for user mode apps
address_space_rw(nsas, vtop_static(SLIDE_SET_INST_VADDR_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_w7_zero_inst,
sizeof(g_w7_zero_inst), 1);
//patch the instruction that writes the kernel task port pointer
//in task_create_internal so we can catch it without MMIO
address_space_rw(nsas, vtop_static(NOTIFY_KERNEL_TASK_PTR_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_qemu_call,
sizeof(g_qemu_call), 1);
address_space_rw(nsas, vtop_static(TFP0_TASK_FOR_PID_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_nop_inst,
sizeof(g_nop_inst), 1);
address_space_rw(nsas, vtop_static(TFP0_CNVRT_PORT_TO_TASK_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_compare_true_inst,
sizeof(g_compare_true_inst), 1);
address_space_rw(nsas, vtop_static(TFP0_PORT_NAME_TO_TASK_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_compare_true_inst,
sizeof(g_compare_true_inst), 1);
address_space_rw(nsas, vtop_static(TFP0_KERNEL_TASK_CMP_1_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_compare_true_inst,
sizeof(g_compare_true_inst), 1);
address_space_rw(nsas, vtop_static(TFP0_KERNEL_TASK_CMP_2_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_compare_true_inst,
sizeof(g_compare_true_inst), 1);
address_space_rw(nsas, vtop_static(CORE_TRUST_CHECK_16B92),
MEMTXATTRS_UNSPECIFIED, (uint8_t *)&g_mov_w0_01_inst,
sizeof(g_mov_w0_01_inst), 1);
*sysmem = get_system_memory();
object_property_set_link(cpuobj, OBJECT(*sysmem), "memory",
&error_abort);
//set secure monitor to false
object_property_set_bool(cpuobj, false, "has_el3", NULL);
object_property_set_bool(cpuobj, false, "has_el2", NULL);
object_property_set_bool(cpuobj, true, "realized", &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 n66_set_xnu_ramfb(Object obj, const char value,
Error *errp)
{
N66MachineState nms = N66_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;
}
}
/xnu-qemu-arm64/hw/arm/n66_iphone6splus.c `/*
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/n66_iphone6splus.h"
include "hw/arm/exynos4210.h"
include "hw/arm/guest-services/general.h"
define N66_SECURE_RAM_SIZE (0x100000)
define N66_PHYS_BASE (0x40000000)
//compiled nop instruction: mov x0, x0
define NOP_INST (0xaa0003e0)
define MOV_W0_01_INST (0x52800020)
define CMP_X9_x9_INST (0xeb09013f)
//compiled instruction: mov w7, #0
define W7_ZERO_INST (0x52800007)
define INITIAL_BRANCH_VADDR_16B92 (0xfffffff0070a5098)
define BZERO_COND_BRANCH_VADDR_16B92 (0xfffffff0070996d8)
define SMC_INST_VADDR_16B92 (0xfffffff0070a7d3c)
define SLIDE_SET_INST_VADDR_16B92 (0xfffffff00748ef30)
define NOTIFY_KERNEL_TASK_PTR_16B92 (0xfffffff0070f4d90)
define CORE_TRUST_CHECK_16B92 (0xfffffff0061e136c)
define TFP0_TASK_FOR_PID_16B92 (0xfffffff0074a27bc)
define TFP0_CNVRT_PORT_TO_TASK_16B92 (0xfffffff0070d7cb8)
define TFP0_PORT_NAME_TO_TASK_16B92 (0xfffffff0070d82d8)
define TFP0_KERNEL_TASK_CMP_1_16B92 (0xfffffff0070d7b04)
define TFP0_KERNEL_TASK_CMP_2_16B92 (0xfffffff0070d810c)
//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 N66_CPREG_FUNCS(name) \
static uint64_t n66_cpregread##name(CPUARMState env, \ const ARMCPRegInfo ri) \ { \ N66MachineState nms = (N66MachineState )ri->opaque; \ return nms->N66_CPREG_VAR_NAME(name); \ } \ static void n66_cpregwrite##name(CPUARMState env, const ARMCPRegInfo ri, \ uint64_t value) \ { \ N66MachineState nms = (N66MachineState )ri->opaque; \ nms->N66_CPREG_VAR_NAME(name) = value; \ }
define N66_CPREG_DEF(p_name, p_op0, p_op1, p_crn, p_crm, p_op2, p_access) \
N66_CPREG_FUNCS(ARM64_REG_HID11) N66_CPREG_FUNCS(ARM64_REG_HID3) N66_CPREG_FUNCS(ARM64_REG_HID5) N66_CPREG_FUNCS(ARM64_REG_HID4) N66_CPREG_FUNCS(ARM64_REG_HID8) N66_CPREG_FUNCS(ARM64_REG_HID7) N66_CPREG_FUNCS(ARM64_REG_LSU_ERR_STS) N66_CPREG_FUNCS(PMC0) N66_CPREG_FUNCS(PMC1) N66_CPREG_FUNCS(PMCR1) N66_CPREG_FUNCS(PMSR) N66_CPREG_FUNCS(L2ACTLR_EL1)
static const ARMCPRegInfo n66_cp_reginfo_kvm[] = { // Apple-specific registers N66_CPREG_DEF(ARM64_REG_HID11, 3, 0, 15, 13, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID3, 3, 0, 15, 3, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID5, 3, 0, 15, 5, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID4, 3, 0, 15, 4, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID8, 3, 0, 15, 8, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID7, 3, 0, 15, 7, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_LSU_ERR_STS, 3, 3, 15, 0, 0, PL1_RW), N66_CPREG_DEF(PMC0, 3, 2, 15, 0, 0, PL1_RW), N66_CPREG_DEF(PMC1, 3, 2, 15, 1, 0, PL1_RW), N66_CPREG_DEF(PMCR1, 3, 1, 15, 1, 0, PL1_RW), N66_CPREG_DEF(PMSR, 3, 1, 15, 13, 0, PL1_RW), N66_CPREG_DEF(L2ACTLR_EL1, 3, 1, 15, 0, 0, PL1_RW),
};
// 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 n66_cp_reginfo_tcg[] = { // Apple-specific registers N66_CPREG_DEF(ARM64_REG_HID11, 3, 0, 15, 13, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID3, 3, 0, 15, 3, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID5, 3, 0, 15, 5, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID4, 3, 0, 15, 4, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID8, 3, 0, 15, 8, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_HID7, 3, 0, 15, 7, 0, PL1_RW), N66_CPREG_DEF(ARM64_REG_LSU_ERR_STS, 3, 3, 15, 0, 0, PL1_RW), N66_CPREG_DEF(PMC0, 3, 2, 15, 0, 0, PL1_RW), N66_CPREG_DEF(PMC1, 3, 2, 15, 1, 0, PL1_RW), N66_CPREG_DEF(PMCR1, 3, 1, 15, 1, 0, PL1_RW), N66_CPREG_DEF(PMSR, 3, 1, 15, 13, 0, PL1_RW),
};
static uint32_t g_nop_inst = NOP_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_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) // aa1f03e1 mov x1, xzr # x1 = 0 // 140007ec b 0x1fc0 # branch to regular start 0x91400c21, 0xd378dc21, 0xd5181041, 0xaa1f03e1, 0x140007ec }; static uint32_t g_bzero_branch_unconditionally_inst = 0x14000039; static uint32_t g_qemu_call = 0xd51bff1f;
static void n66_add_cpregs(N66MachineState nms) { ARMCPU cpu = nms->cpu;
}
static void n66_create_s3c_uart(const N66MachineState nms, Chardev chr) { qemu_irq irq; DeviceState d; SysBusDevice s; hwaddr base = nms->uart_mmio_pa;
}
static void n66_patch_kernel(AddressSpace nsas) { //patch the initial branch with instructions that set up CPACR address_space_rw(nsas, vtop_static(INITIAL_BRANCH_VADDR_16B92), MEMTXATTRS_UNSPECIFIED, (uint8_t )&g_set_cpacr_and_branch_inst, sizeof(g_set_cpacr_and_branch_inst), 1);
}
static void n66_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}; N66MachineState nms = N66_MACHINE(machine);
}
static void n66_memory_setup(MachineState machine, MemoryRegion sysmem, MemoryRegion secure_sysmem, AddressSpace nsas) { n66_ns_memory_setup(machine, sysmem, nsas); }
static void n66_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);
}
static void n66_bootargs_setup(MachineState machine) { N66MachineState nms = N66_MACHINE(machine); nms->bootinfo.firmware_loaded = true; }
static void n66_cpu_reset(void opaque) { N66MachineState nms = N66_MACHINE((MachineState )opaque); ARMCPU cpu = nms->cpu; CPUState cs = CPU(cpu); CPUARMState env = &cpu->env;
}
//hooks arg is expected like this: //"hookfilepath@va@scratch_reg#hookfilepath@va@scratch_reg#..."
static void n66_machine_init_hook_funcs(N66MachineState 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;
}
static void n66_machine_init(MachineState machine) { N66MachineState nms = N66_MACHINE(machine); MemoryRegion sysmem; MemoryRegion secure_sysmem; AddressSpace nsas; ARMCPU cpu; DeviceState *cpudev;
}
static void n66_set_ramdisk_filename(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj);
}
static char n66_get_ramdisk_filename(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); return g_strdup(nms->ramdisk_filename); }
static void n66_set_kernel_filename(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj);
}
static char n66_get_kernel_filename(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); return g_strdup(nms->kernel_filename); }
static void n66_set_dtb_filename(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj);
}
static char n66_get_dtb_filename(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); return g_strdup(nms->dtb_filename); }
static void n66_set_kern_args(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj);
}
static char n66_get_kern_args(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); return g_strdup(nms->kern_args); }
static void n66_set_tunnel_port(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj); nms->tunnel_port = atoi(value); }
static char n66_get_tunnel_port(Object obj, Error *errp) { char buf[128]; N66MachineState nms = N66_MACHINE(obj); snprintf(buf, 128, "%d", nms->tunnel_port); return g_strdup(buf); }
static void n66_set_hook_funcs(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj);
}
static char n66_get_hook_funcs(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); return g_strdup(nms->hook_funcs_cfg); }
static void n66_set_driver_filename(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj);
}
static char n66_get_driver_filename(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); return g_strdup(nms->driver_filename); }
static void n66_set_qc_file_0_filename(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj);
}
static char n66_get_qc_file_0_filename(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); return g_strdup(nms->qc_file_0_filename); }
static void n66_set_qc_file_1_filename(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj);
}
static char n66_get_qc_file_1_filename(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); return g_strdup(nms->qc_file_1_filename); }
static void n66_set_qc_file_log_filename(Object obj, const char value, Error *errp) { N66MachineState nms = N66_MACHINE(obj);
}
static char n66_get_qc_file_log_filename(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); return g_strdup(nms->qc_file_log_filename); }
static void n66_set_xnu_ramfb(Object obj, const char value, Error *errp) { N66MachineState nms = N66_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 n66_get_xnu_ramfb(Object obj, Error *errp) { N66MachineState nms = N66_MACHINE(obj); if (nms->use_ramfb) return g_strdup("on"); else return g_strdup("off"); }
static void n66_instance_init(Object *obj) { object_property_add_str(obj, "ramdisk-filename", n66_get_ramdisk_filename, n66_set_ramdisk_filename, NULL); object_property_set_description(obj, "ramdisk-filename", "Set the ramdisk filename to be loaded", NULL);
}
static void n66_machine_class_init(ObjectClass klass, void data) { MachineClass *mc = MACHINE_CLASS(klass); mc->desc = "iPhone 6s plus (n66 - s8000)"; mc->init = n66_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 n66_machine_info = { .name = TYPE_N66_MACHINE, .parent = TYPE_MACHINE, .instance_size = sizeof(N66MachineState), .class_size = sizeof(N66MachineClass), .class_init = n66_machine_class_init, .instance_init = n66_instance_init, };
static void n66_machine_types(void) { type_register_static(&n66_machine_info); }
type_init(n66_machine_types)`
xnu-qemu-arm64/hw/arm/xnu_pagetable.c `/
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) & \
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) << \
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);
}
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); } }`