Skip to content

Commit

Permalink
Add support for arm64 hosts
Browse files Browse the repository at this point in the history
This adds infrastructure for support different types of host systems,
specifically adding arm64 support.

Tested on an rpi4 with Debian bullseye

Based on a patch by Ryan Gonzalez <[email protected]>

Signed-off-by: Sjoerd Simons <[email protected]>
  • Loading branch information
sjoerdsimons committed Jul 22, 2023
1 parent 3221840 commit 246072f
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 14 deletions.
4 changes: 2 additions & 2 deletions backend.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build linux && amd64
// +build linux,amd64
//go:build linux
// +build linux

package fakemachine

Expand Down
46 changes: 41 additions & 5 deletions backend_qemu.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build linux && amd64
// +build linux,amd64
//go:build linux && (arm64 || amd64)

package fakemachine

Expand Down Expand Up @@ -35,8 +34,40 @@ func (b qemuBackend) Supported() (bool, error) {
return true, nil
}

type qemuMachine struct {
binary string
console string
machine string
/* Cpu to use for qemu backend if the architecture doesn't have a good default */
qemuCPU string
}

var qemuMachines = map[Arch]qemuMachine{
Amd64: {
binary: "qemu-system-x86_64",
console: "ttyS0",
machine: "pc",
},
Arm64: {
binary: "qemu-system-aarch64",
console: "ttyAMA0",
machine: "virt",
/* The default cpu is a 32 bit one, which isn't very usefull
* for 64 bit arm. There is no cpu setting for "minimal" 64
* bit linux capable processor. The only generic setting
* is "max", but that can be very slow to emulate. So pick
* a specific small cortex-a processor instead */
qemuCPU: "cortex-a53",
},
}

func (b qemuBackend) QemuPath() (string, error) {
return exec.LookPath("qemu-system-x86_64")
machine, ok := qemuMachines[b.machine.arch]
if !ok {
return "", fmt.Errorf("unsupported arch for qemu: %s", b.machine.arch)
}

return exec.LookPath(machine.binary)
}

func (b qemuBackend) KernelRelease() (string, error) {
Expand Down Expand Up @@ -166,14 +197,15 @@ func (b qemuBackend) Start() (bool, error) {

func (b qemuBackend) StartQemu(kvm bool) (bool, error) {
m := b.machine
qemuMachine := qemuMachines[m.arch]

kernelPath, err := b.KernelPath()
if err != nil {
return false, err
}
memory := fmt.Sprintf("%d", m.memory)
numcpus := fmt.Sprintf("%d", m.numcpus)
qemuargs := []string{"qemu-system-x86_64",
qemuargs := []string{qemuMachine.binary,
"-smp", numcpus,
"-m", memory,
"-kernel", kernelPath,
Expand All @@ -185,9 +217,13 @@ func (b qemuBackend) StartQemu(kvm bool) (bool, error) {
qemuargs = append(qemuargs,
"-cpu", "host",
"-enable-kvm")
} else if qemuMachine.qemuCPU != "" {
qemuargs = append(qemuargs, "-cpu", qemuMachine.qemuCPU)
}

kernelargs := []string{"console=ttyS0", "panic=-1",
qemuargs = append(qemuargs, "-machine", qemuMachine.machine)
console := fmt.Sprintf("console=%s", qemuMachine.console)
kernelargs := []string{console, "panic=-1",
"systemd.unit=fakemachine.service"}

if m.showBoot {
Expand Down
9 changes: 7 additions & 2 deletions backend_uml.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build linux && amd64
// +build linux,amd64
//go:build linux
// +build linux

package fakemachine

Expand Down Expand Up @@ -27,6 +27,11 @@ func (b umlBackend) Name() string {
}

func (b umlBackend) Supported() (bool, error) {
// only support amd64
if b.machine.arch != Amd64 {
return false, fmt.Errorf("unsupported arch: %s", b.machine.arch)
}

// check the kernel exists
if _, err := b.KernelPath(); err != nil {
return false, err
Expand Down
33 changes: 28 additions & 5 deletions machine.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build linux && amd64
// +build linux,amd64
//go:build linux && (arm64 || amd64)

package fakemachine

Expand Down Expand Up @@ -153,6 +152,23 @@ func realDir(path string) (string, error) {
return filepath.Dir(p), nil
}

type Arch string

const (
Amd64 Arch = "amd64"
Arm64 Arch = "arm64"
)

var archMap = map[string]Arch{
"amd64": Amd64,
"arm64": Arm64,
}

var archDynamicLinker = map[Arch]string{
Amd64: "/lib64/ld-linux-x86-64.so.2",
Arm64: "/lib/ld-linux-aarch64.so.1",
}

type mountPoint struct {
hostDirectory string
machineDirectory string
Expand All @@ -166,6 +182,7 @@ type image struct {
}

type Machine struct {
arch Arch
backend backend
mounts []mountPoint
count int
Expand Down Expand Up @@ -193,6 +210,11 @@ func NewMachineWithBackend(backendName string) (*Machine, error) {
var err error
m := &Machine{memory: 2048, numcpus: runtime.NumCPU()}

var ok bool
if m.arch, ok = archMap[runtime.GOARCH]; !ok {
return nil, fmt.Errorf("unsupported arch %s", runtime.GOARCH)
}

m.backend, err = newBackend(backendName, m)
if err != nil {
return nil, err
Expand Down Expand Up @@ -669,6 +691,7 @@ func (m *Machine) startup(command string, extracontent [][2]string) (int, error)
{Target: "/usr/sbin", Link: "/sbin", Perm: 0755},
{Target: "/usr/bin", Link: "/bin", Perm: 0755},
{Target: "/usr/lib", Link: "/lib", Perm: 0755},
{Target: "/usr/lib64", Link: "/lib64", Perm: 0755},
})
if err != nil {
return -1, err
Expand Down Expand Up @@ -704,14 +727,14 @@ func (m *Machine) startup(command string, extracontent [][2]string) (int, error)
return -1, err
}

/* Amd64 dynamic linker */
err = w.CopyFile("/lib64/ld-linux-x86-64.so.2")
dynamicLinker := archDynamicLinker[m.arch]
err = w.CopyFile(prefix + dynamicLinker)
if err != nil {
return -1, err
}

/* C libraries */
libraryDir, err := realDir("/lib64/ld-linux-x86-64.so.2")
libraryDir, err := realDir(dynamicLinker)
if err != nil {
return -1, err
}
Expand Down

0 comments on commit 246072f

Please sign in to comment.