Skip to content

Commit

Permalink
feat: support boot_core for aarch64 and optimize some code
Browse files Browse the repository at this point in the history
  • Loading branch information
yfblock committed Sep 15, 2024
1 parent b4e16a8 commit e296b1b
Show file tree
Hide file tree
Showing 19 changed files with 217 additions and 138 deletions.
25 changes: 15 additions & 10 deletions example/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ endif
OBJDUMP := rust-objdump --arch-name=riscv64
OBJCOPY := rust-objcopy --binary-architecture=riscv64

ifneq ($(GUI), true)
QEMU_EXEC += -nographic
else
QEMU_EXEC += -serial stdio -vga std
endif
QEMU_EXEC += -smp $(SMP)
QEMU_EXEC += -D qemu.log -d in_asm,int,pcall,cpu_reset,guest_errors
ifeq ($(TEST), true)
QEMU_EXEC += >output.log 2>&1 || echo "QEMU exited"
endif

build: env $(KERNEL_BIN)

env:
Expand All @@ -62,20 +73,14 @@ kernel:
@echo Platform: $(BOARD)
@cargo build $(BUILD_ARGS) --release --target $(TARGET)

clean-log:
@rm qemu*.log

clean:
@cargo clean

run: run-inner

ifneq ($(GUI), true)
QEMU_EXEC += -nographic
endif
QEMU_EXEC += -smp $(SMP)
QEMU_EXEC += -D qemu-%d.log -d in_asm,int,pcall,cpu_reset,guest_errors,tid
ifeq ($(TEST), true)
QEMU_EXEC += >output.log 2>&1 || echo "QEMU exited"
endif

run-inner: build
$(QEMU_EXEC)
ifeq ($(TEST), true)
Expand Down Expand Up @@ -104,4 +109,4 @@ gdb:
-ex 'set arch x86_64' \
-ex 'target remote localhost:1234'

.PHONY: build env kernel clean run-inner
.PHONY: build env kernel clean clean-log run-inner
13 changes: 10 additions & 3 deletions example/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ static LOCK_FRAME_ALLOCATOR: Lazy<LockedFrameAllocator<32>> =
Lazy::new(|| LockedFrameAllocator::new());

pub fn add_frame_range(mm_start: usize, mm_end: usize) {
let start = mm_start / PAGE_SIZE;
let end = mm_end / PAGE_SIZE;
LOCK_FRAME_ALLOCATOR.lock().add_frame(start, end);
extern "C" {
fn end();
}
let mm_start = if mm_start <= mm_end && mm_end > end as usize {
(end as usize + PAGE_SIZE - 1) / PAGE_SIZE
} else {
mm_start / PAGE_SIZE
};
let mm_end = mm_end / PAGE_SIZE;
LOCK_FRAME_ALLOCATOR.lock().add_frame(mm_start, mm_end);
}

pub fn frame_alloc(count: usize) -> PhysPage {
Expand Down
46 changes: 34 additions & 12 deletions example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ mod frame;
mod logging;
mod pci;
use core::panic::PanicInfo;
use core::sync::atomic::{AtomicU32, Ordering};

use frame::frame_alloc;
use polyhal::addr::PhysPage;
use polyhal::common::{get_mem_areas, PageAlloc};
use polyhal::consts::VIRT_ADDR_START;
use polyhal::common::{get_fdt, get_mem_areas, PageAlloc};
use polyhal::debug_console::DebugConsole;
use polyhal::define_entry;
use polyhal::instruction::{ebreak, shutdown};
use polyhal::multicore::boot_core;
use polyhal::pagetable::PAGE_SIZE;
use polyhal::trap::TrapType::{self, *};
use polyhal::trapframe::{TrapFrame, TrapFrameArgs};

Expand All @@ -37,7 +36,7 @@ fn kernel_interrupt(ctx: &mut TrapFrame, trap_type: TrapType) {
// println!("trap_type @ {:x?} {:#x?}", trap_type, ctx);
match trap_type {
Breakpoint => {
log::info!("@BP @ {:#x}", ctx[TrapFrameArgs::SEPC]);
log::info!("BreakPoint @ {:#x}", ctx[TrapFrameArgs::SEPC]);
}
SysCall => {
// jump to next instruction anyway
Expand All @@ -59,16 +58,17 @@ fn kernel_interrupt(ctx: &mut TrapFrame, trap_type: TrapType) {
}
}

#[polyhal::arch_entry]
static CORE_SET: AtomicU32 = AtomicU32::new(0);

/// kernel main function, entry point.
fn main(hartid: usize) {
if hartid != 0 {
log::info!("Hello Other Hart: {}", hartid);
let _ = CORE_SET.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
Some(x | (1 << hartid))
});
loop {}
}
if hartid != 0 {
return;
}

println!("[kernel] Hello, world!");
allocator::init_allocator();
Expand All @@ -85,11 +85,31 @@ fn main(hartid: usize) {
frame::add_frame_range(start, start + size);
});

if let Some(fdt) = get_fdt() {
fdt.all_nodes().for_each(|x| {
if let Some(compatibles) = x.compatible() {
log::debug!("Node Compatiable: {:?}", compatibles.first());
}
});

log::debug!("boot args: {}", fdt.chosen().bootargs().unwrap_or(""));
}

// Boot another core that id is 1.
let sp = frame_alloc(16);
boot_core(1, (sp.to_addr() | VIRT_ADDR_START) + 16 * PAGE_SIZE);
#[cfg(not(target_arch = "x86_64"))]
{
use polyhal::consts::VIRT_ADDR_START;

use polyhal::multicore::boot_core;
use polyhal::pagetable::PAGE_SIZE;
let sp = frame_alloc(16);
boot_core(1, (sp.to_addr() | VIRT_ADDR_START) + 16 * PAGE_SIZE);
// Waiting for Core Booting
while CORE_SET.fetch_and(1 << 1, Ordering::SeqCst) == 0 {}
log::info!("Core 1 Has Booted successfully!");
}

// Test BreakPoint
// Test BreakPoint Interrupt
ebreak();

crate::pci::init();
Expand All @@ -104,6 +124,8 @@ fn main(hartid: usize) {
shutdown();
}

define_entry!(main);

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
if let Some(location) = info.location() {
Expand Down
7 changes: 3 additions & 4 deletions example/src/pci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ pub fn init() {
let pci_addr = pci_node.reg().map(|mut x| x.next().unwrap()).unwrap();
log::info!("PCI Address: {:#p}", pci_addr.starting_address);
enumerate_pci((pci_addr.starting_address as usize | VIRT_ADDR_START) as *mut u8);
return;
}
}
#[cfg(target_arch = "x86_64")]
enumerate_pci((0xb000_0000 | VIRT_ADDR_START) as *mut u8);
#[cfg(target_arch = "loongarch64")]
enumerate_pci((0x2000_0000 | VIRT_ADDR_START) as *mut u8);
}

