From d9bbf6c473c3c0c64b4957f5c7ff8cd2dc5723b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=9D=BF?= <34859362+ZR233@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:06:09 +0800 Subject: [PATCH] Add Linux header for aarch64 (#221) * add linux header * add phytium dtb info in doc. --- configs/platforms/aarch64-qemu-virt.toml | 4 +- doc/platform_phytium_pi.md | 16 +- .../axhal/src/platform/aarch64_common/boot.rs | 161 +++++++++++------- 3 files changed, 116 insertions(+), 65 deletions(-) diff --git a/configs/platforms/aarch64-qemu-virt.toml b/configs/platforms/aarch64-qemu-virt.toml index 08b3661926..28d544b1f6 100644 --- a/configs/platforms/aarch64-qemu-virt.toml +++ b/configs/platforms/aarch64-qemu-virt.toml @@ -15,9 +15,9 @@ phys-memory-base = 0x4000_0000 # uint # Size of the whole physical memory. (128M) phys-memory-size = 0x800_0000 # uint # Base physical address of the kernel image. -kernel-base-paddr = 0x4008_0000 # uint +kernel-base-paddr = 0x4020_0000 # uint # Base virtual address of the kernel image. -kernel-base-vaddr = "0xffff_0000_4008_0000" # uint +kernel-base-vaddr = "0xffff_0000_4020_0000" # uint # Linear mapping offset, for quick conversions between physical and virtual # addresses. phys-virt-offset = "0xffff_0000_0000_0000" # uint diff --git a/doc/platform_phytium_pi.md b/doc/platform_phytium_pi.md index e748747d68..63b8001c4f 100644 --- a/doc/platform_phytium_pi.md +++ b/doc/platform_phytium_pi.md @@ -29,11 +29,23 @@ ostool run uboot ![select](./figures/phytium_select_dtb.png) -We can ignore select dtb step by pressing `enter` directly. ArceOS dose not support dtb yet. +`dtb` path is `tools/phytium_pi/phytiumpi_firefly.dtb` Then the cmdline will wait for you to put board power on or reset. -You can modify config in `.project.toml` to change the default behavior. +`Ctrl+C` to exit. + +Modify config in `.project.toml` to change platform for phytium pi. + +Find `shell=[[ ... "make A=examples/helloworld ARCH=aarch64" ]]`, add `PLATFORM` like: + + `"make A=examples/helloworld PLATFORM=aarch64-phytium-pi"`. + +Find `elf = "examples/helloworld/helloworld_aarch64-qemu-virt.elf"` and change to: + +`elf = "examples/helloworld/helloworld_aarch64-phytium-pi.elf"`. + +Then run `ostool run uboot` again. When see `等待 U-Boot 启动...` , put board power on or reset. If everything goes well, you will see the following output: diff --git a/modules/axhal/src/platform/aarch64_common/boot.rs b/modules/axhal/src/platform/aarch64_common/boot.rs index 31a5e222db..5136978433 100644 --- a/modules/axhal/src/platform/aarch64_common/boot.rs +++ b/modules/axhal/src/platform/aarch64_common/boot.rs @@ -14,6 +14,10 @@ static mut BOOT_PT_L0: [A64PTE; 512] = [A64PTE::empty(); 512]; #[unsafe(link_section = ".data.boot_page_table")] static mut BOOT_PT_L1: [A64PTE; 512] = [A64PTE::empty(); 512]; +const FLAG_LE: usize = 0b0; +const FLAG_PAGE_SIZE_4K: usize = 0b10; +const FLAG_ANY_MEM: usize = 0b1000; + unsafe fn switch_to_el1() { SPSel.write(SPSel::SP::ELx); SP_EL0.set(0); @@ -47,11 +51,13 @@ unsafe fn switch_to_el1() { + SPSR_EL2::I::Masked + SPSR_EL2::F::Masked, ); - core::arch::asm!( - " - mov x8, sp - msr sp_el1, x8" - ); + unsafe { + core::arch::asm!( + " + mov x8, sp + msr sp_el1, x8" + ) + }; ELR_EL2.set(LR.get()); asm::eret(); } @@ -100,44 +106,75 @@ unsafe fn init_boot_page_table() { crate::platform::mem::init_boot_page_table(addr_of_mut!(BOOT_PT_L0), addr_of_mut!(BOOT_PT_L1)); } -/// The earliest entry point for the primary CPU. +/// Kernel entry point with Linux image header. +/// +/// Some bootloaders require this header to be present at the beginning of the +/// kernel image. +/// +/// Documentation: #[naked] #[unsafe(no_mangle)] #[unsafe(link_section = ".text.boot")] unsafe extern "C" fn _start() -> ! { - // PC = 0x8_0000 - // X0 = dtb - core::arch::naked_asm!(" - mrs x19, mpidr_el1 - and x19, x19, #0xffffff // get current CPU id - mov x20, x0 // save DTB pointer - - adrp x8, {boot_stack} // setup boot stack - add x8, x8, {boot_stack_size} - mov sp, x8 - - bl {switch_to_el1} // switch to EL1 - bl {enable_fp} // enable fp/neon - bl {init_boot_page_table} - bl {init_mmu} // setup MMU - - mov x8, {phys_virt_offset} // set SP to the high address - add sp, sp, x8 - - mov x0, x19 // call rust_entry(cpu_id, dtb) - mov x1, x20 - ldr x8, ={entry} - blr x8 - b .", - switch_to_el1 = sym switch_to_el1, - init_boot_page_table = sym init_boot_page_table, - init_mmu = sym init_mmu, - enable_fp = sym enable_fp, - boot_stack = sym BOOT_STACK, - boot_stack_size = const TASK_STACK_SIZE, - phys_virt_offset = const PHYS_VIRT_OFFSET, - entry = sym crate::platform::rust_entry, - ) + unsafe { + // PC = bootloader load address + // X0 = dtb + core::arch::naked_asm!(" + add x13, x18, #0x16 // 'MZ' magic + b {entry} // Branch to kernel start, magic + + .quad 0 // Image load offset from start of RAM, little-endian + .quad _ekernel - _start // Effective size of kernel image, little-endian + .quad {flags} // Kernel flags, little-endian + .quad 0 // reserved + .quad 0 // reserved + .quad 0 // reserved + .ascii \"ARM\\x64\" // Magic number + .long 0 // reserved (used for PE COFF offset)", + flags = const FLAG_LE | FLAG_PAGE_SIZE_4K | FLAG_ANY_MEM, + entry = sym _start_primary, + ) + } +} + +/// The earliest entry point for the primary CPU. +#[naked] +#[unsafe(link_section = ".text.boot")] +unsafe extern "C" fn _start_primary() -> ! { + unsafe { + // X0 = dtb + core::arch::naked_asm!(" + mrs x19, mpidr_el1 + and x19, x19, #0xffffff // get current CPU id + mov x20, x0 // save DTB pointer + + adrp x8, {boot_stack} // setup boot stack + add x8, x8, {boot_stack_size} + mov sp, x8 + + bl {switch_to_el1} // switch to EL1 + bl {enable_fp} // enable fp/neon + bl {init_boot_page_table} + bl {init_mmu} // setup MMU + + mov x8, {phys_virt_offset} // set SP to the high address + add sp, sp, x8 + + mov x0, x19 // call rust_entry(cpu_id, dtb) + mov x1, x20 + ldr x8, ={entry} + blr x8 + b .", + switch_to_el1 = sym switch_to_el1, + init_boot_page_table = sym init_boot_page_table, + init_mmu = sym init_mmu, + enable_fp = sym enable_fp, + boot_stack = sym BOOT_STACK, + boot_stack_size = const TASK_STACK_SIZE, + phys_virt_offset = const PHYS_VIRT_OFFSET, + entry = sym crate::platform::rust_entry, + ) + } } /// The earliest entry point for the secondary CPUs. @@ -146,26 +183,28 @@ unsafe extern "C" fn _start() -> ! { #[unsafe(no_mangle)] #[unsafe(link_section = ".text.boot")] unsafe extern "C" fn _start_secondary() -> ! { - core::arch::naked_asm!(" - mrs x19, mpidr_el1 - and x19, x19, #0xffffff // get current CPU id - - mov sp, x0 - bl {switch_to_el1} - bl {init_mmu} - bl {enable_fp} - - mov x8, {phys_virt_offset} // set SP to the high address - add sp, sp, x8 - - mov x0, x19 // call rust_entry_secondary(cpu_id) - ldr x8, ={entry} - blr x8 - b .", - switch_to_el1 = sym switch_to_el1, - init_mmu = sym init_mmu, - enable_fp = sym enable_fp, - phys_virt_offset = const PHYS_VIRT_OFFSET, - entry = sym crate::platform::rust_entry_secondary, - ) + unsafe { + core::arch::naked_asm!(" + mrs x19, mpidr_el1 + and x19, x19, #0xffffff // get current CPU id + + mov sp, x0 + bl {switch_to_el1} + bl {init_mmu} + bl {enable_fp} + + mov x8, {phys_virt_offset} // set SP to the high address + add sp, sp, x8 + + mov x0, x19 // call rust_entry_secondary(cpu_id) + ldr x8, ={entry} + blr x8 + b .", + switch_to_el1 = sym switch_to_el1, + init_mmu = sym init_mmu, + enable_fp = sym enable_fp, + phys_virt_offset = const PHYS_VIRT_OFFSET, + entry = sym crate::platform::rust_entry_secondary, + ) + } }