mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 17:26:31 +00:00
feat(riscv): riscv下能够运行hello world用户程序 (#770)
* feat(riscv): riscv下能够运行hello world用户程序
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
kernel_driver_subdirs:=acpi disk multiboot2 timers
|
||||
kernel_driver_subdirs:=acpi multiboot2
|
||||
|
||||
ECHO:
|
||||
@echo "$@"
|
||||
|
@ -34,11 +34,11 @@ impl RiscVSbiTimer {
|
||||
|
||||
fn handle_irq(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
|
||||
// 更新下一次中断时间
|
||||
kdebug!(
|
||||
"riscv_sbi_timer: handle_irq: cpu_id: {}, time: {}",
|
||||
smp_get_processor_id().data(),
|
||||
CurrentTimeArch::get_cycles() as u64
|
||||
);
|
||||
// kdebug!(
|
||||
// "riscv_sbi_timer: handle_irq: cpu_id: {}, time: {}",
|
||||
// smp_get_processor_id().data(),
|
||||
// CurrentTimeArch::get_cycles() as u64
|
||||
// );
|
||||
sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
|
||||
ProcessManager::update_process_times(trap_frame.is_from_user());
|
||||
Ok(())
|
||||
|
@ -1,10 +0,0 @@
|
||||
SRC = $(wildcard *.c)
|
||||
OBJ = $(SRC:.c=.o)
|
||||
CFLAGS += -I .
|
||||
|
||||
.PHONY: all
|
||||
|
||||
all: $(OBJ)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
13
kernel/src/driver/firmware/efi/esrt.rs
Normal file
13
kernel/src/driver/firmware/efi/esrt.rs
Normal file
@ -0,0 +1,13 @@
|
||||
//! 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/esrt.c#1
|
||||
|
||||
use super::efi_manager;
|
||||
|
||||
#[inline(never)]
|
||||
pub(super) fn efi_esrt_init() {
|
||||
if !efi_manager().esrt_table_exists() {
|
||||
return;
|
||||
}
|
||||
|
||||
// todo: 参考linux 的 `efi_esrt_init`来实现
|
||||
todo!("efi_esrt_init")
|
||||
}
|
@ -29,6 +29,15 @@ pub static EFI_MEMRESERVE_TABLE_GUID: Guid = Guid::new(
|
||||
0xf0,
|
||||
[0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2],
|
||||
);
|
||||
|
||||
pub static EFI_SYSTEM_RESOURCE_TABLE_GUID: Guid = Guid::new(
|
||||
unsafe { mem::transmute_copy(&0xb122a263u32) },
|
||||
unsafe { mem::transmute_copy(&0x3661u32) },
|
||||
unsafe { mem::transmute_copy(&0x4f68u32) },
|
||||
0x99,
|
||||
0x29,
|
||||
[0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80],
|
||||
);
|
||||
/// 表示内核被加载到的地址的信息。
|
||||
///
|
||||
/// 对应 `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID`
|
||||
|
@ -5,7 +5,10 @@ use uefi_raw::table::boot::{MemoryAttribute, MemoryType};
|
||||
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
driver::{firmware::efi::EFIInitFlags, open_firmware::fdt::open_firmware_fdt_driver},
|
||||
driver::{
|
||||
firmware::efi::{esrt::efi_esrt_init, EFIInitFlags},
|
||||
open_firmware::fdt::open_firmware_fdt_driver,
|
||||
},
|
||||
libs::align::{page_align_down, page_align_up},
|
||||
mm::{
|
||||
allocator::page_frame::PhysPageFrame, early_ioremap::EarlyIoRemap,
|
||||
@ -66,6 +69,11 @@ pub fn efi_init() {
|
||||
// todo: 模仿Linux的行为,做好接下来的几步工作:
|
||||
// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/efi-init.c#217
|
||||
|
||||
// todo: early_init_dt_check_for_usable_mem_range
|
||||
|
||||
efi_find_mirror();
|
||||
efi_esrt_init();
|
||||
|
||||
// 保留mmap table的内存
|
||||
let base = page_align_down(data_from_fdt.mmap_base.unwrap() as usize);
|
||||
let offset = data_from_fdt.mmap_base.unwrap() as usize - base;
|
||||
@ -78,7 +86,7 @@ pub fn efi_init() {
|
||||
.expect("Failed to reserve memory for EFI mmap table");
|
||||
|
||||
// 保留内核的内存
|
||||
if let Some(info) = efi_manager().inner.read().dragonstub_load_info {
|
||||
if let Some(info) = efi_manager().inner_read().dragonstub_load_info {
|
||||
mem_block_manager()
|
||||
.reserve_block(
|
||||
PhysAddr::new(info.paddr as usize),
|
||||
@ -92,6 +100,31 @@ pub fn efi_init() {
|
||||
kinfo!("UEFI init done!");
|
||||
}
|
||||
|
||||
fn efi_find_mirror() {
|
||||
let efi_guard = efi_manager().inner_read();
|
||||
let mut total_size = 0;
|
||||
let mut mirror_size = 0;
|
||||
for md in efi_guard.mmap.iter() {
|
||||
let start = PhysAddr::new(md.phys_start as usize);
|
||||
let size = (md.page_count << (MMArch::PAGE_SHIFT as u64)) as usize;
|
||||
|
||||
if md.att.contains(MemoryAttribute::MORE_RELIABLE) {
|
||||
mem_block_manager().mark_mirror(start, size).unwrap();
|
||||
mirror_size += size;
|
||||
}
|
||||
|
||||
total_size += size;
|
||||
}
|
||||
|
||||
if mirror_size > 0 {
|
||||
kinfo!(
|
||||
"Memory: {}M/{}M mirrored memory",
|
||||
mirror_size >> 20,
|
||||
total_size >> 20
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
|
||||
// 定义错误处理函数
|
||||
@ -142,7 +175,7 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
|
||||
let st_ref = unsafe { st_ptr.as_ref().unwrap() };
|
||||
|
||||
let runtime_service_paddr = efi_vaddr_2_paddr(st_ref.runtime_services as usize);
|
||||
let mut inner_write_guard = efi_manager().inner.write();
|
||||
let mut inner_write_guard = efi_manager().inner_write();
|
||||
inner_write_guard.runtime_paddr = Some(runtime_service_paddr);
|
||||
inner_write_guard.runtime_service_version = Some(st_ref.header.revision);
|
||||
|
||||
@ -189,7 +222,7 @@ fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> {
|
||||
///
|
||||
/// 在进入该函数前,请不要持有`efi_manager().inner`的写锁
|
||||
fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr {
|
||||
let guard = efi_manager().inner.read();
|
||||
let guard = efi_manager().inner_read();
|
||||
let mmap = &guard.mmap;
|
||||
|
||||
let efi_vaddr: u64 = efi_vaddr as u64;
|
||||
@ -236,6 +269,11 @@ fn reserve_memory_regions() {
|
||||
if md.is_memory() {
|
||||
open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64);
|
||||
if !md.is_usable_memory() {
|
||||
// kdebug!(
|
||||
// "Marking non-usable memory as nomap: {:#x}-{:#x}",
|
||||
// phys_start,
|
||||
// phys_start + size
|
||||
// );
|
||||
mem_block_manager()
|
||||
.mark_nomap(PhysAddr::new(phys_start), size)
|
||||
.unwrap();
|
||||
|
@ -1,9 +1,13 @@
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{libs::rwlock::RwLock, mm::PhysAddr};
|
||||
use crate::{
|
||||
libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
mm::PhysAddr,
|
||||
};
|
||||
|
||||
use self::{guid::DragonStubPayloadEFI, memmap::EFIMemoryMapInfo};
|
||||
|
||||
pub mod esrt;
|
||||
mod fdt;
|
||||
pub mod guid;
|
||||
pub mod init;
|
||||
@ -39,6 +43,8 @@ struct InnerEFIManager {
|
||||
pub memory_attribute_table_paddr: Option<PhysAddr>,
|
||||
/// uefi 内存保留表的物理地址
|
||||
pub memreserve_table_paddr: Option<PhysAddr>,
|
||||
/// uefi esrt表的物理地址
|
||||
pub esrt_table_paddr: Option<PhysAddr>,
|
||||
}
|
||||
|
||||
impl EFIManager {
|
||||
@ -52,6 +58,7 @@ impl EFIManager {
|
||||
dragonstub_load_info: None,
|
||||
memory_attribute_table_paddr: None,
|
||||
memreserve_table_paddr: None,
|
||||
esrt_table_paddr: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -97,6 +104,19 @@ impl EFIManager {
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn inner_read(&self) -> RwLockReadGuard<InnerEFIManager> {
|
||||
self.inner.read()
|
||||
}
|
||||
|
||||
fn inner_write(&self) -> RwLockWriteGuard<InnerEFIManager> {
|
||||
self.inner.write()
|
||||
}
|
||||
|
||||
/// 是否存在ESRT表
|
||||
fn esrt_table_exists(&self) -> bool {
|
||||
self.inner_read().esrt_table_paddr.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
// 在Rust中,我们使用枚举和bitflags来表示这些宏
|
||||
|
@ -20,7 +20,9 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
guid::{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID},
|
||||
guid::{
|
||||
EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID, EFI_SYSTEM_RESOURCE_TABLE_GUID,
|
||||
},
|
||||
EFIManager,
|
||||
};
|
||||
|
||||
@ -29,6 +31,7 @@ static TABLE_PARSERS: &[&TableMatcher] = &[
|
||||
&TableMatcher::new(&MatchTableDragonStubPayloadEFI),
|
||||
&TableMatcher::new(&MatchTableMemoryAttributes),
|
||||
&TableMatcher::new(&MatchTableMemReserve),
|
||||
&TableMatcher::new(&MatchTableEsrt),
|
||||
];
|
||||
|
||||
impl EFIManager {
|
||||
@ -99,7 +102,7 @@ impl EFIManager {
|
||||
}
|
||||
|
||||
// 如果存在mem reserve table
|
||||
if let Some(mem_reserve) = efi_manager().inner.read().memreserve_table_paddr {
|
||||
if let Some(mem_reserve) = efi_manager().inner_read().memreserve_table_paddr {
|
||||
let mut prev_paddr = mem_reserve;
|
||||
while !prev_paddr.is_null() {
|
||||
let vaddr = EarlyIoRemap::map_not_aligned(prev_paddr, MMArch::PAGE_SIZE, true)
|
||||
@ -283,7 +286,7 @@ impl MatchTable for MatchTableDragonStubPayloadEFI {
|
||||
let vendor_table_vaddr = vendor_table_vaddr.unwrap();
|
||||
let data = unsafe { *(vendor_table_vaddr.data() as *const DragonStubPayloadEFI) };
|
||||
|
||||
efi_manager().inner.write().dragonstub_load_info = Some(data);
|
||||
efi_manager().inner_write().dragonstub_load_info = Some(data);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
@ -349,6 +352,33 @@ impl MatchTable for MatchTableMemReserve {
|
||||
}
|
||||
}
|
||||
|
||||
struct MatchTableEsrt;
|
||||
|
||||
impl MatchTable for MatchTableEsrt {
|
||||
fn name(&self) -> &'static str {
|
||||
"ESRT"
|
||||
}
|
||||
|
||||
fn guid(&self) -> &'static uefi_raw::Guid {
|
||||
&EFI_SYSTEM_RESOURCE_TABLE_GUID
|
||||
}
|
||||
|
||||
fn map_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
fn post_process(
|
||||
&self,
|
||||
_vendor_table_vaddr: Option<VirtAddr>,
|
||||
table_raw: &ConfigurationTable,
|
||||
) -> Result<(), SystemError> {
|
||||
efi_manager().inner.write_irqsave().esrt_table_paddr =
|
||||
Some(PhysAddr::new(table_raw.vendor_table as usize));
|
||||
kdebug!("esrt_table_paddr: {:#x}", table_raw.vendor_table as usize);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
/// 用于匹配配置表的匹配器
|
||||
struct TableMatcher {
|
||||
table: &'static dyn MatchTable,
|
||||
|
@ -162,7 +162,7 @@ pub unsafe fn riscv_intc_init() -> Result<(), SystemError> {
|
||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-riscv-intc.c#23
|
||||
pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) {
|
||||
let hwirq = HardwareIrqNumber::new(trap_frame.cause.code() as u32);
|
||||
kdebug!("riscv64_do_irq: interrupt {hwirq:?}");
|
||||
// kdebug!("riscv64_do_irq: interrupt {hwirq:?}");
|
||||
GenericIrqHandler::handle_domain_irq(riscv_intc_domain().clone().unwrap(), hwirq, trap_frame)
|
||||
.ok();
|
||||
if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() {
|
||||
|
@ -1,6 +0,0 @@
|
||||
all:
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
#HPET.o: HPET/HPET.c
|
||||
# $(CC) $(CFLAGS) -c HPET/HPET.c -o HPET/HPET.o
|
Reference in New Issue
Block a user