mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-24 15:43:11 +00:00
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:
parent
accb393510
commit
869d2ae35c
10 changed files with 77 additions and 29 deletions
|
@ -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,
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
12
src/main.c
12
src/main.c
|
@ -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);
|
||||||
|
|
12
src/memory.c
12
src/memory.c
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue