summaryrefslogtreecommitdiffstats
path: root/rsnix/src/memory.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rsnix/src/memory.rs')
-rw-r--r--rsnix/src/memory.rs44
1 files changed, 44 insertions, 0 deletions
diff --git a/rsnix/src/memory.rs b/rsnix/src/memory.rs
index 099f607..2a32da8 100644
--- a/rsnix/src/memory.rs
+++ b/rsnix/src/memory.rs
@@ -1194,6 +1194,50 @@ pub fn alloc_pages(count: usize) -> Option<usize> {
1194 alloc_pages_aligned(count, 1) 1194 alloc_pages_aligned(count, 1)
1195} 1195}
1196 1196
1197/// Allocate `count` contiguous physical pages at or above `min_addr`
1198/// (first-fit upward from there). Used for controller DMA buffers that
1199/// must avoid low conventional memory — the first 640 K on some real
1200/// chipsets is hostile to PCI masters and shows up as a controller
1201/// "System Error" (SE) halt. Page-aligned like `alloc_pages`.
1202pub fn alloc_pages_above(count: usize, min_addr: usize) -> Option<usize> {
1203 if count == 0 {
1204 return None;
1205 }
1206 unsafe {
1207 if BITMAP.is_null() {
1208 return None;
1209 }
1210 let span = SPAN_PAGES;
1211 let min_page = min_addr.div_ceil(PAGE_SIZE).max(BASE_PAGE);
1212 if min_page >= BASE_PAGE + span {
1213 return None;
1214 }
1215 let start_idx = min_page - BASE_PAGE;
1216 let mut run_start = 0usize;
1217 let mut run_len = 0usize;
1218 for idx in start_idx..span {
1219 let free = (*BITMAP.add(idx / 8) >> (idx % 8)) & 1 == 0;
1220 if free {
1221 if run_len == 0 {
1222 run_start = idx;
1223 }
1224 run_len += 1;
1225 if run_len >= count {
1226 let p = (BASE_PAGE + run_start) * PAGE_SIZE;
1227 for k in run_start..run_start + count {
1228 *BITMAP.add(k / 8) |= 1 << (k % 8);
1229 }
1230 FREE_PAGES -= count;
1231 return Some(p);
1232 }
1233 } else {
1234 run_len = 0;
1235 }
1236 }
1237 None
1238 }
1239}
1240
1197/// Allocate `count` contiguous physical pages whose start address is 1241/// Allocate `count` contiguous physical pages whose start address is
1198/// aligned to `align_pages` (a power of two, in page units). 1242/// aligned to `align_pages` (a power of two, in page units).
1199pub fn alloc_pages_aligned(count: usize, align_pages: usize) -> Option<usize> { 1243pub fn alloc_pages_aligned(count: usize, align_pages: usize) -> Option<usize> {