-
Notifications
You must be signed in to change notification settings - Fork 279
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Boot ArceOS on Phytium Pi
- Loading branch information
Showing
8 changed files
with
317 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# How to run ArceOS on Phytium Pi | ||
|
||
See more details in [this doc](https://chenlongos.com/Phytium-Car/ch1-1.html). | ||
|
||
Build ArceOS: `make A=examples/helloworld PLATFORM=aarch64-phytium-pi LOG=trace`. | ||
|
||
Prepare a USB flash disk and copy `examples/helloworld/helloworld_aarch64-phytium-pi.bin` to it. | ||
|
||
Stop autoboot in U-Boot and execute following commands: | ||
|
||
``` | ||
Phytium-Pi# usb start | ||
Phytium-Pi# fatload usb 0:2 0x90100000 helloworld_aarch64-phytium-pi.bin | ||
Phytium-Pi# go 0x90100000 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use crate::mem::*; | ||
use page_table_entry::{aarch64::A64PTE, GenericPTE, MappingFlags}; | ||
|
||
/// Returns the default free memory regions (kernel image end to physical memory end). | ||
fn __free_regions() -> impl Iterator<Item = MemRegion> { | ||
let start = virt_to_phys( | ||
VirtAddr::from(_ekernel as usize + axconfig::NOCACHE_MEMORY_SIZE).align_up_4k(), | ||
); | ||
let end = PhysAddr::from(axconfig::PHYS_MEMORY_END); | ||
core::iter::once(MemRegion { | ||
paddr: start, | ||
size: end.as_usize() - start.as_usize(), | ||
flags: MemRegionFlags::FREE | MemRegionFlags::READ | MemRegionFlags::WRITE, | ||
name: "free memory", | ||
}) | ||
} | ||
|
||
/// Returns the default free memory regions (kernel image end to physical memory end). | ||
fn __nocache_regions() -> impl Iterator<Item = MemRegion> { | ||
let start = VirtAddr::from(_ekernel as usize).align_up_4k(); | ||
let start = virt_to_phys(start); | ||
|
||
core::iter::once(MemRegion { | ||
paddr: start, | ||
size: axconfig::NOCACHE_MEMORY_SIZE, | ||
flags: MemRegionFlags::DEVICE | MemRegionFlags::READ | MemRegionFlags::WRITE, | ||
name: "nocache memory", | ||
}) | ||
} | ||
|
||
/// Returns platform-specific memory regions. | ||
pub(crate) fn platform_regions() -> impl Iterator<Item = MemRegion> { | ||
core::iter::once(MemRegion { | ||
paddr: 0x0.into(), | ||
size: 0x1000, | ||
flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE, | ||
name: "spintable", | ||
}) | ||
.chain(crate::mem::__nocache_regions()) | ||
.chain(crate::mem::__free_regions()) | ||
.chain(crate::mem::default_mmio_regions()) | ||
} | ||
|
||
pub(crate) unsafe fn init_boot_page_table( | ||
boot_pt_l0: *mut [A64PTE; 512], | ||
boot_pt_l1: *mut [A64PTE; 512], | ||
) { | ||
let boot_pt_l0 = &mut *boot_pt_l0; | ||
let boot_pt_l1 = &mut *boot_pt_l1; | ||
// 0x0000_0000_0000 ~ 0x0080_0000_0000, table | ||
boot_pt_l0[0] = A64PTE::new_table(PhysAddr::from(boot_pt_l1.as_ptr() as usize)); | ||
// 0x0000_0000_0000..0x0000_8000_0000, 1G block, device memory | ||
boot_pt_l1[0] = A64PTE::new_page( | ||
PhysAddr::from(0), | ||
MappingFlags::READ | MappingFlags::WRITE | MappingFlags::DEVICE, | ||
true, | ||
); | ||
boot_pt_l1[2] = A64PTE::new_page( | ||
PhysAddr::from(0x8000_0000), | ||
MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE, | ||
true, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
pub mod mem; | ||
use core::ptr; | ||
|
||
#[cfg(feature = "smp")] | ||
pub mod mp; | ||
|
||
#[cfg(feature = "irq")] | ||
pub mod irq { | ||
pub use crate::platform::aarch64_common::gic::*; | ||
} | ||
|
||
pub mod console { | ||
pub use crate::platform::aarch64_common::pl011::*; | ||
} | ||
|
||
pub mod time { | ||
pub use crate::platform::aarch64_common::generic_timer::*; | ||
} | ||
|
||
pub mod misc { | ||
pub fn terminate() -> ! { | ||
info!("Shutting down..."); | ||
loop { | ||
crate::arch::halt(); | ||
} | ||
} | ||
} | ||
|
||
extern "C" { | ||
fn exception_vector_base(); | ||
fn rust_main(cpu_id: usize, dtb: usize); | ||
#[cfg(feature = "smp")] | ||
fn rust_main_secondary(cpu_id: usize); | ||
} | ||
|
||
pub(crate) unsafe extern "C" fn rust_entry(cpu_id: usize, dtb: usize) { | ||
crate::mem::clear_bss(); | ||
put_debug2(); | ||
crate::arch::set_exception_vector_base(exception_vector_base as usize); | ||
put_debug2(); | ||
crate::arch::write_page_table_root0(0.into()); // disable low address access | ||
put_debug_paged2(); | ||
crate::cpu::init_primary(cpu_id); | ||
put_debug_paged2(); | ||
super::aarch64_common::pl011::init_early(); | ||
put_debug_paged2(); | ||
super::aarch64_common::generic_timer::init_early(); | ||
put_debug_paged2(); | ||
rust_main(cpu_id, dtb); | ||
} | ||
|
||
#[cfg(all(target_arch = "aarch64"))] | ||
#[no_mangle] | ||
unsafe extern "C" fn put_debug2() { | ||
#[cfg(platform_family = "aarch64-phytium-pi")] | ||
{ | ||
let state = (0x2800D018 as usize) as *mut u8; | ||
let put = (0x2800D000 as usize) as *mut u8; | ||
while (ptr::read_volatile(state) & (0x20 as u8)) != 0 {} | ||
*put = b'a'; | ||
} | ||
} | ||
|
||
#[cfg(all(target_arch = "aarch64"))] | ||
#[no_mangle] | ||
unsafe extern "C" fn put_debug_paged2() { | ||
#[cfg(platform_family = "aarch64-phytium-pi")] | ||
{ | ||
let state = (0xFFFF00002800D018 as usize) as *mut u8; | ||
let put = (0xFFFF00002800D000 as usize) as *mut u8; | ||
while (ptr::read_volatile(state) & (0x20 as u8)) != 0 {} | ||
*put = b'a'; | ||
} | ||
} | ||
|
||
#[cfg(feature = "smp")] | ||
pub(crate) unsafe extern "C" fn rust_entry_secondary(cpu_id: usize) { | ||
crate::arch::set_exception_vector_base(exception_vector_base as usize); | ||
crate::arch::write_page_table_root0(0.into()); // disable low address access | ||
crate::cpu::init_secondary(cpu_id); | ||
rust_main_secondary(cpu_id); | ||
} | ||
|
||
/// Initializes the platform devices for the primary CPU. | ||
/// | ||
/// For example, the interrupt controller and the timer. | ||
pub fn platform_init() { | ||
#[cfg(feature = "irq")] | ||
super::aarch64_common::gic::init_primary(); | ||
super::aarch64_common::generic_timer::init_percpu(); | ||
super::aarch64_common::pl011::init(); | ||
} | ||
|
||
/// Initializes the platform devices for secondary CPUs. | ||
#[cfg(feature = "smp")] | ||
pub fn platform_init_secondary() { | ||
#[cfg(feature = "irq")] | ||
super::aarch64_common::gic::init_secondary(); | ||
super::aarch64_common::generic_timer::init_percpu(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
use crate::mem::{phys_to_virt, virt_to_phys, PhysAddr, VirtAddr}; | ||
|
||
static mut SECONDARY_STACK_TOP: usize = 0; | ||
|
||
extern "C" { | ||
fn _start_secondary(); | ||
} | ||
|
||
#[naked] | ||
#[link_section = ".text.boot"] | ||
unsafe extern "C" fn modify_stack_and_start() { | ||
core::arch::asm!(" | ||
ldr x21, ={secondary_boot_stack} // the secondary CPU hasn't set the TTBR1 | ||
mov x8, {phys_virt_offset} // minus the offset to get the phys addr of the boot stack | ||
sub x21, x21, x8 | ||
ldr x21, [x21] | ||
mov x0, x21 // x0 will be set to SP in the beginning of _start_secondary | ||
b _start_secondary", | ||
secondary_boot_stack = sym SECONDARY_STACK_TOP, | ||
phys_virt_offset = const axconfig::PHYS_VIRT_OFFSET, | ||
options(noreturn) | ||
); | ||
} | ||
|
||
pub static CPU_SPIN_TABLE: [PhysAddr; 4] = [ | ||
PhysAddr::from(0xd8), | ||
PhysAddr::from(0xe0), | ||
PhysAddr::from(0xe8), | ||
PhysAddr::from(0xf0), | ||
]; | ||
|
||
/// Starts the given secondary CPU with its boot stack. | ||
pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) { | ||
let entry_paddr = virt_to_phys(VirtAddr::from(modify_stack_and_start as usize)).as_usize(); | ||
unsafe { | ||
// set the boot code address of the given secondary CPU | ||
let spintable_vaddr = phys_to_virt(CPU_SPIN_TABLE[cpu_id]); | ||
let release_ptr = spintable_vaddr.as_mut_ptr() as *mut usize; | ||
release_ptr.write_volatile(entry_paddr); | ||
crate::arch::flush_dcache_line(spintable_vaddr); | ||
|
||
// set the boot stack of the given secondary CPU | ||
SECONDARY_STACK_TOP = stack_top.as_usize(); | ||
crate::arch::flush_dcache_line(VirtAddr::from( | ||
(&SECONDARY_STACK_TOP as *const usize) as usize, | ||
)); | ||
} | ||
aarch64_cpu::asm::sev(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# Architecture identifier. | ||
arch = "aarch64" | ||
# Platform identifier. | ||
platform = "aarch64-phytium-pi" | ||
# Platform family. | ||
family = "aarch64-phytium-pi" | ||
|
||
# Base address of the whole physical memory. | ||
phys-memory-base = "0x8000_0000" | ||
# Size of the whole physical memory. | ||
phys-memory-size = "0x8000_0000" # 2G | ||
# Base physical address of the kernel image. | ||
kernel-base-paddr = "0x9010_0000" | ||
# Base virtual address of the kernel image. | ||
kernel-base-vaddr = "0xffff_0000_9010_0000" | ||
# Linear mapping offset, for quick conversions between physical and virtual | ||
# addresses. | ||
phys-virt-offset = "0xffff_0000_0000_0000" | ||
# Kernel address space base. | ||
kernel-aspace-base = "0xffff_0000_0000_0000" | ||
# Kernel address space size. | ||
kernel-aspace-size = "0x0000_ffff_ffff_f000" | ||
# MMIO regions with format (`base_paddr`, `size`). | ||
mmio-regions = [ | ||
# ["0xFE00_B000", "0x1000"], # mailbox | ||
# ["0xFE20_1000", "0x1000"], # PL011 UART | ||
# ["0xFF84_1000", "0x8000"], # GICv2 | ||
#["0x40000000", "0xfff_ffff"], # pcie ecam | ||
|
||
|
||
# ["0x6_0000_0000", "0x4000_0000"] # pcie control | ||
|
||
|
||
["0x2800_C000", "0x1000"], # UART 0 | ||
["0x2800_D000", "0x1000"], # UART 1 | ||
["0x2800_E000", "0x1000"], # UART 2 | ||
["0x2800_F000", "0x1000"], # UART 3 | ||
# ["0x32a0_0000", "0x2_0000"], # usb0 | ||
# ["0x32a2_0000", "0x2_0000"], # usb0 | ||
# ["0x3200_C000", "0x2000"], #Ethernet1 | ||
# ["0x3200_E000", "0x2000"], #Ethernet2 | ||
# ["0x3080_0000", "0x8000"], # GICv2 | ||
["0x3000_0000","0x800_0000"], #other devices | ||
["0x4000_0000", "0x1000_0000"], # pcie ecam | ||
|
||
["0x2801_4000", "0x2000"], # MIO0 - I2C | ||
["0x2801_6000", "0x2000"], # MIO1 - I2C | ||
["0x2801_8000", "0x2000"], # MIO2 - I2C | ||
["0x2801_A000", "0x2000"], # MIO3 - I2C | ||
["0x2801_C000", "0x2000"], # MIO4 - I2C | ||
|
||
["0x000_2803_4000", "0x1000"], # GPIO0 | ||
["0x000_2803_5000", "0x1000"], # GPIO1 | ||
["0x000_2803_6000", "0x1000"], # GPIO2 | ||
["0x000_2803_7000", "0x1000"], # GPIO3 | ||
["0x000_2803_8000", "0x1000"], # GPIO4 | ||
["0x000_2803_9000", "0x1000"], # GPIO5 | ||
|
||
# ["0x6_0000_0000", "0x4000_0000"] # pcie control | ||
] | ||
virtio-mmio-regions = [] | ||
# UART Address | ||
uart-paddr = "0x2800_D000" | ||
uart-irq = "24" | ||
|
||
# MIO0 I2C | ||
MIO0 = "0x2801_4000" | ||
|
||
# GIC Address | ||
gicc-paddr = "0xFF84_2000" | ||
gicd-paddr = "0xFF84_1000" | ||
|
||
# Base physical address of the PCIe ECAM space. | ||
pci-ecam-base = "0x40000000" | ||
# End PCI bus number. | ||
pci-bus-end = "0x2" | ||
# PCI device memory ranges. | ||
pci-ranges = [["0x58000000", "0x7fffffff"], ["0x6_0000_0000", "0x6_3fff_ffff"]] | ||
|
||
# Size of the nocache memory region | ||
nocache-memory-size = "0x60_0000" |