3 // These are the interfaces through which operations are performed on
4 // virtual and physical address spaces.
9 // There are two main kinds of mappable objects:
10 // 1. Objects that can be mapped directly into physical address space.
11 // This includes memory, device I/O, nested AddrSpaces, etc. Objects
12 // with this capability implement the Mappable interface.
13 // 2. Objects that are mapped by copying the content into RAM
14 // (disks, remote objects, dynamically generated data, etc.)
15 // These objects implement the Cacheable interface.
17 // Type #1 is simple; all it needs to do is translate mappable offsets
18 // into physical. Type #2 requires an intervening Cache to manage the
19 // backing RAM store. Memory-like type #1 objects should also implement
20 // Cacheable so that they can be used remotely.
22 // Address spaces may be stacked, such that (for example) a debugger maps
23 // an application which maps a file which maps a filesystem which maps a
24 // RAID volume which maps several physical disks; only the disks would be
25 // represented by Caches, everything else by AddrSpaces. Changes at any
26 // level immediately (well, before the operation finishes) propagate up
27 // to the page tables higher levels, and clone() will work at any level
28 // (and can make either the old or new address space the anonymous-
29 // memory-using "shadow" object). Stacked address spaces can also be
30 // used to implement access control.
32 struct Region inline {
33 // Both bounds are inclusive
37 struct RegionWithOffset inline : Region {
41 bitfield AccessFlags:3 {
42 // Allow reads to this page. On some platforms, this is assumed
43 // if writes are allowed, due to hardware limitations.
46 // Allow writes to this page.
49 // Allow execution of code from this page. On some platforms,
50 // this is assumed if reads are allowed, due to hardware
55 interface BlockObject {
56 guid: "4425AF91-52BE-11DA-BD60-000A95BB581A";
58 // Returns the current size in blocks of the object.
60 get_size(ulong size out);
62 // Returns the object's block size in bytes. Requests to map, read,
63 // write, etc. this object must be done with this granularity. The
64 // block size must be a power of two.
66 get_block_size(ulong block_size out);
69 // Finer grained mapping than the block size may be done via the virtual
70 // address space, but the AddrSpace will always request object->physical
71 // mappings that are a multiple of the block size.
73 interface Mappable : BlockObject {
74 guid: "B8E7A0DF-EAB6-11D9-BEFB-000A95BB581A";
78 interface Cacheable : BlockObject {
79 guid: "BB4C729D-EAB6-11D9-ADA2-000A95BB581A";
81 // Add the pages in the specified region to the specified cache.
82 // The start and end of the region will be aligned to the larger
83 // of the page size and the block size.
85 fill(Cache cache, Region region) async;
88 // This is the Mappable used to map a Cacheable object.
89 // Calling get_subspace on a Cache returns a pure Mappable; holders of
90 // such a reference alone can only map it, not add or remove pages or
91 // change its cacheable.
93 interface Cache : Mappable {
94 guid: "BD9A04F5-EAB6-11D9-A420-000A95BB581A";
96 // Get and set the object mapped through this Cache. Any other
97 // methods when obj is null (or never set) throw an InvalidState
98 // exception. Calling set_cacheable while this Cache has any
99 // current mappings throws an InvalidState exception.
101 set_cacheable(Cacheable obj);
102 get_cacheable(Cacheable obj out);
104 // Add one or more pages to the cache. Addr must be page-aligned, and
105 // the size of buf must be a multiple of the page size.
107 fill(ulong addr, octet[] buf push) async;
109 // Add one or more zero-filled pages to the cache. The region must
110 // start and end on a page boundary.
112 fill_zero(Region region) async;
114 // Remove one or more pages from the cache. The region must start and
115 // end on a page boundary. It is not an error to remove pages that are
118 remove(Region region);
120 // Wait until all of the pages in the region have been added to the
121 // cache. It is the caller's responsibility to ensure that the adding
122 // has been requested, and that blocking will not cause a deadlock.
123 // If there are multiple pages in the region, it is as if this method
124 // were called sequentially on each page; the kernel will not check
125 // whether previously checked pages have been removed while waiting
128 block_on_region(Region region);
130 // Like block_on_region, but returning a blocker suitable for use
131 // with Thread.block_multi.
133 region_blocker(Region region, Proc.Blocker blocker out);
136 bitfield AllocFlags {
137 Zero, // Zero out any freshly allocated memory.
139 Insecure, // It is not necessary to zero out the page after it
140 // is freed, unless the next allocator requests it.
142 Commit, // Commit the allocation to actual memory or
143 // swap, failing if this cannot be done.
145 Lock, // Only allocate actual memory, and lock it against
146 // swapping. Fails if not enough actual RAM is
147 // available (either in general or in the caller's
148 // locked RAM quota). If Lock is set, Commit is
151 NoZeroLocal, // Accept secure pages from the current address
152 // space without first zeroing. Ignored if Zero is
153 // specified. Overmap should be set to None when
154 // this is used, and every byte should be
155 // overwritten before data in any such pages is
156 // passed to another address space.
158 Paranoid, // Zero pages even when going to a NoZeroLocal allocator
159 // in the current address space. Use this for pages which
160 // are particularly likely to contain sensitive data.
164 Fixed, // Fail if the exact starting address is unavailable.
165 // Otherwise, if the supplied starting address
166 // unavailable, the address space manager allocates a
167 // free region and returns it in "start". If this
168 // behavior is explicitly desired (as it ususally is),
169 // "start" should contain all bits set, which is always
170 // invalid. For non-process (stacked) address spaces,
171 // this flag is treated as always set.
173 Replace, // Atomically replace any existing mapping with the new
174 // mapping, rather than fail. This flag is only
175 // meaningful if Fixed is set.
177 CopyOnWrite, // Share the mapped object only until it is written to;
178 // then, before the write takes place, copy the object.
179 // It is undefined whether this mapping will receive
180 // the copy or the original. Ignored for alloc_and_map.
182 AccessFlags access:3,
183 // These are the requested read/write/execute
184 // permissions on the mapping. A missing permission (or
185 // unmapped page) at any level in an address space stack
186 // will cause a MemoryFault, even if the page is mapped
187 // with the needed permissions at the top level. The
188 // map() call will not fail due to such a condition.
191 None, // Never map non-argument memory to a callee's address
194 ReadOnly, // Allow read-only mappings of non-argument data within
195 // the same page as an argument into the callee's
198 ReadWrite // Allow all mappings of non-argument data within the
199 // same page as an argument into the callee's address
204 interface AddrSpace {
205 guid: "BF9D2070-EAB6-11D9-A2D2-000A95BB581A";
207 const ulong unspecified_start = 0xffffffffffffffff;
209 // Return the mappable associated with this address space, which can
210 // be used to allow another address space to stack with this one.
211 // The mappable handle only allows pages to be mapped; it does not
212 // allow any changes to the mappings, nor can a handle to the AddrSpace
213 // be obtained from it. This method must always return the same
214 // Mappable object when called on the same AddrSpace.
216 get_mappable(Mappable ma out);
218 // Create a new AddrSpace that is a copy-on-write clone of this AddrSpace.
219 // This method is used to implement fork() and in-memory file versioning,
220 // and could also be used to assist garbage collection and other purposes.
222 // By default, the old address space continues to be backed by
223 // whatever Mappables were in use, and pages in the new address space
224 // are backed by anonymous memory when a page in either is written to.
225 // If old_space_is_anon is true, though, this is reversed, which is useful
226 // when versioning a file to make the new version the one that gets
229 clone(AddrSpace addrspace out, bool clone_is_real);
231 // Create an anonymous RAM mapping.
233 alloc_and_map(ulong len, ulong vstart inout,
234 AllocFlags aflags, MapFlags mflags);
236 // Mappable must be implemented by the local kernel, and must hold
237 // read/write/exec permissions appropriate for the MapFlags given.
239 map(Mappable ma, Region region, ulong vstart inout, MapFlags flags);
240 unmap(Region region);
242 // Set the flags on all pages in the region. CopyOnWrite can be
243 // set, but not cleared, using this method. Fixed is ignored.
245 set_mapflags(Region region, MapFlags flags);
247 // Returns the flags on the given region, if all pages have the
248 // same flags (except for CopyOnWrite, which is not returned by
249 // this method, as it can be asynchronously cleared).
251 get_mapflags(Region region, MapFlags flags out, bool all_same out);
253 // Returns the Mappable that covers the specified range, and the offset
254 // into the Mappable that corresponds to the first page in the region.
255 // If any pages within the range are not mapped, or if more than one
256 // Mappable is mapped within the region, or if the offsets into the
257 // Mappable are not contiguous, then NULL is returned in ma.
259 // This is used to implement mremap().
261 get_mapping(Region region, Mappable ma out, ulong offset out);
263 // Returns the minimum page size (and thus mapping size/alignment)
264 // supported in this address space. An attempt to create a mapping
265 // that violates this will result in an InvalidArgument exception.
267 get_page_size(uint page_size out);
269 // Returns the minimum alignment supported for mapping requests;
270 // (vstart % min_align) must equal (region.start % min_align). This
271 // is at least the minimum page size, but may be more on certain
272 // hardware, such as virtually-indexed-physically-tagged caches, where
273 // larger alignment is needed to ensure the absence of cache aliases.
274 // An attempt to create a mapping that violates this will result in an
275 // InvalidArgument exception.
277 get_min_align(uint min_align out);
280 interface AllocHandle {
281 guid: "CB029266-EAB6-11D9-BCA0-000A95BB581A";
283 get_regions(Region[] regions out);
285 // Free a portion of an allocation. To free all of an allocation,
286 // simply release all references to the handle. Each region shall
287 // start and end on block size boundaries. Throws OperationNotSupported
288 // if the allocator does not support partial frees.
290 free(Region[] regions);
293 interface Allocator {
294 guid: "CCF5D83C-EAB6-11D9-8BB7-000A95BB581A";
296 const ulong unspecified_start = 0xffffffffffffffff;
298 bitfield AllocFlags {
299 // If set, fail if the exact starting address is unavailable (or if
300 // the allocator does not support caller-supplied starting
303 // Otherwise, if the supplied starting address unavailable, the
304 // allocator allocates a free region and returns it in "start". If
305 // this behavior is explicitly desired (as it ususally is), "start"
306 // should be set to unspecified_start, which is always invalid.
307 // Using unspecified_start may be faster than specifying other
308 // invalid addresses (as the allocator can check for this value
309 // rather than checking address availability), and zero should not
310 // be used for this purpose as it may be a valid address.
315 alloc(ulong start inout, ulong len, AllocFlags flags,
316 AllocHandle handle out);
319 interface GenericAllocator : Allocator {
320 guid: "D033DD3A-EAB6-11D9-96E4-000A95BB581A";
322 // Set the minimal block size used by the allocator.
323 // This can only be done before any alloc() or
324 // add_regions() calls; an InvalidState exception may
325 // be thrown otherwise.
327 set_block_size(ulong block_size);
329 // Make one or more regions available for allocations.
330 // The regions may not overlap each other or any existing
331 // regions (whether or not allocated). Regions may not
332 // be removed once added using this interface; allocators
333 // may optionally provide a mechanism for doing so.
335 add_regions(Region[] regions);