Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

T6030 (M3 Pro) changes #402

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions proxyclient/m1n1/hv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
4 changes: 3 additions & 1 deletion proxyclient/tools/chainload.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
119 changes: 106 additions & 13 deletions src/aic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand All @@ -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;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/aic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions src/aic_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/hv_exc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
65 changes: 41 additions & 24 deletions src/mcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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");
Expand All @@ -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;
Expand All @@ -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;
Expand Down
9 changes: 8 additions & 1 deletion src/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
Loading
Loading