]> git.buserror.net Git - polintos/scott/priv.git/blob - idl/addrspace.idl
Add first draft of marshalling spec
[polintos/scott/priv.git] / idl / addrspace.idl
1 // AddrSpace
2 //
3 // These are the interfaces through which operations are performed on
4 // virtual and physical address spaces.
5 //
6  
7 namespace Mem;
8
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.
16 //  
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.
21 //
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.
31
32 struct Region inline {
33         // Both bounds are inclusive
34         ulong start, end;
35 };
36
37 struct RegionWithOffset inline : Region {
38         ulong offset;
39 };
40
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.
44         Read,
45                 
46         // Allow writes to this page.
47         Write,
48         
49         // Allow execution of code from this page.  On some platforms,
50         // this is assumed if reads are allowed, due to hardware
51         // limitations.
52         Exec
53 };
54
55 interface BlockObject {
56         guid: "4425AF91-52BE-11DA-BD60-000A95BB581A";
57
58         // Returns the current size in blocks of the object.
59
60         get_size(ulong size out);
61         
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.
65         
66         get_block_size(ulong block_size out);
67 };
68    
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.
72
73 interface Mappable : BlockObject {
74         guid: "B8E7A0DF-EAB6-11D9-BEFB-000A95BB581A";
75         
76 };
77
78 interface Cacheable : BlockObject {
79         guid: "BB4C729D-EAB6-11D9-ADA2-000A95BB581A";
80
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.
84
85         fill(Cache cache, Region region) async;
86 };
87
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.
92
93 interface Cache : Mappable {
94         guid: "BD9A04F5-EAB6-11D9-A420-000A95BB581A";
95
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.
100
101         set_cacheable(Cacheable obj);
102         get_cacheable(Cacheable obj out);
103         
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.
106         
107         fill(ulong addr, octet[] buf push) async;
108         
109         // Add one or more zero-filled pages to the cache.  The region must
110         // start and end on a page boundary.
111         
112         fill_zero(Region region) async;
113         
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
116         // not in the cache.
117         
118         remove(Region region);
119         
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
126         // for later pages.
127         
128         block_on_region(Region region);
129         
130         // Like block_on_region, but returning a blocker suitable for use
131         // with Thread.block_multi.
132         
133         region_blocker(Region region, Proc.Blocker blocker out);
134 };
135
136 bitfield AllocFlags {
137         Zero,          // Zero out any freshly allocated memory.
138
139         Insecure,      // It is not necessary to zero out the page after it
140                        // is freed, unless the next allocator requests it.
141
142         Commit,        // Commit the allocation to actual memory or
143                        // swap, failing if this cannot be done.
144
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
149                        // ignored.
150         
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.
157
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.
161 };
162
163 bitfield MapFlags {
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.
172         
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.
176
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.
181
182         Snapshot,      // The mapped object will also be made CopyOnWrite, so
183                        // that any writes to the mapped page via any mapping
184                        // will cause a fault.  Thus, after the snapshot, the
185                        // only changes that will be visible will be through
186                        // the new mapping.  This is ideal for things like fork()
187                        // and file versioning, and is used by AddrSpace.clone().
188                        //
189                        // If not set, then only the new mapping will be
190                        // CopyOnWrite, so if another mapping updates the page
191                        // before a write occurs through this mapping (thus
192                        // breaking CopyOnWrite), the change will be visible in
193                        // the new mapping.  This is ideal for private
194                        // mappings, where all that is desired is that the new
195                        // mapping cannot change the underlying object (while
196                        // keeping the mapping writeable).
197                        //
198                        // Ignored if CopyOnWrite is not set.
199
200         AccessFlags access:3,
201                        // These are the requested read/write/execute
202                        // permissions on the mapping.  A missing permission (or
203                        // unmapped page) at any level in an address space stack
204                        // will cause a MemoryFault, even if the page is mapped
205                        // with the needed permissions at the top level.  The
206                        // map() call will not fail due to such a condition.
207
208         enum OverMap:2 {
209                 None,       // Never map non-argument memory to a callee's address
210                             // space.
211
212                 ReadOnly,   // Allow read-only mappings of non-argument data within
213                             // the same page as an argument into the callee's
214                             // address space.
215
216                 ReadWrite   // Allow all mappings of non-argument data within the
217                             // same page as an argument into the callee's address
218                             // space.
219         } overmap
220 };
221
222 interface AddrSpace {
223         guid: "BF9D2070-EAB6-11D9-A2D2-000A95BB581A";
224
225         const ulong unspecified_start = 0xffffffffffffffff;
226         
227         // Return the mappable associated with this address space, which can
228         // be used to allow another address space to stack with this one.
229         // The mappable handle only allows pages to be mapped; it does not
230         // allow any changes to the mappings, nor can a handle to the AddrSpace
231         // be obtained from it.  This method must always return the same
232         // Mappable object when called on the same AddrSpace.
233         
234         get_mappable(Mappable ma out);
235         
236         // Create a new AddrSpace that is a copy-on-write clone of this AddrSpace.
237         // This method is used to implement fork() and in-memory file versioning,
238         // and could also be used to assist garbage collection and other purposes.
239         //
240         // By default, the old address space continues to be backed by
241         // whatever Mappables were in use, and pages in the new address space
242         // are backed by anonymous memory when a page in either is written to. 
243         // If flags.Reverse is true, though, this is reversed, which is useful
244         // when versioning a file to make the new version the one that gets
245         // stored to disk.
246         //
247         // The upstream address space is also marked as copy-on
248
249         clone(AddrSpace addrspace out, CloneFlags flags);
250         
251         bitfield CloneFlags {
252                 Reverse
253         };
254         
255         // Mappable must be implemented by the local kernel, and must hold
256         // read/write/exec permissions appropriate for the MapFlags given.
257         
258         map(Mappable ma, Region region, ulong vstart inout, MapFlags flags);
259         unmap(Region region);
260
261         // Set the flags on all pages in the region.  CopyOnWrite can be
262         // set, but not cleared, using this method.  Fixed is ignored.
263
264         set_mapflags(Region region, MapFlags flags);
265         
266         // Returns the flags on the given region, if all pages have the
267         // same flags (except for CopyOnWrite, which is not returned by
268         // this method, as it can be asynchronously cleared).
269         
270         get_mapflags(Region region, MapFlags flags out, bool all_same out);
271         
272         // Returns the Mappable that covers the specified range, and the offset
273         // into the Mappable that corresponds to the first page in the region. 
274         // If any pages within the range are not mapped, or if more than one
275         // Mappable is mapped within the region, or if the offsets into the
276         // Mappable are not contiguous, then NULL is returned in ma.
277         //
278         // This is used to implement mremap().
279         
280         get_mapping(Region region, Mappable ma out, ulong offset out);
281
282         // Returns the minimum page size (and thus mapping size/alignment)
283         // supported in this address space.  An attempt to create a mapping
284         // that violates this will result in an InvalidArgument exception.
285
286         get_page_size(uint page_size out);
287
288         // Returns the minimum alignment supported for mapping requests;
289         // (vstart % min_align) must equal (region.start % min_align).  This
290         // is at least the minimum page size, but may be more on certain
291         // hardware, such as virtually-indexed-physically-tagged caches, where
292         // larger alignment is needed to ensure the absence of cache aliases. 
293         // An attempt to create a mapping that violates this will result in an
294         // InvalidArgument exception.
295         
296         get_min_align(uint min_align out);
297 };
298
299 interface AllocHandle {
300         guid: "CB029266-EAB6-11D9-BCA0-000A95BB581A";
301
302         get_regions(Region[] regions out);
303         
304         // Free a portion of an allocation.  To free all of an allocation,
305         // simply release all references to the handle.  Each region shall
306         // start and end on block size boundaries.  Throws OperationNotSupported
307         // if the allocator does not support partial frees.
308         
309         free(Region[] regions);
310 };
311
312 interface Allocator {
313         guid: "CCF5D83C-EAB6-11D9-8BB7-000A95BB581A";
314
315         const ulong unspecified_start = 0xffffffffffffffff;
316
317         bitfield AllocFlags {
318                 // If set, fail if the exact starting address is unavailable (or if
319                 // the allocator does not support caller-supplied starting
320                 // addresses).
321                 //
322                 // Otherwise, if the supplied starting address unavailable, the
323                 // allocator allocates a free region and returns it in "start".  If
324                 // this behavior is explicitly desired (as it ususally is), "start"
325                 // should be set to unspecified_start, which is always invalid. 
326                 // Using unspecified_start may be faster than specifying other
327                 // invalid addresses (as the allocator can check for this value
328                 // rather than checking address availability), and zero should not
329                 // be used for this purpose as it may be a valid address.
330                 
331                 Fixed
332         };
333
334         alloc(ulong start inout, ulong len, AllocFlags flags,
335               AllocHandle handle out);
336 };
337
338 interface GenericAllocator : Allocator {
339         guid: "D033DD3A-EAB6-11D9-96E4-000A95BB581A";
340
341         // Set the minimal block size used by the allocator.
342         // This can only be done before any alloc() or
343         // add_regions() calls; an InvalidState exception may
344         // be thrown otherwise.
345         
346         set_block_size(ulong block_size);
347         
348         // Make one or more regions available for allocations.
349         // The regions may not overlap each other or any existing
350         // regions (whether or not allocated).  Regions may not
351         // be removed once added using this interface; allocators
352         // may optionally provide a mechanism for doing so.
353         
354         add_regions(Region[] regions);
355 };