Skip to content
Open
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 .github/workflows/build-macos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Build macOS kernel (experimental)
on:
pull_request:
workflow_dispatch:

jobs:
build:
name: Build aarch64 kernel on macOS
runs-on: macos-latest
steps:
- name: Code checkout
uses: actions/checkout@v6

- name: Create case-sensitive build volume
run: |
hdiutil create -size 8g -type SPARSE -fs "Case-sensitive APFS" -volname libkrunfw-cs "$RUNNER_TEMP/libkrunfw-cs.sparseimage"
hdiutil attach "$RUNNER_TEMP/libkrunfw-cs.sparseimage" -mountpoint "$RUNNER_TEMP/libkrunfw-cs" -nobrowse
rsync -a ./ "$RUNNER_TEMP/libkrunfw-cs/libkrunfw/"
echo "BUILD_DIR=$RUNNER_TEMP/libkrunfw-cs/libkrunfw" >> "$GITHUB_ENV"

- name: Install dependencies
run: |
brew install gnu-sed gnu-tar llvm lld make bc bison flex
python3 -m venv "${BUILD_DIR}/.venv"
source "${BUILD_DIR}/.venv/bin/activate"
pip3 install pyelftools

- name: Build libkrunfw
working-directory: ${{ env.BUILD_DIR }}
run: |
for pkg in gnu-sed gnu-tar; do
PATH="$(brew --prefix)/opt/${pkg}/libexec/gnubin:$PATH"
done
PATH="$(brew --prefix)/opt/llvm/bin:$PATH"
export PATH
source .venv/bin/activate
make MACOS_BUILDER=native
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ __pycache__
*.pyc
*~
libkrunfw.so*
libkrunfw.*.dylib
kernel.c
vmlinux
/tarballs
Expand Down
71 changes: 65 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ KERNEL_FLAGS = KBUILD_BUILD_TIMESTAMP=$(TIMESTAMP)
KERNEL_FLAGS += KBUILD_BUILD_USER=root
KERNEL_FLAGS += KBUILD_BUILD_HOST=libkrunfw

ifeq ($(origin OS),command line)
# Use the explicit OS value from command line (e.g. make OS=Windows)
else
OS := $(shell uname -s)
endif
ifeq ($(OS),Darwin)
ifeq ($(origin MACOS_BUILDER),command line)
# Use the explicit MACOS_BUILDER value from command line (e.g. MACOS_BUILDER=native)
else
MACOS_BUILDER := krunvm
endif
endif

ifeq ($(SEV),1)
VARIANT = -sev
KERNEL_PATCHES += $(shell find patches-tee/ -name "0*.patch" | sort)
Expand All @@ -23,13 +36,13 @@ ifeq ($(TDX),1)
endif

HOSTARCH = $(shell uname -m)
ifeq ($(origin OS),command line)
# Use the explicit OS value from command line (e.g. make OS=Windows)
else
OS := $(shell uname -s)
endif
ifeq ($(ARCH),)
GUESTARCH := $(HOSTARCH)
ifeq ($(OS),Darwin)
ifeq ($(HOSTARCH),arm64)
GUESTARCH := aarch64
endif
endif
STRIP := strip
else ifeq ($(ARCH),arm64)
GUESTARCH := aarch64
Expand Down Expand Up @@ -81,6 +94,30 @@ ifeq ($(PREFIX),)
PREFIX := /usr/local
endif

ifeq ($(OS),Darwin)
ifeq ($(MACOS_BUILDER),native)
# Native macOS kernel build tools (override on the make command line).
KERNEL_MAKE ?= gmake
KERNEL_CC ?= clang
KERNEL_LD ?= ld.lld
KERNEL_AR ?= llvm-ar
KERNEL_NM ?= llvm-nm
KERNEL_OBJCOPY ?= llvm-objcopy
KERNEL_OBJDUMP ?= llvm-objdump
KERNEL_STRIP ?= llvm-strip
KERNEL_READELF ?= llvm-readelf
KERNEL_HOSTCC ?= $(KERNEL_CC)

KERNEL_KBUILD_FLAGS = LLVM=1 ARCH=arm64 \
CC=$(KERNEL_CC) LD=$(KERNEL_LD) AR=$(KERNEL_AR) NM=$(KERNEL_NM) \
OBJCOPY=$(KERNEL_OBJCOPY) OBJDUMP=$(KERNEL_OBJDUMP) STRIP=$(KERNEL_STRIP) \
READELF=$(KERNEL_READELF) HOSTCC=$(KERNEL_HOSTCC) \
$(KERNEL_FLAGS)
MACOS_HOST_INCLUDE = $(CURDIR)/include/macos-host
KERNEL_HOSTFLAGS = HOSTCFLAGS="-I$(MACOS_HOST_INCLUDE) -D_UUID_T -D__GETHOSTUUID_H"
endif
endif

ifeq ($(SEV),1)
QBOOT_BINARY = qboot/sev/bios.bin
QBOOT_C_BUNDLE = qboot.c
Expand All @@ -106,20 +143,42 @@ $(KERNEL_SOURCES): $(KERNEL_TARBALL)
tar xf $(KERNEL_TARBALL)
for patch in $(KERNEL_PATCHES); do patch -p1 -d $(KERNEL_SOURCES) < "$$patch"; done
cp config-libkrunfw$(VARIANT)_$(GUESTARCH) $(KERNEL_SOURCES)/.config
ifeq ($(OS),Darwin)
ifeq ($(MACOS_BUILDER),native)
cd $(KERNEL_SOURCES) && $(KERNEL_MAKE) $(KERNEL_KBUILD_FLAGS) $(KERNEL_HOSTFLAGS) olddefconfig
else
cd $(KERNEL_SOURCES) ; $(MAKE) olddefconfig
endif
else
cd $(KERNEL_SOURCES) ; $(MAKE) olddefconfig
endif

