From ebeb2847e2e9281eeef28a9059fa711991d0f4f7 Mon Sep 17 00:00:00 2001 From: Otis Chung Date: Mon, 30 Jun 2025 16:11:11 +0800 Subject: [PATCH 1/2] arm64: enable virtio-net and add network scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable POSIX timers to support ping’s POSIX timer syscalls: - CONFIG_POSIX_TIMERS=y in configs/linux-arm64.config Enable network stack and virtio-net in kernel config: - CONFIG_NET, CONFIG_INET, CONFIG_IP_MULTICAST, CONFIG_IP_PNP - CONFIG_IP_PNP_DHCP, CONFIG_NETDEVICES, CONFIG_VIRTIO - CONFIG_VIRTIO_NET, CONFIG_VIRTIO_RING, CONFIG_UNIX - CONFIG_UNIX_SCM, CONFIG_AF_UNIX_OOB Add virtio_net_dev to FDT generation: - src/arch/arm64/vm.c: include virtio_net_dev in interrupt-map Define VIRTIO_NET_IRQ=2 (SPI 34) in src/arch/arm64/desc.h Add scripts for host and guest network setup: - scripts/set-host-bridge.sh to configure TAP bridge and default route - scripts/set-guest-route.sh to configure guest static IP and route Update README.md with new scripts and build instructions These changes have been validated on a Raspberry Pi 5 Model B (Revision 1.0) running Ubuntu 25.10 with Linux kernel version 6.14.0. --- README.md | 57 ++++++++++++++++++++++++++++++++++++++ configs/linux-arm64.config | 14 +++++++++- scripts/set-guest-route.sh | 3 ++ scripts/set-host-bridge.sh | 9 ++++++ src/arch/arm64/desc.h | 1 + src/arch/arm64/vm.c | 35 ++++++++++++++++------- 6 files changed, 108 insertions(+), 11 deletions(-) create mode 100755 scripts/set-guest-route.sh create mode 100755 scripts/set-host-bridge.sh diff --git a/README.md b/README.md index 35f1a66..998a373 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ make check ## Usage +### Start Emulator + ``` build/kvm-host -k bzImage [-i initrd] [-d disk-image] ``` @@ -42,8 +44,63 @@ containing concatenated `bootsect.o + setup.o + misc.o + piggy.o`. `initrd` is t initial RAM disk image, which is an optional argument. `disk-image` is the path to disk image which can be mounted as a block device via virtio. For the reference Linux guest, ext4 filesystem is used for disk image. +### Stop Emulator + To exit kvm-host, press "Ctrl-A", release both keys, and then press "x". +### Enable Static Route to Test the Guest VirtIO-Net Interface + +1. Start the kvm-host emulator. Once initialized, the TUN/TAP interface (for example, `tap0`) is visible in the output of `ip a`. The following is sample output from the host: + + ```shell + ❯ ip a + 1: lo: ... + 2: eth0: ... + 3: wlan0: mtu 1500 qdisc fq_codel state UP group default qlen 1000 + link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff + altname xxxxxxxxxxxxxxx + inet 192.168.x.x/24 brd 192.168.x.255 scope global dynamic noprefixroute wlan0 + valid_lft xxxxxxsec preferred_lft xxxxxxsec + inet6 ... + 11: tap0: mtu 1500 qdisc noop state DOWN group default qlen 1000 + link/ether 5a:1d:bd:2d:7c:1f brd ff:ff:ff:ff:ff:ff + ``` + +2. Execute the shell script `./scripts/set-host-bridge.sh`, which configures a bridge by assigning the default route to 10.0.0.1, integrating the TUN/TAP interface into the bridge, and activating the network interfaces. The following is sample output of `ip a` from the host: + + ```shell + ❯ ip a + ... + 11: tap0: mtu 1500 qdisc noop state DOWN group default qlen 1000 + link/ether 5a:1d:bd:2d:7c:1f brd ff:ff:ff:ff:ff:ff + 12: br0: mtu 1500 qdisc noop state DOWN group default qlen 1000 + link/ether d6:92:97:85:e8:7c brd ff:ff:ff:ff:ff:ff + inet 10.0.0.1/24 scope global br0 + valid_lft forever preferred_lft forever + ``` + +3. Copy the commands from `scripts/set-guest-route.sh` into the guest environment and execute them. Below is a sample `ip a` output from the guest: + + ```shell + ~ # ip a + 1: lo: mtu 65536 qdisc noop qlen 1000 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + 2: eth0: mtu 1500 qdisc pfifo_fast qlen 1000 + link/ether c2:5a:92:87:97:42 brd ff:ff:ff:ff:ff:ff + inet 10.0.0.2/24 scope global eth0 + valid_lft forever preferred_lft forever + inet6 fe80::c05a:92ff:fe87:9742/64 scope link + valid_lft forever preferred_lft forever + 3: sit0@NONE: mtu 1480 qdisc noop qlen 1000 + link/sit 0.0.0.0 brd 0.0.0.0 + ``` + +4. Test guest network connectivity by pinging the configured default gateway. + + ```bash + ping 10.0.0.1 + ``` + ## License `kvm-host` is released under the BSD 2 clause license. Use of this source code is governed by diff --git a/configs/linux-arm64.config b/configs/linux-arm64.config index 395c4be..60a6523 100644 --- a/configs/linux-arm64.config +++ b/configs/linux-arm64.config @@ -12,7 +12,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_MULTIUSER is not set # CONFIG_SYSFS_SYSCALL is not set # CONFIG_FHANDLE is not set -# CONFIG_POSIX_TIMERS is not set +CONFIG_POSIX_TIMERS=y # CONFIG_BUG is not set # CONFIG_BASE_FULL is not set # CONFIG_FUTEX is not set @@ -66,3 +66,15 @@ CONFIG_EXT4_FS=y # CONFIG_DEBUG_MISC is not set # CONFIG_FTRACE is not set # CONFIG_STRICT_DEVMEM is not set +CONFIG_NET=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NETDEVICES=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_RING=y +CONFIG_UNIX=y +CONFIG_UNIX_SCM=y +CONFIG_AF_UNIX_OOB=y diff --git a/scripts/set-guest-route.sh b/scripts/set-guest-route.sh new file mode 100755 index 0000000..66fa6eb --- /dev/null +++ b/scripts/set-guest-route.sh @@ -0,0 +1,3 @@ +ip addr add 10.0.0.2/24 dev eth0 +ip link set eth0 up +ip route add default via 10.0.0.1 diff --git a/scripts/set-host-bridge.sh b/scripts/set-host-bridge.sh new file mode 100755 index 0000000..d0d53af --- /dev/null +++ b/scripts/set-host-bridge.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +sudo ip link delete br0 || true +sudo brctl addbr br0 +sudo ip addr add 10.0.0.1/24 dev br0 +sudo ip route add default via 10.0.0.1 dev br0 +sudo ip link set br0 up +sudo ip link set tap0 master br0 +sudo ip link set tap0 up diff --git a/src/arch/arm64/desc.h b/src/arch/arm64/desc.h index b567c33..49d2619 100644 --- a/src/arch/arm64/desc.h +++ b/src/arch/arm64/desc.h @@ -3,4 +3,5 @@ #define RAM_BASE (1UL << 31) #define SERIAL_IRQ 0 #define VIRTIO_BLK_IRQ 1 +#define VIRTIO_NET_IRQ 2 #define KERNEL_OPTS "console=ttyS0" diff --git a/src/arch/arm64/vm.c b/src/arch/arm64/vm.c index b9720aa..42d5e04 100644 --- a/src/arch/arm64/vm.c +++ b/src/arch/arm64/vm.c @@ -378,10 +378,12 @@ static int generate_fdt(vm_t *v) __FDT(property, "ranges", &pci_ranges, sizeof(pci_ranges)); /* interrupt-map contains the interrupt mapping between the PCI device and * the IRQ number of interrupt controller. - * virtio-blk is the only PCI device. + * interrupt-map: map each PCI device’s INTA#: GIC SPI */ struct virtio_blk_dev *virtio_blk = &v->virtio_blk_dev; struct pci_dev *virtio_blk_pci = (struct pci_dev *) virtio_blk; + struct virtio_net_dev *virtio_net = &v->virtio_net_dev; + struct pci_dev *virtio_net_pci = (struct pci_dev *) virtio_net; struct { uint32_t pci_hi; uint64_t pci_addr; @@ -390,15 +392,28 @@ static int generate_fdt(vm_t *v) uint32_t gic_type; uint32_t gic_irqn; uint32_t gic_irq_type; - } __attribute__((packed)) pci_irq_map[] = {{ - cpu_to_fdt32(virtio_blk_pci->config_dev.base & ~(1UL << 31)), - 0, - cpu_to_fdt32(1), - cpu_to_fdt32(FDT_PHANDLE_GIC), - cpu_to_fdt32(ARM_FDT_IRQ_TYPE_SPI), - cpu_to_fdt32(VIRTIO_BLK_IRQ), - cpu_to_fdt32(ARM_FDT_IRQ_EDGE_TRIGGER), - }}; + } __attribute__((packed)) pci_irq_map[] = { + /* virtio-blk: SPI VIRTIO_BLK_IRQ */ + { + cpu_to_fdt32(virtio_blk_pci->config_dev.base & ~(1UL << 31)), + 0, + cpu_to_fdt32(1), + cpu_to_fdt32(FDT_PHANDLE_GIC), + cpu_to_fdt32(ARM_FDT_IRQ_TYPE_SPI), + cpu_to_fdt32(VIRTIO_BLK_IRQ), + cpu_to_fdt32(ARM_FDT_IRQ_EDGE_TRIGGER), + }, + /* virtio-net: SPI VIRTIO_NET_IRQ */ + { + cpu_to_fdt32(virtio_net_pci->config_dev.base & ~(1UL << 31)), + 0, + cpu_to_fdt32(1), + cpu_to_fdt32(FDT_PHANDLE_GIC), + cpu_to_fdt32(ARM_FDT_IRQ_TYPE_SPI), + cpu_to_fdt32(VIRTIO_NET_IRQ), + cpu_to_fdt32(ARM_FDT_IRQ_EDGE_TRIGGER), + }, + }; __FDT(property, "interrupt-map", &pci_irq_map, sizeof(pci_irq_map)); __FDT(end_node); /* End of /pci node */ From 60835d65f83a46281cf1f5b7709ccf6d766c709e Mon Sep 17 00:00:00 2001 From: Otis Chung Date: Mon, 30 Jun 2025 16:20:05 +0800 Subject: [PATCH 2/2] Fix the URL in README.md The previous URL of The Linux/x86 Boot Protocol returned a 404 error due to an incorrect origin. Updated the link to point to the correct resource. References: - The Linux/x86 Boot Protocol: https://www.kernel.org/doc/html/latest/arch/x86/boot.html --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 998a373..d6bad6a 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ a BSD-style license that can be found in the LICENSE file. ## References * [kvmtool](https://github.com/kvmtool/kvmtool) * [KVM (Kernel-based Virtual Machine) API](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt) -* [The Linux/x86 Boot Protocol](https://www.kernel.org/doc/html/latest/x86/boot.html) +* [The Linux/x86 Boot Protocol](https://www.kernel.org/doc/html/latest/arch/x86/boot.html) * [Using the KVM API](https://lwn.net/Articles/658511/) * [gokvm](https://github.com/bobuhiro11/gokvm) * [KVM Host in a few lines of code](https://zserge.com/posts/kvm/)