From 7db635454bd9509e803d5a689146f16adcf279fa Mon Sep 17 00:00:00 2001 From: James Dunne Date: Tue, 11 Apr 2023 11:03:03 -0500 Subject: [PATCH 1/2] Add ROSETTA virtiofs directory share exposed to guest linux OS --- README.md | 36 ++++++++++++++++++++++++++++++++++++ vftool/main.m | 21 +++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/README.md b/README.md index 799164b..33e8cb6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,39 @@ +# Rosetta Support + +This fork adds to the Linux guest a virtiofs directory share named `ROSETTA` which contains a single arm64 executable +named `rosetta`. This executable is an amd64 emulator which uses the native Rosetta functionality on MacOS to execute +amd64 Linux binaries on the arm64 host (Mac M1, M2, etc.). + +To actually make use of it you must explicitly register a custom binfmt handler in the Linux guest by following the +steps below: + +## PREREQUISITES +The `binfmt-support` Ubuntu package must be installed. This package contains the `update-binfmts` required tool. +```shell +% sudo apt install binfmt-support +``` + +## INSTALLATION +```shell +% mkdir /tmp/rosetta +% sudo mount -t virtiofs ROSETTA /tmp/rosetta +% ls /tmp/rosetta rosetta +% sudo /usr/sbin/update-binfmts --install rosetta /tmp/rosetta/rosetta \ + --magic "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00" \ + --mask "\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" \ + --credentials yes --preserve no --fix-binary yes +``` + +You may see this error on first use of `update-binfmts` but ignore it and repeat the command and it should succeed. +``` +update-binfmts: warning: unable to close /proc/sys/fs/binfmt_misc/register: No such file or directory +update-binfmts: warning: unable to enable binary format rosetta +update-binfmts: exiting due to previous errors +``` + +## Original README follows + +--- # Virtualization.framework tool (vftool) Here lies a _really minimalist_ and very noddy command-line wrapper to run VMs in the macOS Big Sur Virtualization.framework. diff --git a/vftool/main.m b/vftool/main.m index 2e1f528..b92078e 100644 --- a/vftool/main.m +++ b/vftool/main.m @@ -210,6 +210,27 @@ static int createPty(bool waitForConnection) [conf setStorageDevices:discs]; + // expose the Rosetta directory share: + NSString *tag = @"ROSETTA"; + + NSError *validationError; + if (![VZVirtioFileSystemDeviceConfiguration validateTag:tag error:&validationError]) { + // Handle validation error here. + NSLog(@"-- Configuration validation failure! %@\n", validationError); + return nil; + } + + VZLinuxRosettaDirectoryShare *rosettaDirectoryShare = [[VZLinuxRosettaDirectoryShare alloc] initWithError:&validationError]; + if (validationError) { + NSLog(@"-- Configuration validation failure! %@\n", validationError); + return nil; + } + + VZVirtioFileSystemDeviceConfiguration *fileSystemDevice = [[VZVirtioFileSystemDeviceConfiguration alloc] initWithTag:tag]; + fileSystemDevice.share = rosettaDirectoryShare; + + conf.directorySharingDevices = @[fileSystemDevice]; + return conf; } From daf432111ceb62f310cec8c998babdcc096f3145 Mon Sep 17 00:00:00 2001 From: James Dunne Date: Wed, 12 Apr 2023 08:44:14 -0500 Subject: [PATCH 2/2] Added Rosetta support via optional -g commandline option to specify the virtiofs directory share tag. Clarified README --- README.md | 44 +++++++++++++++++++++++++++++++++++--------- vftool/main.m | 47 +++++++++++++++++++++++++++-------------------- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 33e8cb6..c9c8c3d 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,62 @@ -# Rosetta Support +# Rosetta Support for Linux guests -This fork adds to the Linux guest a virtiofs directory share named `ROSETTA` which contains a single arm64 executable -named `rosetta`. This executable is an amd64 emulator which uses the native Rosetta functionality on MacOS to execute -amd64 Linux binaries on the arm64 host (Mac M1, M2, etc.). +This fork adds a commandline option `-g ` to specify the name of the directory share tag +used to expose the Rosetta virtiofs directory share to the arm64 Linux guest. The tag can be any name you choose so long +as it conforms to virtiofs naming conventions. -To actually make use of it you must explicitly register a custom binfmt handler in the Linux guest by following the -steps below: +The virtiofs directory share contains a single linux/arm64 executable named `rosetta`. This executable is an amd64 +emulator which uses the native Rosetta functionality on MacOS to execute amd64 Linux binaries on the arm64 host +running Apple Silicon. + +To actually make use of it in your arm64 Linux guest you must explicitly register a custom binfmt handler in the arm64 +Linux guest by following the installation steps below. + +Example usage of `vftool` with `-g ROSETTA`: +```shell +vftool/build/vftool -k vmlinux -i initrd -g ROSETTA -d root.img -d varlibdocker.img -m 8192 -p 6 -t 0 -a "root=/dev/vda" "$@" +``` ## PREREQUISITES -The `binfmt-support` Ubuntu package must be installed. This package contains the `update-binfmts` required tool. +The `binfmt-support` Ubuntu package must be installed in the arm64 Linux guest; this package contains the required +`update-binfmts` tool. ```shell % sudo apt install binfmt-support ``` ## INSTALLATION +Run these commands in your arm64 Linux guest on every boot: ```shell % mkdir /tmp/rosetta % sudo mount -t virtiofs ROSETTA /tmp/rosetta -% ls /tmp/rosetta rosetta % sudo /usr/sbin/update-binfmts --install rosetta /tmp/rosetta/rosetta \ --magic "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00" \ --mask "\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" \ --credentials yes --preserve no --fix-binary yes ``` -You may see this error on first use of `update-binfmts` but ignore it and repeat the command and it should succeed. +The token `ROSETTA` in the `mount` command above MUST MATCH the tag name given to vftool `-g` commandline option. + +You may see this error on first use of `update-binfmts`; ignore it and repeat the command and it should succeed. ``` update-binfmts: warning: unable to close /proc/sys/fs/binfmt_misc/register: No such file or directory update-binfmts: warning: unable to enable binary format rosetta update-binfmts: exiting due to previous errors ``` +If you intend to use `docker` in the arm64 Linux guest to run containers with the `linux/amd64` platform, it's a good +idea to set this environment variable in your MacOS host for the MacOS `docker` client to use as a default: + +```shell +export DOCKER_DEFAULT_PLATFORM=linux/amd64 +``` + +This environment variable could also be specified in the `/lib/systemd/system/docker.service` systemd unit file on the +arm64 Linux guest by adding this line to the `[Service]` stanza: + +```ini +Environment=DOCKER_DEFAULT_PLATFORM=linux/amd64 +``` + ## Original README follows --- diff --git a/vftool/main.m b/vftool/main.m index b92078e..ee512f1 100644 --- a/vftool/main.m +++ b/vftool/main.m @@ -96,7 +96,8 @@ static int createPty(bool waitForConnection) NSString *initrd_path, struct disc_info *dinfo, unsigned int num_discs, - NSString *bridged_eth) + NSString *bridged_eth, + NSString *rosetta_tag) { /* **************************************************************** */ /* Linux bootloader setup: @@ -210,26 +211,26 @@ static int createPty(bool waitForConnection) [conf setStorageDevices:discs]; - // expose the Rosetta directory share: - NSString *tag = @"ROSETTA"; - - NSError *validationError; - if (![VZVirtioFileSystemDeviceConfiguration validateTag:tag error:&validationError]) { - // Handle validation error here. - NSLog(@"-- Configuration validation failure! %@\n", validationError); - return nil; - } + // expose the Rosetta directory share as value of rosetta_tag NSString: + if (rosetta_tag) { + NSError *validationError; + if (![VZVirtioFileSystemDeviceConfiguration validateTag:rosetta_tag error:&validationError]) { + // Handle validation error here. + NSLog(@"-- Configuration validation failure! %@\n", validationError); + return nil; + } - VZLinuxRosettaDirectoryShare *rosettaDirectoryShare = [[VZLinuxRosettaDirectoryShare alloc] initWithError:&validationError]; - if (validationError) { - NSLog(@"-- Configuration validation failure! %@\n", validationError); - return nil; - } + VZLinuxRosettaDirectoryShare *rosettaDirectoryShare = [[VZLinuxRosettaDirectoryShare alloc] initWithError:&validationError]; + if (validationError) { + NSLog(@"-- Configuration validation failure! %@\n", validationError); + return nil; + } - VZVirtioFileSystemDeviceConfiguration *fileSystemDevice = [[VZVirtioFileSystemDeviceConfiguration alloc] initWithTag:tag]; - fileSystemDevice.share = rosettaDirectoryShare; + VZVirtioFileSystemDeviceConfiguration *fileSystemDevice = [[VZVirtioFileSystemDeviceConfiguration alloc] initWithTag:rosetta_tag]; + fileSystemDevice.share = rosettaDirectoryShare; - conf.directorySharingDevices = @[fileSystemDevice]; + conf.directorySharingDevices = @[fileSystemDevice]; + } return conf; } @@ -249,6 +250,7 @@ static void usage(const char *me) "\t-p (Default 1)\n" "\t-m (Default 512MB)\n" "\t-t (0 = stdio, 1 = pty (default))\n" + "\t-g \n" "\n\tSpecify multiple discs with multiple -d/-c options, in order (max %d)\n", me, MAX_DISCS); } @@ -263,6 +265,7 @@ int main(int argc, char *argv[]) NSString *disc_path = NULL; NSString *cdrom_path = NULL; NSString *eth_if = NULL; + NSString *rosetta_tag = NULL; unsigned int cpus = 0; unsigned int mem = 0; unsigned int tty_type = 1; @@ -271,7 +274,7 @@ int main(int argc, char *argv[]) unsigned int num_discs = 0; int ch; - while ((ch = getopt(argc, argv, "k:a:i:d:c:b:p:m:t:h")) != -1) { + while ((ch = getopt(argc, argv, "k:a:i:d:c:b:p:m:t:g:h")) != -1) { switch (ch) { case 'k': kern_path = [NSString stringWithUTF8String:optarg]; @@ -310,6 +313,9 @@ int main(int argc, char *argv[]) return 1; } break; + case 'g': + rosetta_tag = [NSString stringWithUTF8String:optarg]; + break; case 'h': default: @@ -344,7 +350,8 @@ int main(int argc, char *argv[]) VZVirtualMachineConfiguration *conf = getVMConfig(mem, cpus, tty_type, cmdline, kern_path, initrd_path, dinfo, num_discs, - eth_if); + eth_if, + rosetta_tag); if (!conf) { NSLog(@"Couldn't create configuration for VM.\n");