Skip to content

Commit 571fd39

Browse files
committed
refactor: address code review feedback
This commit addresses PR review comments from @SuperSandro2000: - Changed kernelCmdLine to use a list with concatStringsSep instead of toString - Simplified deviceArgs list formatting (removed redundant ++ operators) - Simplified share protocol error handling (combined 9p and unknown cases) - Simplified network interface error handling (combined tap/macvtap and unknown cases) - Changed vfkit binary path to use lib.getExe - Refactored rosetta args to use list with concatStringsSep instead of string concatenation - Added Rosetta NixOS module that automatically handles mounting and binfmt configuration - Added mountPoint option for configurable Rosetta mount location (defaults to /run/rosetta) - Updated documentation to reflect automatic module configuration - Improved Rosetta documentation with concrete usage example using pkgsCross.gnu64 - Simplified flake.nix to use lib.optional, replaceString, and map instead of if/then/else, replaceStrings, and builtins.map
1 parent 1f4177c commit 571fd39

File tree

6 files changed

+83
-62
lines changed

6 files changed

+83
-62
lines changed

doc/src/vfkit-rosetta.md

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,55 +21,52 @@ Enable Rosetta in your MicroVM configuration:
2121
enable = true;
2222
# Optional: install Rosetta automatically if missing
2323
install = true;
24+
# Optional: customize mount point (defaults to /run/rosetta)
25+
mountPoint = "/run/rosetta";
2426
};
2527
};
2628
}
2729
```
2830

29-
## Guest Setup
31+
The NixOS module automatically handles mounting the Rosetta virtiofs share and configuring binfmt to use Rosetta for x86_64 binaries. No additional guest configuration is required.
3032

31-
After enabling Rosetta, you need to mount the share and configure binfmt in your guest:
33+
## Usage
3234

33-
```nix
34-
{
35-
# Mount the Rosetta share
36-
fileSystems."/mnt/rosetta" = {
37-
device = "rosetta";
38-
fsType = "virtiofs";
39-
};
35+
Once configured, you can run any x86_64 binary in your ARM64 VM. To verify Rosetta is working:
4036

41-
# Configure binfmt to use Rosetta for x86_64 binaries
42-
boot.binfmt.registrations.rosetta = {
43-
interpreter = "/mnt/rosetta/rosetta";
44-
magicOrExtension = ''\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00'';
45-
mask = ''\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'';
46-
};
47-
}
37+
```nix
38+
# Add an x86_64 package to your configuration
39+
environment.systemPackages = with pkgs; [
40+
file # to verify binary architecture
41+
(pkgsCross.gnu64.hello) # x86_64 version of hello
42+
];
4843
```
4944

50-
## Testing
51-
52-
Once configured, you can verify Rosetta is working:
45+
Then in the VM:
5346

5447
```bash
55-
# Inside the VM
48+
# Verify you're running on ARM64
5649
uname -m
57-
# Should show: aarch64
50+
# Output: aarch64
5851

59-
# Try running an x86_64 binary (if you have one)
60-
file /path/to/x86_64/binary
61-
# Should show: ELF 64-bit LSB executable, x86-64
52+
# Check the binary architecture
53+
file $(which hello)
54+
# Output: ELF 64-bit LSB executable, x86-64, ...
6255

63-
/path/to/x86_64/binary
64-
# Should run successfully via Rosetta
56+
# Run the x86_64 binary via Rosetta
57+
hello
58+
# Output: Hello, world!
6559
```
6660

61+
You can use `pkgsCross.gnu64.<package>` to cross-compile any package from nixpkgs to x86_64 and run it via Rosetta.
62+
6763
## Options Reference
6864

6965
| Option | Type | Default | Description |
7066
|--------|------|---------|-------------|
7167
| `microvm.vfkit.rosetta.enable` | bool | `false` | Enable Rosetta support |
7268
| `microvm.vfkit.rosetta.mountTag` | string | `"rosetta"` | Mount tag for the virtiofs share |
69+
| `microvm.vfkit.rosetta.mountPoint` | string | `"/run/rosetta"` | Directory where Rosetta will be mounted in the guest |
7370
| `microvm.vfkit.rosetta.install` | bool | `false` | Auto-install Rosetta if missing |
7471
| `microvm.vfkit.rosetta.ignoreIfMissing` | bool | `false` | Continue if Rosetta unavailable |
7572

