Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ backtrace = []

# 运行时依赖项
[dependencies]
acpi = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/acpi-rs.git", rev = "fb69243dcf" }
acpi = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/acpi-rs.git", rev = "fb69243dcf" }
atomic_enum = "0.2.0"
bit_field = "0.10"
bitfield-struct = "0.5.3"
Expand All @@ -39,12 +39,12 @@ klog_types = { path = "crates/klog_types" }
linkme = "0.2"
num = { version = "0.4.0", default-features = false }
num-derive = "0.3"
num-traits = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }
num-traits = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }
raw-cpuid = "11.0.1"
smoltcp = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/smoltcp.git", rev = "9027825", default-features = false, features = ["log", "alloc", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "socket-dhcpv4", "socket-dns", "proto-ipv4", "proto-ipv6"]}
smoltcp = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/smoltcp.git", rev = "9027825", default-features = false, features = ["log", "alloc", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "socket-dhcpv4", "socket-dns", "proto-ipv4", "proto-ipv6"]}
system_error = { path = "crates/system_error" }
unified-init = { path = "crates/unified-init" }
virtio-drivers = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/virtio-drivers.git", rev = "f1d1cbb" }
virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers.git", rev = "f1d1cbb" }
fdt = "0.1.5"

# target为x86_64时,使用下面的依赖
Expand Down
7 changes: 6 additions & 1 deletion kernel/src/arch/riscv64/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub(super) mod init;

pub type PageMapper = crate::mm::page::PageMapper<RiscV64MMArch, LockedFrameAllocator>;

/// RiscV64的内存管理架构结构体
/// RiscV64的内存管理架构结构体(sv39)
#[derive(Debug, Clone, Copy, Hash)]
pub struct RiscV64MMArch;

Expand Down Expand Up @@ -53,6 +53,11 @@ impl MemoryManagementArch for RiscV64MMArch {

const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000);

/// 在距离sv39的顶端还有1G的位置,设置为FIXMAP的起始地址
const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000);
/// 设置1MB的fixmap空间
const FIXMAP_SIZE: usize = 256 * 4096;

unsafe fn init() {
todo!()
}
Expand Down
4 changes: 4 additions & 0 deletions kernel/src/arch/x86_64/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ impl MemoryManagementArch for X86_64MMArch {
const USER_BRK_START: VirtAddr = VirtAddr::new(0x700000000000);
const USER_STACK_START: VirtAddr = VirtAddr::new(0x6ffff0a00000);

const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffffb00000000000);
/// 设置FIXMAP区域大小为1M
const FIXMAP_SIZE: usize = 256 * 4096;

