Skip to content

Commit bf8ddbe

Browse files
committed
Add a ptr to the interrupt page to the VMStoreContext.
1 parent bcdba44 commit bf8ddbe

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

crates/wasmtime/src/runtime/vm/vmcontext.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use core::mem::{self, MaybeUninit};
1616
use core::ops::Range;
1717
use core::ptr::{self, NonNull};
1818
use core::sync::atomic::{AtomicUsize, Ordering};
19+
use rustix::mm::{MapFlags, ProtFlags, mmap_anonymous, munmap};
20+
use rustix::param::page_size;
1921
use wasmtime_environ::{
2022
BuiltinFunctionIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
2123
DefinedTagIndex, VMCONTEXT_MAGIC, VMSharedTypeIndex, WasmHeapTopType, WasmValType,
@@ -1093,6 +1095,13 @@ pub struct VMStoreContext {
10931095
/// yield if running asynchronously.
10941096
pub epoch_deadline: UnsafeCell<u64>,
10951097

1098+
/// The page of virtual memory used to signal that it's time to switch
1099+
/// tasks. Compiled guest code regularly attempts a read at this address.
1100+
/// When it is time to switch, the host uses mprotect() to forbid reads. The
1101+
/// fault soon caused by guest code then lands in the signal handler, which
1102+
/// effects a switch and resets the page permissions.
1103+
pub epoch_interrupt_page_ptr: Option<VmPtr<c_void>>, // ptr-sized
1104+
10961105
/// Current stack limit of the wasm module.
10971106
///
10981107
/// For more information see `crates/cranelift/src/lib.rs`.
@@ -1175,6 +1184,23 @@ impl Default for VMStoreContext {
11751184
VMStoreContext {
11761185
fuel_consumed: UnsafeCell::new(0),
11771186
epoch_deadline: UnsafeCell::new(0),
1187+
// TODO: Allocate this only when epoch_interruption_via_mmu is on.
1188+
// Probably set it to None here and allocate it elsewhere.
1189+
epoch_interrupt_page_ptr: unsafe {
1190+
let page_ptr = mmap_anonymous(
1191+
ptr::null_mut(), // Let the kernel pick location.
1192+
page_size(),
1193+
ProtFlags::READ,
1194+
// Privacy doesn't matter, as we never write to the
1195+
// interrupt page. However, private is the safer choice in
1196+
// case someone starts doing so.
1197+
MapFlags::PRIVATE,
1198+
)
1199+
.expect("an interrupt page should be allocable");
1200+
let non_null_page_ptr = NonNull::new(page_ptr)
1201+
.expect("if mmap returns successfully, its result should not be null");
1202+
Some(non_null_page_ptr.into())
1203+
},
11781204
stack_limit: UnsafeCell::new(usize::max_value()),
11791205
gc_heap: VMMemoryDefinition {
11801206
base: NonNull::dangling().into(),
@@ -1189,6 +1215,17 @@ impl Default for VMStoreContext {
11891215
}
11901216
}
11911217

1218+
// TODO: Kill this and find somewhere else to munmap it, because VMStoreContext
1219+
// is documented as being pod-type above.
1220+
// impl Drop for VMStoreContext {
1221+
// fn drop(&mut self) {
1222+
// unsafe {
1223+
// munmap(self.epoch_interrupt_page_ptr, page_size())
1224+
// .expect("should be able to unmap interrupt page");
1225+
// }
1226+
// }
1227+
// }
1228+
11921229
#[cfg(test)]
11931230
mod test_vmstore_context {
11941231
use super::{VMMemoryDefinition, VMStoreContext};

0 commit comments

Comments
 (0)