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 <towinchenmi@gmail.com>
This commit is contained in:
Nick Chan 2024-08-25 15:22:56 +08:00 committed by Hector Martin
parent accb393510
commit 869d2ae35c
10 changed files with 77 additions and 29 deletions

View file

@ -69,7 +69,7 @@ void init_t6021_avalanche(int rev);
void init_t6031_sawtooth(void); void init_t6031_sawtooth(void);
void init_t6031_everest(int rev); 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) const char *init_cpu(void)
{ {
@ -230,11 +230,17 @@ const char *init_cpu(void)
sysop("isb"); sysop("isb");
msr(SYS_IMP_APL_AMX_CTX_EL1, core); msr(SYS_IMP_APL_AMX_CTX_EL1, core);
/* T8030 SPRR is different */
cpufeat_mmu_sprr = true;
} }
if (part >= MIDR_PART_T8030_LIGHTNING) if (part >= MIDR_PART_T8030_LIGHTNING)
msr(SYS_IMP_APL_AMX_CTL_EL1, 0x100); 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) */ /* Unmask external IRQs, set WFI mode to up (2) */
reg_mask(SYS_IMP_APL_CYC_OVRD, reg_mask(SYS_IMP_APL_CYC_OVRD,
CYC_OVRD_FIQ_MODE_MASK | CYC_OVRD_IRQ_MODE_MASK | CYC_OVRD_WFI_MODE_MASK, CYC_OVRD_FIQ_MODE_MASK | CYC_OVRD_IRQ_MODE_MASK | CYC_OVRD_WFI_MODE_MASK,

View file

@ -264,6 +264,11 @@ int display_start_dcp(void)
return 0; return 0;
#endif #endif
if (!has_dcp) {
printf("display: DCP not present\n");
return -1;
}
const display_config_t *disp_cfg = display_get_config(); const display_config_t *disp_cfg = display_get_config();
display_is_dptx = !!disp_cfg->dptx_phy[0]; display_is_dptx = !!disp_cfg->dptx_phy[0];
@ -622,13 +627,14 @@ int display_init(void)
else else
printf("display: Display is internal\n"); 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"); printf("display: Dummy framebuffer found, initializing display\n");
return display_configure(NULL); return display_configure(NULL);
} else if (display_is_external) { } else if (display_is_external && is_mac) {
printf("display: External display found, reconfiguring\n"); printf("display: External display found, reconfiguring\n");
return display_configure(NULL); 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 " printf("display: Internal display with non-retina flag, assuming Sonoma bug and "
"reconfiguring\n"); "reconfiguring\n");
fb_clear_direct(); // Old m1n1 stage1 ends up with an ugly logo situation, clear it. fb_clear_direct(); // Old m1n1 stage1 ends up with an ugly logo situation, clear it.

View file

