From 869d2ae35c31e14935a63492070699aa359df717 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 25 Aug 2024 15:22:56 +0800 Subject: [PATCH] Skip over features unsupported in A7-A11 SoCs. This includes - GXF - SPRR - PAN (A7-A9) - Atomics (A7-A10) - FIPI (A7-A10) - DCP SPRR on T8030 seems to be quite different from M1 (at least according to qemu-t8030), so keep it disabled for those CPU parts. Signed-off-by: Nick Chan --- src/chickens.c | 8 +++++++- src/display.c | 12 +++++++++--- src/exception.c | 27 ++++++++++++++++----------- src/gxf.c | 3 +++ src/main.c | 12 +++++++----- src/memory.c | 12 ++++++++---- src/start.S | 5 ++++- src/startup.c | 15 +++++++++++++++ src/utils.c | 7 +++++-- src/utils.h | 5 +++-- 10 files changed, 77 insertions(+), 29 deletions(-) diff --git a/src/chickens.c b/src/chickens.c index 02329ef6..08677744 100644 --- a/src/chickens.c +++ b/src/chickens.c @@ -69,7 +69,7 @@ void init_t6021_avalanche(int rev); void init_t6031_sawtooth(void); void init_t6031_everest(int rev); -bool cpufeat_actlr_el2, cpufeat_fast_ipi; +bool cpufeat_actlr_el2, cpufeat_fast_ipi, cpufeat_mmu_sprr; const char *init_cpu(void) { @@ -230,11 +230,17 @@ const char *init_cpu(void) sysop("isb"); msr(SYS_IMP_APL_AMX_CTX_EL1, core); + + /* T8030 SPRR is different */ + cpufeat_mmu_sprr = true; } if (part >= MIDR_PART_T8030_LIGHTNING) msr(SYS_IMP_APL_AMX_CTL_EL1, 0x100); + if (part >= MIDR_PART_T8015_MONSOON) + cpufeat_fast_ipi = true; + /* Unmask external IRQs, set WFI mode to up (2) */ reg_mask(SYS_IMP_APL_CYC_OVRD, CYC_OVRD_FIQ_MODE_MASK | CYC_OVRD_IRQ_MODE_MASK | CYC_OVRD_WFI_MODE_MASK, diff --git a/src/display.c b/src/display.c index 395099b1..1bb28ae2 100644 --- a/src/display.c +++ b/src/display.c @@ -264,6 +264,11 @@ int display_start_dcp(void) return 0; #endif + if (!has_dcp) { + printf("display: DCP not present\n"); + return -1; + } + const display_config_t *disp_cfg = display_get_config(); display_is_dptx = !!disp_cfg->dptx_phy[0]; @@ -622,13 +627,14 @@ int display_init(void) else printf("display: Display is internal\n"); - if (cur_boot_args.video.width == 640 && cur_boot_args.video.height == 1136) { + if ((cur_boot_args.video.width == 640 && cur_boot_args.video.height == 1136) && + chip_id != S5L8960X) { printf("display: Dummy framebuffer found, initializing display\n"); return display_configure(NULL); - } else if (display_is_external) { + } else if (display_is_external && is_mac) { printf("display: External display found, reconfiguring\n"); return display_configure(NULL); - } else if (!(cur_boot_args.video.depth & FB_DEPTH_FLAG_RETINA)) { + } else if ((!(cur_boot_args.video.depth & FB_DEPTH_FLAG_RETINA)) && is_mac) { printf("display: Internal display with non-retina flag, assuming Sonoma bug and " "reconfiguring\n"); fb_clear_direct(); // Old m1n1 stage1 ends up with an ugly logo situation, clear it. diff --git a/src/exception.c b/src/exception.c index 9b2b3753..8588aeb9 100644 --- a/src/exception.c +++ b/src/exception.c @@ -137,7 +137,6 @@ void exception_initialize(void) msr(CNTP_CTL_EL02, 7L); msr(CNTV_CTL_EL02, 7L); } - if (cpufeat_fast_ipi) { reg_clr(SYS_IMP_APL_PMCR0, PMCR0_IACT | PMCR0_IMODE_MASK); reg_clr(SYS_IMP_APL_UPMCR0, UPMCR0_IMODE_MASK); @@ -223,11 +222,13 @@ void print_regs(u64 *regs, int el12) if (is_ecore()) { printf("E_LSU_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_E_LSU_ERR_STS)); printf("E_FED_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_E_FED_ERR_STS)); - printf("E_MMU_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_E_MMU_ERR_STS)); + if (cpufeat_fast_ipi) + printf("E_MMU_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_E_MMU_ERR_STS)); } else { printf("LSU_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_LSU_ERR_STS)); printf("FED_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_FED_ERR_STS)); - printf("MMU_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_MMU_ERR_STS)); + if (cpufeat_fast_ipi) + printf("MMU_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_MMU_ERR_STS)); } } @@ -383,15 +384,19 @@ void exc_fiq(u64 *regs) printf(" PMC IRQ, masking\n"); reg_clr(SYS_IMP_APL_PMCR0, PMCR0_IACT | PMCR0_IMODE_MASK); } - reg = mrs(SYS_IMP_APL_UPMCR0); - if ((reg & UPMCR0_IMODE_MASK) == UPMCR0_IMODE_FIQ && (mrs(SYS_IMP_APL_UPMSR) & UPMSR_IACT)) { - printf(" UPMC IRQ, masking\n"); - reg_clr(SYS_IMP_APL_UPMCR0, UPMCR0_IMODE_MASK); - } - if (mrs(SYS_IMP_APL_IPI_SR_EL1) & IPI_SR_PENDING) { - printf(" Fast IPI IRQ, clearing\n"); - msr(SYS_IMP_APL_IPI_SR_EL1, IPI_SR_PENDING); + if (cpufeat_fast_ipi) { + reg = mrs(SYS_IMP_APL_UPMCR0); + if ((reg & UPMCR0_IMODE_MASK) == UPMCR0_IMODE_FIQ && + (mrs(SYS_IMP_APL_UPMSR) & UPMSR_IACT)) { + printf(" UPMC IRQ, masking\n"); + reg_clr(SYS_IMP_APL_UPMCR0, UPMCR0_IMODE_MASK); + } + + if (mrs(SYS_IMP_APL_IPI_SR_EL1) & IPI_SR_PENDING) { + printf(" Fast IPI IRQ, clearing\n"); + msr(SYS_IMP_APL_IPI_SR_EL1, IPI_SR_PENDING); + } } UNUSED(regs); diff --git a/src/gxf.c b/src/gxf.c index 7b751c5f..2b1e52a9 100644 --- a/src/gxf.c +++ b/src/gxf.c @@ -30,6 +30,9 @@ void gxf_init(void) bool gxf_enabled(void) { + if (!supports_gxf()) + return false; + if (!(mrs(SYS_IMP_APL_SPRR_CONFIG_EL1) & SPRR_CONFIG_EN)) return false; diff --git a/src/main.c b/src/main.c index d922cb18..2f1a7cc9 100644 --- a/src/main.c +++ b/src/main.c @@ -51,6 +51,7 @@ void get_device_info(void) printf(" Target: %s\n", target); is_mac = !!strstr(model, "Mac"); + has_dcp = adt_path_offset(adt, "/arm-io/dcp") > 0; int chosen = adt_path_offset(adt, "/chosen"); if (chosen > 0) { @@ -146,13 +147,13 @@ void m1n1_main(void) printf("Running in EL%lu\n\n", mrs(CurrentEL) >> 2); - get_device_info(); firmware_init(); heapblock_init(); #ifndef BRINGUP - gxf_init(); + if (supports_gxf()) + gxf_init(); mcc_init(); mmu_init(); aic_init(); @@ -160,13 +161,14 @@ void m1n1_main(void) wdt_disable(); #ifndef BRINGUP pmgr_init(); - #ifdef USE_FB display_init(); // Kick DCP to sleep, so dodgy monitors which cause reconnect cycles don't cause us to lose the // framebuffer. - display_shutdown(DCP_SLEEP_IF_EXTERNAL); - fb_init(false); + if (has_dcp) + display_shutdown(DCP_SLEEP_IF_EXTERNAL); + // On idevice we need to always clear, because otherwise it looks scuffed on white devices + fb_init(!is_mac); fb_display_logo(); #ifdef FB_SILENT_MODE fb_set_active(!cur_boot_args.video.display); diff --git a/src/memory.c b/src/memory.c index b4abecf9..733cbafa 100644 --- a/src/memory.c +++ b/src/memory.c @@ -503,10 +503,12 @@ void mmu_init(void) mmu_init_pagetables(); mmu_add_default_mappings(); mmu_configure(); - mmu_init_sprr(); + if (cpufeat_mmu_sprr) + mmu_init_sprr(); // Enable EL0 memory access by EL1 - msr(PAN, 0); + if (supports_pan()) + msr(PAN, 0); // RES1 bits u64 sctlr = SCTLR_LSMAOE | SCTLR_nTLSMD | SCTLR_TSCXT | SCTLR_ITD; @@ -521,10 +523,12 @@ void mmu_init(void) static void mmu_secondary_setup(void) { mmu_configure(); - mmu_init_sprr(); + if (cpufeat_mmu_sprr) + mmu_init_sprr(); // Enable EL0 memory access by EL1 - msr(PAN, 0); + if (supports_pan()) + msr(PAN, 0); // RES1 bits u64 sctlr = SCTLR_LSMAOE | SCTLR_nTLSMD | SCTLR_TSCXT | SCTLR_ITD; diff --git a/src/start.S b/src/start.S index fcefb961..befef997 100644 --- a/src/start.S +++ b/src/start.S @@ -95,6 +95,7 @@ _start: bl debug_putc mov w0, '\n' bl debug_putc + bl pan_fixup mrs x8, CurrentEL cmp x8, #0xc @@ -105,7 +106,6 @@ _start: bl _start_c b . -.globl exception_initialize start_el3: bl exception_initialize adrp x8, _stack_bot_el3 @@ -197,6 +197,9 @@ debug_putc: .globl reboot .type reboot, @function reboot: + mrs x8, id_aa64pfr0_el1 + tst w8, 0xf00 + beq 1f mrs x0, CurrentEL cmp x0, #8 beq 1f diff --git a/src/startup.c b/src/startup.c index a883bea3..b7670543 100644 --- a/src/startup.c +++ b/src/startup.c @@ -44,6 +44,21 @@ void apply_rela(uint64_t base, struct rela_entry *rela_start, struct rela_entry } } +extern uint32_t _v_sp0_sync[], _v_sp0_irq[], _v_sp0_fiq[], _v_sp0_serr[]; +void pan_fixup(void) +{ + if (supports_pan()) + return; + + /* Patch msr pan, #0 to nop */ + _v_sp0_sync[0] = 0xd503201f; + _v_sp0_irq[0] = 0xd503201f; + _v_sp0_fiq[0] = 0xd503201f; + _v_sp0_serr[0] = 0xd503201f; + + sysop("isb"); +} + void dump_boot_args(struct boot_args *ba) { printf(" revision: %d\n", ba->revision); diff --git a/src/utils.c b/src/utils.c index 3ed569fe..8a4b8d0f 100644 --- a/src/utils.c +++ b/src/utils.c @@ -8,10 +8,11 @@ #include "iodev.h" #include "smp.h" #include "types.h" +#include "utils.h" #include "vsprintf.h" #include "xnuboot.h" -bool is_mac = false; +bool is_mac, has_dcp; static char ascii(char s) { @@ -149,7 +150,7 @@ void spin_lock(spinlock_t *lock) __asm__ volatile("1:\n" "mov\t%0, -1\n" "2:\n" - "\tcasa\t%0, %2, %1\n" + "\tldaxr\t%0, %1\n" "\tcmn\t%0, 1\n" "\tbeq\t3f\n" "\tldxr\t%0, %1\n" @@ -158,6 +159,8 @@ void spin_lock(spinlock_t *lock) "\twfe\n" "\tb\t1b\n" "3:" + "\tstxr\t%w0, %2, %1\n" + "\tcbnz\t%w0, 2b\n" : "=&r"(tmp), "+m"(lock->lock) : "r"(me) : "cc", "memory"); diff --git a/src/utils.h b/src/utils.h index 7e823294..b055f29f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -447,8 +447,9 @@ struct vector_args { }; extern u32 board_id, chip_id; -extern bool is_mac; -extern bool cpufeat_actlr_el2, cpufeat_fast_ipi; + +extern bool is_mac, has_dcp; +extern bool cpufeat_actlr_el2, cpufeat_fast_ipi, cpufeat_mmu_sprr; extern struct vector_args next_stage;