#!/usr/bin/env bash # # Copyright (c) 2018 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 #--------------------------------------------------------------------- # Description: This script is the *ONLY* place where "qemu*" build options # should be defined. # # Note to maintainers: # # XXX: Every option group *MUST* be documented explaining why it has # been specified. #--------------------------------------------------------------------- script_name=${0##*/} arch="${3:-$(uname -m)}" # Array of configure options. # # Each element is comprised of two parts in the form: # # tags:option # # Where, # # - 'tags' is a comma-separated list of values which denote why # the option is being specified. # # - 'option' is the hypervisor configuration option. typeset -a qemu_options typeset -A recognised_tags # Prefix were kata will be installed prefix=${PREFIX:-/usr} # The QEMU version on "major.minor" format. qemu_version="" recognised_tags=( [arch]="architecture-specific" [functionality]="required functionality" [minimal]="specified to avoid building unnecessary elements" [misc]="miscellaneous" [security]="specified for security reasons" [size]="minimise binary size" [speed]="maximise startup speed" ) # Given $1 and $2 as version strings with 'x.y.z' format; if $1 >= $2 then # return 0. Otherwise return 1. # Use this function on conditionals to compare versions. # gt_eq() { format='^[0-9]+(\.[0-9]+)*$' if [[ ! ("$1" =~ $format && "$2" =~ $format) ]]; then echo "ERROR: Malformed version string" fi echo -e "$1\n$2" | sort -V -r -C } # Display message to stderr and exit indicating script failed. die() { local msg="$*" echo >&2 "$script_name: ERROR: $msg" exit 1 } # Display usage to stdout. usage() { cat < Options: -d : Dump all options along with the tags explaining why each option is specified. -h : Display this help. -m : Display options one per line (includes continuation characters). -s : Generate options to build static Example: $ $script_name qemu EOF } show_tags_header() { local keys local key local value cat <= 8.0.0. if ! gt_eq "${qemu_version}" "8.0.0" ; then qemu_options+=(functionality:--disable-virtiofsd) fi qemu_options+=(functionality:--enable-virtfs) # Don't build linux-user bsd-user qemu_options+=(size:--disable-bsd-user) qemu_options+=(size:--disable-linux-user) # Don't build sparse check tool qemu_options+=(size:--disable-sparse) # Don't build VDE networking backend qemu_options+=(size:--disable-vde) # Don't build other options which can't be depent on build server. if ! gt_eq "${qemu_version}" "7.0.50" ; then qemu_options+=(size:--disable-xfsctl) qemu_options+=(size:--disable-libxml2) fi qemu_options+=(size:--disable-nettle) # Disable XEN driver qemu_options+=(size:--disable-xen) # Disable Capstone qemu_options+=(size:--disable-capstone) # Disable graphics qemu_options+=(size:--disable-virglrenderer) # Disable block replication qemu_options+=(size:--disable-replication) # Disable USB smart card reader qemu_options+=(size:--disable-smartcard) # Disable guest agent qemu_options+=(size:--disable-guest-agent) qemu_options+=(size:--disable-guest-agent-msi) # unused image formats qemu_options+=(size:--disable-vvfat) qemu_options+=(size:--disable-vdi) qemu_options+=(size:--disable-qed) qemu_options+=(size:--disable-qcow1) qemu_options+=(size:--disable-bochs) qemu_options+=(size:--disable-cloop) qemu_options+=(size:--disable-dmg) qemu_options+=(size:--disable-parallels) # Disable new available features from 8.2.4 qemu_options+=(size:--disable-colo-proxy) qemu_options+=(size:--disable-debug-graph-lock) qemu_options+=(size:--disable-hexagon-idef-parser) qemu_options+=(size:--disable-libdw) qemu_options+=(size:--disable-pipewire) qemu_options+=(size:--disable-pixman) qemu_options+=(size:--disable-relocatable) qemu_options+=(size:--disable-rutabaga-gfx) qemu_options+=(size:--disable-vmdk) qemu_options+=(size:--disable-avx512bw) qemu_options+=(size:--disable-vpc) qemu_options+=(size:--disable-vhdx) qemu_options+=(size:--disable-hv-balloon) # Disable various features based on the qemu_version if gt_eq "${qemu_version}" "9.1.0" ; then # Disable Query Processing Library support qemu_options+=(size:--disable-qpl) # Disable UADK Library support qemu_options+=(size:--disable-uadk) # Disable syscall buffer debugging support qemu_options+=(size:--disable-debug-remap) fi # Disable gio support qemu_options+=(size:--disable-gio) # Disable libdaxctl part of ndctl support qemu_options+=(size:--disable-libdaxctl) qemu_options+=(size:--disable-oss) # Building static binaries for aarch64 requires disabling PIE # We get an GOT overflow and the OS libraries are only build with fpic # and not with fPIC which enables unlimited sized GOT tables. if [ "${static}" == "true" ] && [ "${arch}" == "aarch64" ]; then qemu_options+=(arch:"--disable-pie") fi #--------------------------------------------------------------------- # Enabled options # Enable kernel Virtual Machine support. # This is the default, but be explicit to avoid any future surprises qemu_options+=(speed:--enable-kvm) # Required for fast network access qemu_options+=(speed:--enable-vhost-net) # Support Linux AIO (native) qemu_options+=(size:--enable-linux-aio) qemu_options+=(size:--enable-linux-io-uring) # Support Ceph RADOS Block Device (RBD) [ -z "${static}" ] && qemu_options+=(functionality:--enable-rbd) # In "passthrough" security mode # (-fsdev "...,security_model=passthrough,..."), qemu uses a helper # application called virtfs-proxy-helper(1) to make certain 9p # operations safer. qemu_options+=(functionality:--enable-virtfs) qemu_options+=(functionality:--enable-attr) # virtio-fs needs cap-ng and seccomp qemu_options+=(functionality:--enable-cap-ng) qemu_options+=(functionality:--enable-seccomp) # AVX2 is enabled by default by x86_64, make sure it's enabled only # for that architecture if [ "$arch" == x86_64 ]; then qemu_options+=(speed:--enable-avx2) qemu_options+=(speed:--enable-avx512bw) else qemu_options+=(speed:--disable-avx2) fi # We're disabling pmem support, it is heavilly broken with # Ubuntu's static build of QEMU qemu_options+=(functionality:--disable-libpmem) # Enable libc malloc_trim() for memory optimization. qemu_options+=(speed:--enable-malloc-trim) #--------------------------------------------------------------------- # Other options # 64-bit only if [ "${arch}" = "ppc64le" ]; then qemu_options+=(arch:"--target-list=ppc64-softmmu") else qemu_options+=(arch:"--target-list=${arch}-softmmu") fi # SECURITY: Create binary as a Position Independant Executable, # and take advantage of ASLR, making ROP attacks much harder to perform. # (https://wiki.debian.org/Hardening) [ -z "${static}" ] && qemu_options+=(arch:"--enable-pie") _qemu_cflags="" # compile with high level of optimisation # On version 5.2.0 onward the Meson build system warns to not use -O3 _qemu_cflags+=" -O2" # Improve code quality by assuming identical semantics for interposed # synmbols. # Only enable if gcc is 5.3 or newer if gt_eq "${gcc_version}" "5.3.0" ; then _qemu_cflags+=" -fno-semantic-interposition" fi # Performance optimisation _qemu_cflags+=" -falign-functions=32" # SECURITY: make the compiler check for common security issues # (such as argument and buffer overflows checks). _qemu_cflags+=" -D_FORTIFY_SOURCE=2" # Set compile options qemu_options+=(functionality,security,speed,size:"--extra-cflags=\"${_qemu_cflags}\"") unset _qemu_cflags _qemu_ldflags="" # SECURITY: Disallow executing code on the stack. _qemu_ldflags+=" -z noexecstack" # SECURITY: Make the linker set some program sections to read-only # before the program is run to stop certain attacks. _qemu_ldflags+=" -z relro" # SECURITY: Make the linker resolve all symbols immediately on program # load. _qemu_ldflags+=" -z now" qemu_options+=(security:"--extra-ldflags=\"${_qemu_ldflags}\"") unset _qemu_ldflags # Where to install qemu helper binaries qemu_options+=(misc:--prefix=${prefix}) # Where to install qemu libraries qemu_options+=(arch:--libdir=${prefix}/lib/${hypervisor}) # Where to install qemu helper binaries qemu_options+=(misc:--libexecdir=${prefix}/libexec/${hypervisor}) # Where to install data files qemu_options+=(misc:--datadir=${prefix}/share/${hypervisor}) } # Entry point main() { action="" while getopts "dhms" opt; do case "$opt" in d) action="dump" ;; h) usage exit 0 ;; m) action="multi" ;; s) static="true" ;; esac done shift $((OPTIND - 1)) [ -z "$1" ] && die "need hypervisor name" hypervisor="$1" local qemu_version_file="VERSION" [ -f ${qemu_version_file} ] || die "QEMU version file '$qemu_version_file' not found" # Remove any pre-release identifier so that it returns the version on # major.minor.patch format (e.g 5.2.0-rc4 becomes 5.2.0) qemu_version="$(awk 'BEGIN {FS = "-"} {print $1}' ${qemu_version_file})" [ -n "${qemu_version}" ] || die "cannot determine qemu version from file $qemu_version_file" if ! gt_eq "${qemu_version}" "6.1.0" ; then die "Kata requires QEMU >= 6.1.0" fi local gcc_version_major=$(gcc -dumpversion | cut -f1 -d.) [ -n "${gcc_version_major}" ] || die "cannot determine gcc major version, please ensure it is installed" # -dumpversion only returns the major version since GCC 7.0 if gt_eq "${gcc_version_major}" "7.0.0" ; then local gcc_version_minor=$(gcc -dumpfullversion | cut -f2 -d.) else local gcc_version_minor=$(gcc -dumpversion | cut -f2 -d.) fi [ -n "${gcc_version_minor}" ] || die "cannot determine gcc minor version, please ensure it is installed" local gcc_version="${gcc_version_major}.${gcc_version_minor}" # Generate qemu options generate_qemu_options show_array "$action" "${qemu_options[@]}" exit 0 } main $@