$(KERNEL_BINARY_$(GUESTARCH)): $(KERNEL_SOURCES)
ifeq ($(OS),Darwin)
ifeq ($(MACOS_BUILDER),native)
cd $(KERNEL_SOURCES) && rm -f .version && $(KERNEL_MAKE) $(MAKEFLAGS) $(KERNEL_KBUILD_FLAGS) $(KERNEL_HOSTFLAGS)
else
cd $(KERNEL_SOURCES) ; rm -f .version ; $(MAKE) $(MAKEFLAGS) $(KERNEL_FLAGS)
endif
else
cd $(KERNEL_SOURCES) ; rm -f .version ; $(MAKE) $(MAKEFLAGS) $(KERNEL_FLAGS)
endif

ifeq ($(OS),Darwin)
ifeq ($(MACOS_BUILDER),krunvm)
$(KERNEL_C_BUNDLE):
@echo "Building on macOS, using ./build_on_krunvm.sh"
@echo "Building on macOS using krunvm (./build_on_krunvm.sh)"
./build_on_krunvm.sh
else
$(KERNEL_C_BUNDLE): $(KERNEL_BINARY_$(GUESTARCH))
@echo "Generating $(KERNEL_C_BUNDLE) from $(KERNEL_BINARY_$(GUESTARCH))..."
@python3 bin2cbundle.py --os $(OS) -t $(KBUNDLE_TYPE_$(GUESTARCH)) $(KERNEL_BINARY_$(GUESTARCH)) kernel.c
endif
else
$(KERNEL_C_BUNDLE): $(KERNEL_BINARY_$(GUESTARCH))
@echo "Generating $(KERNEL_C_BUNDLE) from $(KERNEL_BINARY_$(GUESTARCH))..."
@python3 bin2cbundle.py --os $(OS) -t $(KBUNDLE_TYPE_$(GUESTARCH)) $(KERNEL_BINARY_$(GUESTARCH)) kernel.c
endif

ifeq ($(SEV),1)
$(QBOOT_C_BUNDLE): $(QBOOT_BINARY)
Expand Down
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ sudo make SEV=1 install

### macOS

#### Requirements
#### Building the library using krunvm

Compiling a Linux kernel natively on macOS is not an easy feat. For this reason, the recommended way for building ```libkrunfw``` in this platform is by already having installed a binary version of [krunvm](https://github.com/containers/krunvm) and its dependencies ([libkrun](https://github.com/containers/libkrun), and ```libkrunfw``` itself), such as the one available in the [krunvm Homebrew repo](https://github.com/slp/homebrew-krun), and then executing the [build_on_krunvm.sh](build_on_krunvm.sh) script found in this repository.

This will create a lightweight Linux VM using ```krunvm``` with the current working directory mapped inside it, and build the kernel on it.

#### Building the library using krunvm
```
./build_on_krunvm.sh
make
Expand All @@ -54,6 +53,30 @@ BUILDER=debian ./build_on_krunvm.sh

In general, `./build_on_krunvm.sh` will always delegate to `./build_on_krunvm_${BUILDER}.sh` so additional environments can be added like this if needed.

#### Building the library natively (experimental)

The Linux kernel can be compiled natively on macOS. You will need some dependencies:
* LLVM toolchain (`clang`, `lld`, etc.) (the version provided by Apple may not work)
* GNU `make`
* GNU `sed`
* GNU `tar`
* A case-sensitive file system

The name of the `make`, `cc`, and some other executables can be overridden as arguments to the Makefile. If needed, you can also prepend to the `PATH` so that GNU versions of executables are chosen at higher priority.

```
# Create a case-sensitive disk image and mount it
hdiutil create -size 8g -type SPARSE -fs "Case-sensitive APFS" -volname libkrunfw-cs ../libkrunfw-cs.sparseimage
hdiutil attach ../libkrunfw-cs.sparseimage

# Copy this source tree into the mounted disk image
rsync -a ./ /Volumes/libkrunfw-cs/

# Set up paths to the dependencies as needed, for example
export PATH=/path/to/dir/containing/gnu/sed:/path/to/dir/containing/gnu/tar:$PATH
make MACOS_BUILDER=native
```

### Windows (cross-compilation from Linux)

#### Requirements
Expand Down
6 changes: 6 additions & 0 deletions include/macos-host/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Vendored from https://github.com/bee-headers/headers.

* elf.h — GNU Lesser General Public License v2.1 only (from GNU C Library)
* endian.h, byteswap.h — GNU General Public License v2.0 only

See the top-level LICENSE-GPL-2.0-only and LICENSE-LGPL-2.1-only files in this repository.
9 changes: 9 additions & 0 deletions include/macos-host/byteswap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _BYTESWAP_H
#define _BYTESWAP_H 1

#define bswap_16 __builtin_bswap16
#define bswap_32 __builtin_bswap32
#define bswap_64 __builtin_bswap64

#endif /* _BYTESWAP_H */
Loading