diff --git a/.gitignore b/.gitignore index 107809a42e..7801ea1b3d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ *.bin qemu.log rusty-tags.vi +/.project.toml diff --git a/doc/figures/phytium_select_app.png b/doc/figures/phytium_select_app.png new file mode 100644 index 0000000000..eea2083510 Binary files /dev/null and b/doc/figures/phytium_select_app.png differ diff --git a/doc/figures/phytium_select_dtb.png b/doc/figures/phytium_select_dtb.png new file mode 100644 index 0000000000..8f9b60e816 Binary files /dev/null and b/doc/figures/phytium_select_dtb.png differ diff --git a/doc/figures/phytium_select_platform.png b/doc/figures/phytium_select_platform.png new file mode 100644 index 0000000000..5a1e65d0eb Binary files /dev/null and b/doc/figures/phytium_select_platform.png differ diff --git a/doc/platform_phytium_pi.md b/doc/platform_phytium_pi.md new file mode 100644 index 0000000000..406d11a414 --- /dev/null +++ b/doc/platform_phytium_pi.md @@ -0,0 +1,32 @@ +# How to run ArceOS on phytium pi + +First, we need `ostool` to build and upload the image to the board. It also supports windows. + +```bash +cargo install ostool +``` + +We also need to connect the board to the computer with serial port, and connect netwire to the board. The host pc and the board should be in the same network. + +Then, we can run it easily. + +```bash +# cd arceos main dir. +ostool run uboot +``` + +![select](./figures/phytium_select_platform.png) + +Then, press `1` and `enter` to select phytium pi. + +![select](./figures/phytium_select_app.png) + +Then, select app you want to run. Item without `arceos-*` are not app and can not run. Here we select `arceos-helloworld` for test. + +![select](./figures/phytium_select_dtb.png) + +We can ignore select dtb step by pressing `enter` directly. ArceOS dose not support dtb yet. + +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. diff --git a/modules/axconfig/build.rs b/modules/axconfig/build.rs index e8a28b11e0..7ffcea413a 100644 --- a/modules/axconfig/build.rs +++ b/modules/axconfig/build.rs @@ -128,6 +128,16 @@ fn gen_config_rs(config_path: &Path) -> Result> { } } Value::Array(regions) => { + if key == "cpu-id-list" { + writeln!(output, "{comments}")?; + writeln!(output, "pub const {var_name}: &[usize] = &[")?; + for r in regions.iter() { + let r = r.as_str().unwrap(); + writeln!(output, "{},", r)?; + } + writeln!(output, "];")?; + } + if key != "mmio-regions" && key != "virtio-mmio-regions" && key != "pci-ranges" { continue; diff --git a/modules/axconfig/defconfig.toml b/modules/axconfig/defconfig.toml index 5bd110e701..7d9babb6f0 100644 --- a/modules/axconfig/defconfig.toml +++ b/modules/axconfig/defconfig.toml @@ -46,3 +46,6 @@ ticks-per-sec = "100" # Number of CPUs smp = "1" + +# CPU Hardware ID list +cpu-id-list = [] \ No newline at end of file diff --git a/modules/axhal/src/platform/aarch64_common/pl011.rs b/modules/axhal/src/platform/aarch64_common/pl011.rs index 8b4325c04e..4f149185e4 100644 --- a/modules/axhal/src/platform/aarch64_common/pl011.rs +++ b/modules/axhal/src/platform/aarch64_common/pl011.rs @@ -6,6 +6,20 @@ use memory_addr::PhysAddr; use crate::mem::phys_to_virt; +/// Prints a character to the UART before mmu. +#[allow(unused)] +pub(crate) fn put_char_early(c: u8) { + unsafe { + let reg = axconfig::UART_PADDR as *mut u8; + let state = reg.add(0x18); + let data = reg.add(0x00); + + while (state.read_volatile() & 0x20_u8) != 0 {} + + data.write_volatile(c); + } +} + const UART_BASE: PhysAddr = pa!(axconfig::UART_PADDR); static UART: SpinNoIrq = diff --git a/modules/axhal/src/platform/aarch64_phytium_pi/mem.rs b/modules/axhal/src/platform/aarch64_phytium_pi/mem.rs new file mode 100644 index 0000000000..9019dcb7eb --- /dev/null +++ b/modules/axhal/src/platform/aarch64_phytium_pi/mem.rs @@ -0,0 +1,37 @@ +use crate::mem::*; +use page_table_entry::{aarch64::A64PTE, GenericPTE, MappingFlags}; + +/// Returns platform-specific memory regions. +pub(crate) fn platform_regions() -> impl Iterator { + core::iter::once(MemRegion { + paddr: 0x0.into(), + size: 0x1000, + flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE, + name: "spintable", + }) + .chain(crate::mem::default_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(pa!(boot_pt_l1.as_ptr() as usize)); + // 0x0000_0000_0000..0x0000_8000_0000, 1G block, device memory + boot_pt_l1[0] = A64PTE::new_page( + pa!(0), + MappingFlags::READ | MappingFlags::WRITE | MappingFlags::DEVICE, + true, + ); + // 0x0000_8000_0000..0x0000_C000_0000, 2G block, normal memory + boot_pt_l1[2] = A64PTE::new_page( + pa!(0x8000_0000), + MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE, + true, + ); +} diff --git a/modules/axhal/src/platform/aarch64_phytium_pi/mod.rs b/modules/axhal/src/platform/aarch64_phytium_pi/mod.rs new file mode 100644 index 0000000000..c7c7264d4c --- /dev/null +++ b/modules/axhal/src/platform/aarch64_phytium_pi/mod.rs @@ -0,0 +1,69 @@ +pub mod mem; + +#[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(); + 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_primary(cpu_id); + super::aarch64_common::pl011::init_early(); + super::aarch64_common::generic_timer::init_early(); + rust_main(cpu_id, dtb); +} + +#[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(); +} diff --git a/modules/axhal/src/platform/aarch64_phytium_pi/mp.rs b/modules/axhal/src/platform/aarch64_phytium_pi/mp.rs new file mode 100644 index 0000000000..3da70a1749 --- /dev/null +++ b/modules/axhal/src/platform/aarch64_phytium_pi/mp.rs @@ -0,0 +1,14 @@ +use crate::mem::{virt_to_phys, PhysAddr}; + +extern "C" { + fn _start_secondary(); +} + +/// Starts the given secondary CPU with its boot stack. +pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) { + extern "C" { + fn _start_secondary(); + } + let entry = virt_to_phys(va!(_start_secondary as usize)); + crate::platform::aarch64_common::psci::cpu_on(cpu_id, entry.as_usize(), stack_top.as_usize()); +} diff --git a/modules/axhal/src/platform/mod.rs b/modules/axhal/src/platform/mod.rs index a39151c47f..349aac9ae0 100644 --- a/modules/axhal/src/platform/mod.rs +++ b/modules/axhal/src/platform/mod.rs @@ -22,6 +22,9 @@ cfg_if::cfg_if! { } else if #[cfg(all(target_arch = "aarch64", platform_family = "aarch64-bsta1000b"))] { mod aarch64_bsta1000b; pub use self::aarch64_bsta1000b::*; + } else if #[cfg(all(target_arch = "aarch64", platform_family = "aarch64-phytium-pi"))] { + mod aarch64_phytium_pi; + pub use self::aarch64_phytium_pi::*; } else { mod dummy; pub use self::dummy::*; diff --git a/modules/axruntime/src/mp.rs b/modules/axruntime/src/mp.rs index 005d6be132..dd78969194 100644 --- a/modules/axruntime/src/mp.rs +++ b/modules/axruntime/src/mp.rs @@ -1,6 +1,6 @@ use core::sync::atomic::{AtomicUsize, Ordering}; -use axconfig::{SMP, TASK_STACK_SIZE}; +use axconfig::{CPU_ID_LIST, SMP, TASK_STACK_SIZE}; use axhal::mem::{virt_to_phys, VirtAddr}; #[link_section = ".bss.stack"] @@ -8,21 +8,32 @@ static mut SECONDARY_BOOT_STACK: [[u8; TASK_STACK_SIZE]; SMP - 1] = [[0; TASK_ST static ENTERED_CPUS: AtomicUsize = AtomicUsize::new(1); +#[allow(clippy::absurd_extreme_comparisons)] +fn start_secondary_cpus_one(primary_cpu_id: usize, cpu_id: usize, cpu_i: &mut usize) { + if cpu_id != primary_cpu_id && *cpu_i < SMP - 1 { + let stack_top = virt_to_phys(VirtAddr::from(unsafe { + SECONDARY_BOOT_STACK[*cpu_i].as_ptr_range().end as usize + })); + + debug!("starting CPU {}...", cpu_id); + axhal::mp::start_secondary_cpu(cpu_id, stack_top); + *cpu_i += 1; + + while ENTERED_CPUS.load(Ordering::Acquire) <= *cpu_i { + core::hint::spin_loop(); + } + } +} + pub fn start_secondary_cpus(primary_cpu_id: usize) { - let mut logic_cpu_id = 0; - for i in 0..SMP { - if i != primary_cpu_id { - let stack_top = virt_to_phys(VirtAddr::from(unsafe { - SECONDARY_BOOT_STACK[logic_cpu_id].as_ptr_range().end as usize - })); - - debug!("starting CPU {}...", i); - axhal::mp::start_secondary_cpu(i, stack_top); - logic_cpu_id += 1; - - while ENTERED_CPUS.load(Ordering::Acquire) <= logic_cpu_id { - core::hint::spin_loop(); - } + let mut cpu_i = 0; + if CPU_ID_LIST.is_empty() { + for id in 0..SMP { + start_secondary_cpus_one(primary_cpu_id, id, &mut cpu_i); + } + } else { + for id in CPU_ID_LIST { + start_secondary_cpus_one(primary_cpu_id, *id, &mut cpu_i); } } } diff --git a/platforms/aarch64-phytium-pi.toml b/platforms/aarch64-phytium-pi.toml new file mode 100644 index 0000000000..39c7400337 --- /dev/null +++ b/platforms/aarch64-phytium-pi.toml @@ -0,0 +1,82 @@ +# 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 = "0x9000_0000" +# Base virtual address of the kernel image. +kernel-base-vaddr = "0xffff_0000_9000_0000" +# Linear mapping offset, for quick conversions between physical and virtual +# addresses. +phys-virt-offset = "0xffff_0000_0000_0000" +# MMIO regions with format (`base_paddr`, `size`). +mmio-regions = [ + ["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 + + ["0x58000000", "0x7fffffff"], # 32-bit MMIO space + + ["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 +] + +# UART Address +uart-paddr = "0x2800_D000" +# UART Irq num +uart-irq = "24" + +# MIO0 I2C +MIO0 = "0x2801_4000" + +# PSCI +psci-method = "smc" + +# GICC Address +gicc-paddr = "0xFF84_2000" +# GICD Address +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 = [ + ["0x0", "0x50000000"], # PIO space + ["0x58000000", "0x7fffffff"], # 32-bit MMIO space + ["0x6_0000_0000", "0x6_3fff_ffff"], # 64-but MMIO space +] + +# Number of CPUs +smp = "4" + +# CPU Hardware ID list +cpu-id-list = ["0x0", "0x100", "0x200", "0x201"]