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
78 changes: 78 additions & 0 deletions .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,48 @@ jobs:
- name: Setup build environment
uses: ./.github/actions/setup-build-env

- name: Install cross-compilation dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends lld

- name: Add musl target
run: rustup target add x86_64-unknown-linux-musl

- name: Add FreeBSD x86_64 target
run: rustup target add x86_64-unknown-freebsd

- name: Install FreeBSD test prerequisites
run: sudo apt-get install -y --no-install-recommends libarchive-tools

- name: Build FreeBSD sysroot and init
run: make BUILD_BSD_INIT=1 -- init/init-freebsd

- name: Install Go
uses: actions/setup-go@v4
with:
go-version: 'stable'

- name: Build and cache gvproxy (x86_64)
uses: actions/cache@v4
id: gvproxy-cache
with:
path: /tmp/gvproxy-bin/
key: gvproxy-x86_64-${{ github.run_number }}

- name: Build gvproxy from fork
if: steps.gvproxy-cache.outputs.cache-hit != 'true'
run: |
git clone https://github.com/nohajc/gvisor-tap-vsock /tmp/gvproxy-build
cd /tmp/gvproxy-build
mkdir -p /tmp/gvproxy-bin
make
cp bin/gvproxy /tmp/gvproxy-bin/gvproxy-x86_64

- name: Install gvproxy to PATH
run: |
sudo cp /tmp/gvproxy-bin/gvproxy-x86_64 /usr/local/bin/gvproxy

- name: Build and install libkrun to test prefix
run: make test-prefix

Expand Down Expand Up @@ -72,9 +111,48 @@ jobs:
- name: Setup build environment
uses: ./.github/actions/setup-build-env

- name: Install cross-compilation dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends clang lld

- name: Add musl target
run: rustup target add aarch64-unknown-linux-musl

- name: Install nightly toolchain with rust-src for FreeBSD aarch64
run: rustup +nightly-2026-01-25 component add rust-src

- name: Install FreeBSD test prerequisites
run: sudo apt-get install -y --no-install-recommends libarchive-tools

- name: Build FreeBSD sysroot and init
run: make BUILD_BSD_INIT=1 -- init/init-freebsd

- name: Install Go
uses: actions/setup-go@v4
with:
go-version: 'stable'

- name: Build and cache gvproxy (aarch64)
uses: actions/cache@v4
id: gvproxy-cache
with:
path: /tmp/gvproxy-bin/
key: gvproxy-aarch64-${{ github.run_number }}

- name: Build gvproxy from fork
if: steps.gvproxy-cache.outputs.cache-hit != 'true'
run: |
git clone https://github.com/nohajc/gvisor-tap-vsock /tmp/gvproxy-build
cd /tmp/gvproxy-build
mkdir -p /tmp/gvproxy-bin
make
cp bin/gvproxy /tmp/gvproxy-bin/gvproxy-aarch64

- name: Install gvproxy to PATH
run: |
sudo cp /tmp/gvproxy-bin/gvproxy-aarch64 /usr/local/bin/gvproxy

- name: Build and install libkrun to test prefix
run: make test-prefix

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 31 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ AWS_NITRO_INIT_SRC = \

AWS_NITRO_INIT_LD_FLAGS = -larchive -lnsm

INIT_SRC = init/init.c init/dhcp.c

ifeq ($(SEV),1)
VARIANT = -sev
FEATURE_FLAGS := --features amd-sev
Expand All @@ -31,6 +33,19 @@ endif
ifeq ($(VIRGL_RESOURCE_MAP2),1)
FEATURE_FLAGS += --features virgl_resource_map2
endif
# Test targets require the block device (BLK) feature for FreeBSD disk tests
# and the NET feature for gvproxy-based network tests.
# Enable automatically unless the user explicitly set them to a value.
ifeq ($(BLK),)
ifneq ($(filter test test-prefix,$(MAKECMDGOALS)),)
BLK := 1
endif
endif
ifeq ($(NET),)
ifneq ($(filter test test-prefix,$(MAKECMDGOALS)),)
NET := 1
endif
endif
ifeq ($(BLK),1)
FEATURE_FLAGS += --features blk
endif
Expand Down Expand Up @@ -120,7 +135,7 @@ $(AWS_NITRO_INIT_BINARY): $(AWS_NITRO_INIT_SRC)
$(CC) -O2 -static -s -Wall $(AWS_NITRO_INIT_LD_FLAGS) -o $@ $(AWS_NITRO_INIT_SRC) $(AWS_NITRO_INIT_LD_FLAGS)

