diff --git a/build_sdk.py b/build_sdk.py index 5ff324b1..0455946b 100644 --- a/build_sdk.py +++ b/build_sdk.py @@ -163,6 +163,17 @@ class KernelPath: "KernelCustomDTSOverlay": Path("custom_dts/overlay-zynqmp-kria-k26.dts"), } | DEFAULT_KERNEL_OPTIONS_AARCH64, ), + BoardInfo( + name="stm32mp2", + arch=KernelArch.AARCH64, + gcc_cpu="cortex-a35", + loader_link_address=0x88000000, + smp_cores=2, + kernel_options={ + "KernelPlatform": "stm32mp2", + "KernelARMPlatform": "stm32mp257f-ev1", + } | DEFAULT_KERNEL_OPTIONS_AARCH64, + ), BoardInfo( name="tqma8xqp1gb", arch=KernelArch.AARCH64, diff --git a/loader/src/aarch64/cpus.c b/loader/src/aarch64/cpus.c index 13000024..b5210751 100644 --- a/loader/src/aarch64/cpus.c +++ b/loader/src/aarch64/cpus.c @@ -63,6 +63,8 @@ static const size_t psci_target_cpus[4] = {0x00, 0x01, 0x02, 0x03}; static const size_t psci_target_cpus[4] = {0x00, 0x01, 0x02, 0x03}; #elif defined(CONFIG_PLAT_ROCKPRO64) static const size_t psci_target_cpus[4] = {0x00, 0x01, 0x02, 0x03}; +#elif defined(CONFIG_PLAT_STM32MP2) +static const size_t psci_target_cpus[2] = {0x00, 0x01}; #elif defined(CONFIG_PLAT_QEMU_ARM_VIRT) /* QEMU is special and can have arbitrary numbers of cores */ // TODO. diff --git a/loader/src/aarch64/mmu.c b/loader/src/aarch64/mmu.c index 37a9030c..8ef6427c 100644 --- a/loader/src/aarch64/mmu.c +++ b/loader/src/aarch64/mmu.c @@ -23,6 +23,7 @@ uint64_t boot_lvl2_upper[1 << 9] ALIGN(1 << 12); /* Paging structures for identity mapping */ uint64_t boot_lvl0_lower[1 << 9] ALIGN(1 << 12); uint64_t boot_lvl1_lower[1 << 9] ALIGN(1 << 12); +uint64_t boot_lvl2_lower[1 << 9] ALIGN(1 << 12); int arch_mmu_enable(int logical_cpu) { diff --git a/loader/src/uart.c b/loader/src/uart.c index 54b18210..9187f69b 100644 --- a/loader/src/uart.c +++ b/loader/src/uart.c @@ -188,6 +188,20 @@ void putc(uint8_t ch) while ((*UART_REG(ULSR) & ULSR_THRE) == 0); *UART_REG(UTHR) = ch; } +#elif defined(CONFIG_PLAT_STM32MP2) + +#define UART_BASE 0x400e0000 +#define USART_ISR 0x1c +#define USART_TDR 0x28 +#define USART_ISR_TXE 0x80 + +void uart_init(void) {} + +void putc(uint8_t ch) +{ + while (!(*UART_REG(USART_ISR) & USART_ISR_TXE)); + *UART_REG(USART_TDR) = ch; +} #elif defined(CONFIG_ARCH_RISCV64) #include "riscv/sbi.h" diff --git a/platforms.yml b/platforms.yml index 3ae55563..073f5530 100644 --- a/platforms.yml +++ b/platforms.yml @@ -94,3 +94,6 @@ platforms: - name: zcu102 cmake_plat: zcu102 since: 1.3.0 + - name: stm32mp2 + cmake_plat: stm32mp2 + since: dev diff --git a/tool/microkit/src/loader.rs b/tool/microkit/src/loader.rs index 37f63f65..cff165d2 100644 --- a/tool/microkit/src/loader.rs +++ b/tool/microkit/src/loader.rs @@ -485,20 +485,61 @@ impl<'a> Loader<'a> { let (boot_lvl0_upper_addr, boot_lvl0_upper_size) = elf .find_symbol("boot_lvl0_upper") .expect("Could not find 'boot_lvl0_upper' symbol"); + let (boot_lvl2_lower_addr, boot_lvl2_lower_size) = elf + .find_symbol("boot_lvl2_lower") + .expect("Could not find 'boot_lvl2_lower' symbol"); + + let (text_addr, _) = elf + .find_symbol("_text") + .expect("Could not find 'text' symbol"); + let (end_addr, _) = elf + .find_symbol("_bss_end") + .expect("Could not find 'end' symbol"); + + if Aarch64::lvl1_index(text_addr) != Aarch64::lvl1_index(end_addr) { + eprintln!("ERROR: We only map 1GiB, but elfloader paddr range covers multiple GiB"); + std::process::exit(1); + } let mut boot_lvl0_lower: [u8; PAGE_TABLE_SIZE] = [0; PAGE_TABLE_SIZE]; boot_lvl0_lower[..8].copy_from_slice(&(boot_lvl1_lower_addr | 3).to_le_bytes()); let mut boot_lvl1_lower: [u8; PAGE_TABLE_SIZE] = [0; PAGE_TABLE_SIZE]; - for i in 0..512 { - #[allow(clippy::identity_op)] // keep the (0 << 2) for clarity - let pt_entry: u64 = ((i as u64) << AARCH64_1GB_BLOCK_BITS) | - (1 << 10) | // access flag - (0 << 2) | // strongly ordered memory - (1); // 1G block + + // UART + let uart_addr = 0x400e0000; + let uart_page = uart_addr & !mask(AARCH64_1GB_BLOCK_BITS); + let lvl1_idx = Aarch64::lvl1_index(uart_page); + #[allow(clippy::identity_op)] // keep the (0 << 2) for clarity + let pt_entry: u64 = ((lvl1_idx as u64) << AARCH64_1GB_BLOCK_BITS) | + (1 << 10) | // access flag + (0 << 2) | // strongly ordered memory + (1); // 1G block + let start = 8 * lvl1_idx; + let end = 8 * (lvl1_idx + 1); + boot_lvl1_lower[start..end].copy_from_slice(&pt_entry.to_le_bytes()); + + // TEXT + let mut boot_lvl2_lower: [u8; PAGE_TABLE_SIZE] = [0; PAGE_TABLE_SIZE]; + + let pt_entry = (boot_lvl2_lower_addr | 3).to_le_bytes(); + let lvl1_idx = Aarch64::lvl1_index(text_addr); + let start = 8 * lvl1_idx; + let end = 8 * (lvl1_idx + 1); + boot_lvl1_lower[start..end].copy_from_slice(&pt_entry); + + let lvl2_idx = Aarch64::lvl2_index(text_addr); + + for i in lvl2_idx ..= Aarch64::lvl2_index(end_addr) { + let entry_idx = (i - Aarch64::lvl2_index(text_addr)) << AARCH64_2MB_BLOCK_BITS; + let pt_entry: u64 = (entry_idx as u64 + text_addr) | + (1 << 10) | // access flag + (3 << 8) | // inner sharable + (4 << 2) | // MT_NORMAL memory + (1 << 0); // 2M block let start = 8 * i; let end = 8 * (i + 1); - boot_lvl1_lower[start..end].copy_from_slice(&pt_entry.to_le_bytes()); + boot_lvl2_lower[start..end].copy_from_slice(&pt_entry.to_le_bytes()); } let boot_lvl0_upper: [u8; PAGE_TABLE_SIZE] = [0; PAGE_TABLE_SIZE]; @@ -536,6 +577,7 @@ impl<'a> Loader<'a> { (boot_lvl0_upper_addr, boot_lvl0_upper_size, boot_lvl0_upper), (boot_lvl1_upper_addr, boot_lvl1_upper_size, boot_lvl1_upper), (boot_lvl2_upper_addr, boot_lvl2_upper_size, boot_lvl2_upper), + (boot_lvl2_lower_addr, boot_lvl2_lower_size, boot_lvl2_lower), ] } }