flake.nix

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,18 +110,17 @@
110110
nixpkgs.lib.concatMap (configName:
111111
let
112112
config = self.nixosConfigurations.${configName};
113-
packageName = builtins.replaceStrings [ "${system}-" ] [ "" ] configName;
113+
packageName = nixpkgs.lib.replaceString "${system}-" "" configName;
114114
# Check if this config's guest system matches our current build system
115115
# (accounting for darwin hosts building linux guests)
116116
guestSystem = config.pkgs.stdenv.hostPlatform.system;
117117
buildSystem = nixpkgs.lib.replaceString "-darwin" "-linux" system;
118118
in
119-
if guestSystem == buildSystem
120-
then [{
119+
nixpkgs.lib.optional (guestSystem == buildSystem)
120+
{
121121
name = packageName;
122122
value = config.config.microvm.runner.${config.config.microvm.hypervisor};
123-
}]
124-
else []
123+
}
125124
) (builtins.attrNames self.nixosConfigurations)
126125
);
127126

@@ -157,6 +156,8 @@
157156

158157
nixosConfigurations =
159158
let
159+
inherit (nixpkgs.lib) map;
160+
160161
hypervisorsWith9p = [
161162
"qemu"
162163
# currently broken:
@@ -238,8 +239,8 @@
238239
};
239240

