From c45da55256fd15bfe1b4ecbc5331624d3427ee1e Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Tue, 21 Nov 2023 18:24:12 -0500 Subject: [PATCH] More support for M3 chips The UART base has moved from the M2 chips. Everest settings introduce some changes to unknown registers The MCC data has changed as well. There is a drive-by change where I discovered what some of the unknown HID18 bits are and documented them. Signed-off-by: Daniel Berlin --- Makefile | 2 + src/chickens.c | 14 ++++++ src/chickens_avalanche.c | 9 ++-- src/chickens_everest.c | 46 +++++++++++++++++++ src/chickens_firestorm.c | 6 +-- src/chickens_sawtooth.c | 20 +++++++++ src/cpu_regs.h | 27 ++++++----- src/main.c | 1 - src/mcc.c | 97 +++++++++++++++++++++++++++++++++++++++- src/soc.h | 2 + tools/apple_regs.json | 2 + 11 files changed, 208 insertions(+), 18 deletions(-) create mode 100644 src/chickens_everest.c create mode 100644 src/chickens_sawtooth.c diff --git a/Makefile b/Makefile index 164f7205..0d8c0d9a 100644 --- a/Makefile +++ b/Makefile @@ -91,8 +91,10 @@ OBJECTS := \ chickens.o \ chickens_avalanche.o \ chickens_blizzard.o \ + chickens_everest.o \ chickens_firestorm.o \ chickens_icestorm.o \ + chickens_sawtooth.o \ clk.o \ cpufreq.o \ dapf.o \ diff --git a/src/chickens.c b/src/chickens.c index af9c7bc0..97572462 100644 --- a/src/chickens.c +++ b/src/chickens.c @@ -22,6 +22,8 @@ #define MIDR_PART_T6020_AVALANCHE 0x35 #define MIDR_PART_T6021_BLIZZARD 0x38 #define MIDR_PART_T6021_AVALANCHE 0x39 +#define MIDR_PART_T6031_EVEREST 0x49 +#define MIDR_PART_T6031_SAWTOOTH 0x48 #define MIDR_REV_LOW GENMASK(3, 0) #define MIDR_PART GENMASK(15, 4) @@ -37,6 +39,8 @@ void init_t6020_blizzard(void); void init_t6020_avalanche(int rev); void init_t6021_blizzard(void); void init_t6021_avalanche(int rev); +void init_t6031_sawtooth(void); +void init_t6031_everest(int rev); const char *init_cpu(void) { @@ -123,6 +127,16 @@ const char *init_cpu(void) init_t6021_blizzard(); break; + case MIDR_PART_T6031_EVEREST: + cpu = "M3 Max Everest"; + init_t6031_everest(rev); + break; + + case MIDR_PART_T6031_SAWTOOTH: + cpu = "M3 Max Sawtooth"; + init_t6031_sawtooth(); + break; + default: uart_puts(" Unknown CPU type"); break; diff --git a/src/chickens_avalanche.c b/src/chickens_avalanche.c index 1ecccef2..f75611d1 100644 --- a/src/chickens_avalanche.c +++ b/src/chickens_avalanche.c @@ -40,7 +40,8 @@ void init_t8112_avalanche(int rev) reg_mask(SYS_IMP_APL_HID3, HID3_DEV_PCIE_THROTTLE_LIMIT_MASK, HID3_DEV_PCIE_THROTTLE_LIMIT(60)); reg_set(SYS_IMP_APL_HID3, HID3_DEV_PCIE_THROTTLE_ENABLE); - reg_set(SYS_IMP_APL_HID18, HID18_AVL_UNK27 | HID18_AVL_UNK29); + reg_set(SYS_IMP_APL_HID18, + HID18_GEXIT_EL_SPECULATION_DISABLE | HID18_GENTER_SPECULATION_DISABLE); reg_set(SYS_IMP_APL_HID16, HID16_AVL_UNK12); if (rev == 0) { @@ -59,7 +60,8 @@ void init_t6020_avalanche(int rev) reg_mask(SYS_IMP_APL_HID3, HID3_DEV_PCIE_THROTTLE_LIMIT_MASK, HID3_DEV_PCIE_THROTTLE_LIMIT(62)); reg_set(SYS_IMP_APL_HID3, HID3_DEV_PCIE_THROTTLE_ENABLE); - reg_set(SYS_IMP_APL_HID18, HID18_AVL_UNK27 | HID18_AVL_UNK29); + reg_set(SYS_IMP_APL_HID18, + HID18_GEXIT_EL_SPECULATION_DISABLE | HID18_GENTER_SPECULATION_DISABLE); reg_set(SYS_IMP_APL_HID16, HID16_AVL_UNK12); reg_mask(SYS_IMP_APL_HID5, HID5_BLZ_UNK_19_18_MASK, HID5_BLZ_UNK18); @@ -73,7 +75,8 @@ void init_t6021_avalanche(int rev) reg_mask(SYS_IMP_APL_HID3, HID3_DEV_PCIE_THROTTLE_LIMIT_MASK, HID3_DEV_PCIE_THROTTLE_LIMIT(62)); reg_set(SYS_IMP_APL_HID3, HID3_DEV_PCIE_THROTTLE_ENABLE); - reg_set(SYS_IMP_APL_HID18, HID18_AVL_UNK27 | HID18_AVL_UNK29); + reg_set(SYS_IMP_APL_HID18, + HID18_GEXIT_EL_SPECULATION_DISABLE | HID18_GENTER_SPECULATION_DISABLE); reg_set(SYS_IMP_APL_HID16, HID16_AVL_UNK12); reg_mask(SYS_IMP_APL_HID5, HID5_BLZ_UNK_19_18_MASK, HID5_BLZ_UNK19); diff --git a/src/chickens_everest.c b/src/chickens_everest.c new file mode 100644 index 00000000..2f9ac25c --- /dev/null +++ b/src/chickens_everest.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: MIT */ + +#include "cpu_regs.h" +#include "uart.h" +#include "utils.h" +static void init_common_everest(void) +{ + reg_set(SYS_IMP_APL_HID12, BIT(46)); + reg_set(SYS_IMP_APL_HID3, BIT(63)); + reg_mask(SYS_IMP_APL_HID3, GENMASK(ULONG(62), ULONG(56)), BIT(60) | BIT(59) | BIT(58)); + reg_clr(SYS_IMP_APL_HID3, BIT(4)); + reg_set(SYS_IMP_APL_HID9, BIT(17)); + reg_mask(SYS_IMP_APL_HID13, + HID13_POST_OFF_CYCLES_MASK | HID13_POST_ON_CYCLES_MASK | HID13_PRE_CYCLES_MASK | + HID13_GROUP0_FF1_DELAY_MASK | HID13_GROUP0_FF2_DELAY_MASK | + HID13_GROUP0_FF3_DELAY_MASK | HID13_GROUP0_FF4_DELAY_MASK | + HID13_GROUP0_FF5_DELAY_MASK | HID13_GROUP0_FF6_DELAY_MASK | + HID13_GROUP0_FF7_DELAY_MASK | HID13_RESET_CYCLES_MASK, + HID13_POST_OFF_CYCLES(4) | HID13_POST_ON_CYCLES(5) | HID13_PRE_CYCLES(1) | + HID13_GROUP0_FF1_DELAY(4) | HID13_GROUP0_FF2_DELAY(4) | HID13_GROUP0_FF3_DELAY(4) | + HID13_GROUP0_FF4_DELAY(4) | HID13_GROUP0_FF5_DELAY(4) | HID13_GROUP0_FF6_DELAY(4) | + HID13_GROUP0_FF7_DELAY(4) | HID13_RESET_CYCLES(0)); + reg_set(SYS_IMP_APL_HID16, BIT(54)); + reg_set(SYS_IMP_APL_HID18, + HID18_GEXIT_EL_SPECULATION_DISABLE | HID18_GENTER_SPECULATION_DISABLE); + + msr(SYS_IMP_APL_HID26, HID26_GROUP1_OFFSET(0xF88F65588LL) | HID26_GROUP2_OFFSET(0x3F28)); + reg_mask(SYS_IMP_APL_HID27, + GENMASK(43, 40) | GENMASK(39, 36) | GENMASK(35, 32) | GENMASK(31, 28) | + GENMASK(27, 24) | GENMASK(23, 20) | GENMASK(19, 16) | GENMASK(15, 8) | + GENMASK(7, 4) | GENMASK(3, 0), + BIT(40) | BIT(36) | BIT(32) | BIT(28) | BIT(24) | BIT(20) | BIT(16) | 0x2b00uL | + BIT(4) | BIT(0)); + /* This is new to M3 and i have no idea what it is yet */ + reg_set(s3_0_c15_c2_3, BIT(3)); + reg_clr(s3_0_c15_c2_4, BIT(0) | BIT(1) | BIT(16) | BIT(17) | BIT(18) | BIT(22)); +} + +void init_t6031_everest(int rev) +{ + UNUSED(rev); + msr(s3_1_c15_c1_5, 0x3uL); + msr(s3_4_c15_c14_6, 0x3uL); + init_common_everest(); + reg_set(SYS_IMP_APL_HID4, HID4_ENABLE_LFSR_STALL_LOAD_PIPE2_ISSUE); +} \ No newline at end of file diff --git a/src/chickens_firestorm.c b/src/chickens_firestorm.c index 696761bf..a4cd96d2 100644 --- a/src/chickens_firestorm.c +++ b/src/chickens_firestorm.c @@ -72,7 +72,7 @@ void init_t8103_firestorm(int rev) reg_set(SYS_IMP_APL_HID1, HID1_ENABLE_MDSB_STALL_PIPELINE_ECO | HID1_ENABLE_BR_KILL_LIMIT); if (rev >= 0x11) - reg_set(SYS_IMP_APL_HID18, HID18_SPAREBIT17); + reg_set(SYS_IMP_APL_HID18, HID18_PREF_REPLAY_DISABLE); } void init_t6000_firestorm(int rev) @@ -88,7 +88,7 @@ void init_t6000_firestorm(int rev) reg_set(SYS_IMP_APL_HID4, HID4_ENABLE_LFSR_STALL_LOAD_PIPE2_ISSUE | HID4_ENABLE_LFSR_STALL_STQ_REPLAY); - reg_set(SYS_IMP_APL_HID18, HID18_SPAREBIT17); + reg_set(SYS_IMP_APL_HID18, HID18_PREF_REPLAY_DISABLE); } } @@ -108,6 +108,6 @@ void init_t6001_firestorm(int rev) if (rev >= 0x10) { reg_set(SYS_IMP_APL_HID1, HID1_ENABLE_BR_KILL_LIMIT); - reg_set(SYS_IMP_APL_HID18, HID18_SPAREBIT17); + reg_set(SYS_IMP_APL_HID18, HID18_PREF_REPLAY_DISABLE); } } diff --git a/src/chickens_sawtooth.c b/src/chickens_sawtooth.c new file mode 100644 index 00000000..8e9fe317 --- /dev/null +++ b/src/chickens_sawtooth.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: MIT */ + +#include "cpu_regs.h" +#include "utils.h" + +static void init_common_sawtooth(void) +{ + reg_set(SYS_IMP_APL_EHID0, EHID0_BLI_UNK32); +} + +void init_t6031_sawtooth(void) +{ + init_common_sawtooth(); + + reg_mask(SYS_IMP_APL_EHID9, EHID9_DEV_2_THROTTLE_LIMIT_MASK, EHID9_DEV_2_THROTTLE_LIMIT(62)); + reg_set(SYS_IMP_APL_EHID9, EHID9_DEV_2_THROTTLE_ENABLE); + reg_set(SYS_IMP_APL_EHID18, EHID18_BLZ_UNK34); + + reg_mask(SYS_IMP_APL_HID5, HID5_BLZ_UNK_19_18_MASK, HID5_BLZ_UNK19); +} diff --git a/src/cpu_regs.h b/src/cpu_regs.h index de74d7e4..744f092a 100644 --- a/src/cpu_regs.h +++ b/src/cpu_regs.h @@ -299,6 +299,8 @@ #define HID11_ENABLE_FIX_UC_55719865 BIT(15) #define HID11_DISABLE_LD_NT_WIDGET BIT(59) +#define SYS_IMP_APL_HID12 sys_reg(3, 0, 15, 12, 0) + #define SYS_IMP_APL_HID13 sys_reg(3, 0, 15, 14, 0) #define HID13_POST_OFF_CYCLES(x) ((ULONG(x))) #define HID13_POST_OFF_CYCLES_MASK GENMASK(6, 0) @@ -333,12 +335,12 @@ #define HID16_ENABLE_MPX_PICK_45 BIT(61) #define HID16_ENABLE_MP_CYCLONE_7 BIT(62) -#define SYS_IMP_APL_HID18 sys_reg(3, 0, 15, 11, 2) -#define HID18_HVC_SPECULATION_DISABLE BIT(14) -#define HID18_AVL_UNK27 BIT(27) -#define HID18_AVL_UNK29 BIT(29) -#define HID18_SPAREBIT7 BIT(39) -#define HID18_SPAREBIT17 BIT(49) +#define SYS_IMP_APL_HID18 sys_reg(3, 0, 15, 11, 2) +#define HID18_HVC_SPECULATION_DISABLE BIT(14) +#define HID18_GEXIT_EL_SPECULATION_DISABLE BIT(27) +#define HID18_GENTER_SPECULATION_DISABLE BIT(29) +#define HID18_BTP_BRN_DISABLE BIT(39) +#define HID18_PREF_REPLAY_DISABLE BIT(49) #define SYS_IMP_APL_EHID18 sys_reg(3, 0, 15, 11, 3) #define EHID18_BLZ_UNK34 BIT(34) @@ -401,11 +403,12 @@ #define EHID20_FORCE_NONSPEC_TARGETED_TIMER_SEL(x) ((ULONG(x)) << 21) #define EHID20_FORCE_NONSPEC_TARGETED_TIMER_SEL_MASK (3UL << 21) -#define SYS_IMP_APL_HID21 sys_reg(3, 0, 15, 1, 3) +#define SYS_IMP_APL_HID21 sys_reg(3, 0, 15, 1, 3) +// In 6031's, this is marked as "wfi_full_quis" #define HID21_ENABLE_LDREX_FILL_REPLY BIT(19) -#define HID21_LDQ_RTR_WAIT_FOR_OLD_ST_REL_COMPLETION BIT(33) -#define HID21_DISABLE_CDP_REPLY_PURGED_TRANSACTION BIT(34) -#define HID21_AVL_UNK52 BIT(52) +#define HID21_LDQ_RTR_WAIT_FOR_OLD_ST_REL_COMPLETION BIT(34) +#define HID21_DISABLE_CDP_REPLY_PURGED_TRANSACTION BIT(35) +#define HID21_PURGE_MMU_ON_ANY_SPR_SYNC BIT(52) #define SYS_IMP_APL_HID26 sys_reg(3, 0, 15, 0, 3) #define HID26_GROUP1_OFFSET(x) ((ULONG(x)) << 0) @@ -617,3 +620,7 @@ #define IPI_SR_PENDING BIT(0) #define SYS_IMP_APL_IPI_CR_EL1 sys_reg(3, 5, 15, 3, 1) + +/* Lockdown registers */ +#define SYS_IMP_APL_SPR_LOCKDOWN_EL2 sys_reg(3, 4, 15, 0, 5) +#define SYS_IMP_APL_SPR_LOCKDOWN_EL1 sys_reg(3, 4, 15, 0, 6) diff --git a/src/main.c b/src/main.c index 6bf7b301..66c05ba9 100644 --- a/src/main.c +++ b/src/main.c @@ -113,7 +113,6 @@ void run_actions(void) printf("Valid payload found\n"); return; } - fb_set_active(true); printf("No valid payload found\n"); diff --git a/src/mcc.c b/src/mcc.c index 1ba82c79..37538839 100644 --- a/src/mcc.c +++ b/src/mcc.c @@ -23,6 +23,12 @@ 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 PLANE_TZ_MAX_REGS 4 struct tz_regs { @@ -49,6 +55,14 @@ struct tz_regs t602x_tz_regs = { .enable = 0x6c8, }; +struct tz_regs t603x_tz_regs = { + .count = 4, + .stride = 0x14, + .start = 0x6d8, + .end = 0x6dc, + .enable = 0x6e4, +}; + #define PLANE_CACHE_ENABLE 0x1c00 #define PLANE_CACHE_STATUS 0x1c04 @@ -64,6 +78,12 @@ struct tz_regs t602x_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 T8103_CACHE_WAYS 16 #define T8103_CACHE_STATUS_MASK (T8103_CACHE_STATUS_DATA_COUNT | T8103_CACHE_STATUS_TAG_COUNT) #define T8103_CACHE_STATUS_VAL \ @@ -134,6 +154,8 @@ int mcc_enable_cache(void) if (!mcc_initialized) return -1; + /* The 6030 memory controller supports setting a waymask, but the desktop chips do not appear to + use it */ for (int mcc = 0; mcc < mcc_count; mcc++) { for (int plane = 0; plane < mcc_regs[mcc].plane_count; plane++) { plane_write32(mcc, plane, PLANE_CACHE_ENABLE, mcc_regs[mcc].cache_enable_val); @@ -161,7 +183,12 @@ int mcc_unmap_carveouts(void) mcc_carveout_count = 0; memset(mcc_carveouts, 0, sizeof mcc_carveouts); + // All MCCs and planes should have identical configs + // Note: For unhandled machines, the TZ regions can be found (on m1, m2, m3) by looking at + // region-id-2 and region-id-4 on a booted macos, in the /chosen/carveout-memory-map DT node. + // This can be used along with dumping the mcc reg space to find the correct start/end/enable + // above. for (u32 i = 0; i < mcc_regs[0].tz->count; i++) { uint64_t off = mcc_regs[0].tz->stride * i; uint64_t start = plane_read32(0, 0, mcc_regs[0].tz->start + off); @@ -291,6 +318,72 @@ int mcc_init_t6000(int node, int *path, bool t602x) return 0; } +int mcc_init_t6031(int node, int *path) +{ + u32 reg_len; + u32 reg_offset = 3; + + if (!adt_getprop(adt, node, "reg", ®_len)) { + printf("MCC: Failed to get reg property!\n"); + return -1; + } + + mcc_count = reg_len / 16 - reg_offset; + + printf("MCC: Initializing T6031 MCCs (%d instances)...\n", mcc_count); + + if (mcc_count > MAX_MCC_INSTANCES) { + printf("MCC: Too many instances, increase MAX_MCC_INSTANCES!\n"); + mcc_count = MAX_MCC_INSTANCES; + } + + u32 plane_count = 0; + u32 dcs_count = 0; + + if (!ADT_GETPROP(adt, node, "dcs-count-per-amcc", &dcs_count)) { + printf("MCC: Failed to get dcs count!\n"); + return -1; + } + + if (!ADT_GETPROP(adt, node, "plane-count-per-amcc", &plane_count)) { + printf("MCC: Failed to get plane count!\n"); + return -1; + } + + for (int i = 0; i < mcc_count; i++) { + u64 base; + if (adt_get_reg(adt, path, "reg", i + reg_offset, &base, NULL)) { + printf("MCC: Failed to get reg index %d!\n", i + reg_offset); + return -1; + } + + mcc_regs[i].plane_base = base + T6031_PLANE_OFFSET; + mcc_regs[i].plane_stride = T6031_PLANE_STRIDE; + mcc_regs[i].plane_count = plane_count; + + mcc_regs[i].global_base = base + T6031_GLOBAL_OFFSET; + + mcc_regs[i].dcs_base = base + T6031_DCS_OFFSET; + mcc_regs[i].dcs_stride = T6031_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_disable = 0; + + mcc_regs[i].tz = &t603x_tz_regs; + } + + printf("MCC: Initialized T6031 MCCs (%d instances, %d planes, %d channels)\n", mcc_count, + mcc_regs[0].plane_count, mcc_regs[0].dcs_count); + + mcc_initialized = true; + + return 0; +} + int mcc_init(void) { int path[8]; @@ -309,8 +402,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,t6031")) { + return mcc_init_t6031(node, path); } else { - printf("MCC: Unsupported version\n"); + printf("MCC: Unsupported version:%s\n", adt_get_property(adt, node, "compatible")->value); return -1; } } diff --git a/src/soc.h b/src/soc.h index 7bd33a2c..eb375eda 100644 --- a/src/soc.h +++ b/src/soc.h @@ -26,6 +26,8 @@ #define EARLY_UART_BASE 0x39b200000 #elif TARGET == T8112 #define EARLY_UART_BASE 0x235200000 +#elif TARGET == T6034 || TARGET == T6031 +#define EARLY_UART_BASE 0x391200000 #endif #endif diff --git a/tools/apple_regs.json b/tools/apple_regs.json index 7cebf57a..9b8cb739 100644 --- a/tools/apple_regs.json +++ b/tools/apple_regs.json @@ -29,6 +29,8 @@ {"index": 0, "name": "EHID18_EL1", "fullname": "Hardware Implementation-Dependent Register 18 (E-core)", "enc": [3, 0, 15, 11, 3 ], "width": 64}, {"index": 0, "name": "EHID20_EL1", "fullname": "Hardware Implementation-Dependent Register 20 (E-core)", "enc": [3, 0, 15, 1, 2 ], "width": 64}, {"index": 0, "name": "HID21_EL1", "fullname": "Hardware Implementation-Dependent Register 21", "enc": [3, 0, 15, 1, 3 ], "width": 64}, + {"index": 0, "name": "HID26_EL1", "fullname": "Hardware Implementation-Dependent Register 26", "enc": [3, 0, 15, 0, 3 ], "width": 64}, + {"index": 0, "name": "HID27_EL1", "fullname": "Hardware Implementation-Dependent Register 27", "enc": [3, 0, 15, 0, 4 ], "width": 64}, {"index": 0, "name": "PMCR0_EL1", "fullname": "Performance Monitor Control Register 0", "enc": [3, 1, 15, 0, 0 ], "width": 64, "fieldsets": [{"fields": [ {"name": "PMC0_EN", "msb": 0, "lsb": 0},