diff --git a/src/context/context.rs b/src/context/context.rs
index be2e8189ec3c9ee1f476a5c4575e19ff95ee6b6f..854c4bdcd1e5a3219e989f0f28fddd5372297ed9 100644
--- a/src/context/context.rs
+++ b/src/context/context.rs
@@ -64,7 +64,7 @@ impl Status {
 
 #[derive(Clone, Debug)]
 pub enum HardBlockedReason {
-    AwaitingMmap { ctxt: Arc<FmapCtxt>, finished: Option<Frame> },
+    AwaitingMmap { ctxt: Arc<FmapCtxt> },
     // TODO: PageFaultOom?
     // TODO: NotYetStarted/ManuallyBlocked (when new contexts are created)
     // TODO: ptrace_stop?
@@ -294,6 +294,7 @@ pub struct Context {
     /// set since there is no interrupt stack (unless the kernel stack is copied, but that is in my
     /// opinion hackier and less efficient than this (and UB to do in Rust)).
     pub clone_entry: Option<[usize; 2]>,
+    pub fmap_ret: Option<Frame>,
 }
 
 impl Context {
@@ -336,6 +337,7 @@ impl Context {
             ptrace_stop: false,
             sigstack: None,
             clone_entry: None,
+            fmap_ret: None,
         };
         Ok(this)
     }
diff --git a/src/context/memory.rs b/src/context/memory.rs
index 0983a80f7e39e560aadea5b90aa475f259c34e01..898696387fb68acdecd50de84e7529507ab3ef5a 100644
--- a/src/context/memory.rs
+++ b/src/context/memory.rs
@@ -115,7 +115,8 @@ impl AddrSpace {
                     false,
                     fmap.as_ref().map(Arc::clone),
                 )?,
-                Provider::FmapBorrowed { ref fmap } => Grant::borrow_fmap(PageSpan::new(grant_base, grant_info.page_count), grant_info.flags(), Arc::clone(fmap)),
+                // TODO: "clone grant using fmap"
+                Provider::FmapBorrowed { .. } => continue,
             };
 
             new_guard.grants.insert(new_grant);
@@ -660,7 +661,18 @@ impl Grant {
         })
     }
 
