]> git.buserror.net Git - polintos/scott/priv.git/blob - idl/addrspace.idl
Remove Mem.AddrSpace.alloc_and_map(); a Mappable that allocates
[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         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.
189
190         enum OverMap:2 {
191                 None,       // Never map non-argument memory to a callee's address
192                             // space.
193
194                 ReadOnly,   // Allow read-only mappings of non-argument data within
195                             // the same page as an argument into the callee's
196                             // address space.
197
198                 ReadWrite   // Allow all mappings of non-argument data within the
199                             // same page as an argument into the callee's address
200                             // space.
201         } overmap
202 };
203
204 interface AddrSpace {
205         guid: "BF9D2070-EAB6-11D9-A2D2-000A95BB581A";
206
207         const ulong unspecified_start = 0xffffffffffffffff;
208         
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.
215         
216         get_mappable(Mappable ma out);
217         
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.
221         //
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
227         // stored to disk.
228
229         clone(AddrSpace addrspace out, bool clone_is_real);
230         
231         // Mappable must be implemented by the local kernel, and must hold
232         // read/write/exec permissions appropriate for the MapFlags given.
233         
234         map(Mappable ma, Region region, ulong vstart inout, MapFlags flags);
235         unmap(Region region);
236
237         // Set the flags on all pages in the region.  CopyOnWrite can be
238         // set, but not cleared, using this method.  Fixed is ignored.
239
240         set_mapflags(Region region, MapFlags flags);
241         
242         // Returns the flags on the given region, if all pages have the
243         // same flags (except for CopyOnWrite, which is not returned by
244         // this method, as it can be asynchronously cleared).
245         
246         get_mapflags(Region region, MapFlags flags out, bool all_same out);
247         
248         // Returns the Mappable that covers the specified range, and the offset
249         // into the Mappable that corresponds to the first page in the region. 
250         // If any pages within the range are not mapped, or if more than one
251         // Mappable is mapped within the region, or if the offsets into the
252         // Mappable are not contiguous, then NULL is returned in ma.
253         //
254         // This is used to implement mremap().
255         
256         get_mapping(Region region, Mappable ma out, ulong offset out);
257
258         // Returns the minimum page size (and thus mapping size/alignment)
259         // supported in this address space.  An attempt to create a mapping
260         // that violates this will result in an InvalidArgument exception.
261
262         get_page_size(uint page_size out);
263
264         // Returns the minimum alignment supported for mapping requests;
265         // (vstart % min_align) must equal (region.start % min_align).  This
266         // is at least the minimum page size, but may be more on certain
267         // hardware, such as virtually-indexed-physically-tagged caches, where
268         // larger alignment is needed to ensure the absence of cache aliases. 
269         // An attempt to create a mapping that violates this will result in an
270         // InvalidArgument exception.
271         
272         get_min_align(uint min_align out);
273 };
274
275 interface AllocHandle {
276         guid: "CB029266-EAB6-11D9-BCA0-000A95BB581A";
277
278         get_regions(Region[] regions out);
279         
280         // Free a portion of an allocation.  To free all of an allocation,
281         // simply release all references to the handle.  Each region shall
282         // start and end on block size boundaries.  Throws OperationNotSupported
283         // if the allocator does not support partial frees.
284         
285         free(Region[] regions);
286 };
287
288 interface Allocator {
289         guid: "CCF5D83C-EAB6-11D9-8BB7-000A95BB581A";
290
291         const ulong unspecified_start = 0xffffffffffffffff;
292
293         bitfield AllocFlags {
294                 // If set, fail if the exact starting address is unavailable (or if
295                 // the allocator does not support caller-supplied starting
296                 // addresses).
297                 //
298                 // Otherwise, if the supplied starting address unavailable, the
299                 // allocator allocates a free region and returns it in "start".  If
300                 // this behavior is explicitly desired (as it ususally is), "start"
301                 // should be set to unspecified_start, which is always invalid. 
302                 // Using unspecified_start may be faster than specifying other
303                 // invalid addresses (as the allocator can check for this value
304                 // rather than checking address availability), and zero should not
305                 // be used for this purpose as it may be a valid address.
306                 
307                 Fixed
308         };
309
310         alloc(ulong start inout, ulong len, AllocFlags flags,
311               AllocHandle handle out);
312 };
313
314 interface GenericAllocator : Allocator {
315         guid: "D033DD3A-EAB6-11D9-96E4-000A95BB581A";
316
317         // Set the minimal block size used by the allocator.
318         // This can only be done before any alloc() or
319         // add_regions() calls; an InvalidState exception may
320         // be thrown otherwise.
321         
322         set_block_size(ulong block_size);
323         
324         // Make one or more regions available for allocations.
325         // The regions may not overlap each other or any existing
326         // regions (whether or not allocated).  Regions may not
327         // be removed once added using this interface; allocators
328         // may optionally provide a mechanism for doing so.
329         
330         add_regions(Region[] regions);
331 };