Skip to main content

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 hook;
39pub mod inject;
40pub mod jit_abi;
41pub mod memory;
42pub mod mmu;
43pub mod optimize;
44pub mod stats;
45pub mod table;
46pub mod tlb;
47pub mod vm;
48
49pub use hook::{
50    AddressHook, BlockEntryHook, BlockView, CompareHook, Emitter, Hook, HookInjector, Site,
51    WriteWatch,
52};
53pub use inject::CodeInjector;
54pub use jit_abi::{
55    ACCESS_FAULT, ACCESS_OK, qcode_jit_load, qcode_jit_sdiv128, qcode_jit_srem128, qcode_jit_store,
56    qcode_jit_udiv128, qcode_jit_urem128,
57};
58pub use memory::VmMemory;
59pub use mmu::{
60    FaultKind, MemFault, Mmu, MmuSnapshot, PAGE_PERM_OFFSET, PAGE_SIZE, PageData, Perm, perm,
61};
62pub use optimize::{Cleanup, forward_temp_stores};
63pub use stats::Stats;
64pub use table::{HookAction, HookId, InsnAction, MemAccess, TABLE_CODES};
65pub use tlb::{TLB_ENTRIES, TLB_INDEX_BITS, TlbEntry, TranslationCache};
66pub use vm::{
67    BlockExecutor, CodeError, CodeSource, Executed, Interrupt, InterruptKind, ResumeError, Vm,
68    VmExit,
69};