/// @brief 获取物理内存区域
unsafe fn init() {
extern "C" {
Expand Down
169 changes: 169 additions & 0 deletions kernel/src/mm/early_ioremap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
use system_error::SystemError;

use crate::{
arch::MMArch,
libs::{align::page_align_up, spinlock::SpinLock},
mm::no_init::{pseudo_map_phys, pseudo_unmap_phys},
};

use super::{allocator::page_frame::PageFrameCount, MemoryManagementArch, PhysAddr, VirtAddr};

static SLOTS: SpinLock<[Slot; EarlyIoRemap::SLOT_CNT]> =
SpinLock::new([Slot::DEFAULT; EarlyIoRemap::SLOT_CNT]);

/// 早期IO映射机制
///
/// 该机制在内存管理初始化之前,提供IO重映射的功能。
///
/// ## 注意
///
/// 该机制使用固定大小的slot来记录所有的映射,
/// 而这些映射空间是有限的,由MMArch::FIXMAP_SIZE指定
pub struct EarlyIoRemap;

impl EarlyIoRemap {
const SLOT_CNT: usize = MMArch::FIXMAP_SIZE / MMArch::PAGE_SIZE;

/// 把物理内存映射到虚拟内存中
///
/// ## 说明
///
/// 虚拟内存由early io remap机制自动分配。
///
/// ## 参数
///
/// - phys: 物理内存地址(需要按页对齐)
/// - size: 映射的内存大小
///
/// ## 返回值
///
/// - 成功: (虚拟内存地址, 映射的内存大小)
/// - Err(SystemError::ENOMEM): 可用的slot不足
/// - Err(SystemError::EINVAL): 传入的物理地址没有对齐
#[allow(dead_code)]
pub fn map(phys: PhysAddr, size: usize) -> Result<(VirtAddr, usize), SystemError> {
if phys.check_aligned(MMArch::PAGE_SIZE) == false {
return Err(SystemError::EINVAL);
}

let mut slot_guard = SLOTS.lock();

let slot_count = PageFrameCount::from_bytes(page_align_up(size))
.unwrap()
.data();
// 寻找连续的slot
let mut start_slot = None;
for i in 0..(Self::SLOT_CNT - slot_count + 1) {
let mut is_continuous = true;

for j in 0..slot_count {
let slot_idx = i + j;
if slot_guard[slot_idx].start_idx.is_some() {
is_continuous = false;
break;
}
}

if is_continuous {
start_slot = Some(i);
break;
}
}

let start_slot = start_slot.ok_or(SystemError::ENOMEM)?;
let vaddr = Self::idx_to_virt(start_slot);
// 执行映射
unsafe { pseudo_map_phys(vaddr, phys, PageFrameCount::new(slot_count)) }

// 更新slot信息
let map_size = slot_count * MMArch::PAGE_SIZE;
for i in 0..slot_count {
let slot_idx = start_slot + i;
slot_guard[slot_idx].start_idx = Some(start_slot as u32);

if i == 0 {
slot_guard[slot_idx].size = map_size as u32;
slot_guard[slot_idx].phys = phys;
}
}

return Ok((vaddr, map_size));
}

/// 取消映射
///
/// ## 参数
///
/// - virt: 映射范围内的任意虚拟地址
///
/// ## 返回值
///
/// - Ok: 成功
/// - Err(SystemError::EINVAL): 传入的虚拟地址不在early io remap范围内,
/// 或者虚拟地址未映射
#[allow(dead_code)]
pub fn unmap(virt: VirtAddr) -> Result<(), SystemError> {
if virt < MMArch::FIXMAP_START_VADDR || virt >= MMArch::FIXMAP_END_VADDR {
return Err(SystemError::EINVAL);
}

let mut slot_guard = SLOTS.lock();
let mut idx = None;

// 寻找虚拟地址对应的区域的第一个slot
for slot_idx in 0..Self::SLOT_CNT {
let slot = &mut slot_guard[slot_idx];
if let Some(start_idx) = slot.start_idx {
if start_idx == slot_idx as u32 {
let vaddr_start = Self::idx_to_virt(start_idx as usize);
let vaddr_end = vaddr_start + slot.size as usize;
if vaddr_start <= virt && virt < vaddr_end {
// 找到区域了
idx = Some(slot_idx);
break;
}
}
}
}

let idx = idx.ok_or(SystemError::EINVAL)?;

let vaddr = Self::idx_to_virt(idx as usize);
let count = PageFrameCount::from_bytes(slot_guard[idx].size as usize).unwrap();

// 取消映射

unsafe { pseudo_unmap_phys(vaddr, count) };

for i in 0..count.data() {
let slot_idx = idx + i;
let slot = &mut slot_guard[slot_idx];
*slot = Slot::DEFAULT;
}

todo!()
}

/// 把slot下标转换为这个slot对应的虚拟地址
fn idx_to_virt(idx: usize) -> VirtAddr {
MMArch::FIXMAP_START_VADDR + idx * MMArch::PAGE_SIZE
}
}

#[derive(Debug, Clone, Copy)]
struct Slot {
/// 连续映射的起始槽位号
start_idx: Option<u32>,
/// 连续映射的区域大小(仅在起始槽位中设置)
size: u32,
/// 映射的起始物理地址
phys: PhysAddr,
}

impl Slot {
const DEFAULT: Self = Self {
start_idx: None,
size: 0,
phys: PhysAddr::new(0),
};
}
13 changes: 11 additions & 2 deletions kernel/src/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use self::{

pub mod allocator;
pub mod c_adapter;
pub mod early_ioremap;
pub mod kernel_mapper;
pub mod memblock;
pub mod mmio_buddy;
Expand Down Expand Up @@ -92,7 +93,7 @@ impl PhysAddr {

/// @brief 获取物理地址的值
#[inline(always)]
pub fn data(&self) -> usize {
pub const fn data(&self) -> usize {
self.0
}

Expand Down Expand Up @@ -211,7 +212,7 @@ impl VirtAddr {

/// @brief 获取虚拟地址的值
#[inline(always)]
pub fn data(&self) -> usize {
pub const fn data(&self) -> usize {
return self.0;
}

Expand Down Expand Up @@ -429,6 +430,14 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
/// 用户栈起始地址(向下生长,不包含该值)
const USER_STACK_START: VirtAddr;

/// 内核的固定映射区的起始地址
const FIXMAP_START_VADDR: VirtAddr;
/// 内核的固定映射区的大小
const FIXMAP_SIZE: usize;
/// 内核的固定映射区的结束地址
const FIXMAP_END_VADDR: VirtAddr =
VirtAddr::new(Self::FIXMAP_START_VADDR.data() + Self::FIXMAP_SIZE);

/// @brief 用于初始化内存管理模块与架构相关的信息。
/// 该函数应调用其他模块的接口,把可用内存区域添加到memblock,提供给BumpAllocator使用
unsafe fn init();
Expand Down
29 changes: 29 additions & 0 deletions kernel/src/mm/no_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
/// 调用该函数时,必须保证内存管理器尚未初始化。否则将导致未定义的行为
///
/// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准)
#[inline(never)]
pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
assert!(paddr.check_aligned(MMArch::PAGE_SIZE));
Expand All @@ -160,3 +161,31 @@ pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrame

mapper.make_current();
}

/// Unmap physical memory from virtual memory.
///
/// ## 说明
///
/// 该函数在系统启动早期,内存管理尚未初始化的时候使用
#[inline(never)]
pub unsafe fn pseudo_unmap_phys(vaddr: VirtAddr, count: PageFrameCount) {
assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
assert!(count.data() == 1);

let mut pseudo_allocator = PseudoAllocator::<MMArch>::new();

let mut mapper = crate::mm::page::PageMapper::<MMArch, _>::new(
PageTableKind::Kernel,
MMArch::table(PageTableKind::Kernel),
&mut pseudo_allocator,
);

for i in 0..count.data() {
let vaddr = vaddr + i * MMArch::PAGE_SIZE;
mapper.unmap_phys(vaddr, true).map(|(_, _, flusher)| {
flusher.ignore();
});
}

mapper.make_current();
}