blob: 471e234a9e161a6a59b08e7a0e6b4b507d627a16 [file] [log] [blame]
/*
* init.c - common boot-wrapper initialization
*
* Copyright (C) 2021 ARM Limited. All rights reserved.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE.txt file.
*/
#include <cpu.h>
#include <platform.h>
#include <stdbool.h>
void announce_arch(void)
{
unsigned char el = mrs(CurrentEl) >> 2;
print_string("Entered at EL");
print_char('0' + el);
print_string("\r\n");
}
static inline bool kernel_is_32bit(void)
{
#ifdef KERNEL_32
return true;
#else
return false;
#endif
}
static inline bool cpu_has_pauth(void)
{
const unsigned long isar1_pauth = ID_AA64ISAR1_EL1_APA |
ID_AA64ISAR1_EL1_API |
ID_AA64ISAR1_EL1_GPA |
ID_AA64ISAR1_EL1_GPI;
const unsigned long isar2_pauth = ID_AA64ISAR2_EL1_APA3 |
ID_AA64ISAR2_EL1_GPA3;
return (mrs(ID_AA64ISAR1_EL1) & isar1_pauth) ||
(mrs(ID_AA64ISAR2_EL1) & isar2_pauth);
}
void cpu_init_el3(void)
{
unsigned long scr = SCR_EL3_RES1 | SCR_EL3_NS | SCR_EL3_HCE;
unsigned long mdcr = 0;
unsigned long cptr = 0;
unsigned long smcr = 0;
if (cpu_has_pauth())
scr |= SCR_EL3_APK | SCR_EL3_API;
if (mrs_field(ID_AA64ISAR0_EL1, TME))
scr |= SCR_EL3_TME;
if (mrs_field(ID_AA64MMFR0_EL1, FGT))
scr |= SCR_EL3_FGTEN;
if (mrs_field(ID_AA64MMFR0_EL1, ECV) >= 2)
scr |= SCR_EL3_ECVEN;
if (mrs_field(ID_AA64MMFR1_EL1, HCX))
scr |= SCR_EL3_HXEn;
if (mrs_field(ID_AA64PFR1_EL1, MTE) >= 2)
scr |= SCR_EL3_ATA;
if (!kernel_is_32bit())
scr |= SCR_EL3_RW;
msr(SCR_EL3, scr);
msr(CPTR_EL3, cptr);
if (mrs_field(ID_AA64DFR0_EL1, PMSVER))
mdcr |= MDCR_EL3_NSPB_NS_NOTRAP;
if (mrs_field(ID_AA64DFR0_EL1, PMSVER) >= 3)
mdcr |= MDCR_EL3_ENPMSN;
if (mrs_field(ID_AA64DFR0_EL1, TRACEBUFFER))
mdcr |= MDCR_EL3_NSTB_NS_NOTRAP;
if (mrs_field(ID_AA64DFR0_EL1, BRBE))
mdcr |= MDCR_EL3_SBRBE_NOTRAP_NOPROHIBIT;
msr(MDCR_EL3, mdcr);
if (mrs_field(ID_AA64PFR0_EL1, SVE)) {
cptr |= CPTR_EL3_EZ;
msr(CPTR_EL3, cptr);
isb();
/*
* Write the maximum possible vector length, hardware
* will constrain to the actual limit.
*/
msr(ZCR_EL3, ZCR_EL3_LEN_MAX);
}
if (mrs_field(ID_AA64PFR1_EL1, SME)) {
cptr |= CPTR_EL3_ESM;
msr(CPTR_EL3, cptr);
isb();
scr |= SCR_EL3_EnTP2;
msr(SCR_EL3, scr);
isb();
/*
* Write the maximum possible vector length, hardware
* will constrain to the actual limit.
*/
smcr = SMCR_EL3_LEN_MAX;
if (mrs_field(ID_AA64SMFR0_EL1, FA64))
smcr |= SMCR_EL3_FA64;
msr(SMCR_EL3, smcr);
}
msr(CNTFRQ_EL0, COUNTER_FREQ);
}
#ifdef PSCI
extern char psci_vectors[];
bool cpu_init_psci_arch(void)
{
if (mrs(CurrentEL) != CURRENTEL_EL3)
return false;
msr(VBAR_EL3, (unsigned long)psci_vectors);
isb();
return true;
}
#endif