mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
make susres page ownership not hard coded; mark PTs as wired
also marks the ProcessImpl page as wired too
This commit is contained in:
parent
ad9ef3dedc
commit
f66debdd01
5 changed files with 60 additions and 9 deletions
|
|
@ -206,6 +206,15 @@ impl BootConfig {
|
|||
panic!("Tried to change region {:08x} that isn't in defined memory!", addr);
|
||||
}
|
||||
|
||||
#[cfg(feature = "swap")]
|
||||
pub fn mark_as_wired(&mut self, paddr: usize) {
|
||||
if paddr >= self.sram_start as usize && paddr < self.sram_start as usize + self.sram_size {
|
||||
self.runtime_page_tracker[(paddr - self.sram_start as usize) / PAGE_SIZE].set_wired();
|
||||
} else {
|
||||
panic!("Tried to wire address {:08x} that isn't in main RAM!", paddr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Map the given page to the specified process table. If necessary,
|
||||
/// allocate a new page.
|
||||
///
|
||||
|
|
@ -355,6 +364,8 @@ impl BootConfig {
|
|||
FLG_R | FLG_W | FLG_VALID,
|
||||
owner,
|
||||
);
|
||||
#[cfg(feature = "swap")]
|
||||
self.mark_as_wired(addr.get()); // page table entries should never be swapped.
|
||||
if VDBG {
|
||||
println!("<<< Done mapping new address");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@ fn copy_processes(cfg: &mut BootConfig) {
|
|||
// the section load address.
|
||||
last_copy_vaddr = dst_page_vaddr;
|
||||
|
||||
if SDBG {
|
||||
if SDBG && VVDBG {
|
||||
println!("Looping to the next section (swap)");
|
||||
println!(
|
||||
" swap_free_page: {:x}, dst_page_vaddr: {:x}, src_swap_img_addr: {:x}",
|
||||
|
|
|
|||
|
|
@ -271,10 +271,13 @@ pub fn phase_2(cfg: &mut BootConfig, fs_prehash: &[u8; 64]) {
|
|||
{
|
||||
let swap_size_usable = crate::swap::derive_usable_swap(swap_spec.swap_len as usize);
|
||||
let mut swap_count_start = 0;
|
||||
for offset in (0..(swap_size_usable / PAGE_SIZE) * core::mem::size_of::<u32>()).step_by(4096) {
|
||||
for offset in
|
||||
(0..(swap_size_usable / PAGE_SIZE) * core::mem::size_of::<u32>()).step_by(4096).rev()
|
||||
{
|
||||
let count_page = cfg.alloc() as usize; // this also zeroes the page
|
||||
// we want the start page to keep refreshing, because allocations grow *down*, so the
|
||||
// last iteration actually contains the base pointer of the count tracker
|
||||
// last iteration actually contains the base pointer of the count tracker (due to the .rev()
|
||||
// on the iterator)
|
||||
swap_count_start = count_page;
|
||||
cfg.map_page(
|
||||
root,
|
||||
|
|
@ -290,6 +293,7 @@ pub fn phase_2(cfg: &mut BootConfig, fs_prehash: &[u8; 64]) {
|
|||
let counts: &mut [u32] = unsafe {
|
||||
core::slice::from_raw_parts_mut(swap_count_start as *mut u32, swap_size_usable / PAGE_SIZE)
|
||||
};
|
||||
println!("Claiming 0x{:x} swap pages as used", cfg.last_swap_page);
|
||||
for i in 0..cfg.last_swap_page {
|
||||
counts[i] = loader::FLG_SWAP_USED;
|
||||
}
|
||||
|
|
@ -317,11 +321,32 @@ pub fn phase_2(cfg: &mut BootConfig, fs_prehash: &[u8; 64]) {
|
|||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
// Mark pages used by suspend/resume, otherwise they will be handed out to userspace.
|
||||
// However, when not doing suspend/resume, it's safe to hand this out because it's always zeroized
|
||||
// before use and never re-used on a resume cycle.
|
||||
#[cfg(feature = "resume")]
|
||||
{
|
||||
// Mark all of stack as owned by the kernel, because this region contains the backup arguments.
|
||||
// tampering in userspace of the loader stack prior to a resume can be a potent attack vector.
|
||||
let rtp_len = cfg.runtime_page_tracker.len();
|
||||
for page in cfg.runtime_page_tracker[1 + rtp_len - GUARD_MEMORY_BYTES / PAGE_SIZE..].iter_mut() {
|
||||
*page = XousAlloc::from(1);
|
||||
}
|
||||
// allow susres to claim the suspend/resume marker, assumed to be at the limit of the guard memory
|
||||
cfg.runtime_page_tracker[rtp_len - GUARD_MEMORY_BYTES / PAGE_SIZE] = XousAlloc::from(0);
|
||||
}
|
||||
|
||||
println!("Runtime Page Tracker: {} bytes", cfg.runtime_page_tracker.len());
|
||||
// mark pages used by suspend/resume according to their needs
|
||||
cfg.runtime_page_tracker[cfg.sram_size / PAGE_SIZE - 1] = XousAlloc::from(1); // claim the loader stack -- do not allow tampering, as it contains backup kernel args
|
||||
cfg.runtime_page_tracker[cfg.sram_size / PAGE_SIZE - 2] = XousAlloc::from(1); // 8k in total (to allow for digital signatures to be computed)
|
||||
cfg.runtime_page_tracker[cfg.sram_size / PAGE_SIZE - 3] = XousAlloc::from(0); // allow clean suspend page to be mapped in Xous
|
||||
#[cfg(feature = "swap")]
|
||||
if SDBG {
|
||||
println!("Occupied RPT entries:");
|
||||
for (i, entry) in cfg.runtime_page_tracker.iter().enumerate() {
|
||||
if entry.raw_vpn() != 0 {
|
||||
println!(" {:x}: {:x} [{}]", i, entry.raw_vpn(), entry.timestamp());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This describes the kernel as well as initially-loaded processes
|
||||
|
|
@ -402,6 +427,8 @@ impl ProgramDescription {
|
|||
FLG_R | FLG_W | FLG_VALID,
|
||||
pid as XousPid,
|
||||
);
|
||||
#[cfg(feature = "swap")]
|
||||
allocator.mark_as_wired(satp_address); // don't allow the root PT to be swapped in any process
|
||||
|
||||
// Allocate context for this process
|
||||
let thread_address = allocator.alloc() as usize;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ impl BootConfig {
|
|||
let mut num_alloc_pages = 0;
|
||||
for _ in 0..4 {
|
||||
let mut allocated_page_ptr = self.alloc();
|
||||
#[cfg(feature = "swap")]
|
||||
self.mark_as_wired(allocated_page_ptr);
|
||||
num_alloc_pages += 1;
|
||||
let is_aligned = allocated_page_ptr as usize & (ALIGNMENT_16K - 1) == 0;
|
||||
self.change_owner(pid, allocated_page_ptr as usize);
|
||||
|
|
@ -104,6 +106,8 @@ impl BootConfig {
|
|||
pid
|
||||
);
|
||||
allocated_page_ptr = self.alloc();
|
||||
#[cfg(feature = "swap")]
|
||||
self.mark_as_wired(allocated_page_ptr);
|
||||
self.change_owner(pid, allocated_page_ptr as usize);
|
||||
}
|
||||
|
||||
|
|
@ -207,6 +211,8 @@ impl BootConfig {
|
|||
dprintln!("Previously unmapped L1 entry");
|
||||
|
||||
let na = self.alloc();
|
||||
#[cfg(feature = "swap")]
|
||||
self.mark_as_wired(na);
|
||||
let phys = PhysicalAddress::from_ptr(na);
|
||||
let entry_flags =
|
||||
u32::from(PAGE_TABLE_FLAGS::VALID::Enable) | u32::from(PAGE_TABLE_FLAGS::DOMAIN.val(0xf));
|
||||
|
|
|
|||
|
|
@ -134,17 +134,24 @@ impl SwapAlloc {
|
|||
| if (pid == 1) || (pid == SWAPPER_PID) { SWAP_FLG_WIRED } else { 0 };
|
||||
}
|
||||
|
||||
/// Sets the wired bit. Used for marking page table elements as unswappable.
|
||||
pub fn set_wired(&mut self) { self.vpn |= SWAP_FLG_WIRED; }
|
||||
|
||||
/// This is a slight abuse of the naming system to provide us cross-compatibility with the case where the
|
||||
/// structure is defined as an overload of the `u8` type
|
||||
pub fn to_le(&self) -> u8 { self.vpn as u8 }
|
||||
|
||||
pub fn is_wired(&self) -> bool { self.vpn & SWAP_FLG_WIRED != 0 }
|
||||
pub fn is_wired(&self) -> bool { (self.vpn & SWAP_FLG_WIRED) != 0 }
|
||||
|
||||
pub fn is_valid(&self) -> bool { self.timestamp != 0 || self.vpn != 0 }
|
||||
pub fn is_valid(&self) -> bool { self.vpn != 0 }
|
||||
|
||||
pub fn raw_pid(&self) -> u8 { self.vpn as u8 }
|
||||
|
||||
pub fn vaddr(&self) -> usize { (self.vpn & !0xFFFu32) as usize }
|
||||
|
||||
pub fn raw_vpn(&self) -> u32 { self.vpn }
|
||||
|
||||
pub fn timestamp(&self) -> u32 { self.timestamp }
|
||||
}
|
||||
|
||||
impl fmt::Debug for SwapAlloc {
|
||||
|
|
|
|||
Loading…
Reference in a new issue