diff --git a/src/context/memory.rs b/src/context/memory.rs index fa14b57256..b7d4094fb5 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -1425,9 +1425,8 @@ impl Grant { } src_flusher_state = src_flusher.detach(); - if page_info.remove_ref().is_none() { - deallocate_frame(frame); - } + // TODO: there used to be an additional remove_ref here, was that + // correct? new_cow_frame }, @@ -2791,10 +2790,37 @@ pub struct NopFlusher; impl GenericFlusher for NopFlusher { fn queue( &mut self, - _frame: Frame, - _phys_contiguous_count: Option, - _actions: TlbShootdownActions, + frame: Frame, + phys_contiguous_count: Option, + actions: TlbShootdownActions, ) { + if actions.contains(TlbShootdownActions::FREE) { + handle_free_action(frame, phys_contiguous_count); + } + } +} +fn handle_free_action(base: Frame, phys_contiguous_count: Option) { + if let Some(count) = phys_contiguous_count { + for i in 0..count.get() { + let new_rc = get_page_info(base.next_by(i)) + .expect("phys_contiguous frames all need PageInfos") + .remove_ref(); + + assert_eq!(new_rc, None); + } + unsafe { + let order = count.get().next_power_of_two().trailing_zeros(); + deallocate_p2frame(base, order); + } + } else { + let Some(info) = get_page_info(base) else { + return; + }; + if info.remove_ref() == None { + unsafe { + deallocate_frame(base); + } + } } } struct FlusherState<'addrsp> { @@ -2848,7 +2874,7 @@ impl<'guard, 'addrsp> Flusher<'guard, 'addrsp> { pub fn flush(&mut self) { let pages = core::mem::take(&mut self.state.pagequeue); - if pages.is_empty() && core::mem::replace(&mut self.state.dirty, false) == true { + if pages.is_empty() && core::mem::replace(&mut self.state.dirty, false) == false { return; } @@ -2883,28 +2909,7 @@ impl<'guard, 'addrsp> Flusher<'guard, 'addrsp> { else { continue; }; - if let Some(count) = phys_contiguous_count { - for i in 0..count.get() { - let new_rc = get_page_info(base.next_by(i)) - .expect("phys_contiguous frames all need PageInfos") - .remove_ref(); - - assert_eq!(new_rc, None); - } - unsafe { - let order = count.get().next_power_of_two().trailing_zeros(); - deallocate_p2frame(base, order); - } - } else { - let Some(info) = get_page_info(base) else { - continue; - }; - if info.remove_ref() == None { - unsafe { - deallocate_frame(base); - } - } - } + handle_free_action(base, phys_contiguous_count); } } } diff --git a/src/debugger.rs b/src/debugger.rs index 71a2aac96a..b77df19c65 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -1,6 +1,8 @@ -use alloc::collections::BTreeSet; - -use crate::paging::{RmmA, RmmArch, TableKind, PAGE_SIZE}; +use crate::{ + context::Context, + paging::{RmmA, RmmArch, TableKind, PAGE_SIZE}, +}; +use spinning_top::RwSpinlock; //TODO: combine arches into one function (aarch64 one is newest) @@ -209,7 +211,10 @@ pub unsafe fn debugger(target_id: Option) { // Super unsafe due to page table switching and raw pointers! #[cfg(target_arch = "x86_64")] -pub unsafe fn debugger(target_id: Option) { +pub unsafe fn debugger(target_id: Option<*const RwSpinlock>) { + use core::sync::atomic::Ordering; + + use alloc::sync::Arc; use hashbrown::HashSet; use crate::memory::{get_page_info, the_zeroed_frame, RefCount}; @@ -230,12 +235,12 @@ pub unsafe fn debugger(target_id: Option) { let old_table = RmmA::table(TableKind::User); - for (id, context_lock) in crate::context::contexts().iter() { - if target_id.map_or(false, |target_id| *id != target_id) { + for context_lock in crate::context::contexts().iter() { + if target_id.map_or(false, |target_id| Arc::as_ptr(&context_lock.0) != target_id) { continue; } - let context = context_lock.read(); - println!("{}: {}", (*id).get(), context.name); + let context = context_lock.0.read(); + println!("{:p}: {}", Arc::as_ptr(&context_lock.0), context.name); if let Some(ref head) = context.syscall_head { tree.insert(head.get(), (1, false)); @@ -320,22 +325,26 @@ pub unsafe fn debugger(target_id: Option) { println!(); } + crate::scheme::proc::foreach_addrsp(|addrsp| { + let was_new = spaces.insert(addrsp.acquire_read().table.utable.table().phys().data()); + check_consistency(&mut *addrsp.acquire_write(), was_new, &mut tree); + }); for (frame, (count, p)) in tree { let Some(info) = get_page_info(frame) else { assert!(p); continue; }; let rc = info.refcount(); - let c = match rc { - None => 0, - Some(RefCount::One) => 1, - Some(RefCount::Cow(c)) => c.get(), - Some(RefCount::Shared(s)) => s.get(), + let (c, s) = match rc { + None => (0, false), + Some(RefCount::One) => (1, false), + Some(RefCount::Cow(c)) => (c.get(), false), + Some(RefCount::Shared(s)) => (s.get(), true), }; if c != count { println!( - "frame refcount mismatch for {:?} ({} != {})", - frame, c, count + "frame refcount mismatch for {:?} ({} != {} s {})", + frame, c, count, s ); } } diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 5ade776fbc..9b60060bff 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -235,6 +235,21 @@ static NEXT_ID: AtomicUsize = AtomicUsize::new(1); // Using BTreeMap as hashbrown doesn't have a const constructor. static HANDLES: RwLock> = RwLock::new(BTreeMap::new()); +#[cfg(feature = "debugger")] +#[allow(dead_code)] +pub fn foreach_addrsp(mut f: impl FnMut(&Arc)) { + for (_, handle) in HANDLES.read().iter() { + let Handle::Context { + kind: ContextHandle::AddrSpace { addrspace, .. }, + .. + } = handle + else { + continue; + }; + f(&addrspace); + } +} + fn new_handle((handle, fl): (Handle, InternalFlags)) -> Result<(usize, InternalFlags)> { let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); let _ = HANDLES.write().insert(id, handle);