240241
basicExamples = nixpkgs.lib.flatten (
241-
builtins.map (system:
242-
builtins.map (hypervisor: {
242+
map (system:
243+
map (hypervisor: {
243244
name = "${system}-${hypervisor}-example";
244245
value = makeExample { inherit system hypervisor; };
245246
shouldInclude = hypervisorSupportsSystem hypervisor system;
@@ -248,7 +249,7 @@
248249
);
249250

250251
tapExamples = nixpkgs.lib.flatten (
251-
builtins.map (system:
252+
map (system:
252253
nixpkgs.lib.imap1 (idx: hypervisor: {
253254
name = "${system}-${hypervisor}-example-with-tap";
254255
value = makeExample {

lib/runners/vfkit.nix

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ let
1515
inherit (microvmConfig)
1616
hostName vcpu mem user interfaces volumes shares socket
1717
storeOnDisk kernel initrdPath storeDisk kernelParams
18-
devices credentialFiles vsock graphics;
18+
balloon devices credentialFiles vsock graphics;
1919

2020
inherit (microvmConfig.vfkit) extraArgs logLevel rosetta;
2121

@@ -25,63 +25,57 @@ let
2525
kernelPath = "${kernel.out}/${pkgs.stdenv.hostPlatform.linux-kernel.target}";
2626

2727
kernelConsole = if graphics.enable then "tty0" else "hvc0";
28-
kernelCmdLine = "console=${kernelConsole} reboot=t panic=-1 ${toString kernelParams}";
28+
29+
kernelCmdLine = [ "console=${kernelConsole}" "reboot=t" "panic=-1" ] ++ kernelParams;
2930

3031
bootloaderArgs = [
3132
"--bootloader"
32-
"linux,kernel=${kernelPath},initrd=${initrdPath},cmdline=\"${kernelCmdLine}\""
33+
"linux,kernel=${kernelPath},initrd=${initrdPath},cmdline=\"${builtins.concatStringsSep " " kernelCmdLine}\""
3334
];
3435

3536
deviceArgs =
36-
[ "--device" "virtio-rng" ]
37-
++
38-
(if graphics.enable then [
37+
[
38+
"--device" "virtio-rng"
39+
]
40+
++ (if graphics.enable then [
3941
"--device" "virtio-gpu"
4042
"--device" "virtio-input,keyboard"
4143
"--device" "virtio-input,pointing"
4244
] else [
4345
"--device" "virtio-serial,stdio"
4446
])
45-
++
46-
(builtins.concatMap ({ image, ... }: [
47+
++ (builtins.concatMap ({ image, ... }: [
4748
"--device" "virtio-blk,path=${image}"
4849
]) volumesWithLetters)
49-
++
50-
(builtins.concatMap ({ proto, source, tag, ... }:
50+
++ (builtins.concatMap ({ proto, source, tag, ... }:
5151
if proto == "virtiofs" then [
5252
"--device" "virtio-fs,sharedDir=${source},mountTag=${tag}"
5353
]
54-
else if proto == "9p" then
55-
throw "vfkit does not support 9p shares on macOS. Use proto = \"virtiofs\" instead."
5654
else
57-
throw "Unknown share protocol: ${proto}"
55+
throw "vfkit does not support ${proto} share. Use proto = \"virtiofs\" instead."
5856
) shares)
59-
++
60-
(builtins.concatMap ({ type, id, mac, ... }:
57+
++ (builtins.concatMap ({ type, id, mac, ... }:
6158
if type == "user" then [
6259
"--device" "virtio-net,nat,mac=${mac}"
6360
]
64-
else if type == "tap" then
65-
throw "vfkit does not support tap networking on macOS. Use type = \"user\" for NAT networking."
6661
else if type == "bridge" then
6762
throw "vfkit bridge networking requires vmnet-helper which is not yet implemented. Use type = \"user\" for NAT networking."
68-
else if type == "macvtap" then
69-
throw "vfkit does not support macvtap networking on macOS. Use type = \"user\" for NAT networking."
7063
else
71-
throw "Unknown network interface type: ${type}"
64+
throw "vfkit does not support ${type} networking on macOS. Use type = \"user\" for NAT networking."
7265
) interfaces)
73-
++
74-
lib.optionals rosetta.enable (
66+
++ lib.optionals rosetta.enable (
7567
let
76-
rosettaArgs = "rosetta,mountTag=${rosetta.mountTag}"
77-
+ lib.optionalString rosetta.install ",install"
78-
+ lib.optionalString rosetta.ignoreIfMissing ",ignoreIfMissing";
68+
rosettaArgs = builtins.concatStringsSep "," (
69+
[ "rosetta" "mountTag=${rosetta.mountTag}" ]
70+
++ lib.optional rosetta.install "install"
71+
++ lib.optional rosetta.ignoreIfMissing "ignoreIfMissing"
72+
);
7973
in
8074
[ "--device" rosettaArgs ]
8175
);
8276

8377
allArgsWithoutSocket = [
84-
"${vfkit}/bin/vfkit"
78+
"${lib.getExe vfkit}"
8579
"--cpus" (toString vcpu)
8680
"--memory" (toString mem)
8781
]

nixos-modules/microvm/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ in
1919
./pci-devices.nix
2020
./virtiofsd
2121
./graphics.nix
22+
./rosetta.nix
2223
./optimization.nix
2324
./ssh-deploy.nix
2425
];

nixos-modules/microvm/options.nix

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -610,8 +610,8 @@ in
610610
Enable Rosetta support for running x86_64 binaries in ARM64 Linux VMs.
611611
Only works on Apple Silicon (ARM) Macs.
612612
613-
After enabling, you must mount the rosetta share and configure binfmt
614-
in your guest configuration. See the vfkit documentation for details.
613+
When enabled, the Rosetta virtiofs share will be automatically mounted
614+
and binfmt will be configured to use Rosetta for x86_64 binaries.
615615
'';
616616
};
617617

@@ -638,6 +638,15 @@ in
638638
Useful for configurations that should work on both ARM and Intel Macs.
639639
'';
640640
};
641+
642+
mountPoint = mkOption {
643+
type = types.str;
644+
default = "/run/rosetta";
645+
description = ''
646+
Directory where the Rosetta virtiofs share will be mounted in the guest.
647+
The Rosetta binary will be available at {mountPoint}/rosetta.
648+
'';
649+
};
641650
};
642651

643652
prettyProcnames = mkOption {

nixos-modules/microvm/rosetta.nix

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{ config, lib, pkgs, ... }:
2+
3+
let
4+
cfg = config.microvm.vfkit.rosetta;
5+
in
6+
lib.mkIf (config.microvm.hypervisor == "vfkit" && cfg.enable) {
7+
# Mount the Rosetta share
8+
fileSystems.${cfg.mountPoint} = {
9+
device = cfg.mountTag;
10+
fsType = "virtiofs";
11+
};
12+
13+
# Configure binfmt to use Rosetta for x86_64 binaries
14+
boot.binfmt.registrations.rosetta = {
15+
interpreter = "${cfg.mountPoint}/rosetta";
16+
magicOrExtension = ''\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00'';
17+
mask = ''\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'';
18+
};
19+
}

0 commit comments

Comments
 (0)