1/*
2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <stdint.h>
10#include <sel4/sel4.h>
11
12#include <sel4vm/arch/guest_memory_arch.h>
13
14/***
15 * @module guest_memory.h
16 * The libsel4vm memory interface provides useful abstractions to manage your guest VM's address space.
17 * This interface can be leveraged for uses such as mapping device memory into your VM instance
18 * or for creating emulated device regions binded with custom handlers/callbacks.
19 * The main mechanisms this interface provides involves reserving memory regions and using those reservations
20 * to either map memory into your guest VM's address space or emulate subsequent accesses. Reservations
21 * are created through either using `vm_reserve_memory_at` or `vm_reserve_anon_memory`.
22 * The user can then further back the reservation with seL4 frames by performing `vm_map_reservation`.
23 */
24
25typedef struct vm vm_t;
26typedef struct vm_vcpu vm_vcpu_t;
27
28/***
29 * @struct vm_frame_t
30 * Structure representing a mappable memory frame
31 * @param {seL4_CPtr} cptr              Capability to frame
32 * @param {seL4_CapRights_t} rights     Mapping rights of frame
33 * @param {uintptr_t} vaddr             Virtual address of which to map the frame into
34 * @param {size_t} size_bits            Size of frame in bits
35 */
36typedef struct vm_frame {
37    seL4_CPtr cptr; /** Capability to frame */
38    seL4_CapRights_t rights; /** Mapping rights of frame */
39    uintptr_t vaddr; /** Virtual address of which to map the frame into */
40    size_t size_bits; /** Size of frame in bits */
41} vm_frame_t;
42
43/**
44 * Enumeration of results that can be returned by a memory fault callback (type 'memory_fault_callback_fn')
45 */
46typedef enum memory_fault_result {
47    FAULT_HANDLED, /** The memory fault was handled, advance execution */
48    FAULT_UNHANDLED, /** The memory fault was left unhandled */
49    FAULT_RESTART, /** The memory fault should be restarted, restart execution */
50    FAULT_IGNORE, /** Ignore the memory fault, advance execution */
51    FAULT_ERROR /** Handling the memory fault resulted in an error */
52} memory_fault_result_t;
53
54/**
55 * Type signature of memory fault handler/callback function, provided when creating a memory reservation
56 * @param {vm_t *} vm               A handle to the VM
57 * @param {vm_vcpu_t} vcpu          A handle to the fault vcpu
58 * @param {uintptr_t} fault addr    Faulting address
59 * @param {size_t} fault_length     Length of faulted access
60 * @param {void *} cookie           User cookie to pass onto callback
61 * @return                          Fault handling status code: HANDLED, UNHANDLED, RESTART, ERROR
62 */
63typedef memory_fault_result_t (*memory_fault_callback_fn)(vm_t *vm, vm_vcpu_t *vcpu, uintptr_t fault_addr,
64                                                          size_t fault_length,
65                                                          void *cookie);
66/**
67 * Type signature of memory map iterator function, provided when mapping a memory reservation
68 * @param {uintptr_t} addr      Address being mapped
69 * @param {void *} cookie       User cookie to pass onto iterator
70 * @return                      vm_frame_t describing the memory frame that corresponds with the given address
71 */
72typedef vm_frame_t (*memory_map_iterator_fn)(uintptr_t addr, void *cookie);
73
74typedef struct vm_memory_reservation vm_memory_reservation_t;
75typedef struct vm_memory_reservation_cookie vm_memory_reservation_cookie_t;
76
77/***
78 * @function vm_reserve_memory_at(vm, addr, size, fault_callback, cookie)
79 * Reserve a region of the VM's memory at a given base address
80 * @param {vm_t *} vm                                       A handle to the VM
81 * @param {uintptr} addr                                    Base address of the memory region being reserved
82 * @param {size_t} size                                     Size of the memory region being reserved
83 * @param {memory_fault_callback_fn} fault_callback         Callback function that will be invoked if memory region is faulted on
84 * @param {void *} cookie                                   User cookie to pass onto to callback
85 * @return                                                  NULL on failure otherwise a pointer to a reservation object representing the reserved region
86 */
87vm_memory_reservation_t *vm_reserve_memory_at(vm_t *vm, uintptr_t addr, size_t size,
88                                              memory_fault_callback_fn fault_callback, void *cookie);
89
90/***
91 * @function vm_reserve_anon_memory(vm, size, fault_callback, cookie, addr)
92 * Reserve an anonymous region of the VM's memory. This uses memory previously made anonymous
93 * through the `vm_memory_make_anon` function.
94 * @param {vm_t *} vm                                       A handle to the VM
95 * @param {size_t} size                                     Size of the anoymous emory region being reserved
96 * @param {memory_fault_callback_fn} fault_callback         Callback function that will be invoked if memory region is faulted on
97 * @param {void *} cookie                                   User cookie to pass onto to callback
98 * @param {uintptr_t *} addr                                Pointer that will be set with the base address of the reserved anonymous region
99 * @return                                                  NULL on failure otherwise a pointer to a reservation object representing the reserved region
100 */
101vm_memory_reservation_t *vm_reserve_anon_memory(vm_t *vm, size_t size,
102                                                memory_fault_callback_fn fault_callback, void *cookie, uintptr_t *addr);
103
104/*** vm_memory_make_anon(vm, addr, size)
105 * @function
106 * Create an anoymous region of the VM's memory. This claims a region of VM memory that can be used for the creation
107 * of anonymous reservations (achieved by calling 'vm_reserve_anon_memory').
108 * @param {vm_t *} vm               A handle to the VM
109 * @param {uintptr} addr            Base address of the memory region being made into an anoymous reservation
110 * @param {size_t} size             Size of the memory region being reserved
111 * @return                          -1 on failure otherwise 0 for success
112 */
113int vm_memory_make_anon(vm_t *vm, uintptr_t addr, size_t size);
114
115/***
116 * @function vm_free_reserved_memory(vm, reservation)
117 * Free memory reservation from the VM
118 * @param {vm_t *} vm                                   A handle to the VM
119 * @param {vm_memory_reservation_t *} reservation       Pointer to the reservation being free'd
120 * @return                                              -1 on failure otherwise 0 for success
121 */
122int vm_free_reserved_memory(vm_t *vm, vm_memory_reservation_t *reservation);
123
124/***
125 * @function vm_map_reservation(vm, reservation, map_iterator, cookie)
126 * Map a reservation into the VM's virtual address space
127 * @param {vm_t *} vm                                   A handle to the VM
128 * @param {vm_memory_reservation_t *} reservation       Pointer to reservation object being mapped
129 * @param {memory_map_iterator_fn} map_iterator         Iterator function that returns a cap to the memory region being mapped
130 * @param {void *} cookie                               Cookie to pass onto map_iterator function
131 * @return                                              -1 on failure otherwise 0 for success
132 */
133int vm_map_reservation(vm_t *vm, vm_memory_reservation_t *reservation, memory_map_iterator_fn map_iterator,
134                       void *cookie);
135
136/***
137 * @function vm_get_reservation_memory_region(reservation, addr, size)
138 * Get the memory region information (address & size) from a given reservation
139 * @param {vm_memory_reservation_t *} reservation           Pointer to reservation object
140 * @param {uintptr_t *} addr                                Pointer that will be set with the address of reservation
141 * @param {size_t *} size                                   Pointer that will be set with the size of reservation
142 */
143void vm_get_reservation_memory_region(vm_memory_reservation_t *reservation, uintptr_t *addr, size_t *size);
144
145/***
146 * @function vm_memory_init(vm)
147 * Initialise a VM's memory management interface
148 * @param {vm_t *} vm               A handle to the VM
149 * @return                          -1 on failure otherwise 0 for success
150*/
151int vm_memory_init(vm_t *vm);
152