/// Enumerate the PCI devices
Expand Down Expand Up @@ -61,10 +60,10 @@ fn enumerate_pci(mmconfig_base: *mut u8) {
/// Dump bar Contents.
fn dump_bar_contents(root: &mut PciRoot, device_function: DeviceFunction, bar_index: u8) {
let bar_info = root.bar_info(device_function, bar_index).unwrap();
if let Some((addr, size)) = bar_info.memory_address_size() {
if let Some((_addr, size)) = bar_info.memory_address_size() {
if size == 0 {
return;
}
trace!("Dumping bar {}: {:#x?}", bar_index, bar_info,);
trace!("Dumping bar {}: {:#x?}", bar_index, bar_info);
}
}
3 changes: 0 additions & 3 deletions src/components/arch/aarch64/psci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ fn psci_call(func: u32, arg0: usize, arg1: usize, arg2: usize) -> Result<(), Psc

/// Shutdown the whole system, including all CPUs.
pub fn system_off() -> ! {
log::info!("Shutting down...");
psci_call(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0).ok();
log::warn!("It should shutdown!");
loop {
// crate::arch::halt();
}
Expand All @@ -111,7 +109,6 @@ pub fn system_off() -> ! {
/// `entry_point` is the physical address of the secondary CPU's entry point.
/// `arg` will be passed to the `X0` register of the secondary CPU.
pub fn cpu_on(target_cpu: usize, entry_point: usize, arg: usize) {
log::info!("Starting CPU {:x} ON ...", target_cpu);
let res = psci_call(PSCI_0_2_FN64_CPU_ON, target_cpu, entry_point, arg);
if let Err(e) = res {
log::error!("failed to boot CPU {:x} ({:?})", target_cpu, e);
Expand Down
79 changes: 43 additions & 36 deletions src/components/boot/aarch64.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
use aarch64_cpu::{asm, asm::barrier, registers::*};

use fdt::Fdt;
// use page_table_entry::aarch64::{MemAttr, A64PTE};
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};

use crate::{
components::{
common::{CPU_NUM, DTB_PTR},
common::parse_dtb_info, components::{
common::DTB_PTR,
consts::VIRT_ADDR_START,
debug_console::{display_info, println},
instruction,
pagetable::{PTEFlags, TLB},
percpu::percpu_area_init,
timer,
},
multicore::CpuCore,
pagetable::PTE,
PageTable, PhysPage,
}, multicore::CpuCore, pagetable::PTE, PageTable, PhysPage
};

use super::PageAlignment;
Expand Down Expand Up @@ -154,13 +150,26 @@ unsafe extern "C" fn _start() -> ! {
/// The secondary core boot entry point.
#[naked]
#[no_mangle]
unsafe extern "C" fn _secondary_boot() -> ! {
// PC = 0x8_0000
// X0 = dtb
core::arch::asm!(
"
wfi
b _secondary_boot",
pub(crate) unsafe extern "C" fn _secondary_boot() -> ! {
core::arch::asm!("
mrs x19, mpidr_el1
and x19, x19, #0xffffff // get current CPU id
mov sp, x0
bl {switch_to_el1}
bl {init_mmu}
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,
phys_virt_offset = const crate::components::consts::VIRT_ADDR_START,
entry = sym rust_secondary_main,
options(noreturn),
)
}
Expand All @@ -179,36 +188,16 @@ pub fn rust_tmp_main(hart_id: usize, device_tree: usize) {
// Init GIC interrupt controller.
crate::components::irq::init();

timer::init();
init_cpu();

DTB_PTR.init_by(device_tree | VIRT_ADDR_START);

if let Ok(fdt) = unsafe { Fdt::from_ptr(*DTB_PTR as *const u8) } {
CPU_NUM.init_by(fdt.cpus().count());
} else {
CPU_NUM.init_by(1);
}

// Enable Floating Point Feature.
CPACR_EL1.write(CPACR_EL1::FPEN::TrapNothing);
aarch64_cpu::asm::barrier::isb(aarch64_cpu::asm::barrier::SY);

// Display Polyhal and Platform Information
display_info!();
println!(include_str!("../../banner.txt"));
display_info!("Platform Name", "aarch64");
if let Ok(fdt) = unsafe { Fdt::from_ptr(device_tree as *const u8) } {
display_info!("Platform HART Count", "{}", fdt.cpus().count());
fdt.memory().regions().for_each(|x| {
display_info!(
"Platform Memory Region",
"{:#p} - {:#018x}",
x.starting_address,
x.starting_address as usize + x.size.unwrap()
);
});
}
display_info!("Platform Virt Mem Offset", "{:#x}", VIRT_ADDR_START);
parse_dtb_info();
display_info!();
display_info!("Boot HART ID", "{}", hart_id);
display_info!();
Expand All @@ -219,6 +208,24 @@ pub fn rust_tmp_main(hart_id: usize, device_tree: usize) {
instruction::shutdown();
}

/// Rust secondary entry for core except Boot Core.
fn rust_secondary_main(hart_id: usize) {
// Initialize the cpu configuration.
init_cpu();

unsafe { crate::components::boot::_main_for_arch(hart_id) }
}

/// Initialize the CPU configuration.
fn init_cpu() {
// Initialize the Timer
timer::init();

// Enable Floating Point Feature.
CPACR_EL1.write(CPACR_EL1::FPEN::TrapNothing);
aarch64_cpu::asm::barrier::isb(aarch64_cpu::asm::barrier::SY);
}

pub fn boot_page_table() -> PageTable {
PageTable(crate::addr::PhysAddr(unsafe {
BOOT_PT_L1.0.as_ptr() as usize & !VIRT_ADDR_START
Expand Down
20 changes: 9 additions & 11 deletions src/components/boot/loongarch64.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
use loongArch64::register::euen;

use crate::{
arch::hart_id,
components::{
common::CPU_NUM,
arch::hart_id, common::{parse_dtb_info, DTB_PTR}, components::{
consts::VIRT_ADDR_START,
debug_console::{display_info, println, DebugConsole},
percpu::percpu_area_init,
timer,
},
instruction,
multicore::CpuCore,
PageTable, PhysAddr,
}, consts::QEMU_DTB_ADDR, instruction, multicore::CpuCore, PageTable, PhysAddr
};

#[cfg(feature = "trap")]
Expand Down Expand Up @@ -71,7 +66,6 @@ unsafe extern "C" fn _start() -> ! {
/// The earliest entry point for the primary CPU.
///
/// We can't use bl to jump to higher address, so we use jirl to jump to higher address.
/// TODO: Dynamic Stack Pointer.
#[naked]
#[no_mangle]
#[link_section = ".text.entry"]
Expand Down Expand Up @@ -112,18 +106,22 @@ pub fn rust_tmp_main(hart_id: usize) {
#[cfg(feature = "logger")]
DebugConsole::log_init();

unsafe {
if fdt::Fdt::from_ptr((QEMU_DTB_ADDR | VIRT_ADDR_START) as *const u8).is_ok() {
DTB_PTR.init_by(QEMU_DTB_ADDR | VIRT_ADDR_START);
}
}

// Display Information.
display_info!();
println!(include_str!("../../banner.txt"));
display_info!("Platform Name", "loongarch64");
display_info!("Platform Virt Mem Offset", "{:#x}", VIRT_ADDR_START);
parse_dtb_info();
display_info!();
display_info!("Boot HART ID", "{}", hart_id);
display_info!();

// TODO: Detect CPU Num dynamically.
CPU_NUM.init_by(2);

unsafe { super::_main_for_arch(hart_id) };

instruction::shutdown();
Expand Down
Loading

0 comments on commit e296b1b

Please sign in to comment.