Allocation is above the architectural level, except for alloca() and allocf() which have dedicated instructions. Stilll, one can guess the likely implementations that a native OS might use.
Mill is designed to support a client-server software architecture where the participants form an arbitrary service graph (not flat nor nested by level) and are mutually bilaterally distrusting. This lends itself to recursively defined allocations or any resource, not just memory, where an allocator hands out from an internal resource pool and if necessary refills or extends its pool from another service. As with any recursive structure there must be a bottom turtle that obtains its pool from somewhere else instead of from a recursive call to another allocator.
In the case of memory, the “somewhere else” is hardware, or rather is specialized software that talks to the hardware. In our prototype code, the size of the address space is hardwired into the data structure at power-up in raw hex constants. In a sense, the bottom turtle pool is the mind of the programmer writing the boot code.
Besides the totality of the address space, the design starts with a number of subspaces that are also hard-wired. Examples include the threadId and turfId spaces, and the threadlets. Getting these started at power-up involves being in the All permission space and using intrinsics to diddle MMIO registers. Its a perverse kind of fun, for those who get into that kind of thing 🙂