hype

command module
v0.0.0-...-9c233c6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 19, 2024 License: MIT Imports: 16 Imported by: 0

README

Hype is a collection of Go packages related to the Linux Kernel Virtual Machine (KVM). The long-term goal is to learn more about Linux internals, KVM, and virtio. The short-term goal is to boot a Linux guest with a virtio console, block storage, and network access on an amd64 Linux host.

Go reference

  • Package kvm provides wrappers for some KVM ioctls (without cgo)
  • Package vmm provides helpers for configuring and running a VM
  • Package os/linux provides a VM loader that boots a 64-bit bzImage in long mode
  • Package virtio implements parts of the virtio 1.2 spec (basic console, block only)

Booting a VM

This example boots Linux with an Alpine-based initrd. A virtio console is connected to stdin and stdout. The kernel is configured to run /sbin/reboot -f instead of a normal init, which causes the VM to exit as soon as it boots. If you want to run this example yourself, follow the instructions in "Building the guest kernel and initrd" below. Then go run ./cmd/readme-example.

If you remove rdinit=/sbin/reboot -- -f from the loader cmdline, the guest will run an init shell in a tty instead of just rebooting.

package main

import (
	"context"
	"os"

	"github.com/c35s/hype/os/linux"
	"github.com/c35s/hype/virtio"
	"github.com/c35s/hype/vmm"
	"golang.org/x/term"
)

func main() {
	bzImage, err := os.ReadFile(".build/linux/guest/arch/x86/boot/bzImage")
	if err != nil {
		panic(err)
	}

	initrd, err := os.ReadFile(".build/initrd.cpio.gz")
	if err != nil {
		panic(err)
	}

	cfg := vmm.Config{
		Devices: []virtio.DeviceConfig{
			&virtio.ConsoleDevice{
				In:  os.Stdin,
				Out: os.Stdout,
			},
		},

		Loader: &linux.Loader{
			Kernel:  bzImage,
			Initrd:  initrd,
			Cmdline: "reboot=t console=hvc0 rdinit=/sbin/reboot -- -f",
		},
	}

	m, err := vmm.New(cfg)
	if err != nil {
		panic(err)
	}

	if term.IsTerminal(int(os.Stdin.Fd())) {
		old, err := term.MakeRaw(int(os.Stdin.Fd()))
		if err != nil {
			panic(err)
		}

		defer term.Restore(int(os.Stdin.Fd()), old)
	}

	if err := m.Run(context.TODO()); err != nil {
		panic(err)
	}
}

an animation showing the output of the example code

Block devices

Any number of block devices can be configured. Block storage is pluggable, so a device can be backed by memory, a sparse file, an HTTP URL, or any other type implementing the virtio.BlockStorage interface.

Here's how to configure the builtin block storage backends:

f, err := os.OpenFile("blk.raw", os.O_RDWR, 0)
if err != nil {
	panic(err)
}

cfg := vmm.Config{
	Devices: []virtio.DeviceConfig{
		&virtio.BlockDevice{
			Storage: &virtio.MemStorage{
				Bytes: make([]byte, 0x1000),
			},
		},

		&virtio.BlockDevice{
			Storage: &virtio.FileStorage{
				File: f,
			},
		},

		&virtio.BlockDevice{
			Storage: &virtio.HTTPStorage{
				URL: "https://cdn.c35s.co/ubuntu-amd64.squashfs",
			},
		},

		// ...
	},
}

Use something like truncate -s 1G blk.raw to create a local sparse file.

Reference

Development

You will need an amd64 Linux environment with:

  • Linux kernel dev dependencies (to build the guest kernel)
  • Docker (to build the debug initrd)
  • Go 1.21.1 or better

Building the guest kernel and debug initrd

Hype includes a guest Linux kernel configuration for tests and and debugging. To build it, first make sure the lib/linux submodule is cloned by running git submodule update --init. It's gonna take a minute. After the submodule is cloned, run make -j $(nproc) guest to build the guest kernel and the debug initrd. The kernel build config is copied from etc/linux/guest. To edit the config, run make menuconfig-guest.

The debug initrd is built from etc/initrd/Dockerfile. It starts with the alpine base image and adds an init shim that mounts a few helpful things like /dev before executing /bin/sh in a tty. Try it for manual debugging and/or good old-fashioned pokin' around.

# this will connect your terminal to a shell in the vm
go run . -kernel .build/linux/guest/arch/x86/boot/bzImage -initrd .build/initrd.cpio.gz

Your shell is PID 1, so the kernel will get very angry if you exit. Use reboot -f instead.

Panics

To remove a panic, write a test that causes it, then change the code to return an annotated error, write to the log, or otherwise handle the condition instead of panicking. Simply returning the original error usually isn't useful.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
docker2cpio
docker2cpio receives a tar archive generated by "docker image save" as input and outputs a corresponding cpio archive.
docker2cpio receives a tar archive generated by "docker image save" as input and outputs a corresponding cpio archive.
kvm-gen-magic
kvm-gen-magic generates Go source code for some useful KVM constants.
kvm-gen-magic generates Go source code for some useful KVM constants.
kvm-print-ext
kvm-print-ext prints information about the KVM API and extensions.
kvm-print-ext prints information about the KVM API and extensions.
Package kvm provides minimal wrappers for some KVM ioctls.
Package kvm provides minimal wrappers for some KVM ioctls.
os
mmio
Package mmio implements a virtio-mmio device bus.
Package mmio implements a virtio-mmio device bus.
virtq
Package virtq partially implements packed virtqueues as described by the Virtual I/O Device (VIRTIO) Version 1.2 spec.
Package virtq partially implements packed virtqueues as described by the Virtual I/O Device (VIRTIO) Version 1.2 spec.
vmm
Package vmm provides helpers for configuring and running a KVM virtual machine.
Package vmm provides helpers for configuring and running a KVM virtual machine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL