swage_core/memory/
consec_blocks.rs

1use std::{collections::VecDeque, ops::Range};
2
3use crate::memory::{BytePointer, GetConsecPfns};
4
5use crate::memory::{Memory, PhysAddr, VictimMemory};
6
7/// Collection of consecutive physical memory blocks.
8///
9/// This struct manages multiple [`Memory`] blocks that may or may not be physically
10/// contiguous. It provides a unified interface for accessing memory across multiple
11/// allocations while tracking physical address ranges.
12#[derive(Clone, Debug)]
13pub struct ConsecBlocks {
14    /// Vector of memory blocks managed by this collection
15    pub blocks: Vec<Memory>,
16}
17
18impl ConsecBlocks {
19    /// Creates a new collection of consecutive memory blocks.
20    ///
21    /// # Arguments
22    ///
23    /// * `blocks` - Vector of memory blocks to manage
24    pub fn new(blocks: Vec<Memory>) -> Self {
25        ConsecBlocks { blocks }
26    }
27
28    /// Deallocates all memory blocks in this collection.
29    ///
30    /// Consumes self and frees all underlying memory allocations.
31    pub fn dealloc(self) {
32        for block in self.blocks {
33            block.dealloc();
34        }
35    }
36}
37
38impl VictimMemory for ConsecBlocks {}
39
40impl BytePointer for ConsecBlocks {
41    fn addr(&self, offset: usize) -> *mut u8 {
42        assert!(offset < self.len(), "Offset {} >= {}", offset, self.len());
43        let mut offset = offset;
44        for block in &self.blocks {
45            if offset < block.len {
46                return block.addr(offset);
47            }
48            offset -= block.len;
49        }
50        unreachable!("block not found for offset 0x{:x}", offset);
51    }
52
53    fn ptr(&self) -> *mut u8 {
54        self.blocks.first().unwrap().ptr()
55    }
56
57    fn len(&self) -> usize {
58        self.blocks.iter().map(|block| block.len).sum()
59    }
60}
61
62impl GetConsecPfns for ConsecBlocks {
63    fn consec_pfns(&self) -> Result<Vec<Range<PhysAddr>>, crate::memory::memblock::Error> {
64        let mut pfns = vec![];
65        for block in &self.blocks {
66            let mut block_pfns = VecDeque::from(block.consec_pfns()?);
67            let is_cons = pfns
68                .last()
69                .is_some_and(|last: &Range<PhysAddr>| last.start == block_pfns[0].end);
70            if is_cons {
71                let prev = pfns.pop();
72                let next = block_pfns.pop_front();
73                pfns.push(prev.unwrap().start..next.unwrap().end);
74            }
75            pfns.extend(block_pfns);
76        }
77        Ok(pfns)
78    }
79}