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_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,

View file

@ -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.

View file

@ -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,10 +222,12 @@ 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));
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));
if (cpufeat_fast_ipi)
printf("MMU_ERR_STS: 0x%lx\n", mrs(SYS_IMP_APL_MMU_ERR_STS));
}
}
@ -383,8 +384,11 @@ void exc_fiq(u64 *regs)
printf(" PMC IRQ, masking\n");
reg_clr(SYS_IMP_APL_PMCR0, PMCR0_IACT | PMCR0_IMODE_MASK);
}
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)) {
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);
}
@ -393,6 +397,7 @@ void exc_fiq(u64 *regs)
printf(" Fast IPI IRQ, clearing\n");
msr(SYS_IMP_APL_IPI_SR_EL1, IPI_SR_PENDING);
}
}
UNUSED(regs);
// print_regs(regs);

View file

@ -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;

View file

@ -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,12 +147,12 @@ void m1n1_main(void)
printf("Running in EL%lu\n\n", mrs(CurrentEL) >> 2);
get_device_info();
firmware_init();
heapblock_init();
#ifndef BRINGUP
if (supports_gxf())
gxf_init();
mcc_init();
mmu_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.
if (has_dcp)
display_shutdown(DCP_SLEEP_IF_EXTERNAL);
fb_init(false);
// 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);

View file

@ -503,9 +503,11 @@ void mmu_init(void)
mmu_init_pagetables();
mmu_add_default_mappings();
mmu_configure();
if (cpufeat_mmu_sprr)
mmu_init_sprr();
// Enable EL0 memory access by EL1
if (supports_pan())
msr(PAN, 0);
// RES1 bits
@ -521,9 +523,11 @@ void mmu_init(void)
static void mmu_secondary_setup(void)
{
mmu_configure();
if (cpufeat_mmu_sprr)
mmu_init_sprr();
// Enable EL0 memory access by EL1
if (supports_pan())
msr(PAN, 0);
// RES1 bits

View file

@ -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

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)
{
printf(" revision: %d\n", ba->revision);

View file

@ -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");

View file

@ -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;