Solo5 hvt ABI and MFT1/ABI1 note format as wire codecs
0

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-solo5 / lib / tender / machine.mli
6.0 kB 135 lines
1(** The hypervisor boundary a tender backend supplies. 2 3 The aarch64 hvt tender core ({!Cpu}, {!Tender}) is a functor over this 4 signature: it sets up the boot block, page tables and CPU state and drives 5 the guest, while a backend (solo5-hvf on Hypervisor.framework, solo5-kvm on 6 Linux [/dev/kvm]) provides the single VM, its registers, and the run/exit 7 boundary. The register selectors and the {!exit} are normalised here so the 8 core is identical across backends -- a backend that decodes an exception 9 syndrome (HVF) and one whose hypervisor hands back the MMIO access already 10 decoded (KVM) both present the same {!Mmio}. *) 11 12type reg = X of int (** [x0]-[x30] *) | Pc | Cpsr (** A core register. *) 13 14type sysreg = 15 | Sctlr_el1 16 | Mair_el1 17 | Tcr_el1 18 | Ttbr0_el1 19 | Cpacr_el1 20 | Sp_el1 (** A system register. *) 21 22type exit = 23 | Mmio 24 (** A guest MMIO access. Its details are read after the fact through the 25 allocation-free accessors [mmio_addr] and [mmio_write], so an exit 26 carries no payload and the boundary allocates nothing per exit. *) 27 | Vtimer (** The virtual timer fired. *) 28 | Canceled (** The run was interrupted (a delivered signal). *) 29 | Fatal 30 (** An exit the core cannot service (an unexpected exception or a 31 hypervisor entry failure); the diagnostic is read with 32 [fatal_message]. *) 33 34exception Backend_error of string 35(** Raised when a backend's hypervisor call fails; the message names the call 36 and the failure. *) 37 38val reg_code : reg -> int 39(** [reg_code r] is the small integer a backend's C stub maps to its native core 40 register. *) 41 42val sysreg_code : sysreg -> int 43(** [sysreg_code r] is the small integer a backend's C stub maps to its native 44 system register. *) 45 46(** A tender backend: the single VM and vCPU, its registers, and the run/exit 47 boundary the {!Cpu} and {!Tender} functors drive. *) 48module type S = sig 49 val init : bytes:int -> Guest.t 50 (** [init ~bytes] creates the VM and vCPU and maps [bytes] of guest RAM at 51 guest-physical address 0, returning a view of it. Raises {!Backend_error} 52 on failure. *) 53 54 val set_reg : reg -> int64 -> unit 55 (** [set_reg r v] sets core register [r] to [v]. *) 56 57 val reg : reg -> int64 58 (** [reg r] reads core register [r]. *) 59 60 val set_sysreg : sysreg -> int64 -> unit 61 (** [set_sysreg r v] sets system register [r] to [v]. *) 62 63 val sysreg : sysreg -> int64 64 (** [sysreg r] reads system register [r]. *) 65 66 val counter_frequency : unit -> int64 67 (** [counter_frequency ()] is the host counter frequency (CNTFRQ_EL0) in Hz. 68 *) 69 70 val run : unit -> exit 71 (** [run ()] enters the guest and returns at the next VM exit, normalised to 72 an {!exit}. The exit is a constant constructor, and the MMIO details are 73 read through {!mmio_addr} / {!mmio_write} and a fatal diagnostic through 74 {!fatal_message}, so the run boundary allocates nothing per exit. *) 75 76 val mmio_addr : unit -> int 77 (** [mmio_addr ()] is the guest-physical address of the access {!run} last 78 reported as {!Mmio}. *) 79 80 val mmio_write : unit -> int 81 (** [mmio_write ()] is the value of the {!Mmio} access {!run} last reported: a 82 32-bit store value, or [-1] for a load (whose result {!complete} 83 supplies). *) 84 85 val fatal_message : unit -> string 86 (** [fatal_message ()] is the diagnostic for the exit {!run} last reported as 87 {!Fatal}. *) 88 89 val complete : read:int -> unit 90 (** [complete ~read] finishes servicing the current {!Mmio} and prepares the 91 vCPU to resume: for a load, [read] is the value the load reads back; for a 92 store (or any access with no value to return) it is [-1]. *) 93 94 val mask_vtimer : bool -> unit 95 (** [mask_vtimer m] masks ([true]) or unmasks the virtual timer. *) 96 97 val watchdog : float -> unit 98 (** [watchdog secs] arms the runaway-guest watchdog: from then on, every 99 {!run} entry must exit within [secs] seconds, or the backend cancels the 100 vCPU run and {!watchdog_fired} becomes true. The budget covers time spent 101 inside the guest only -- host-side time servicing an exit (a hypercall, a 102 POLL wait) does not count -- so a guest legitimately blocked in a long 103 POLL is never killed; only one that spins or fault-loops at EL1 without 104 ever exiting is. [secs <= 0] is a no-op. Call before {!sandbox}: the 105 backend spawns its watchdog thread here, which the sandbox would deny 106 later. Expiry detection is polled, so a cancel can lag [secs] by a 107 fraction of it. *) 108 109 val watchdog_fired : unit -> bool 110 (** [watchdog_fired ()] is [true] once the watchdog canceled a run; the 111 {!Canceled} exit the tender core then sees is the guest's death notice 112 rather than an operator interrupt. *) 113 114 val sandbox : unit -> unit 115 (** [sandbox ()] narrows the tender process once the VM and devices are set 116 up: it denies opening new files, spawning processes, and the network, 117 while leaving descriptors opened before this call usable. The tender needs 118 no host network of its own -- a slirp gateway, when used, runs in a 119 separate process and the tender only reads and writes its end of the 120 socketpair. Fails closed, raising on error. *) 121 122 val poll_add : Unix.file_descr -> unit 123 (** [poll_add fd] registers [fd] to be watched for readability by 124 {!poll_wait}. Call it before {!sandbox}: on Linux it does the epoll 125 registration (epoll_ctl), which the sandbox allowlist does not permit at 126 runtime. *) 127 128 val poll_wait : float -> bool 129 (** [poll_wait timeout] blocks up to [timeout] seconds and returns whether a 130 descriptor registered with {!poll_add} is readable; with none registered 131 it is a bounded sleep returning [false]. It is the POLL hypercall's wait, 132 using only allowlisted syscalls -- [epoll_pwait] on Linux (as upstream 133 Solo5's [hvt_core.c] does), [select] on macOS, where the Seatbelt sandbox 134 does not filter syscalls. *) 135end