This allows using one single wineprefix, one wineserver and one single wine executable for running both arm and arm64 executables.
This setup actually has worked earlier; Ubuntu 22.04 packages Wine 6.0, where the wine32 + wine64 packages together end up working this way. However, since Wine 6.0, a couple of refactorings has broken this setup along the way; reinstate this way of working.
The new wow64 mode probably won't work on arm, as it's not easily possible to switch between 32 and 64 bit execution mode within a process, as far as I know, but the old wow64 mode is still a great convenience - especially considering distro-packaged use for users who aren't familiar with the particular quirks on this architecture.
-- v2: configure: Allow using --enable-win64 on aarch64 server: Include ARMNT as one of the supported architectures on aarch64 ntdll: Allow running arm/aarch64 in (old) wow64 mode
From: Martin Storsjö martin@martin.st
The new wow64 mode probably won't work though, as it's not easily doable to switch between arm and aarch64 execution modes within a process.
Since 8ac411ed6dc7a9390178a01e6f07a963a593d406, the get_{native,wow}_context functions exist and need to return the right thing in the arm implementation.
Since ae8562ed2277a5c051e131dc317e94aa3d5413c8 and 1456b31eecfef91fc8ffc8c2de29ab69c5b5463b we need to include the arm+arm64 case for starting the right wineloader. --- dlls/ntdll/unix/loader.c | 3 ++- dlls/ntdll/unix/signal_arm.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 68cd4f50420..c97aa3e5a48 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -514,7 +514,8 @@ char *get_alternate_wineloader( WORD machine ) if (machine == current_machine) return NULL;
/* try the 64-bit loader */ - if (current_machine == IMAGE_FILE_MACHINE_I386 && machine == IMAGE_FILE_MACHINE_AMD64) + if ((current_machine == IMAGE_FILE_MACHINE_I386 && machine == IMAGE_FILE_MACHINE_AMD64) || + (current_machine == IMAGE_FILE_MACHINE_ARMNT && machine == IMAGE_FILE_MACHINE_ARM64)) { size_t len = strlen(wineloader);
diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index c9ae492597d..d9bda6a8d2c 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -409,7 +409,7 @@ NTSTATUS signal_set_full_context( CONTEXT *context ) */ void *get_native_context( CONTEXT *context ) { - return context; + return is_old_wow64() ? NULL : context; }
@@ -418,7 +418,7 @@ void *get_native_context( CONTEXT *context ) */ void *get_wow_context( CONTEXT *context ) { - return NULL; + return is_old_wow64() ? context : NULL; }
From: Martin Storsjö martin@martin.st
Since 4022fb9ba3eacd6b09d35b457754a7e17c67564e, we need to reinclud ARMNT as one of the supported architectures in an aarch64 wineprefix. --- server/registry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/registry.c b/server/registry.c index 3f02faaaefd..c60c737feff 100644 --- a/server/registry.c +++ b/server/registry.c @@ -1859,7 +1859,7 @@ static void init_supported_machines(void) { supported_machines[count++] = IMAGE_FILE_MACHINE_ARM64; supported_machines[count++] = IMAGE_FILE_MACHINE_I386; - /* supported_machines[count++] = IMAGE_FILE_MACHINE_ARMNT; not supported yet */ + supported_machines[count++] = IMAGE_FILE_MACHINE_ARMNT; } #else #error Unsupported machine
From: Martin Storsjö martin@martin.st
This renames the installed loader/preloader, to allow them to be used together with an arm build of Wine.
This is not strictly necessary on its own; Debian packaging end up with a working wow64 setup on their on by the way they rename the installed executables anyway, but this allows just doing a build with --enable-win64 and get it set up the right way. --- configure | 1 + configure.ac | 1 + 2 files changed, 2 insertions(+)
diff --git a/configure b/configure index fe7464a61d0..e3233336d39 100755 --- a/configure +++ b/configure @@ -20897,6 +20897,7 @@ fi case "$HOST_ARCH,$PE_ARCHS" in x86_64,*i386*) wine_binary="wine" ;; x86_64,*) wine_binary="wine64" ;; + aarch64,*) test "x$enable_win64" = "xyes" && wine_binary="wine64" || wine_binary="wine" ;; *) wine_binary="wine" ;; esac WINELOADER_PROGRAMS="$wine_binary" diff --git a/configure.ac b/configure.ac index b999e3506e0..d3ffb77c4bf 100644 --- a/configure.ac +++ b/configure.ac @@ -2034,6 +2034,7 @@ dnl **** Platform-specific checks **** case "$HOST_ARCH,$PE_ARCHS" in x86_64,*i386*) wine_binary="wine" ;; x86_64,*) wine_binary="wine64" ;; + aarch64,*) test "x$enable_win64" = "xyes" && wine_binary="wine64" || wine_binary="wine" ;; *) wine_binary="wine" ;; esac AC_SUBST(WINELOADER_PROGRAMS,"$wine_binary")
Jacek Caban (@jacek) commented about dlls/ntdll/unix/loader.c:
if (machine == current_machine) return NULL; /* try the 64-bit loader */
- if (current_machine == IMAGE_FILE_MACHINE_I386 && machine == IMAGE_FILE_MACHINE_AMD64)
- if ((current_machine == IMAGE_FILE_MACHINE_I386 && machine == IMAGE_FILE_MACHINE_AMD64) ||
(current_machine == IMAGE_FILE_MACHINE_ARMNT && machine == IMAGE_FILE_MACHINE_ARM64))
It might be more flexible to avoid restricting `machine` to `IMAGE_FILE_MACHINE_ARM64` and instead check for something like `machine != current_machine`. This would allow a 64-bit loader to use the new wow for x86 emulation while still using the old wow for 32-bit ARM.
Overall, this approach seems reasonable to me, given that the new wow isn't possible in this case.
We might consider swapping the loader naming in this scenario. For instance, the default `wine` could serve as the 64-bit loader (also handling x86 emulation), while something like `wine32` could be used for 32-bit ARM. This would make it easier to package 32-bit ARM separately as an optional addition to the 64-bit Wine package, avoiding dependencies on 32-bit host libraries for users not interested in 32-bit ARM.
(I don't think it's a blocker for this MR, I'm just suggesting it for consideration.)
On Tue Jan 28 09:50:41 2025 +0000, Jacek Caban wrote:
It might be more flexible to avoid restricting `machine` to `IMAGE_FILE_MACHINE_ARM64` and instead check for something like `machine != current_machine`. This would allow a 64-bit loader to use the new wow for x86 emulation while still using the old wow for 32-bit ARM.
As we have a `machine == current_machine` early return above on line 514, the whole rest of the function essentially is operating under `machine != current_machine` already.
Of course I don't mind extending how this works, but I'm not hands-on familiar with the whole new-wow64 and in particular x86/x86_64 emulation cases, so I'd prefer to leave that to someone else; I've mostly tried to mirror what is done for x86 old wow64 here.