On Tue, Apr 26, 2022 at 12:04 AM Chris Robinson chris.kcat@gmail.com wrote:
On Sunday, April 24, 2022 7:18:49 PM PDT Derek Lesho wrote:
The solutions which I've seen laid out so far:
- Use the mremap(2) interface, allowing us to duplicate the mapping we
receive into the 32-bit address space. This solution would match what is already done for Crossover Mac's 32on64 support using Mac's mach_vm_remap functionality [2]. However, right now it is not possible to use the MREMAP_DONTUNMAP flag with mappings that aren't private and anonymous, which rules out there use on mapped FDs from libdrm. Due to this, a kernel change would be necessary.
This doesn't sound at all safe, since it's essentially moving the memory mapping out from under the driver. MREMAP_DONTUNMAP avoids unmapping the original memory space, but that memory space becomes all but invalid, a page fault when accessed and is otherwise zero-filled to satisfy accesses:
MREMAP_DONTUNMAP (since Linux 5.7) ... After completion, any access to the range specified by old_address and old_size will result in a page fault. The page fault will be handled by a userfaultfd(2) handler if the address is in a range previously registered with userfaultfd(2). Otherwise, the kernel allocates a zero-filled page to handle the fault.
You can't know what a driver will do with mapped memory or pointer addresses it returns to the application, or where such memory comes from, so you can't be sure it doesn't have some bookkeeping with it or does manual copying using a cached pointer instead of the remapped location. You also can't know if it's using a preallocated pool that it returns to the app when "mapping" and reuses after "unmapping".
What you'd need for something like this is a method to duplicate a memory mapping, leaving the original intact instead of wiping it, so different pages/ addresses refer to the same underlying hardware memory. There doesn't seem to be an option for that, currently.
Indeed, that's what CrossOver's macOS hack does at the moment, by means of the mach_vm_remap() API. It sounds like currently there is no equivalent functionality in Linux. I have no clue if the Linux memory management infrastructure makes supporting that particularly hard, but otherwise I wouldn't expect any particular opposition on a matter of principle to introducing the support we need into the kernel.
Personally I find this to be the only really practical strategy, at least among those that have been mentioned. As Zeb pointed out, that's not to say there won't be any use in also pursuing other options though.