kmem_region/region/
mod.rs1#![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
23pub 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 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}