qcode_vm/lib.rs
1//! A virtual machine layer over the QCode interpreter.
2//!
3//! [`qcode_emulator`] interprets QCode over a *pre-lifted, immutable* module: it
4//! answers "what does this IR compute". This crate adds what a machine needs on
5//! top of that — mapped memory with permissions, faults delivered as values
6//! rather than aborts, code discovered on demand as the guest reaches it, and
7//! snapshots — so that a guest program can be run rather than merely evaluated.
8//!
9//! # Faults are values, not aborts
10//!
11//! A bad guest access is returned to the caller, so a harness can observe it
12//! and carry on rather than dying:
13//!
14//! ```
15//! use qcode_vm::{VmMemory, FaultKind, perm};
16//!
17//! let mut memory = VmMemory::new();
18//! // One read-only page of initialised memory.
19//! memory.mmu.map(0x1000, 0x1000, perm::MAP | perm::READ | perm::INIT).unwrap();
20//!
21//! let mut buffer = [0u8; 4];
22//! assert!(memory.mmu.read(0x1000, &mut buffer).is_ok());
23//!
24//! // Writing it faults, and says why and where.
25//! let fault = memory.mmu.write(0x1000, &[0xff]).unwrap_err();
26//! assert_eq!(fault.kind, FaultKind::WritePerm);
27//! assert_eq!(fault.addr, 0x1000);
28//!
29//! // So does touching an address that was never mapped.
30//! let fault = memory.mmu.read(0x9000, &mut buffer).unwrap_err();
31//! assert_eq!(fault.kind, FaultKind::ReadUnmapped);
32//! ```
33//!
34//! Execution strategy is pluggable through `set_block_executor`, which is how
35//! [`qcode_jit`](https://docs.rs/qcode_jit) is installed on a machine.
36
37pub mod flat;
38pub mod jit_abi;
39pub mod memory;
40pub mod mmu;
41pub mod optimize;
42pub mod stats;
43pub mod tlb;
44pub mod vm;
45
46pub use jit_abi::{
47 ACCESS_FAULT, ACCESS_OK, qcode_jit_load, qcode_jit_sdiv128, qcode_jit_srem128, qcode_jit_store,
48 qcode_jit_udiv128, qcode_jit_urem128,
49};
50pub use memory::VmMemory;
51pub use mmu::{
52 FaultKind, MemFault, Mmu, MmuSnapshot, PAGE_PERM_OFFSET, PAGE_SIZE, PageData, Perm, perm,
53};
54pub use optimize::{Cleanup, forward_temp_stores};
55pub use stats::Stats;
56pub use tlb::{TLB_ENTRIES, TLB_INDEX_BITS, TlbEntry, TranslationCache};
57pub use vm::{BlockExecutor, CodeError, CodeSource, Executed, Vm, VmExit};