-    pub fn borrow_fmap(span: PageSpan, flags: PageFlags<RmmA>, fmap: Arc<FmapCtxt>) -> Self {
+    pub fn borrow_fmap(span: PageSpan, flags: PageFlags<RmmA>, fmap: Arc<FmapCtxt>, src: Option<BorrowedFmapSource<'_>>, mapper: &mut PageMapper, mut flusher: impl Flusher<RmmA>) -> Self {
+        if let Some(mut src) = src {
+            for dst_page in span.pages() {
+                let src_page = src.src_page.next_by(dst_page.offset_from(span.base));
+
+                let (frame, _) = src.src_mapper.translate(src_page.start_address()).unwrap();
+                unsafe {
+                    flusher.consume(mapper.map_phys(dst_page.start_address(), frame, flags).unwrap());
+                }
+            }
+        }
+
         Self {
             base: span.base,
             info: GrantInfo {
@@ -1250,13 +1262,11 @@ pub fn try_correcting_page_tables(faulting_page: Page, access: AccessMode) -> Re
             user_inner.request_fmap(scheme_number, offset, 1, flags).unwrap();
 
             let context_lock = super::current().map_err(|_| PfError::NonfatalInternalError)?;
-            context_lock.write().hard_block(HardBlockedReason::AwaitingMmap { ctxt, finished: None });
+            context_lock.write().hard_block(HardBlockedReason::AwaitingMmap { ctxt });
 
             unsafe { super::switch(); }
 
-            let super::Status::HardBlocked { reason: HardBlockedReason::AwaitingMmap { finished: Some(frame), .. } } = core::mem::replace(&mut context_lock.write().status, super::Status::Runnable) else {
-                return Err(PfError::NonfatalInternalError);
-            };
+            let frame = context_lock.write().fmap_ret.take().ok_or(PfError::NonfatalInternalError)?;
 
             addr_space_guard = addr_space_lock.write();
             addr_space = &mut *addr_space_guard;
@@ -1286,3 +1296,8 @@ pub enum MmapMode {
     Cow,
     Shared,
 }
+
+pub struct BorrowedFmapSource<'a> {
+    pub src_page: Page,
+    pub src_mapper: &'a PageMapper,
+}
diff --git a/src/scheme/user.rs b/src/scheme/user.rs
index 9539d0552c4688f26be7b42037be709f4a6afd61..52bc5a6f33b16e6f20c98edd5f3ec1633fba58dc 100644
--- a/src/scheme/user.rs
+++ b/src/scheme/user.rs
@@ -1,6 +1,7 @@
 use alloc::sync::{Arc, Weak};
 use alloc::boxed::Box;
 use alloc::collections::BTreeMap;
+use rmm::PageFlushAll;
 use syscall::{SKMSG_FRETURNFD, CallerCtx, SKMSG_PROVIDE_MMAP};
 use core::num::NonZeroUsize;
 use core::sync::atomic::{AtomicBool, Ordering};
@@ -11,7 +12,7 @@ use spin::{Mutex, RwLock};
 use crate::context::context::HardBlockedReason;
 use crate::context::{self, Context, BorrowedHtBuf, Status};
 use crate::context::file::FileDescription;
-use crate::context::memory::{AddrSpace, DANGLING, Grant, GrantFileRef, PageSpan, MmapMode, page_flags, FmapCtxt};
+use crate::context::memory::{AddrSpace, DANGLING, Grant, GrantFileRef, PageSpan, MmapMode, page_flags, FmapCtxt, BorrowedFmapSource};
 use crate::event;
 use crate::memory::Frame;
 use crate::paging::{PAGE_SIZE, Page, VirtualAddress};
@@ -39,6 +40,7 @@ pub struct UserInner {
     fmap: Mutex<BTreeMap<u64, Weak<RwLock<Context>>>>,
     unmounting: AtomicBool,
 }
+#[derive(Debug)]
 pub enum Response {
     Regular(usize),
     Fd(Arc<RwLock<FileDescription>>),
@@ -346,6 +348,7 @@ impl UserInner {
         Ok(packets_read * mem::size_of::<Packet>())
     }
     pub fn request_fmap(&self, id: usize, offset: u64, required_page_count: usize, flags: MapFlags) -> Result<()> {
+        log::info!("REQUEST FMAP");
         self.todo.send(Packet {
             id: self.next_id(),
             pid: context::context_id().into(),
@@ -383,26 +386,27 @@ impl UserInner {
                     let offset = u64::from(packet.uid) | (u64::from(packet.gid) << 32);
 
                     if offset % PAGE_SIZE as u64 != 0 {
-                        return dbg!(Err(Error::new(EINVAL)));
+                        return Err(Error::new(EINVAL));
                     }
 
                     let base_addr = VirtualAddress::new(packet.c);
                     if base_addr.data() % PAGE_SIZE != 0 {
-                        return dbg!(Err(Error::new(EINVAL)));
+                        return Err(Error::new(EINVAL));
                     }
 
                     let page_count = packet.d;
 
-                    if page_count != 1 { return dbg!(Err(Error::new(EINVAL))); }
+                    if page_count != 1 { return Err(Error::new(EINVAL)); }
                     let context = self.fmap.lock().remove(&packet.id).ok_or(Error::new(EINVAL))?.upgrade().ok_or(Error::new(ESRCH))?;
 
                     let (frame, _) = AddrSpace::current()?.read().table.utable.translate(base_addr).ok_or(Error::new(EFAULT))?;
 
                     let mut context = context.write();
                     match context.status {
-                        Status::HardBlocked { reason: HardBlockedReason::AwaitingMmap { ref mut finished, .. } } => *finished = Some(Frame::containing_address(frame)),
+                        Status::HardBlocked { reason: HardBlockedReason::AwaitingMmap { .. } } => context.status = Status::Runnable,
                         _ => (),
                     }
+                    context.fmap_ret = Some(Frame::containing_address(frame));
 
                 }
                 _ => return Err(Error::new(EINVAL)),
@@ -433,7 +437,7 @@ impl UserInner {
         }
 
         if map.address % PAGE_SIZE != 0 {
-            return Err(Error::new(EINVAL))
+            return Err(Error::new(EINVAL));
         };
         let dst_base = (map.address != 0).then_some(Page::containing_address(VirtualAddress::new(map.address)));
 
@@ -447,6 +451,11 @@ impl UserInner {
             MmapMode::Cow
         };
 
+        let src_address_space = Arc::clone(
+            self.context.upgrade().ok_or(Error::new(ENODEV))?
+                .read().addr_space()?
+        );
+
         let (pid, desc) = {
             let context_lock = context::current()?;
             let context = context_lock.read();
@@ -481,8 +490,9 @@ impl UserInner {
             gid: (map.offset >> 32) as u32,
         })?;
 
-        let _ = match response {
-            Response::Regular(code) => Error::demux(code)?,
+        let base_page_opt = match response {
+            Response::Regular(code) => (!map.flags.contains(MapFlags::MAP_LAZY))
+                .then_some(Error::demux(code)?),
             Response::Fd(_) => {
                 log::debug!("Scheme incorrectly returned an fd for fmap.");
 
@@ -499,9 +509,17 @@ impl UserInner {
                         base_offset: map.offset,
                     },
                 });
+                let src_guard = src_address_space.read();
+                let src = match base_page_opt {
+                    Some(base_addr) => Some(BorrowedFmapSource {
+                        src_page: Page::containing_address(VirtualAddress::new(base_addr)),
+                        src_mapper: &src_guard.table.utable,
+                    }),
+                    None => None,
+                };
                 let page_count_nz = NonZeroUsize::new(page_count).expect("already validated map.size != 0");
-                dst_addr_space.write().mmap(dst_base, page_count_nz, map.flags, |dst_base, flags, _mapper, _flusher| {
-                    Ok(Grant::borrow_fmap(PageSpan::new(dst_base, page_count), page_flags(map.flags), ctxt))
+                dst_addr_space.write().mmap(dst_base, page_count_nz, map.flags, |dst_base, flags, mapper, flusher| {
+                    Ok(Grant::borrow_fmap(PageSpan::new(dst_base, page_count), page_flags(map.flags), ctxt, src, mapper, flusher))
                 })?
             }
         };
diff --git a/syscall b/syscall
index 6024e1e1fa0fdd9d31b1afbe034ebb0d84c1a98c..d587771fc36eabc07472ad6bb0f00b2d2a931711 160000
--- a/syscall
+++ b/syscall
@@ -1 +1 @@
-Subproject commit 6024e1e1fa0fdd9d31b1afbe034ebb0d84c1a98c
+Subproject commit d587771fc36eabc07472ad6bb0f00b2d2a931711