ifeq ($(OS),Darwin)
# If SYSROOT_BSD is not set and we're on macOS, generate sysroot automatically
# macOS -> FreeBSD cross-compilation
ifeq ($(SYSROOT_BSD),)
SYSROOT_BSD = $(FREEBSD_ROOTFS_DIR)
SYSROOT_BSD_TARGET = $(FREEBSD_ROOTFS_DIR)/.sysroot_ready
Expand All @@ -129,6 +144,16 @@ else
endif
# Cross-compile on macOS with the LLVM linker (brew install lld)
CC_BSD=$(CLANG) -target $(ARCH)-unknown-freebsd -fuse-ld=lld -stdlib=libc++ -Wl,-strip-debug --sysroot $(SYSROOT_BSD)
else ifeq ($(OS),Linux)
# Linux -> FreeBSD cross-compilation
ifeq ($(SYSROOT_BSD),)
SYSROOT_BSD = $(FREEBSD_ROOTFS_DIR)
SYSROOT_BSD_TARGET = $(FREEBSD_ROOTFS_DIR)/.sysroot_ready
else
SYSROOT_BSD_TARGET =
endif
# Cross-compile on Linux with clang
CC_BSD=$(CLANG) -target $(ARCH)-unknown-freebsd -fuse-ld=lld -Wl,-strip-debug --sysroot $(SYSROOT_BSD)
else
# Build on FreeBSD host
CC_BSD=$(CC)
Expand All @@ -138,7 +163,7 @@ endif
ifeq ($(BUILD_BSD_INIT),1)
INIT_BINARY_BSD = init/init-freebsd
$(INIT_BINARY_BSD): $(INIT_SRC) $(SYSROOT_BSD_TARGET)
$(CC_BSD) -std=c23 -O2 -static -Wall $(INIT_DEFS) -lutil -o $@ $(INIT_SRC) $(INIT_DEFS)
$(CC_BSD) -std=c23 -O2 -static -Wall -lutil -o $@ $(INIT_SRC)
endif

# Sysroot preparation rules for cross-compilation on macOS
Expand Down Expand Up @@ -179,10 +204,12 @@ $(FREEBSD_ROOTFS_DIR)/.sysroot_ready: $(FREEBSD_BASE_TXZ)
@cd $(FREEBSD_ROOTFS_DIR) && tar xJf base.txz 2>/dev/null || true
@touch $@

BSD_ARCH=$(subst x86_64,amd64,$(subst aarch64,arm64,$(ARCH)))

$(FREEBSD_BASE_TXZ):
@echo "Downloading FreeBSD $(FREEBSD_VERSION) base for $(ARCH)..."
@echo "Downloading FreeBSD $(FREEBSD_VERSION) base for $(BSD_ARCH)..."
@mkdir -p $(FREEBSD_ROOTFS_DIR)
@curl -fL -o $@ https://download.freebsd.org/releases/$(ARCH)/$(FREEBSD_VERSION)/base.txz
@curl -fL -o $@ https://download.freebsd.org/releases/$(BSD_ARCH)/$(FREEBSD_VERSION)/base.txz

clean-sysroot:
rm -rf $(ROOTFS_DIR)
Expand Down
94 changes: 90 additions & 4 deletions init/dhcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@

#include <arpa/inet.h>
#include <errno.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
Expand All @@ -24,6 +20,22 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef __linux__
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#else /* FreeBSD */
#include <ifaddrs.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <netlink/netlink.h>
#include <netlink/route/common.h>
#include <netlink/route/ifaddrs.h>
#include <netlink/route/interface.h>
#include <netlink/route/route.h>
#include <sys/sockio.h>
#endif

