Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions cmd/vmhost/bridge_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//go:build linux

package vmhostcmder

import (
"os"
"os/exec"
"path/filepath"
)

// findBridgeHelper locates the QEMU bridge helper binary by searching
// common installation paths. See pkg/vm/bridge_linux.go for details.
func findBridgeHelper(qemuBinary string) string {
if qemuBin, err := exec.LookPath(qemuBinary); err == nil {
resolved, err := filepath.EvalSymlinks(qemuBin)
if err == nil {
prefix := filepath.Dir(filepath.Dir(resolved))
candidate := filepath.Join(prefix, "libexec", "qemu-bridge-helper")
if _, err := os.Stat(candidate); err == nil {
return candidate
}
}
}

candidates := []string{
"/usr/lib/qemu/qemu-bridge-helper",
"/usr/libexec/qemu-bridge-helper",
"/usr/lib64/qemu/qemu-bridge-helper",
}
for _, c := range candidates {
if _, err := os.Stat(c); err == nil {
return c
}
}

return ""
}
7 changes: 4 additions & 3 deletions cmd/vmhost/platform_darwin_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ func bootAppleVirt(ctx context.Context, baseDir string, inst *vm.Instance, logge
// getPlatformConfig returns the QEMU platform configuration for darwin/arm64.
func getPlatformConfig(_ string) *vm.QEMUPlatformConfig {
return &vm.QEMUPlatformConfig{
Accelerator: "hvf",
Binary: "qemu-system-aarch64",
MachineType: "virt",
Accelerator: "hvf",
Binary: "qemu-system-aarch64",
MachineType: "virt",
MachineProps: "highmem=on",
EFISearchPaths: []string{
"{qemu_prefix}/share/qemu/edk2-aarch64-code.fd",
"/opt/homebrew/share/qemu/edk2-aarch64-code.fd",
Expand Down
39 changes: 39 additions & 0 deletions cmd/vmhost/platform_linux_amd64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//go:build linux && amd64

package vmhostcmder

import (
"context"
"fmt"
"log"

"github.com/papercomputeco/masterblaster/pkg/vm"
"github.com/papercomputeco/masterblaster/pkg/vmhost"
)

func bootAppleVirt(_ context.Context, _ string, _ *vm.Instance, _ *log.Logger) (vmhost.VMController, error) {
return nil, fmt.Errorf("apple Virtualization.framework is only available on macOS/Apple Silicon")
}

// getPlatformConfig returns the QEMU platform configuration for Linux x86_64.
func getPlatformConfig(_ string) *vm.QEMUPlatformConfig {
const binary = "qemu-system-x86_64"

return &vm.QEMUPlatformConfig{
Accelerator: "kvm",
Binary: binary,
MachineType: "q35",
EFISearchPaths: []string{
"{qemu_prefix}/share/qemu/edk2-x86_64-code.fd",
"/usr/share/qemu/edk2-x86_64-code.fd",
"/usr/share/OVMF/OVMF_CODE.fd",
"/usr/share/edk2/x86_64/OVMF_CODE.fd",
},
ControlPlaneMode: "vsock",
VsockDevice: "vhost-vsock-pci",
DirectKernelBoot: true,
DiskAIO: "io_uring",
DiskCache: "none",
BridgeHelper: findBridgeHelper(binary),
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build linux
//go:build linux && arm64

package vmhostcmder

Expand All @@ -15,12 +15,15 @@ func bootAppleVirt(_ context.Context, _ string, _ *vm.Instance, _ *log.Logger) (
return nil, fmt.Errorf("apple Virtualization.framework is only available on macOS/Apple Silicon")
}

// getPlatformConfig returns the QEMU platform configuration for Linux.
// getPlatformConfig returns the QEMU platform configuration for Linux ARM64.
func getPlatformConfig(_ string) *vm.QEMUPlatformConfig {
const binary = "qemu-system-aarch64"

return &vm.QEMUPlatformConfig{
Accelerator: "kvm",
Binary: "qemu-system-aarch64",
MachineType: "virt",
Accelerator: "kvm",
Binary: binary,
MachineType: "virt",
MachineProps: "highmem=on",
EFISearchPaths: []string{
"{qemu_prefix}/share/qemu/edk2-aarch64-code.fd",
"/usr/share/qemu/edk2-aarch64-code.fd",
Expand All @@ -32,5 +35,6 @@ func getPlatformConfig(_ string) *vm.QEMUPlatformConfig {
DirectKernelBoot: true,
DiskAIO: "io_uring",
DiskCache: "none",
BridgeHelper: findBridgeHelper(binary),
}
}
6 changes: 2 additions & 4 deletions jcard.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ cpus = 2
memory = "8GiB"

[[agents]]
type = "native"
harness = "opencode"
prompt = "Use cowsay to print Hello world!"
extra_packages = [ "cowsay" ]
replicas = 10
prompt = "Hello world"
replicas = 3
5 changes: 5 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ type NetworkConfig struct {
// Mode is the network mode: "nat" (default), "bridged", or "none".
Mode string `toml:"mode"`

// Bridge is the host bridge interface for bridged mode on Linux
// (e.g. "virbr0", "br0"). Ignored on macOS where vmnet-shared is
// used instead. Defaults to "virbr0" (the libvirt default NAT bridge).
Bridge string `toml:"bridge"`

// Forwards are port forwards from host to sandbox (nat mode only).
Forwards []PortForward `toml:"forwards"`

Expand Down
7 changes: 4 additions & 3 deletions pkg/vm/backend_darwin_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ func NewPlatformBackend(baseDir string) (Backend, error) {
// so the stereosd control plane is forwarded via TCP through QEMU's
// user-mode networking.
platform := &QEMUPlatformConfig{
Accelerator: "hvf",
Binary: "qemu-system-aarch64",
MachineType: "virt",
Accelerator: "hvf",
Binary: "qemu-system-aarch64",
MachineType: "virt",
MachineProps: "highmem=on",
EFISearchPaths: []string{
"{qemu_prefix}/share/qemu/edk2-aarch64-code.fd",
"/opt/homebrew/share/qemu/edk2-aarch64-code.fd",
Expand Down
29 changes: 29 additions & 0 deletions pkg/vm/backend_linux_amd64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//go:build linux && amd64

package vm

// NewPlatformBackend returns the QEMU backend for Linux on x86_64,
// configured for KVM acceleration with native vsock support.
func NewPlatformBackend(baseDir string) (Backend, error) {
const binary = "qemu-system-x86_64"

platform := &QEMUPlatformConfig{
Accelerator: "kvm",
Binary: binary,
MachineType: "q35",
EFISearchPaths: []string{
"{qemu_prefix}/share/qemu/edk2-x86_64-code.fd",
"/usr/share/qemu/edk2-x86_64-code.fd",
"/usr/share/OVMF/OVMF_CODE.fd",
"/usr/share/edk2/x86_64/OVMF_CODE.fd",
},
ControlPlaneMode: "vsock",
VsockDevice: "vhost-vsock-pci",
DirectKernelBoot: true,
DiskAIO: "io_uring",
DiskCache: "none",
BridgeHelper: findBridgeHelper(binary),
}

return NewQEMUBackend(baseDir, platform), nil
}
17 changes: 9 additions & 8 deletions pkg/vm/backend_linux.go → pkg/vm/backend_linux_arm64.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
//go:build linux
//go:build linux && arm64

package vm

// NewPlatformBackend returns the appropriate VM backend for Linux.
// This returns the QEMU backend configured for KVM acceleration with
// native vsock support via vhost-vsock-pci.
// NewPlatformBackend returns the QEMU backend for Linux on ARM64,
// configured for KVM acceleration with native vsock support.
func NewPlatformBackend(baseDir string) (Backend, error) {
// TODO: Implement KVM/libvirt backend for better performance.
const binary = "qemu-system-aarch64"

platform := &QEMUPlatformConfig{
Accelerator: "kvm",
Binary: "qemu-system-aarch64",
MachineType: "virt",
Accelerator: "kvm",
Binary: binary,
MachineType: "virt",
MachineProps: "highmem=on",
EFISearchPaths: []string{
"{qemu_prefix}/share/qemu/edk2-aarch64-code.fd",
"/usr/share/qemu/edk2-aarch64-code.fd",
Expand All @@ -23,6 +23,7 @@ func NewPlatformBackend(baseDir string) (Backend, error) {
DirectKernelBoot: true,
DiskAIO: "io_uring",
DiskCache: "none",
BridgeHelper: findBridgeHelper(binary),
}

return NewQEMUBackend(baseDir, platform), nil
Expand Down
45 changes: 45 additions & 0 deletions pkg/vm/bridge_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//go:build linux

package vm

import (
"os"
"os/exec"
"path/filepath"
)

// findBridgeHelper locates the QEMU bridge helper binary by searching
// common installation paths. The helper creates tap devices and attaches
// them to a bridge interface, enabling bridged networking without root
// privileges on the QEMU process itself.
//
// The helper binary must have setuid root or CAP_NET_ADMIN capability,
// and the target bridge must be listed in /etc/qemu/bridge.conf.
func findBridgeHelper(qemuBinary string) string {
// Try the QEMU installation prefix first. This works for Nix,
// Homebrew-on-Linux, and custom QEMU installs.
if qemuBin, err := exec.LookPath(qemuBinary); err == nil {
resolved, err := filepath.EvalSymlinks(qemuBin)
if err == nil {
prefix := filepath.Dir(filepath.Dir(resolved))
candidate := filepath.Join(prefix, "libexec", "qemu-bridge-helper")
if _, err := os.Stat(candidate); err == nil {
return candidate
}
}
}

// Common distro paths.
candidates := []string{
"/usr/lib/qemu/qemu-bridge-helper", // Ubuntu, Debian, Arch
"/usr/libexec/qemu-bridge-helper", // Fedora, RHEL
"/usr/lib64/qemu/qemu-bridge-helper", // Some RHEL/CentOS variants
}
for _, c := range candidates {
if _, err := os.Stat(c); err == nil {
return c
}
}

return ""
}
30 changes: 30 additions & 0 deletions pkg/vm/clone_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//go:build linux

package vm

import (
"fmt"
"os"

"golang.org/x/sys/unix"
)

// cloneFile attempts an instant copy-on-write clone via ioctl(FICLONE).
// This works on btrfs, xfs (with reflink), and other CoW filesystems.
// Returns an error if the filesystem doesn't support cloning, causing
// the caller to fall back to streaming io.Copy.
func cloneFile(src, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return fmt.Errorf("opening source for clone: %w", err)
}
defer srcFile.Close()

dstFile, err := os.Create(dst)
if err != nil {
return fmt.Errorf("creating destination for clone: %w", err)
}
defer dstFile.Close()

return unix.IoctlFileClone(int(dstFile.Fd()), int(srcFile.Fd()))
}
2 changes: 1 addition & 1 deletion pkg/vm/clone_other.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !darwin
//go:build !darwin && !linux

package vm

Expand Down
11 changes: 11 additions & 0 deletions pkg/vm/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ type QEMUPlatformConfig struct {
// Set to "none" (O_DIRECT) when using io_uring for best performance,
// or leave empty to use QEMU's default (writeback).
DiskCache string

// MachineProps are extra comma-separated properties appended to the
// -machine argument. For example, "highmem=on" is valid for the ARM
// "virt" machine type but not for x86_64 "q35".
MachineProps string

// BridgeHelper is the resolved path to the QEMU bridge helper binary
// (qemu-bridge-helper). Only set on Linux where bridged networking
// uses tap devices via the helper. Empty on macOS where vmnet-shared
// is used instead.
BridgeHelper string
}

// DefaultMachineType returns the machine type, defaulting to "virt".
Expand Down
Loading