Skip to content

Commit

Permalink
Add Linux header for aarch64 (#221)
Browse files Browse the repository at this point in the history
* add linux header
* add phytium dtb info in doc.
  • Loading branch information
ZR233 authored Jan 23, 2025
1 parent 0778fe3 commit d9bbf6c
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 65 deletions.
4 changes: 2 additions & 2 deletions configs/platforms/aarch64-qemu-virt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 14 additions & 2 deletions doc/platform_phytium_pi.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
161 changes: 100 additions & 61 deletions modules/axhal/src/platform/aarch64_common/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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: <https://docs.kernel.org/arch/arm64/booting.html>
#[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.
Expand All @@ -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,
)
}
}

0 comments on commit d9bbf6c

Please sign in to comment.