diff --git a/proxyclient/m1n1/hv/__init__.py b/proxyclient/m1n1/hv/__init__.py index 37cbdb1ed..47b14160a 100644 --- a/proxyclient/m1n1/hv/__init__.py +++ b/proxyclient/m1n1/hv/__init__.py @@ -90,7 +90,7 @@ def __init__(self, iface, proxy, utils): self.sym_offset = 0 self.symbols = [] self.symbol_dict = {} - self.sysreg = {0: {}} + self.sysreg = {0: {}, 6:{}} self.novm = False self._in_handler = False self._sigint_pending = False @@ -1369,6 +1369,10 @@ def init(self): print(f"Disable iodev {iodev!s}") self.p.iodev_set_usage(iodev, 0) + for cpu in self.adt["cpus"]: + if cpu.state == "running": + self.boot_cpu = cpu + print("Initializing hypervisor over iodev %s" % self.iodev) self.p.hv_init() @@ -1558,7 +1562,7 @@ def cpustart_wh(base, off, data, width): chip_id = self.u.adt["/chosen"].chip_id if chip_id in (0x8103, 0x6000, 0x6001, 0x6002): cpu_start = 0x54000 + die * 0x20_0000_0000 - elif chip_id in (0x8112,): + elif chip_id in (0x8112,0x6030): cpu_start = 0x34000 + die * 0x20_0000_0000 elif chip_id in (0x6020, 0x6021, 0x6022): cpu_start = 0x28000 + die * 0x20_0000_0000 @@ -1755,7 +1759,9 @@ def load_raw(self, image, entryoffset=0x800, use_xnu_symbols=False, vmin=0): print("Setting secondary CPU RVBARs...") rvbar = self.entry & ~0xfff - for cpu in self.adt["cpus"][1:]: + for cpu in self.adt["cpus"]: + if cpu.state == "running": + continue addr, size = cpu.cpu_impl_reg print(f" {cpu.name}: [0x{addr:x}] = 0x{rvbar:x}") self.p.write64(addr, rvbar) @@ -1906,7 +1912,7 @@ def start(self): # Does not return self.started = True - self.started_cpus[0] = (0, 0, 0) + self.started_cpus[self.boot_cpu.cpu_id] = (0, self.boot_cpu.cluster_id, self.boot_cpu.reg & 0xff) self.p.hv_start(self.entry, self.guest_base + self.bootargs_off) from .. import trace diff --git a/proxyclient/tools/chainload.py b/proxyclient/tools/chainload.py index 12eac1c7b..2639e5314 100755 --- a/proxyclient/tools/chainload.py +++ b/proxyclient/tools/chainload.py @@ -85,7 +85,9 @@ print("Setting secondary CPU RVBARs...") rvbar = entry & ~0xfff -for cpu in u.adt["cpus"][1:]: +for cpu in u.adt["cpus"]: + if cpu.state == "running": + continue addr, size = cpu.cpu_impl_reg print(f" {cpu.name}: [0x{addr:x}] = 0x{rvbar:x}") p.write64(addr, rvbar) diff --git a/src/aic.c b/src/aic.c index 9ef900acd..b994c688d 100644 --- a/src/aic.c +++ b/src/aic.c @@ -33,8 +33,34 @@ static struct aic aic2 = { }, }; +static struct aic aic3 = { + .version = 3, + .regs = + { + .config = AIC3_IRQ_CFG, + }, +}; + struct aic *aic; +static void aic_ext_int_cfg(int node){ + u32 ext_intr_config_len; + const u8 *ext_intr_config = adt_getprop(adt, node, "aic-ext-intr-cfg", &ext_intr_config_len); + + if (ext_intr_config) { + printf("AIC: Configuring %d external interrupts\n", ext_intr_config_len / 3); + for (u32 i = 0; i < ext_intr_config_len; i += 3) { + u8 die = ext_intr_config[i + 1] >> 4; + u16 irq = ext_intr_config[i] | ((ext_intr_config[i + 1] & 0xf) << 8); + u8 target = ext_intr_config[i + 2]; + assert(die < aic->nr_die); + assert(irq < aic->nr_irq); + mask32(aic->base + aic->regs.config + die * aic->die_stride + 4 * irq, + AIC2_IRQ_CFG_TARGET, FIELD_PREP(AIC2_IRQ_CFG_TARGET, target)); + } + } +} + static int aic2_init(int node) { int ret = ADT_GETPROP(adt, node, "aic-iack-offset", &aic->regs.event); @@ -80,22 +106,82 @@ static int aic2_init(int node) printf("AIC: AIC2 with %u/%u dies, %u/%u IRQs, reg_size:%05lx die_stride:%05x\n", aic->nr_die, aic->max_die, aic->nr_irq, aic->max_irq, aic->regs.reg_size, aic->die_stride); - u32 ext_intr_config_len; - const u8 *ext_intr_config = adt_getprop(adt, node, "aic-ext-intr-cfg", &ext_intr_config_len); + aic_ext_int_cfg(node); + return 0; +} - if (ext_intr_config) { - printf("AIC: Configuring %d external interrupts\n", ext_intr_config_len / 3); - for (u32 i = 0; i < ext_intr_config_len; i += 3) { - u8 die = ext_intr_config[i + 1] >> 4; - u16 irq = ext_intr_config[i] | ((ext_intr_config[i + 1] & 0xf) << 8); - u8 target = ext_intr_config[i + 2]; - assert(die < aic->nr_die); - assert(irq < aic->nr_irq); - mask32(aic->base + aic->regs.config + die * aic->die_stride + 4 * irq, - AIC2_IRQ_CFG_TARGET, FIELD_PREP(AIC2_IRQ_CFG_TARGET, target)); - } +static int aic3_init(int node) +{ + int ret = ADT_GETPROP(adt, node, "aic-iack-offset", &aic->regs.event); + if (ret < 0) { + printf("AIC: failed to get property aic-iack-offset\n"); + return ret; + } + + int maxnumirq_offset; + ret = ADT_GETPROP(adt, node, "maxnumirq-offset", &maxnumirq_offset); + if (ret < 0) { + printf("AIC: AIC3: failed to get property maxnumirq-offset\n"); + return ret; + } + + int max_irq_interrupt_umask = 0; + ADT_GETPROP(adt, node, "max_irq_interrupt_umask", &max_irq_interrupt_umask); + if (max_irq_interrupt_umask == 0) { + max_irq_interrupt_umask = 0xffff; + } + + int maxnumirq = read32(aic->base + maxnumirq_offset); + + aic->max_irq = maxnumirq & max_irq_interrupt_umask; + aic->max_die = (maxnumirq >> 0x18) & 0xf; + + int cap0_offset; + ret = ADT_GETPROP(adt, node, "cap0-offset", &cap0_offset); + if (ret < 0) { + printf("AIC: AIC3: failed to get property cap0-offset\n"); + return ret; } + int cap0_max_interrupt_mask = 0; + ADT_GETPROP(adt, node, "cap0_max_interrupt_umask", &cap0_max_interrupt_mask); + if (cap0_max_interrupt_mask == 0) { + cap0_max_interrupt_mask = 0xffff; + } + + int cap0 = read32(aic->base + cap0_offset); + + aic->nr_irq = cap0 & cap0_max_interrupt_mask; + aic->nr_die = ((cap0 >> 0x18) & 0xf) + 1; + + if (aic->max_die > AIC3_MAX_MAX_DIES) { + printf("AIC: AIC3: more max dies than supported: %u\n", aic->max_die); + return -1; + } + + if (aic->max_irq > AIC_MAX_HW_NUM) { + printf("AIC: AIC3: more IRQs than supported: %u\n", aic->max_irq); + return -1; + } + + const u64 start_off = aic->regs.config; + u64 off = start_off + AIC3_EXT_CFG_SECT_STRIDE; /* IRQ_CFG */ + + aic->regs.sw_set = off; + off += AIC3_CFG_SECT_STRIDE; /* SW_SET */ + aic->regs.sw_clr = off; + off += AIC3_CFG_SECT_STRIDE; /* SW_CLR */ + aic->regs.mask_set = off; + off += AIC3_CFG_SECT_STRIDE; /* MASK_SET */ + aic->regs.mask_clr = off; + + aic->die_stride = AIC3_DIE_STRIDE; + aic->regs.reg_size = aic->regs.event + 4; + + printf("AIC: AIC3 with %u/%u dies, %u/%u IRQs, reg_size:%05lx die_stride:%05x\n", aic->nr_die, + aic->max_die, aic->nr_irq, aic->max_irq, aic->regs.reg_size, aic->die_stride); + + aic_ext_int_cfg(node); return 0; } @@ -113,6 +199,8 @@ void aic_init(void) aic = &aic1; } else if (adt_is_compatible(adt, node, "aic,2")) { aic = &aic2; + } else if (adt_is_compatible(adt, node, "aic,3")) { + aic = &aic3; } else { printf("AIC: Error: Unsupported version\n"); return; @@ -132,6 +220,11 @@ void aic_init(void) int ret = aic2_init(node); if (ret < 0) aic = NULL; + } else if (aic->version == 3) { + printf("AIC: Version 3 @ 0x%lx\n", aic->base); + int ret = aic3_init(node); + if (ret < 0) + aic = NULL; } } diff --git a/src/aic.h b/src/aic.h index 1f401b1c3..b541b957b 100644 --- a/src/aic.h +++ b/src/aic.h @@ -6,6 +6,7 @@ #include "types.h" #define AIC_MAX_DIES 4 +#define AIC3_MAX_MAX_DIES 8 struct aic_regs { uint64_t reg_size; diff --git a/src/aic_regs.h b/src/aic_regs.h index 8cc360b7d..b4a622ca5 100644 --- a/src/aic_regs.h +++ b/src/aic_regs.h @@ -51,3 +51,9 @@ #define AIC1_MAX_IRQ 0x400 #define AIC_MAX_HW_NUM (0x80 * 32) // max_irq of the M1 Max + +// Apple Interrupt Controller 3 +#define AIC3_IRQ_CFG 0x10000 +#define AIC3_DIE_STRIDE 0x4a00 +#define AIC3_EXT_CFG_SECT_STRIDE 0x4000 +#define AIC3_CFG_SECT_STRIDE 0x200 diff --git a/src/hv_exc.c b/src/hv_exc.c index 0f5e13afd..f8bc782f4 100644 --- a/src/hv_exc.c +++ b/src/hv_exc.c @@ -509,7 +509,7 @@ void hv_exc_fiq(struct exc_info *ctx) int interruptible_cpu = hv_pinned_cpu; if (interruptible_cpu == -1) - interruptible_cpu = 0; + interruptible_cpu = boot_cpu_idx; if (smp_id() != interruptible_cpu && !(mrs(ISR_EL1) & 0x40) && hv_want_cpu == -1) { // Non-interruptible CPU and it was just a timer tick (or spurious), so just update FIQs diff --git a/src/mcc.c b/src/mcc.c index 375388399..f3e7cad60 100644 --- a/src/mcc.c +++ b/src/mcc.c @@ -23,11 +23,11 @@ static bool mcc_initialized = false; #define T6000_DCS_STRIDE 0x100000 #define T6000_DCS_COUNT 4 -#define T6031_PLANE_OFFSET 0 -#define T6031_PLANE_STRIDE 0x40000 -#define T6031_GLOBAL_OFFSET 0x100000 -#define T6031_DCS_OFFSET 0x400000 -#define T6031_DCS_STRIDE 0x200000 +#define T603X_PLANE_OFFSET 0 +#define T603X_PLANE_STRIDE 0x40000 +#define T603X_GLOBAL_OFFSET 0x100000 +#define T603X_DCS_OFFSET 0x400000 +#define T603X_DCS_STRIDE 0x200000 #define PLANE_TZ_MAX_REGS 4 @@ -55,7 +55,15 @@ struct tz_regs t602x_tz_regs = { .enable = 0x6c8, }; -struct tz_regs t603x_tz_regs = { +struct tz_regs t6030_tz_regs = { + .count = 4, + .stride = 0x14, + .start = 0x6dc, + .end = 0x6e0, + .enable = 0x6e8, +}; + +struct tz_regs t6031_tz_regs = { .count = 4, .stride = 0x14, .start = 0x6d8, @@ -78,11 +86,11 @@ struct tz_regs t603x_tz_regs = { (FIELD_PREP(T6000_CACHE_STATUS_DATA_COUNT, T6000_CACHE_WAYS) | \ FIELD_PREP(T6000_CACHE_STATUS_TAG_COUNT, T6000_CACHE_WAYS)) -#define T6031_CACHE_WAYS 12 -#define T6031_CACHE_STATUS_MASK (T6000_CACHE_STATUS_DATA_COUNT | T6000_CACHE_STATUS_TAG_COUNT) -#define T6031_CACHE_STATUS_VAL \ - (FIELD_PREP(T6000_CACHE_STATUS_DATA_COUNT, T6031_CACHE_WAYS) | \ - FIELD_PREP(T6000_CACHE_STATUS_TAG_COUNT, T6031_CACHE_WAYS)) +#define T603X_CACHE_WAYS 12 +#define T603X_CACHE_STATUS_MASK (T6000_CACHE_STATUS_DATA_COUNT | T6000_CACHE_STATUS_TAG_COUNT) +#define T603X_CACHE_STATUS_VAL \ + (FIELD_PREP(T6000_CACHE_STATUS_DATA_COUNT, T603X_CACHE_WAYS) | \ + FIELD_PREP(T6000_CACHE_STATUS_TAG_COUNT, T603X_CACHE_WAYS)) #define T8103_CACHE_WAYS 16 #define T8103_CACHE_STATUS_MASK (T8103_CACHE_STATUS_DATA_COUNT | T8103_CACHE_STATUS_TAG_COUNT) @@ -318,7 +326,7 @@ int mcc_init_t6000(int node, int *path, bool t602x) return 0; } -int mcc_init_t6031(int node, int *path) +int mcc_init_t603x(int node, int *path, int lsn) { u32 reg_len; u32 reg_offset = 3; @@ -330,7 +338,7 @@ int mcc_init_t6031(int node, int *path) mcc_count = reg_len / 16 - reg_offset; - printf("MCC: Initializing T6031 MCCs (%d instances)...\n", mcc_count); + printf("MCC: Initializing T603%x MCCs (%d instances)...\n", lsn, mcc_count); if (mcc_count > MAX_MCC_INSTANCES) { printf("MCC: Too many instances, increase MAX_MCC_INSTANCES!\n"); @@ -357,26 +365,33 @@ int mcc_init_t6031(int node, int *path) return -1; } - mcc_regs[i].plane_base = base + T6031_PLANE_OFFSET; - mcc_regs[i].plane_stride = T6031_PLANE_STRIDE; + mcc_regs[i].plane_base = base + T603X_PLANE_OFFSET; + mcc_regs[i].plane_stride = T603X_PLANE_STRIDE; mcc_regs[i].plane_count = plane_count; - mcc_regs[i].global_base = base + T6031_GLOBAL_OFFSET; + mcc_regs[i].global_base = base + T603X_GLOBAL_OFFSET; - mcc_regs[i].dcs_base = base + T6031_DCS_OFFSET; - mcc_regs[i].dcs_stride = T6031_DCS_STRIDE; + mcc_regs[i].dcs_base = base + T603X_DCS_OFFSET; + mcc_regs[i].dcs_stride = T603X_DCS_STRIDE; mcc_regs[i].dcs_count = dcs_count; mcc_regs[i].cache_enable_val = 1; - mcc_regs[i].cache_ways = T6031_CACHE_WAYS; - mcc_regs[i].cache_status_mask = T6031_CACHE_STATUS_MASK; - mcc_regs[i].cache_status_val = T6031_CACHE_STATUS_VAL; + mcc_regs[i].cache_ways = T603X_CACHE_WAYS; + mcc_regs[i].cache_status_mask = T603X_CACHE_STATUS_MASK; + mcc_regs[i].cache_status_val = T603X_CACHE_STATUS_VAL; mcc_regs[i].cache_disable = 0; - mcc_regs[i].tz = &t603x_tz_regs; + if(lsn == 0){ + mcc_regs[i].tz = &t6030_tz_regs; + } else if(lsn == 1){ + mcc_regs[i].tz = &t6031_tz_regs; + } else { + printf("MCC: Unsupported chip (T603%x)", lsn); + return -1; + } } - printf("MCC: Initialized T6031 MCCs (%d instances, %d planes, %d channels)\n", mcc_count, + printf("MCC: Initialized T603%x MCCs (%d instances, %d planes, %d channels)\n", lsn, mcc_count, mcc_regs[0].plane_count, mcc_regs[0].dcs_count); mcc_initialized = true; @@ -402,8 +417,10 @@ int mcc_init(void) return mcc_init_t6000(node, path, false); } else if (adt_is_compatible(adt, node, "mcc,t6020")) { return mcc_init_t6000(node, path, true); + } else if (adt_is_compatible(adt, node, "mcc,t6030")) { + return mcc_init_t603x(node, path, 0); } else if (adt_is_compatible(adt, node, "mcc,t6031")) { - return mcc_init_t6031(node, path); + return mcc_init_t603x(node, path, 1); } else { printf("MCC: Unsupported version:%s\n", adt_get_property(adt, node, "compatible")->value); return -1; diff --git a/src/smp.c b/src/smp.c index fe5b08a36..d70809774 100644 --- a/src/smp.c +++ b/src/smp.c @@ -210,6 +210,7 @@ void smp_start_secondaries(void) break; case T8112: case T8122: + case T6030: cpu_start_off = CPU_START_OFF_T8112; break; case T6020: @@ -266,6 +267,12 @@ void smp_start_secondaries(void) return; } + if (in_el2()) + msr(TPIDR_EL2, boot_cpu_idx); + else + msr(TPIDR_EL1, boot_cpu_idx); + + for (int i = 0; i < MAX_CPUS; i++) { if (i == boot_cpu_idx) @@ -334,7 +341,7 @@ void smp_call4(int cpu, void *func, u64 arg0, u64 arg1, u64 arg2, u64 arg3) struct spin_table *target = &spin_table[cpu]; - if (cpu == 0) + if (cpu == boot_cpu_idx) return; u64 flag = target->flag; diff --git a/src/soc.h b/src/soc.h index eb375edac..7bc6b1790 100644 --- a/src/soc.h +++ b/src/soc.h @@ -12,6 +12,7 @@ #define T6001 0x6001 #define T6002 0x6002 #define T6020 0x6020 +#define T6030 0x6030 #define T6021 0x6021 #define T6022 0x6022 #define T6031 0x6031