diff --git a/proxyclient/m1n1/constructutils.py b/proxyclient/m1n1/constructutils.py index 8f7e35781..041328f67 100644 --- a/proxyclient/m1n1/constructutils.py +++ b/proxyclient/m1n1/constructutils.py @@ -890,4 +890,9 @@ def show_struct_trace(log=print): for addr, desc in sorted(list(g_struct_trace)): log(f"{addr:>#18x}: {desc}") -__all__ = ["ConstructClass", "ConstructValueClass", "Dec", "ROPointer", "show_struct_trace", "ZPadding", "Ver"] +def Bool(c): + return ExprAdapter(c, lambda d, ctx: bool(d & 1), lambda d, ctx: int(d)) + +bool_ = Bool(Int8ul) + +__all__ = ["ConstructClass", "ConstructValueClass", "Dec", "ROPointer", "show_struct_trace", "ZPadding", "Ver", "Bool", "bool_"] diff --git a/proxyclient/m1n1/fw/afk/epic.py b/proxyclient/m1n1/fw/afk/epic.py index 090a06cfe..099f1980a 100644 --- a/proxyclient/m1n1/fw/afk/epic.py +++ b/proxyclient/m1n1/fw/afk/epic.py @@ -5,6 +5,7 @@ from construct import * from ..common import * from ...utils import * +from ...constructutils import Bool from ..asc import StandardASC from ..asc.base import * from .rbep import AFKRingBufEndpoint diff --git a/proxyclient/m1n1/fw/common.py b/proxyclient/m1n1/fw/common.py index 479e2dfc8..506c16f07 100644 --- a/proxyclient/m1n1/fw/common.py +++ b/proxyclient/m1n1/fw/common.py @@ -18,9 +18,6 @@ ulong = uint64_t long_ = int64_t -def Bool(c): - return ExprAdapter(c, lambda d, ctx: bool(d & 1), lambda d, ctx: int(d)) - def SizedArray(count, svar, subcon): return Padded(subcon.sizeof() * count, Array(lambda ctx: min(count, ctx.get(svar, ctx._.get(svar))), subcon)) @@ -30,8 +27,6 @@ def SizedBytes(count, svar): def UnkBytes(s): return Default(HexDump(Bytes(s)), b"\x00" * s) -bool_ = Bool(Int8ul) - class OSObject(Construct): TYPE = None diff --git a/proxyclient/m1n1/fw/dcp/iboot.py b/proxyclient/m1n1/fw/dcp/iboot.py index 8124ca93a..111140cba 100644 --- a/proxyclient/m1n1/fw/dcp/iboot.py +++ b/proxyclient/m1n1/fw/dcp/iboot.py @@ -2,6 +2,7 @@ from construct import * from ...utils import * +from ...constructutils import Bool from ..asc import StandardASC from ..afk.epic import * from .dcpav import * diff --git a/proxyclient/m1n1/fw/dcp/ipc.py b/proxyclient/m1n1/fw/dcp/ipc.py index e73331ade..170d22726 100644 --- a/proxyclient/m1n1/fw/dcp/ipc.py +++ b/proxyclient/m1n1/fw/dcp/ipc.py @@ -7,7 +7,7 @@ from ..common import * from m1n1.utils import * from construct import * -from m1n1.constructutils import Ver +from m1n1.constructutils import Ver, Bool, bool_ @dataclass class ByRef: diff --git a/proxyclient/m1n1/hv/__init__.py b/proxyclient/m1n1/hv/__init__.py index fd8595698..baf5bf79a 100644 --- a/proxyclient/m1n1/hv/__init__.py +++ b/proxyclient/m1n1/hv/__init__.py @@ -714,7 +714,10 @@ def handle_msr(self, ctx, iss=None): sys.stdout.flush() if enc in xlate: value = self.p.hv_translate(value, True, False) - self.u.msr(enc2, value, call=self.p.gl2_call) + call=None + if self.u.cpu_features.apple_sysregs_unlocked: + call=self.p.gl2_call + self.u.msr(enc2, value, call=call) self.log(f"Pass: msr {name}, x{iss.Rt} = {value:x} (OK) ({sysreg_name(enc2)})") ctx.elr += 4 @@ -1429,15 +1432,16 @@ def init(self): self.u.msr(MDCR_EL2, mdcr.value) self.u.msr(MDSCR_EL1, MDSCR(MDE=1).value) - # Enable AMX - amx_ctl = AMX_CONFIG(self.u.mrs(AMX_CONFIG_EL1)) - amx_ctl.EN_EL1 = 1 - self.u.msr(AMX_CONFIG_EL1, amx_ctl.value) + if self.u.cpu_features.apple_sysregs_unlocked: + # Enable AMX + amx_ctl = AMX_CONFIG(self.u.mrs(AMX_CONFIG_EL1)) + amx_ctl.EN_EL1 = 1 + self.u.msr(AMX_CONFIG_EL1, amx_ctl.value) - # Set guest AP keys - self.u.msr(VMKEYLO_EL2, 0x4E7672476F6E6147) - self.u.msr(VMKEYHI_EL2, 0x697665596F755570) - self.u.msr(APSTS_EL12, 1) + # Set guest AP keys + self.u.msr(VMKEYLO_EL2, 0x4E7672476F6E6147) + self.u.msr(VMKEYHI_EL2, 0x697665596F755570) + self.u.msr(APSTS_EL12, 1) self.map_vuart() @@ -1487,13 +1491,11 @@ def rh(base, off, width): pmgr_hooks = [] def hook_pmgr_dev(dev): - ps = pmgr.ps_regs[dev.psreg] - if dev.psidx or dev.psreg: - addr = pmgr.get_reg(ps.reg)[0] + ps.offset + dev.psidx * 8 - pmgr_hooks.append(addr) - for idx in self.adt.pmgr_dev_get_parents(dev): - if idx in dev_by_id: - hook_pmgr_dev(dev_by_id[idx]) + addr = self.adt.pmgr_dev_get_addr(dev) + pmgr_hooks.append(addr) + for idx in self.adt.pmgr_dev_get_parents(dev): + if idx in dev_by_id: + hook_pmgr_dev(dev_by_id[idx]) for name in hook_devs: dev = dev_by_name[name] @@ -1562,11 +1564,11 @@ 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, 0x8122, 0x6030): + elif chip_id in (0x8112, 0x8122, 0x8132, 0x8140, 0x6030): cpu_start = 0x34000 + die * 0x20_0000_0000 elif chip_id in (0x6020, 0x6021, 0x6022): cpu_start = 0x28000 + die * 0x20_0000_0000 - elif chip_id in (0x6031,): + elif chip_id in (0x6031, 0x6034, 0x6040): cpu_start = 0x88000 + die * 0x20_0000_0000 else: self.log("CPUSTART unknown for this SoC!") @@ -1576,6 +1578,19 @@ def cpustart_wh(base, off, data, width): self.map_hook(pmgr0_start + cpu_start, 0x20, write=cpustart_wh) self.add_tracer(zone, "CPU_START", TraceMode.RESERVED) + if not self.u.cpu_features.apple_sysregs_unlocked: + + def rvbar_rh(base, off, width): + ret = self.entry & ~0xfff | 1 + self.log(f"RVBAR R {base:x}+{off:x}:{width} -> 0x{ret:x}") + return ret + + for cpu in self.adt["cpus"]: + addr, _ = cpu.cpu_impl_reg + zone = irange(addr, 4) + self.map_hook(addr, 4, read=rvbar_rh) + self.add_tracer(zone, "RVBAR", TraceMode.RESERVED) + def start_secondary(self, die, cluster, cpu): self.log(f"Starting guest secondary {die}:{cluster}:{cpu}") @@ -1586,7 +1601,10 @@ def start_secondary(self, die, cluster, cpu): self.log("CPU not found!") return - entry = self.p.read64(node.cpu_impl_reg[0]) & 0xfffffffffff + if self.u.cpu_features.apple_sysregs_unlocked: + entry = self.p.read64(node.cpu_impl_reg[0]) & 0xfffffffffff + else: + entry = self.entry & ~0xfff index = node.cpu_id self.log(f" CPU #{index}: RVBAR = {entry:#x}") @@ -1779,14 +1797,15 @@ def remove_oslog(node): elif self.tba.revision == 3: self.iface.writemem(guest_base + self.bootargs_off, BootArgs_r3.build(self.tba)) - print("Setting secondary CPU RVBARs...") - rvbar = self.entry & ~0xfff - 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) + if self.u.cpu_features.apple_sysregs_unlocked: + print("Setting secondary CPU RVBARs...") + rvbar = self.entry & ~0xfff + 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) def _load_macho_symbols(self): self.symbol_dict = self.macho.symbols @@ -1968,11 +1987,12 @@ def start(self): print("Shutting down framebuffer...") self.p.fb_shutdown(True) - print("Enabling SPRR...") - self.u.msr(SPRR_CONFIG_EL1, 1) + if self.u.cpu_features.apple_sysregs_unlocked: + print("Enabling SPRR...") + self.u.msr(SPRR_CONFIG_EL1, 1) - print("Enabling GXF...") - self.u.msr(GXF_CONFIG_EL1, 1) + print("Enabling GXF...") + self.u.msr(GXF_CONFIG_EL1, 1) print(f"Jumping to entrypoint at 0x{self.entry:x}") diff --git a/proxyclient/m1n1/proxy.py b/proxyclient/m1n1/proxy.py index 16ed89467..ad9faf9a1 100644 --- a/proxyclient/m1n1/proxy.py +++ b/proxyclient/m1n1/proxy.py @@ -5,6 +5,7 @@ from serial.tools.miniterm import Miniterm from .utils import * +from .constructutils import bool_ from .sysreg import * __all__ = ["REGION_RWX_EL0", "REGION_RW_EL0", "REGION_RX_EL1"] @@ -480,6 +481,35 @@ class GUARD(IntFlag): REGION_RW_EL0 = 0xa0000000000 REGION_RX_EL1 = 0xc0000000000 +SleepMode = "SleepMode" / Enum(Int32ul, + SLEEP_NONE = 0, + SLEEP_LEGACY = 1, + SLEEP_GLOBAL = 2, +) + +UncoreVersion = "UncoreVersion" / Enum(Int32ul, + UNCORE_NONE = 0, + UNCORE_V1 = 1, + UNCORE_V2 = 2, +) + +CPUFeatures = Struct( + "sleep_mode" / SleepMode, + "uncore_version" / UncoreVersion, + "disable_dc_mva" / bool_, + "acc_cfg" / bool_, + "apple_sysregs_unlocked" / bool_, + "workaround_cyclone_cache" / bool_, + "nex_powergating" / bool_, + "fast_ipi" / bool_, + "mmu_sprr" / bool_, + "siq_cfg" / bool_, + "amx" / bool_, + "actlr_el2" / bool_, + "counter_redirect" / bool_, + "padding" / Bytes(1), +) + # Uses UartInterface.proxyreq() to send requests to M1N1 and process # responses sent back. class M1N1Proxy(Reloadable): @@ -506,6 +536,7 @@ class M1N1Proxy(Reloadable): P_SLEEP = 0x011 P_EL3_CALL = 0x012 P_GET_CHIPID = 0x013 + P_GET_CPU_FEATURES = 0x014 P_WRITE64 = 0x100 P_WRITE32 = 0x101 @@ -740,6 +771,11 @@ def get_bootargs_rev(self): return (ba_addr, rev) def get_base(self): return self.request(self.P_GET_BASE) + def get_cpu_features(self): + addr = self.request(self.P_GET_CPU_FEATURES, CPUFeatures.sizeof()) + if not addr: + raise ValueError("Size mismatch (Outdated CPUFeatures struct definition?)") + return self.iface.readstruct(addr, CPUFeatures) def set_baud(self, baudrate): self.iface.tty_enable = False def change(): diff --git a/proxyclient/m1n1/proxyutils.py b/proxyclient/m1n1/proxyutils.py index 0824fcf9e..ed95cad80 100644 --- a/proxyclient/m1n1/proxyutils.py +++ b/proxyclient/m1n1/proxyutils.py @@ -44,6 +44,12 @@ def __init__(self, p, heap_size=1024 * 1024 * 1024): self.iface = p.iface self.proxy = p self.base = p.get_base() + + try: + self.cpu_features = p.get_cpu_features() + except ProxyRemoteError: + pass + (self.ba_addr, self.ba_rev) = p.get_bootargs_rev() if self.ba_rev <= 1: diff --git a/src/hv.c b/src/hv.c index 8236ce6cf..5b9cd0a77 100644 --- a/src/hv.c +++ b/src/hv.c @@ -193,7 +193,8 @@ void hv_start(void *entry, u64 regs[4]) static void hv_init_secondary(struct hv_secondary_info_t *info) { - gxf_init(); + if (cpu_features->apple_sysregs_unlocked) + gxf_init(); msr(VBAR_EL1, _hv_vectors_start); @@ -203,18 +204,23 @@ static void hv_init_secondary(struct hv_secondary_info_t *info) msr(VTTBR_EL2, info->vttbr); msr(MDCR_EL2, info->mdcr); msr(MDSCR_EL1, info->mdscr); - msr(SYS_IMP_APL_AMX_CTL_EL2, info->amx_ctl); - msr(SYS_IMP_APL_APVMKEYLO_EL2, info->apvmkeylo); - msr(SYS_IMP_APL_APVMKEYHI_EL2, info->apvmkeyhi); - msr(SYS_IMP_APL_APSTS_EL12, info->apsts); + + if (cpu_features->apple_sysregs_unlocked) { + msr(SYS_IMP_APL_AMX_CTL_EL2, info->amx_ctl); + msr(SYS_IMP_APL_APVMKEYLO_EL2, info->apvmkeylo); + msr(SYS_IMP_APL_APVMKEYHI_EL2, info->apvmkeyhi); + msr(SYS_IMP_APL_APSTS_EL12, info->apsts); + } msr(ACTLR_EL2, info->actlr_el2); if (cpu_features->actlr_el2) msr(SYS_ACTLR_EL12, info->actlr_el1); else msr(SYS_IMP_APL_ACTLR_EL12, info->actlr_el1); msr(CNTHCTL_EL2, info->cnthctl); - msr(SYS_IMP_APL_SPRR_CONFIG_EL1, info->sprr_config); - msr(SYS_IMP_APL_GXF_CONFIG_EL1, info->gxf_config); + if (cpu_features->apple_sysregs_unlocked) { + msr(SYS_IMP_APL_SPRR_CONFIG_EL1, info->sprr_config); + msr(SYS_IMP_APL_GXF_CONFIG_EL1, info->gxf_config); + } if (cpu_features->counter_redirect) { msr(SYS_IMP_APL_AGTCNTRDIR_EL1, info->agt_cnt_rdir_el1); msr(SYS_IMP_APL_AGTCNTRDIR_EL12, info->agt_cnt_rdir_el12); diff --git a/src/proxy.c b/src/proxy.c index 3f020c045..0c1501662 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -54,6 +54,15 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply) case P_GET_BOOTARGS: reply->retval = boot_args_addr; break; + case P_GET_CPU_FEATURES: + if (request->args[0] == sizeof(struct midr_part_features)) + reply->retval = (u64)cpu_features; + else { + printf("size mismatch: sizeof(struct midr_part_features) = %ld != %ld\n", + sizeof(struct midr_part_features), request->args[0]); + reply->retval = 0; + } + break; case P_GET_BASE: reply->retval = (u64)_base; break; diff --git a/src/proxy.h b/src/proxy.h index 1e8acdf06..ea9992ee5 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -26,6 +26,7 @@ typedef enum { P_SLEEP, P_EL3_CALL, P_GET_CHIPID, + P_GET_CPU_FEATURES, P_WRITE64 = 0x100, // Generic register functions P_WRITE32,