|
From: | Luca Dariz |
Subject: | Mixing 32 and 64 bit userspace tasks (was: Re: [PATCH gnumach] Define rpc_vm_size_array_t and rpc_vm_offset_array_t) |
Date: | Fri, 3 Feb 2023 20:13:47 +0100 |
Il 01/02/23 10:36, Sergey Bugaev ha scritto:
Note that another way to handle the size conversion between rpc_* and regular types would be to add some new VM types to include/mach/message.h; in this case, the shrink/expand would happen in copyinmsg()/copyoutmsg() instead of the mig-generated code (as for mach ports), but this approach would require to plan for a staged introduction of this change.Actually, yes, that's what I've been thinking about. Currently vm_size_t & friends are conditionally (but statically) defined to either MACH_MSG_TYPE_INTEGER_32 or MACH_MSG_TYPE_INTEGER_64. But what if we also had MACH_MSG_TYPE_INTEGER_PTRSIZE (name TBD), which would be equivalent to MACH_MSG_TYPE_INTEGER_{32,64} for {32,64}-bit tasks; but the kernel would know about this and change its size accordingly when transferring messages between 64- and 32-bit tasks. A value sent as MACH_MSG_TYPE_INTEGER_32 is always received as MACH_MSG_TYPE_INTEGER_32, no matter if the intent was to send a pointer-sized value, whereas a 32-bit value sent by a 32-bit task as MACH_MSG_TYPE_INTEGER_PTRSIZE would get received as a 64-bit value, still MACH_MSG_TYPE_INTEGER_PTRSIZE, by a 64-bit task.
While this shouldn't be a problem for normal data transfers, where the kernel already copies the data from one task to the other adjusting the size of vm fields, I wonder if there are cases where the virtual address is not supposed to be translated between tasks, e.g. if we really need to send a task-specific virtual address. For example, are there cases where a task allocates memory on behalf of another task? (except for the exec task)
I think a more difficult case is the rpc_time_value_t type, but this case could be solved by adding yet another MACH_MSG_TYPE_TIME_VALUE value.This would allow 32- and 64- bit tasks (including the kernel task) to communicate transparently, without requiring separate rpc_* versions of all the pointer-sized types. Possibly. Maybe. Uness there are a lot of subtler details to this, which there of course are.
However the problem exists for any struct type (which are just int[] of fixed size in mig), because there could be differences due to both alignment and pointer-type fields. So either the kernel knows all the data structures exchanged by user-space tasks, or the task needs to handle a message differently depending if the sender is a 32 or 64 bit task. Maybe this could be handled by the mig stubs, I'm not sure. The information about the sending task could be encoded in one of the unused bits of the msg header.
Something similar to rpc_ types would still be needed for regular syscalls, but then they could be renamed to vm_offset_32_t and similar, since syscalls would have different entry points.
But I'm sure it has been a conscious decision to go with the current design and not this way?
For the parts that I wrote, the choice was based on some information that I found in the wiki, on irc and to some extent it seemed faster to implement. Considering the above issue with struct, I'm not sure how much a new vm type would simplify message handling.
I'm also not arguing that mixing 32- and 64-bit tasks is worth supporting. This was a hard requirement for OS X, since they had to be able to run existing proprietary binaries unmodified. We build everything from source, so just having all of the userland be 64-bit (and fixing any issues we find on the way) sounds very viable. Using 32-bit win32 software via Wine has been the single reason to run 32-bit processes on my GNU/Linux system, but apparently that's now changing too (WoW64). And I don't know how relevant using Wine on the Hurd is anyway.
Maybe one advantage could be a reduced memory usage for 32-bit subhurds, if we want also 64-bit subhurds on the same machine.
Luca
[Prev in Thread] | Current Thread | [Next in Thread] |