@ -137,7 +137,6 @@ void exception_initialize(void)
msr(CNTP_CTL_EL02, 7L); msr(CNTP_CTL_EL02, 7L);
msr(CNTV_CTL_EL02, 7L); msr(CNTV_CTL_EL02, 7L);
} }
if (cpufeat_fast_ipi) { if (cpufeat_fast_ipi) {
reg_clr(SYS_IMP_APL_PMCR0, PMCR0_IACT | PMCR0_IMODE_MASK); reg_clr(SYS_IMP_APL_PMCR0, PMCR0_IACT | PMCR0_IMODE_MASK);
reg_clr(SYS_IMP_APL_UPMCR0, UPMCR0_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()) { if (is_ecore()) {
printf("E_LSU_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_E_LSU_ERR_STS)); 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_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 { } else {
printf("LSU_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_LSU_ERR_STS)); 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("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"); printf(" PMC IRQ, masking\n");
reg_clr(SYS_IMP_APL_PMCR0, PMCR0_IACT | PMCR0_IMODE_MASK); 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) { if (cpufeat_fast_ipi) {
printf(" Fast IPI IRQ, clearing\n"); reg = mrs(SYS_IMP_APL_UPMCR0);
msr(SYS_IMP_APL_IPI_SR_EL1, IPI_SR_PENDING); 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); UNUSED(regs);

View file

@ -30,6 +30,9 @@ void gxf_init(void)
bool gxf_enabled(void) bool gxf_enabled(void)
{ {
if (!supports_gxf())
return false;
if (!(mrs(SYS_IMP_APL_SPRR_CONFIG_EL1) & SPRR_CONFIG_EN)) if (!(mrs(SYS_IMP_APL_SPRR_CONFIG_EL1) & SPRR_CONFIG_EN))
return false; return false;

View file

@ -51,6 +51,7 @@ void get_device_info(void)
printf(" Target: %s\n", target); printf(" Target: %s\n", target);
is_mac = !!strstr(model, "Mac"); is_mac = !!strstr(model, "Mac");
has_dcp = adt_path_offset(adt, "/arm-io/dcp") > 0;
int chosen = adt_path_offset(adt, "/chosen"); int chosen = adt_path_offset(adt, "/chosen");
if (chosen > 0) { if (chosen > 0) {
@ -146,13 +147,13 @@ void m1n1_main(void)
printf("Running in EL%lu\n\n", mrs(CurrentEL) >> 2); printf("Running in EL%lu\n\n", mrs(CurrentEL) >> 2);
get_device_info();
firmware_init(); firmware_init();
heapblock_init(); heapblock_init();
#ifndef BRINGUP #ifndef BRINGUP
gxf_init(); if (supports_gxf())
gxf_init();
mcc_init(); mcc_init();
mmu_init(); mmu_init();
aic_init(); aic_init();
@ -160,13 +161,14 @@ void m1n1_main(void)
wdt_disable(); wdt_disable();
#ifndef BRINGUP #ifndef BRINGUP
pmgr_init(); pmgr_init();
#ifdef USE_FB #ifdef USE_FB
display_init(); display_init();
// Kick DCP to sleep, so dodgy monitors which cause reconnect cycles don't cause us to lose the // Kick DCP to sleep, so dodgy monitors which cause reconnect cycles don't cause us to lose the
// framebuffer. // framebuffer.
display_shutdown(DCP_SLEEP_IF_EXTERNAL); if (has_dcp)
fb_init(false); 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(); fb_display_logo();
#ifdef FB_SILENT_MODE #ifdef FB_SILENT_MODE
fb_set_active(!cur_boot_args.video.display); fb_set_active(!cur_boot_args.video.display);

View file

@ -503,10 +503,12 @@ void mmu_init(void)
mmu_init_pagetables(); mmu_init_pagetables();
mmu_add_default_mappings(); mmu_add_default_mappings();
mmu_configure(); mmu_configure();
mmu_init_sprr(); if (cpufeat_mmu_sprr)
mmu_init_sprr();
// Enable EL0 memory access by EL1 // Enable EL0 memory access by EL1
msr(PAN, 0); if (supports_pan())
msr(PAN, 0);
// RES1 bits // RES1 bits
u64 sctlr = SCTLR_LSMAOE | SCTLR_nTLSMD | SCTLR_TSCXT | SCTLR_ITD; u64 sctlr = SCTLR_LSMAOE | SCTLR_nTLSMD | SCTLR_TSCXT | SCTLR_ITD;
@ -521,10 +523,12 @@ void mmu_init(void)
static void mmu_secondary_setup(void) static void mmu_secondary_setup(void)
{ {
mmu_configure(); mmu_configure();
mmu_init_sprr(); if (cpufeat_mmu_sprr)
mmu_init_sprr();
// Enable EL0 memory access by EL1 // Enable EL0 memory access by EL1
msr(PAN, 0); if (supports_pan())
msr(PAN, 0);
// RES1 bits // RES1 bits
u64 sctlr = SCTLR_LSMAOE | SCTLR_nTLSMD | SCTLR_TSCXT | SCTLR_ITD; u64 sctlr = SCTLR_LSMAOE | SCTLR_nTLSMD | SCTLR_TSCXT | SCTLR_ITD;

View file

@ -95,6 +95,7 @@ _start:
bl debug_putc bl debug_putc
mov w0, '\n' mov w0, '\n'
bl debug_putc bl debug_putc
bl pan_fixup
mrs x8, CurrentEL mrs x8, CurrentEL
cmp x8, #0xc cmp x8, #0xc
@ -105,7 +106,6 @@ _start:
bl _start_c bl _start_c
b . b .
.globl exception_initialize
start_el3: start_el3:
bl exception_initialize bl exception_initialize
adrp x8, _stack_bot_el3 adrp x8, _stack_bot_el3
@ -197,6 +197,9 @@ debug_putc:
.globl reboot .globl reboot
.type reboot, @function .type reboot, @function
reboot: reboot:
mrs x8, id_aa64pfr0_el1
tst w8, 0xf00
beq 1f
mrs x0, CurrentEL mrs x0, CurrentEL
cmp x0, #8 cmp x0, #8
beq 1f beq 1f

View file

@ -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) void dump_boot_args(struct boot_args *ba)
{ {
printf(" revision: %d\n", ba->revision); printf(" revision: %d\n", ba->revision);

View file

@ -8,10 +8,11 @@
#include "iodev.h" #include "iodev.h"
#include "smp.h" #include "smp.h"
#include "types.h" #include "types.h"
#include "utils.h"
#include "vsprintf.h" #include "vsprintf.h"
#include "xnuboot.h" #include "xnuboot.h"
bool is_mac = false; bool is_mac, has_dcp;
static char ascii(char s) static char ascii(char s)
{ {
@ -149,7 +150,7 @@ void spin_lock(spinlock_t *lock)
__asm__ volatile("1:\n" __asm__ volatile("1:\n"
"mov\t%0, -1\n" "mov\t%0, -1\n"
"2:\n" "2:\n"
"\tcasa\t%0, %2, %1\n" "\tldaxr\t%0, %1\n"
"\tcmn\t%0, 1\n" "\tcmn\t%0, 1\n"
"\tbeq\t3f\n" "\tbeq\t3f\n"
"\tldxr\t%0, %1\n" "\tldxr\t%0, %1\n"
@ -158,6 +159,8 @@ void spin_lock(spinlock_t *lock)
"\twfe\n" "\twfe\n"
"\tb\t1b\n" "\tb\t1b\n"
"3:" "3:"
"\tstxr\t%w0, %2, %1\n"
"\tcbnz\t%w0, 2b\n"
: "=&r"(tmp), "+m"(lock->lock) : "=&r"(tmp), "+m"(lock->lock)
: "r"(me) : "r"(me)
: "cc", "memory"); : "cc", "memory");

View file

@ -447,8 +447,9 @@ struct vector_args {
}; };
extern u32 board_id, chip_id; 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; extern struct vector_args next_stage;