diff --git a/doc/patch-author-guide.md b/doc/patch-author-guide.md index d85950e2..7dfeae3e 100644 --- a/doc/patch-author-guide.md +++ b/doc/patch-author-guide.md @@ -29,6 +29,8 @@ Table of contents - [Exported symbol versioning](#exported-symbol-versioning) - [System calls](#system-calls) - [Symbol Namespaces](#symbol-namespaces) +- [Cross Compile](#cross-compile) + Patch analysis -------------- @@ -964,3 +966,25 @@ ERROR: modpost: module livepatch-test uses symbol dma_buf_export from namespace ``` To manually import the required namespace, add the MODULE_IMPORT_NS() macro to the patch source. For example: `MODULE_IMPORT_NS("DMA_BUF")` + +Cross Compile +------------- + +It is recommended to build the livepatch in the same environment (compiler/library/etc.) as +the target kernel. When the target kernel was cross compiled for a different architecture, +it is recommended to cross compile the livepatch. + +There are two options to cross compile a livepatch. + +To specify a separate set of cross compilers, +we can set the `CROSS_COMPILE` environment variable. For example, to use `aarch64-gcc` and `aarch64-ld`, +we can run kpatch-build as +``` +CROSS_COMPILE=aarch64- kpatch-build ... +``` + +llvm/clang supports cross compile with the same binaries. To specify a cross compile target, we can +use the TARGET_ARCH environment variable, for example: +``` +TARGET_ARCH=aarch64 kpatch-build ... +``` diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 3343f37d..d91280da 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -40,6 +40,7 @@ set -o pipefail BASE="$PWD" SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")" ARCH="$(uname -m)" +TARGET_ARCH="${TARGET_ARCH:-$ARCH}" CPUS="$(getconf _NPROCESSORS_ONLN)" CACHEDIR="${CACHEDIR:-$HOME/.kpatch}" KERNEL_SRCDIR="$CACHEDIR/src" @@ -390,7 +391,7 @@ find_special_section_data() { check[e]=true # exception_table_entry # Arch-specific features - case "$ARCH" in + case "$TARGET_ARCH" in "x86_64") check[a]=true # alt_instr kernel_version_gte 5.10.0 && check[s]=true # static_call_site @@ -722,6 +723,15 @@ print_supported_distro(){ fi } +# Used in "make ARCH=xxx" when making the kernel. +# Match "aarch64" to "arm64", while keep everything else the same. +kernel_make_arch() { + if [[ "$1" == "aarch64" ]]; then + echo "arm64" + else + echo "$1" + fi +} usage() { echo "usage: $(basename "$0") [options] " >&2 @@ -1299,6 +1309,11 @@ else MAKEVARS+=("LD=${KPATCH_CC_PREFIX}${LD}") fi +if [[ "$ARCH" != "$TARGET_ARCH" ]]; then + KARCH=$(kernel_make_arch "$TARGET_ARCH") + MAKEVARS+=("ARCH=$KARCH") +fi + # $TARGETS used as list, no quotes. # shellcheck disable=SC2086 @@ -1489,7 +1504,12 @@ fi cd "$TEMPDIR/output" || die # $KPATCH_LDFLAGS and result of find used as list, no quotes. # shellcheck disable=SC2086,SC2046 -"$LD" -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die +if [[ "$ARCH" != "$TARGET_ARCH" ]]; then + # if cross compiling, use LLD to link + "$LLD" -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die +else + "$LD" -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die +fi if [[ "$USE_KLP" -eq 1 ]]; then cp -f "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o || die