This feature is enabled at build time with the BOXEDWINE_64BIT_MMU define. It is only supported on 64-bit platforms and requires platform.c in c/platforms to implement a couple of functions
- allocNativeMemory
- freeNativeMemory
- reserveNativeMemory
- releaseNativeMemory
- makeCodePageReadOnly
- clearCodePageReadOnly
- platformRunThreadSlice (will need to catch exceptions)
Currently only the windows platform has implemented these.
Compared to soft MMU, hard MMU does not need to lookup permissions or an offset to map emulated memory to physical memory. The mapping is handled by these two functions
INLINE void* getNativeAddress(struct Memory* memory, U32 address) { return (void*)(address + memory->ids[address >> PAGE_SHIFT]); } INLINE U32 getHostAddress(struct KThread* thread, void* address) { return (U32)address; }
Notice that memory->ids allows more complicated lookups, but for the most part this will always be the same values. memory->ids is a work in progress to get shared memory working between emulated processes.
This comparison of a byte read with hard MMU shows that it is simpler than soft MMU
Hard MMU
INLINE void* getNativeAddress(struct Memory* memory, U32 address) { return (void*)(address + memory->ids[address >> PAGE_SHIFT]); } U8 readb(struct KThread* thread, U32 address) { return *(U8*)getNativeAddress(thread->process->memory, address); }
Soft MMU
INLINE U8 host_readb(U32 address) { return ram[address]; } static U8 ram_readb(struct KThread* thread, U32 address) { int index = address >> PAGE_SHIFT; return host_readb(address-thread->process->memory->read[index]); } U8 readb(struct KThread* thread, U32 address) { struct Memory* memory = thread->process->memory; int index = address >> 12; if (memory->read[index]) return host_readb(address-memory->read[index]); return memory->mmu[index]->readb(thread, address); }
Currently hard MMU does not implement read-only pages and exceptions. But I don’t think this should be too hard to do in the future. hard MMU also does not map a file into memory on demand, it will just copy the entire file into memory, so if a program tried to map a large file, this could cause a problem. I suspect this will need to be addressed as larger games become more playable.