#define DHCP_BUFFER_SIZE 576
#define DHCP_MSG_OFFER 2
Expand All @@ -33,6 +45,9 @@
static int nl_send(int sock, struct nlmsghdr *nlh)
{
struct sockaddr_nl sa = {
#ifdef __FreeBSD__
.nl_len = sizeof(struct sockaddr_nl),
#endif
.nl_family = AF_NETLINK,
};

Expand Down Expand Up @@ -194,6 +209,7 @@ static int mod_route4(int nl_sock, int iface_index, int cmd, struct in_addr gw)
static int mod_addr4(int nl_sock, int iface_index, int cmd, struct in_addr addr,
unsigned char prefix_len)
{
#ifdef __linux__
char buf[4096];
struct nlmsghdr *nlh;
struct nlmsgerr *err;
Expand Down Expand Up @@ -241,6 +257,45 @@ static int mod_addr4(int nl_sock, int iface_index, int cmd, struct in_addr addr,
}

return 0;
#else /* FreeBSD */
char iface_name[IFNAMSIZ];
struct ifaliasreq ifra;
struct sockaddr_in *sin;
int s, ret;

(void)nl_sock;
(void)cmd;

if (if_indextoname(iface_index, iface_name) == NULL) {
perror("if_indextoname failed for mod_addr4");
return -1;
}

memset(&ifra, 0, sizeof(ifra));
strncpy(ifra.ifra_name, iface_name, IFNAMSIZ - 1);

sin = (struct sockaddr_in *)&ifra.ifra_addr;
sin->sin_len = sizeof(*sin);
sin->sin_family = AF_INET;
sin->sin_addr = addr;

sin = (struct sockaddr_in *)&ifra.ifra_mask;
sin->sin_len = sizeof(*sin);
sin->sin_family = AF_INET;
sin->sin_addr.s_addr =
prefix_len == 0 ? 0 : htonl(~((1U << (32 - prefix_len)) - 1));

s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket failed for mod_addr4");
return -1;
}
ret = ioctl(s, SIOCAIFADDR, &ifra);
if (ret < 0)
perror("SIOCAIFADDR failed");
close(s);
return ret;
#endif
}

/* Count leading ones in a 32-bit value */
Expand Down Expand Up @@ -420,6 +475,9 @@ int do_dhcp(const char *iface)
}

struct sockaddr_nl sa = {
#ifdef __FreeBSD__
.nl_len = sizeof(struct sockaddr_nl),
#endif
.nl_family = AF_NETLINK,
.nl_pid = getpid(),
.nl_groups = 0,
Expand All @@ -444,11 +502,13 @@ int do_dhcp(const char *iface)
goto cleanup;
}

#ifdef __linux__
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface,
strlen(iface) + 1) < 0) {
perror("setsockopt SO_BINDTODEVICE failed");
goto cleanup;
}
#endif

/* Bind to port 68 (DHCP client) */
memset(&bind_addr, 0, sizeof(bind_addr));
Expand Down Expand Up @@ -477,6 +537,7 @@ int do_dhcp(const char *iface)
request.magic = htonl(0x63825363); /* Magic cookie */

/* Populate chaddr with the interface's MAC address */
#ifdef __linux__
struct ifreq mac_ifr;
memset(&mac_ifr, 0, sizeof(mac_ifr));
strncpy(mac_ifr.ifr_name, iface, IFNAMSIZ);
Expand All @@ -486,6 +547,31 @@ int do_dhcp(const char *iface)
goto cleanup;
}
memcpy(request.chaddr, mac_ifr.ifr_hwaddr.sa_data, 6);
#else /* FreeBSD */
{
struct ifaddrs *ifap, *ifa;
bool mac_found = false;

if (getifaddrs(&ifap) < 0) {
perror("getifaddrs failed");
goto cleanup;
}
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK &&
strcmp(ifa->ifa_name, iface) == 0) {
struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
memcpy(request.chaddr, LLADDR(sdl), 6);
mac_found = true;
break;
}
}
freeifaddrs(ifap);
if (!mac_found) {
fprintf(stderr, "could not find MAC address for %s\n", iface);
goto cleanup;
}
}
#endif

/* Build DHCP options */
int opt_offset = 0;
Expand Down
3 changes: 3 additions & 0 deletions src/arch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,8 @@ kvm-bindings = { version = "0.12", features = ["fam-wrappers"] }
kvm-ioctls = "0.22"
tdx = { version = "0.1.0", optional = true }

[target.'cfg(target_arch = "x86_64")'.dependencies]
linux-loader = { version = "0.13.2", features = ["elf"] }

[dev-dependencies]
utils = { path = "../utils" }
11 changes: 9 additions & 2 deletions src/arch/src/x86_64/gdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ fn get_base(entry: u64) -> u64 {
}

fn get_limit(entry: u64) -> u32 {
((((entry) & 0x000F_0000_0000_0000) >> 32) | ((entry) & 0x0000_0000_0000_FFFF)) as u32
let limit =
((((entry) & 0x000F_0000_0000_0000) >> 32) | ((entry) & 0x0000_0000_0000_FFFF)) as u32;

if get_g(entry) == 1 {
(limit << 12) | 0xFFF
} else {
limit
}
}

fn get_g(entry: u64) -> u8 {
Expand Down Expand Up @@ -109,7 +116,7 @@ mod tests {
assert_eq!(0xB, seg.type_);
// base and limit
assert_eq!(0x10_0000, seg.base);
assert_eq!(0xfffff, seg.limit);
assert_eq!(0xffffffff, seg.limit);
assert_eq!(0x0, seg.unusable);
}
}
Loading
Loading