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..4737362331 100644 --- a/modules/axconfig/build.rs +++ b/modules/axconfig/build.rs @@ -127,24 +127,34 @@ fn gen_config_rs(config_path: &Path) -> Result> { writeln!(output, "pub const {var_name}: &str = \"{s}\";")?; } } - Value::Array(regions) => { - if key != "mmio-regions" && key != "virtio-mmio-regions" && key != "pci-ranges" - { - continue; + Value::Array(regions) => match 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, "];")?; } - writeln!(output, "{comments}")?; - writeln!(output, "pub const {var_name}: &[(usize, usize)] = &[")?; - for r in regions.iter() { - let r = r.as_array().unwrap(); - writeln!( - output, - " ({}, {}),", - r.get(0).unwrap().as_str().unwrap(), - r.get(1).unwrap().as_str().unwrap() - )?; + "mmio-regions" | "virtio-mmio-regions" | "pci-ranges" => { + writeln!(output, "{comments}")?; + writeln!(output, "pub const {var_name}: &[(usize, usize)] = &[")?; + for r in regions.iter() { + let r = r.as_array().unwrap(); + writeln!( + output, + " ({}, {}),", + r.get(0).unwrap().as_str().unwrap(), + r.get(1).unwrap().as_str().unwrap() + )?; + } + writeln!(output, "];")?; } - writeln!(output, "];")?; - } + _ => { + 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_bsta1000b/mp.rs b/modules/axhal/src/platform/aarch64_bsta1000b/mp.rs index e5ee9bf9a7..4adf3d466a 100644 --- a/modules/axhal/src/platform/aarch64_bsta1000b/mp.rs +++ b/modules/axhal/src/platform/aarch64_bsta1000b/mp.rs @@ -5,6 +5,11 @@ pub const MAX_HARTS: usize = 8; /// CPU HWID from cpu device tree nodes with "reg" property pub const CPU_HWID: [usize; MAX_HARTS] = [0x00, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700]; +/// Converts the given CPU hardware ID to its logical ID. +pub fn cpu_hard_id_to_logic_id(hard_id: usize) -> usize { + hard_id +} + /// Starts the given secondary CPU with its boot stack. pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) { if cpu_id >= MAX_HARTS { 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..20726fb340 --- /dev/null +++ b/modules/axhal/src/platform/aarch64_phytium_pi/mem.rs @@ -0,0 +1,30 @@ +use crate::mem::*; +use page_table_entry::{aarch64::A64PTE, GenericPTE, MappingFlags}; + +/// Returns platform-specific memory regions. +pub(crate) fn platform_regions() -> impl Iterator { + 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, 1G 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..829b229180 --- /dev/null +++ b/modules/axhal/src/platform/aarch64_phytium_pi/mp.rs @@ -0,0 +1,28 @@ +use axconfig::CPU_ID_LIST; + +use crate::mem::{virt_to_phys, PhysAddr}; + +extern "C" { + fn _start_secondary(); +} + +pub fn cpu_hard_id_to_logic_id(hard_id: usize) -> usize { + if CPU_ID_LIST.is_empty() { + hard_id + } else { + CPU_ID_LIST.iter().position(|&x| x == hard_id).unwrap() + } +} + +/// 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_LIST[cpu_id], + entry.as_usize(), + stack_top.as_usize(), + ); +} diff --git a/modules/axhal/src/platform/aarch64_qemu_virt/mp.rs b/modules/axhal/src/platform/aarch64_qemu_virt/mp.rs index 5c3936dd11..406adf8c1e 100644 --- a/modules/axhal/src/platform/aarch64_qemu_virt/mp.rs +++ b/modules/axhal/src/platform/aarch64_qemu_virt/mp.rs @@ -8,3 +8,8 @@ pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) { 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()); } + +/// Converts the given CPU hardware ID to its logical ID. +pub fn cpu_hard_id_to_logic_id(hard_id: usize) -> usize { + hard_id +} diff --git a/modules/axhal/src/platform/aarch64_raspi/mp.rs b/modules/axhal/src/platform/aarch64_raspi/mp.rs index 8447daec8d..6a9c78c13c 100644 --- a/modules/axhal/src/platform/aarch64_raspi/mp.rs +++ b/modules/axhal/src/platform/aarch64_raspi/mp.rs @@ -40,3 +40,8 @@ pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) { } aarch64_cpu::asm::sev(); } + +/// Converts the given CPU hardware ID to its logical ID. +pub fn cpu_hard_id_to_logic_id(hard_id: usize) -> usize { + hard_id +} diff --git a/modules/axhal/src/platform/dummy/mod.rs b/modules/axhal/src/platform/dummy/mod.rs index e0d229ff3a..19d0464089 100644 --- a/modules/axhal/src/platform/dummy/mod.rs +++ b/modules/axhal/src/platform/dummy/mod.rs @@ -23,6 +23,9 @@ pub mod misc { #[cfg(feature = "smp")] pub mod mp { + pub fn cpu_hard_id_to_logic_id(hard_id: usize) -> usize { + 0 + } /// Starts the given secondary CPU with its boot stack. pub fn start_secondary_cpu(cpu_id: usize, stack_top: crate::mem::PhysAddr) {} } 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/axhal/src/platform/riscv64_qemu_virt/mp.rs b/modules/axhal/src/platform/riscv64_qemu_virt/mp.rs index ddcecca4d1..c45175c8a5 100644 --- a/modules/axhal/src/platform/riscv64_qemu_virt/mp.rs +++ b/modules/axhal/src/platform/riscv64_qemu_virt/mp.rs @@ -12,3 +12,8 @@ pub fn start_secondary_cpu(hartid: usize, stack_top: PhysAddr) { let entry = virt_to_phys(va!(_start_secondary as usize)); sbi_rt::hart_start(hartid, entry.as_usize(), stack_top.as_usize()); } + +/// Converts the given CPU hardware ID to its logical ID. +pub fn cpu_hard_id_to_logic_id(hard_id: usize) -> usize { + hard_id +} diff --git a/modules/axhal/src/platform/x86_pc/mp.rs b/modules/axhal/src/platform/x86_pc/mp.rs index fb194934d2..c91f5baca1 100644 --- a/modules/axhal/src/platform/x86_pc/mp.rs +++ b/modules/axhal/src/platform/x86_pc/mp.rs @@ -43,3 +43,8 @@ pub fn start_secondary_cpu(apic_id: usize, stack_top: PhysAddr) { busy_wait(Duration::from_micros(200)); // 200us unsafe { lapic.send_sipi(START_PAGE_IDX, apic_id) }; } + +/// Converts the given CPU hardware ID to its logical ID. +pub fn cpu_hard_id_to_logic_id(hard_id: usize) -> usize { + hard_id +} diff --git a/modules/axruntime/src/mp.rs b/modules/axruntime/src/mp.rs index 005d6be132..44d36eadb8 100644 --- a/modules/axruntime/src/mp.rs +++ b/modules/axruntime/src/mp.rs @@ -8,10 +8,11 @@ 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)] 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 { + if i != axhal::mp::cpu_hard_id_to_logic_id(primary_cpu_id) && logic_cpu_id < SMP - 1 { let stack_top = virt_to_phys(VirtAddr::from(unsafe { SECONDARY_BOOT_STACK[logic_cpu_id].as_ptr_range().end as usize })); diff --git a/platforms/aarch64-phytium-pi.toml b/platforms/aarch64-phytium-pi.toml new file mode 100644 index 0000000000..546d50e8d8 --- /dev/null +++ b/platforms/aarch64-phytium-pi.toml @@ -0,0 +1,80 @@ +# 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" +# 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 = [ + ["0x2800_C000", "0x1000"], # UART 0 + ["0x2800_D000", "0x1000"], # UART 1 + ["0x2800_E000", "0x1000"], # UART 2 + ["0x2800_F000", "0x1000"], # UART 3 + + ["0x3000_0000", "0x800_0000"], # other devices + ["0x4000_0000", "0x1000_0000"], # Pcie ecam + + ["0x58000000", "0x2800_0000"], # 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 +] + +# 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", "0x80000000"], # 32-bit MMIO space + ["0x6_0000_0000", "0x6_4000_0000"], # 64-but MMIO space +] + +# Number of CPUs +smp = "4" + +# CPU Hardware ID list +cpu-id-list = ["0x0", "0x100", "0x200", "0x201"]