strat9_kernel/memory/
zone.rs1use x86_64::PhysAddr;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[repr(u8)]
8pub enum ZoneType {
9 DMA = 0,
11 Normal = 1,
13 HighMem = 2,
15}
16
17impl ZoneType {
18 pub const COUNT: usize = 3;
20}
21
22pub const MAX_ORDER: usize = 11;
24
25#[derive(Debug, Clone, Copy)]
30pub struct BuddyBitmap {
31 pub data: *mut u8,
32 pub num_bits: usize,
33}
34
35impl BuddyBitmap {
36 pub const fn empty() -> Self {
38 Self {
39 data: core::ptr::null_mut(),
40 num_bits: 0,
41 }
42 }
43
44 #[inline]
46 pub fn is_empty(&self) -> bool {
47 self.data.is_null() || self.num_bits == 0
48 }
49
50 #[inline]
52 pub fn toggle(&self, idx: usize) -> bool {
53 debug_assert!(idx < self.num_bits);
54 let byte_idx = idx >> 3;
55 let mask = 1u8 << (idx & 7);
56 unsafe {
57 let byte = self.data.add(byte_idx);
58 let new_val = *byte ^ mask;
59 *byte = new_val;
60 (new_val & mask) != 0
61 }
62 }
63
64 #[inline]
66 pub fn test(&self, idx: usize) -> bool {
67 if idx >= self.num_bits || self.is_empty() {
68 return false;
69 }
70 let byte_idx = idx >> 3;
71 let mask = 1u8 << (idx & 7);
72 unsafe { (*self.data.add(byte_idx) & mask) != 0 }
73 }
74
75 #[inline]
77 pub fn set(&self, idx: usize) {
78 debug_assert!(idx < self.num_bits);
79 let byte_idx = idx >> 3;
80 let mask = 1u8 << (idx & 7);
81 unsafe {
82 *self.data.add(byte_idx) |= mask;
83 }
84 }
85
86 #[inline]
88 pub fn clear(&self, idx: usize) {
89 debug_assert!(idx < self.num_bits);
90 let byte_idx = idx >> 3;
91 let mask = 1u8 << (idx & 7);
92 unsafe {
93 *self.data.add(byte_idx) &= !mask;
94 }
95 }
96}
97
98pub struct Zone {
100 pub zone_type: ZoneType,
102
103 pub base: PhysAddr,
105
106 pub page_count: usize,
108
109 pub span_pages: usize,
113
114 pub allocated: usize,
116
117 pub free_lists: [u64; MAX_ORDER + 1],
120
121 pub buddy_bitmaps: [BuddyBitmap; MAX_ORDER + 1],
123
124 #[cfg(debug_assertions)]
126 pub alloc_bitmap: BuddyBitmap,
127}
128
129impl Zone {
130 pub const fn new(zone_type: ZoneType) -> Self {
132 Zone {
133 zone_type,
134 base: PhysAddr::new(0),
135 page_count: 0,
136 span_pages: 0,
137 allocated: 0,
138 free_lists: [0; MAX_ORDER + 1],
139 buddy_bitmaps: [BuddyBitmap::empty(); MAX_ORDER + 1],
140 #[cfg(debug_assertions)]
141 alloc_bitmap: BuddyBitmap::empty(),
142 }
143 }
144
145 pub fn contains_address(&self, addr: PhysAddr) -> bool {
147 let zone_start = self.base.as_u64();
148 let zone_end = zone_start + (self.span_pages as u64 * 4096);
149 let addr_val = addr.as_u64();
150 addr_val >= zone_start && addr_val < zone_end
151 }
152
153 pub fn available_pages(&self) -> usize {
155 self.page_count.saturating_sub(self.allocated)
156 }
157}
158
159unsafe impl Send for BuddyBitmap {}