Skip to main content

kmem_region/region/
mod.rs

1#![allow(unused)]
2
3use core::{fmt::Debug, ops::Deref};
4
5use crate::{PhysAddr, VirtAddr};
6
7include!(concat!(env!("OUT_DIR"), "/constant.rs"));
8
9const REGION_ONE: usize = (1 << ADDR_BITS) / 16;
10
11#[cfg(feature = "space-lo")]
12pub const OFFSET_LINER: usize = 0;
13#[cfg(not(feature = "space-lo"))]
14pub const OFFSET_LINER: usize = ADDR_BASE + REGION_ONE * 8;
15pub const STACK_TOP: usize = ADDR_BASE + REGION_ONE * 15 + REGION_ONE / 16 * 10;
16pub const PERCPU_TOP: usize = ADDR_BASE + REGION_ONE * 15 + REGION_ONE / 16 * 11;
17
18static mut KCODE_VA_OFFSET: usize = 0;
19
20pub const KERNEL_ADDR_SPACE_START: usize = ADDR_BASE;
21pub const KERNEL_ADDR_SPACE_SIZE: usize = (1 << ADDR_BITS) - 1;
22
23/// 设置内核代码的虚拟地址偏移量
24///
25/// # Safety
26///
27/// 确保 `offset` 是一个合法的虚拟地址偏移量
28pub unsafe fn set_kcode_va_offset(offset: usize) {
29    unsafe { KCODE_VA_OFFSET = offset };
30}
31
32pub fn kcode_offset() -> usize {
33    unsafe { KCODE_VA_OFFSET }
34}
35
36bitflags::bitflags! {
37    #[repr(transparent)]
38    #[derive(Clone, Copy, PartialEq, Eq)]
39    pub struct AccessFlags: u8 {
40        const Read = 1;
41        const Write = 1 << 2;
42        const Execute = 1 << 3;
43        const LowerRead = 1 << 4;
44        const LowerWrite = 1 << 5;
45        const LowerExecute = 1 << 6;
46    }
47}
48
49impl Debug for AccessFlags {
50    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51        write!(
52            f,
53            "{}{}{} |L: {}{}{}",
54            if self.contains(AccessFlags::Read) {
55                "R"
56            } else {
57                "-"
58            },
59            if self.contains(AccessFlags::Write) {
60                "W"
61            } else {
62                "-"
63            },
64            if self.contains(AccessFlags::Execute) {
65                "X"
66            } else {
67                "-"
68            },
69            if self.contains(AccessFlags::LowerRead) {
70                "R"
71            } else {
72                "-"
73            },
74            if self.contains(AccessFlags::LowerWrite) {
75                "W"
76            } else {
77                "-"
78            },
79            if self.contains(AccessFlags::LowerExecute) {
80                "X"
81            } else {
82                "-"
83            },
84        )
85    }
86}
87
88#[repr(u8)]
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub enum CacheConfig {
91    Normal,
92    Device,
93    /// 需要强制写入主存的场景(如 DMA 缓冲区)
94    WriteThrough,
95}
96
97#[repr(C)]
98#[derive(Clone, Copy)]
99pub struct MemConfig {
100    pub access: AccessFlags,
101    pub cache: CacheConfig,
102}
103
104impl Debug for MemConfig {
105    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
106        write!(f, "{:?} {:?}", self.access, self.cache)
107    }
108}
109
110#[repr(C)]
111#[derive(Clone)]
112pub struct MemRegion {
113    pub virt_start: VirtAddr,
114    pub size: usize,
115    pub phys_start: PhysAddr,
116    pub name: &'static str,
117    pub config: MemConfig,
118    pub kind: MemRegionKind,
119}
120
121#[repr(u8)]
122#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
123pub enum MemRegionKind {
124    Memory,
125    Reserved,
126    Code,
127    Stack,
128    PerCpu,
129    Device,
130}
131
132struct VirtFound {
133    ptr: VirtAddr,
134    kind: MemRegionKind,
135}
136
137pub fn region_phys_to_virt<D: Deref<Target = MemRegion>, I: Iterator<Item = D>>(
138    regions: I,
139    p: PhysAddr,
140) -> VirtAddr {
141    let mut found: Option<VirtFound> = None;
142    for region in regions {
143        if p >= region.phys_start && p < region.phys_start + region.size {
144            let ptr = region.virt_start + (p - region.phys_start);
145            if let Some(f) = &found
146                && region.kind < f.kind
147            {
148                continue;
149            }
150            found = Some(VirtFound {
151                ptr,
152                kind: region.kind,
153            });
154        }
155    }
156    if let Some(found) = found {
157        found.ptr
158    } else {
159        (p.raw() + OFFSET_LINER).into()
160    }
161}
162
163pub fn region_virt_to_phys<D: Deref<Target = MemRegion>, I: Iterator<Item = D>>(
164    regions: I,
165    v: VirtAddr,
166) -> PhysAddr {
167    for region in regions {
168        let end = region.virt_start + region.size;
169        if region.virt_start <= v && v < end {
170            return region.phys_start + (v - region.virt_start);
171        }
172    }
173    (v.raw() - OFFSET_LINER).into()
174}