mirror of https://github.com/wolfSSL/wolfBoot.git
Fixes for EL2 -> EL1 on boot
parent
ee3c313a66
commit
ae63f60efc
|
|
@ -1208,14 +1208,12 @@ void hal_init(void)
|
|||
"========================================\n";
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_UART
|
||||
uart_init();
|
||||
|
||||
#ifdef __WOLFBOOT
|
||||
wolfBoot_printf("%s", banner);
|
||||
#endif
|
||||
wolfBoot_printf("Current EL: %d\n", current_el());
|
||||
#endif /* DEBUG_UART */
|
||||
#endif
|
||||
|
||||
#ifdef EXT_FLASH
|
||||
qspi_init();
|
||||
|
|
|
|||
10
hal/versal.h
10
hal/versal.h
|
|
@ -59,6 +59,14 @@
|
|||
/* ARM Errata */
|
||||
#define CONFIG_ARM_ERRATA_855873 1
|
||||
|
||||
/* BL31-applied errata/CVEs (preserve when modifying CPUACTLR):
|
||||
* - Erratum 859971
|
||||
* - Erratum 1319367
|
||||
* - CVE-2017-5715 (Spectre V2)
|
||||
* - CVE-2018-3639 (SSB)
|
||||
* - CVE-2022-23960
|
||||
*/
|
||||
|
||||
#endif /* USE_BUILTIN_STARTUP */
|
||||
|
||||
/* ============================================================================
|
||||
|
|
@ -519,7 +527,9 @@
|
|||
#define GQSPI_DUMMY_READ 8 /* Dummy clocks for Fast/Quad Read */
|
||||
#endif
|
||||
|
||||
#ifndef XALIGNED
|
||||
#define XALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
|
||||
|
||||
/* ============================================================================
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@
|
|||
#include "loader.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
|
||||
/* Include platform-specific header for EL configuration defines */
|
||||
#ifdef TARGET_versal
|
||||
#include "hal/versal.h"
|
||||
#endif
|
||||
|
||||
/* Linker exported variables */
|
||||
extern unsigned int __bss_start__;
|
||||
extern unsigned int __bss_end__;
|
||||
|
|
@ -47,12 +52,15 @@ extern void gicv2_init_secure(void);
|
|||
#define SKIP_GIC_INIT
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_versal
|
||||
/* current_el() is defined in hal/versal.h for Versal */
|
||||
unsigned int current_el(void)
|
||||
{
|
||||
unsigned long el;
|
||||
asm volatile("mrs %0, CurrentEL" : "=r" (el) : : "cc");
|
||||
return (unsigned int)((el >> 2) & 0x3U);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOT_EL1) && defined(EL2_HYPERVISOR) && EL2_HYPERVISOR == 1
|
||||
/**
|
||||
|
|
@ -66,83 +74,7 @@ unsigned int current_el(void)
|
|||
* @param entry_point Address to jump to in EL1
|
||||
* @param dts_addr Device tree address (passed in x0 to application)
|
||||
*/
|
||||
static void RAMFUNCTION el2_to_el1_boot(uintptr_t entry_point, uintptr_t dts_addr)
|
||||
{
|
||||
/* 1. Configure timer access for EL1 */
|
||||
asm volatile(
|
||||
"mrs x0, cnthctl_el2\n\t"
|
||||
"orr x0, x0, #3\n\t" /* EL1PCEN | EL1PCTEN - enable EL1 timer access */
|
||||
"msr cnthctl_el2, x0\n\t"
|
||||
"msr cntvoff_el2, xzr" /* Clear virtual timer offset */
|
||||
::: "x0"
|
||||
);
|
||||
|
||||
/* 2. Configure virtual processor ID */
|
||||
asm volatile(
|
||||
"mrs x0, midr_el1\n\t"
|
||||
"msr vpidr_el2, x0\n\t"
|
||||
"mrs x0, mpidr_el1\n\t"
|
||||
"msr vmpidr_el2, x0"
|
||||
::: "x0"
|
||||
);
|
||||
|
||||
/* 3. Disable coprocessor traps to EL2 */
|
||||
asm volatile(
|
||||
"mov x0, #0x33ff\n\t" /* CPTR_EL2: RES1 bits, no traps */
|
||||
"msr cptr_el2, x0\n\t"
|
||||
"msr hstr_el2, xzr\n\t" /* No traps to EL2 on system registers */
|
||||
"mov x0, #(3 << 20)\n\t" /* CPACR_EL1: Full FP/SIMD access */
|
||||
"msr cpacr_el1, x0"
|
||||
::: "x0"
|
||||
);
|
||||
|
||||
/* 4. Initialize SCTLR_EL1 with safe defaults (RES1 bits, MMU/cache off) */
|
||||
asm volatile(
|
||||
"ldr x0, =0x30d00800\n\t" /* RES1 bits: 29,28,23,22,20,11 */
|
||||
"msr sctlr_el1, x0"
|
||||
::: "x0"
|
||||
);
|
||||
|
||||
/* 5. Migrate stack pointer and vector base to EL1 */
|
||||
asm volatile(
|
||||
"mov x0, sp\n\t"
|
||||
"msr sp_el1, x0\n\t"
|
||||
"mrs x0, vbar_el2\n\t"
|
||||
"msr vbar_el1, x0"
|
||||
::: "x0"
|
||||
);
|
||||
|
||||
/* 6. Configure HCR_EL2 - EL1 is AArch64, no hypervisor calls */
|
||||
asm volatile(
|
||||
"mov x0, #(1 << 31)\n\t" /* RW: EL1 is AArch64 */
|
||||
"orr x0, x0, #(1 << 29)\n\t" /* HCD: Disable HVC instruction */
|
||||
"msr hcr_el2, x0"
|
||||
::: "x0"
|
||||
);
|
||||
|
||||
/* 7. Set up SPSR_EL2 for return to EL1h with all interrupts masked */
|
||||
asm volatile(
|
||||
"mov x0, #0x3c4\n\t" /* DAIF masked (0xF<<6) + M[4:0]=0b00100 (EL1h) */
|
||||
"msr spsr_el2, x0"
|
||||
::: "x0"
|
||||
);
|
||||
|
||||
/* 8. Set exception return address and DTB pointer, then ERET */
|
||||
asm volatile(
|
||||
"msr elr_el2, %0\n\t" /* Entry point in ELR_EL2 */
|
||||
"mov x0, %1\n\t" /* DTB address in x0 (first arg) */
|
||||
"mov x1, xzr\n\t" /* Zero remaining argument registers */
|
||||
"mov x2, xzr\n\t"
|
||||
"mov x3, xzr\n\t"
|
||||
"eret"
|
||||
:
|
||||
: "r"(entry_point), "r"(dts_addr)
|
||||
: "x0", "x1", "x2", "x3"
|
||||
);
|
||||
|
||||
/* Should never reach here */
|
||||
__builtin_unreachable();
|
||||
}
|
||||
extern void el2_to_el1_boot(uintptr_t entry_point, uintptr_t dts_addr);
|
||||
#endif /* BOOT_EL1 && EL2_HYPERVISOR */
|
||||
|
||||
void boot_entry_C(void)
|
||||
|
|
|
|||
|
|
@ -198,8 +198,11 @@ InitEL3:
|
|||
orr w1, w1, #(1 << 1) /* Set IRQ bit (IRQs routed to EL3) */
|
||||
msr SCR_EL3, x1
|
||||
|
||||
/* Configure cpu auxiliary control register EL1 */
|
||||
ldr x0,=0x80CA000 /* L1 Data prefetch control - 5, Enable device split throttle, 2 independent data prefetch streams */
|
||||
/* Configure CPUACTLR_EL1 - read-modify-write to preserve BL31 workarounds:
|
||||
* 859971, 1319367, CVE-2017-5715, CVE-2018-3639, CVE-2022-23960 */
|
||||
mrs x0, S3_1_C15_C2_0 /* Read current CPUACTLR_EL1 */
|
||||
ldr x1,=0x80CA000 /* L1 Data prefetch control - 5, Enable device split throttle, 2 independent data prefetch streams */
|
||||
orr x0, x0, x1 /* Merge with existing value */
|
||||
#if defined(CONFIG_ARM_ERRATA_855873) && CONFIG_ARM_ERRATA_855873
|
||||
/* Set ENDCCASCI bit in CPUACTLR_EL1 register, to execute data
|
||||
* cache clean operations as data cache clean and invalidate
|
||||
|
|
@ -1231,4 +1234,101 @@ gicv2_init_secure:
|
|||
1:
|
||||
ret
|
||||
|
||||
#if defined(BOOT_EL1) && defined(EL2_HYPERVISOR) && EL2_HYPERVISOR == 1
|
||||
/*
|
||||
* Transition from EL2 to EL1 and jump to application
|
||||
*
|
||||
* Parameters:
|
||||
* x0: entry_point - Address to jump to in EL1
|
||||
* x1: dts_addr - Device tree address (passed in x0 to application)
|
||||
*
|
||||
* This function configures the necessary system registers for EL1 operation
|
||||
* and performs an exception return (ERET) to drop from EL2 to EL1.
|
||||
*
|
||||
* Based on ARM Architecture Reference Manual and U-Boot implementation.
|
||||
*/
|
||||
.global el2_to_el1_boot
|
||||
el2_to_el1_boot:
|
||||
/* Save parameters - x0=entry_point, x1=dts_addr */
|
||||
mov x19, x0 /* Save entry_point in x19 */
|
||||
mov x20, x1 /* Save dts_addr in x20 */
|
||||
|
||||
/* 1. Configure timer access for EL1 */
|
||||
mrs x0, CNTHCTL_EL2
|
||||
orr x0, x0, #3 /* EL1PCEN | EL1PCTEN - enable EL1 timer access */
|
||||
msr CNTHCTL_EL2, x0
|
||||
msr CNTVOFF_EL2, xzr /* Clear virtual timer offset */
|
||||
|
||||
/* 2. Configure virtual processor ID */
|
||||
mrs x0, MIDR_EL1
|
||||
msr VPIDR_EL2, x0
|
||||
mrs x0, MPIDR_EL1
|
||||
msr VMPIDR_EL2, x0
|
||||
|
||||
/* 3. Disable coprocessor traps to EL2 */
|
||||
mov x0, #0x33ff /* CPTR_EL2: RES1 bits, no traps */
|
||||
msr CPTR_EL2, x0
|
||||
msr HSTR_EL2, xzr /* No traps to EL2 on system registers */
|
||||
mov x0, #(3 << 20) /* CPACR_EL1: Full FP/SIMD access */
|
||||
msr CPACR_EL1, x0
|
||||
|
||||
/* 4. Initialize SCTLR_EL1 with safe defaults (RES1 bits, MMU/cache off) */
|
||||
/* RES1 bits: 29,28,23,22,20,11 = 0x30d00800 */
|
||||
movz x0, #0x800
|
||||
movk x0, #0x30d0, lsl #16
|
||||
msr SCTLR_EL1, x0
|
||||
|
||||
/* 5. Migrate stack pointer and vector base to EL1 */
|
||||
/* SP_EL1 must be 16-byte aligned per ARM spec */
|
||||
mov x0, sp
|
||||
bic x0, x0, #0xF /* Ensure 16-byte alignment */
|
||||
msr SP_EL1, x0
|
||||
mrs x0, VBAR_EL2
|
||||
msr VBAR_EL1, x0
|
||||
dsb sy /* Ensure SP_EL1 and VBAR_EL1 writes complete */
|
||||
isb /* Ensure writes take effect */
|
||||
|
||||
/* 6. Configure HCR_EL2 - EL1 is AArch64, no hypervisor calls */
|
||||
/* Check if PAuth (Pointer Authentication) is supported */
|
||||
mrs x0, ID_AA64ISAR1_EL1 /* Read ISA feature register */
|
||||
mov x1, #(0xF << 28) /* GPI mask */
|
||||
orr x1, x1, #(0xF << 24) /* GPA mask */
|
||||
orr x1, x1, #(0xF << 8) /* API mask */
|
||||
orr x1, x1, #(0xF << 4) /* APA mask */
|
||||
tst x0, x1 /* Test if PAuth supported (Z=1 if not supported) */
|
||||
mov x0, #(1 << 31) /* RW: EL1 is AArch64 */
|
||||
orr x0, x0, #(1 << 29) /* HCD: Disable HVC instruction */
|
||||
mov x1, x0 /* Copy base value */
|
||||
orr x1, x1, #(1 << 41) /* API: Trap PAuth instructions */
|
||||
orr x1, x1, #(1 << 40) /* APK: Trap PAuth key access */
|
||||
csel x0, x0, x1, eq /* If PAuth not supported (eq), use x0 (base), else x1 (with traps) */
|
||||
msr HCR_EL2, x0
|
||||
dsb sy /* Ensure HCR_EL2 write completes */
|
||||
isb /* Ensure HCR_EL2 takes effect */
|
||||
|
||||
/* 7. Set up SPSR_EL2 for return to EL1h with all interrupts masked */
|
||||
/* M[3:0] = 0101 = EL1h (EL1 with SP_EL1) - NOT 0100 which is EL1t! */
|
||||
/* M[4] = 0 = AArch64 mode (bit 4 must be 0 for AArch64, 1 for AArch32) */
|
||||
/* DAIF = 0xF = all interrupts masked */
|
||||
/* Value: 0x3C5 = (0xF << 6) | 0x5 */
|
||||
movz x0, #0x3C5 /* DAIF=0xF (bits 9:6), M[3:0]=0x5 (EL1h) */
|
||||
msr SPSR_EL2, x0
|
||||
dsb sy /* Ensure SPSR_EL2 write completes */
|
||||
isb /* Ensure SPSR_EL2 takes effect */
|
||||
|
||||
/* 8. Set exception return address and DTB pointer, then ERET */
|
||||
/* Critical: All register writes must complete before eret */
|
||||
msr ELR_EL2, x19 /* Entry point in ELR_EL2 */
|
||||
mov x0, x20 /* DTB address in x0 (first arg) */
|
||||
mov x1, xzr /* Zero remaining argument registers */
|
||||
mov x2, xzr
|
||||
mov x3, xzr
|
||||
dsb sy /* Ensure all writes complete */
|
||||
isb /* Ensure all effects are visible */
|
||||
eret /* Exception return to EL1 */
|
||||
|
||||
/* Should never reach here */
|
||||
b .
|
||||
#endif /* BOOT_EL1 && EL2_HYPERVISOR */
|
||||
|
||||
.end
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ void main(void)
|
|||
{
|
||||
uint32_t boot_version, update_version;
|
||||
|
||||
/* Initialize HAL (UART, etc.) */
|
||||
hal_init();
|
||||
|
||||
/* Get versions from both partitions */
|
||||
|
|
@ -44,9 +43,11 @@ void main(void)
|
|||
wolfBoot_printf(" wolfBoot Test Application - AMD Versal\n");
|
||||
wolfBoot_printf("===========================================\n\n");
|
||||
|
||||
wolfBoot_printf("Current EL: %d\n", current_el());
|
||||
|
||||
/* Print firmware versions */
|
||||
wolfBoot_printf("Boot Partition Version: %d (0x%08x)\n", boot_version, boot_version);
|
||||
wolfBoot_printf("Update Partition Version: %d (0x%08x)\n", update_version, update_version);
|
||||
wolfBoot_printf("BOOT: Version: %d (0x%08x)\n", boot_version, boot_version);
|
||||
wolfBoot_printf("UPDATE: Version: %d (0x%08x)\n", update_version, update_version);
|
||||
|
||||
wolfBoot_printf("Application running successfully!\n");
|
||||
wolfBoot_printf("\nEntering idle loop...\n");
|
||||
|
|
|
|||
|
|
@ -331,7 +331,10 @@ esac
|
|||
# Build wolfBoot
|
||||
log_info "Building wolfBoot..."
|
||||
cp config/examples/versal_vmk180.config .config
|
||||
make clean && make
|
||||
|
||||
make clean
|
||||
make || { log_error "Failed to build wolfBoot"; exit 1; }
|
||||
[ ! -f "wolfboot.elf" ] && { log_error "wolfboot.elf not found after build"; exit 1; }
|
||||
|
||||
# Build test app if requested
|
||||
if [ "$FLASH_TEST_APP" = "true" ]; then
|
||||
|
|
@ -396,6 +399,7 @@ fi
|
|||
|
||||
# Generate BOOT.BIN
|
||||
log_info "Generating BOOT.BIN..."
|
||||
[ ! -f "wolfboot.elf" ] && { log_error "wolfboot.elf not found - cannot generate BOOT.BIN"; exit 1; }
|
||||
|
||||
# Set PREBUILT_DIR (relative to wolfBoot root)
|
||||
export PREBUILT_DIR="${WOLFBOOT_ROOT}/../soc-prebuilt-firmware/vmk180-versal"
|
||||
|
|
@ -414,16 +418,12 @@ cp "${PREBUILT_DIR}/psmfw.elf" .
|
|||
cp "${PREBUILT_DIR}/bl31.elf" .
|
||||
cp "${PREBUILT_DIR}/system-default.dtb" .
|
||||
|
||||
# Generate BOOT.BIN from wolfBoot root directory
|
||||
source "${VITIS_PATH}/settings64.sh"
|
||||
bootgen -arch versal -image ./tools/scripts/versal_boot.bif -w -o BOOT.BIN
|
||||
|
||||
# Copy BOOT.BIN to TFTP directory
|
||||
cp BOOT.BIN "${TFTP_DIR}/"
|
||||
|
||||
rm -f BOOT.BIN
|
||||
bootgen -arch versal -image ./tools/scripts/versal_boot.bif -w -o BOOT.BIN || { log_error "bootgen failed"; exit 1; }
|
||||
cp BOOT.BIN "${TFTP_DIR}/" || { log_error "Failed to copy BOOT.BIN to TFTP directory"; exit 1; }
|
||||
filesize=$(stat -c%s "${TFTP_DIR}/BOOT.BIN")
|
||||
filesize_hex=$(printf "0x%x" $filesize)
|
||||
log_info "BOOT.BIN size: $filesize bytes"
|
||||
|
||||
# Get test app size if flashing it
|
||||
testapp_size_hex="0x0"
|
||||
|
|
|
|||
Loading…
Reference in New Issue