1#!/usr/bin/env bash 2 3if [ -z "${BASH_VERSINFO[0]}" ] || [ "${BASH_VERSINFO[0]}" -lt 4 ] ; then 4 echo "Error: Bash version 4 or newer is required for the kvm-unit-tests" 5 exit 1 6fi 7 8srcdir=$(cd "$(dirname "$0")"; pwd) 9prefix=/usr/local 10cc=gcc 11cflags= 12ld=ld 13objcopy=objcopy 14objdump=objdump 15ar=ar 16addr2line=addr2line 17arch=$(uname -m | sed -e 's/i.86/i386/;s/arm64/aarch64/;s/arm.*/arm/;s/ppc64.*/ppc64/') 18host=$arch 19cross_prefix= 20endian="" 21pretty_print_stacks=yes 22environ_default=yes 23u32_long= 24wa_divide= 25target= 26errata_force=0 27erratatxt="$srcdir/errata.txt" 28host_key_document= 29gen_se_header= 30page_size= 31earlycon= 32efi= 33 34# Enable -Werror by default for git repositories only (i.e. developer builds) 35if [ -e "$srcdir"/.git ]; then 36 werror=-Werror 37else 38 werror= 39fi 40 41usage() { 42 cat <<-EOF 43 Usage: $0 [options] 44 45 Options include: 46 --arch=ARCH architecture to compile for ($arch) 47 --processor=PROCESSOR processor to compile for ($arch) 48 --target=TARGET target platform that the tests will be running on (qemu or 49 kvmtool, default is qemu) (arm/arm64 only) 50 --cross-prefix=PREFIX cross compiler prefix 51 --cc=CC c compiler to use ($cc) 52 --cflags=FLAGS extra options to be passed to the c compiler 53 --ld=LD ld linker to use ($ld) 54 --prefix=PREFIX where to install things ($prefix) 55 --endian=ENDIAN endianness to compile for (little or big, ppc64 only) 56 --[enable|disable]-pretty-print-stacks 57 enable or disable pretty stack printing (enabled by default) 58 --[enable|disable]-default-environ 59 enable or disable the generation of a default environ when 60 no environ is provided by the user (enabled by default) 61 --erratatxt=FILE specify a file to use instead of errata.txt. Use 62 '--erratatxt=' to ensure no file is used. 63 --host-key-document=HOST_KEY_DOCUMENT 64 Specify the machine-specific host-key document for creating 65 a PVM image with 'genprotimg' (s390x only) 66 --gen-se-header=GEN_SE_HEADER 67 Provide an executable to generate a PV header 68 requires --host-key-document. (s390x-snippets only) 69 --page-size=PAGE_SIZE 70 Specify the page size (translation granule) (4k, 16k or 71 64k, default is 64k, arm64 only) 72 --earlycon=EARLYCON 73 Specify the UART name, type and address (optional, arm and 74 arm64 only). The specified address will overwrite the UART 75 address set by the --target option. EARLYCON can be one of 76 (case sensitive): 77 uart[8250],mmio,ADDR 78 Specify an 8250 compatible UART at address ADDR. Supported 79 register stride is 8 bit only. 80 pl011,ADDR 81 pl011,mmio32,ADDR 82 Specify a PL011 compatible UART at address ADDR. Supported 83 register stride is 32 bit only. 84 --[enable|disable]-efi Boot and run from UEFI (disabled by default, x86_64 only) 85 --[enable|disable]-werror 86 Select whether to compile with the -Werror compiler flag 87EOF 88 exit 1 89} 90 91while [[ "$1" = -* ]]; do 92 opt="$1"; shift 93 arg= 94 if [[ "$opt" = *=* ]]; then 95 arg="${opt#*=}" 96 opt="${opt%%=*}" 97 fi 98 case "$opt" in 99 --prefix) 100 prefix="$arg" 101 ;; 102 --arch) 103 arch="$arg" 104 ;; 105 --processor) 106 processor="$arg" 107 ;; 108 --target) 109 target="$arg" 110 ;; 111 --cross-prefix) 112 cross_prefix="$arg" 113 ;; 114 --endian) 115 endian="$arg" 116 ;; 117 --cc) 118 cc="$arg" 119 ;; 120 --cflags) 121 cflags="$arg" 122 ;; 123 --ld) 124 ld="$arg" 125 ;; 126 --enable-pretty-print-stacks) 127 pretty_print_stacks=yes 128 ;; 129 --disable-pretty-print-stacks) 130 pretty_print_stacks=no 131 ;; 132 --enable-default-environ) 133 environ_default=yes 134 ;; 135 --disable-default-environ) 136 environ_default=no 137 ;; 138 --erratatxt) 139 erratatxt= 140 [ "$arg" ] && erratatxt=$(eval realpath "$arg") 141 ;; 142 --host-key-document) 143 host_key_document="$arg" 144 ;; 145 --gen-se-header) 146 gen_se_header="$arg" 147 ;; 148 --page-size) 149 page_size="$arg" 150 ;; 151 --earlycon) 152 earlycon="$arg" 153 ;; 154 --enable-efi) 155 efi=y 156 ;; 157 --disable-efi) 158 efi=n 159 ;; 160 --enable-werror) 161 werror=-Werror 162 ;; 163 --disable-werror) 164 werror= 165 ;; 166 --help) 167 usage 168 ;; 169 *) 170 usage 171 ;; 172 esac 173done 174 175if [ -n "$host_key_document" ] && [ ! -f "$host_key_document" ]; then 176 echo "Host key document doesn't exist at the specified location." 177 exit 1 178fi 179 180if [ "$erratatxt" ] && [ ! -f "$erratatxt" ]; then 181 echo "erratatxt: $erratatxt does not exist or is not a regular file" 182 exit 1 183fi 184 185arch_name=$arch 186[ "$arch" = "aarch64" ] && arch="arm64" 187[ "$arch_name" = "arm64" ] && arch_name="aarch64" 188 189if [ -z "$target" ]; then 190 target="qemu" 191else 192 if [ "$arch" != "arm64" ] && [ "$arch" != "arm" ]; then 193 echo "--target is not supported for $arch" 194 usage 195 fi 196fi 197 198if [ "$efi" ] && [ "$arch" != "x86_64" ]; then 199 echo "--[enable|disable]-efi is not supported for $arch" 200 usage 201fi 202 203if [ -z "$page_size" ]; then 204 [ "$arch" = "arm64" ] && page_size="65536" 205 [ "$arch" = "arm" ] && page_size="4096" 206else 207 if [ "$arch" != "arm64" ]; then 208 echo "--page-size is not supported for $arch" 209 usage 210 fi 211 212 if [ "${page_size: -1}" = "K" ] || [ "${page_size: -1}" = "k" ]; then 213 page_size=$(( ${page_size%?} * 1024 )) 214 fi 215 if [ "$page_size" != "4096" ] && [ "$page_size" != "16384" ] && 216 [ "$page_size" != "65536" ]; then 217 echo "arm64 doesn't support page size of $page_size" 218 usage 219 fi 220fi 221 222[ -z "$processor" ] && processor="$arch" 223 224if [ "$processor" = "arm64" ]; then 225 processor="cortex-a57" 226elif [ "$processor" = "arm" ]; then 227 processor="cortex-a15" 228fi 229 230if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then 231 testdir=x86 232elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 233 testdir=arm 234 if [ "$target" = "qemu" ]; then 235 arm_uart_early_addr=0x09000000 236 elif [ "$target" = "kvmtool" ]; then 237 arm_uart_early_addr=0x1000000 238 errata_force=1 239 else 240 echo "--target must be one of 'qemu' or 'kvmtool'!" 241 usage 242 fi 243 244 if [ "$earlycon" ]; then 245 IFS=, read -r name type_addr addr <<<"$earlycon" 246 if [ "$name" != "uart" ] && [ "$name" != "uart8250" ] && 247 [ "$name" != "pl011" ]; then 248 echo "unknown earlycon name: $name" 249 usage 250 fi 251 252 if [ "$name" = "pl011" ]; then 253 if [ -z "$addr" ]; then 254 addr=$type_addr 255 else 256 if [ "$type_addr" != "mmio32" ]; then 257 echo "unknown $name earlycon type: $type_addr" 258 usage 259 fi 260 fi 261 else 262 if [ "$type_addr" != "mmio" ]; then 263 echo "unknown $name earlycon type: $type_addr" 264 usage 265 fi 266 fi 267 268 if [ -z "$addr" ]; then 269 echo "missing $name earlycon address" 270 usage 271 fi 272 if [[ $addr =~ ^0(x|X)[0-9a-fA-F]+$ ]] || 273 [[ $addr =~ ^[0-9]+$ ]]; then 274 arm_uart_early_addr=$addr 275 else 276 echo "invalid $name earlycon address: $addr" 277 usage 278 fi 279 fi 280elif [ "$arch" = "ppc64" ]; then 281 testdir=powerpc 282 firmware="$testdir/boot_rom.bin" 283 if [ "$endian" != "little" ] && [ "$endian" != "big" ]; then 284 echo "You must provide endianness (big or little)!" 285 usage 286 fi 287else 288 testdir=$arch 289fi 290if [ ! -d "$srcdir/$testdir" ]; then 291 echo "$testdir does not exist!" 292 exit 1 293fi 294if [ -f "$srcdir/$testdir/run" ]; then 295 ln -fs "$srcdir/$testdir/run" $testdir-run 296fi 297 298testsubdir=$testdir 299if [ "$efi" = "y" ]; then 300 testsubdir=$testdir/efi 301fi 302 303# check if uint32_t needs a long format modifier 304cat << EOF > lib-test.c 305__UINT32_TYPE__ 306EOF 307u32_long=$("$cross_prefix$cc" -E lib-test.c | grep -v '^#' | grep -q long && echo yes) 308rm -f lib-test.c 309 310# check if slash can be used for division 311if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then 312 cat << EOF > lib-test.S 313foo: 314 movl (8 / 2), %eax 315EOF 316 wa_divide=$("$cross_prefix$cc" -c lib-test.S >/dev/null 2>&1 || echo yes) 317 rm -f lib-test.{o,S} 318fi 319 320# require enhanced getopt 321getopt -T > /dev/null 322if [ $? -ne 4 ]; then 323 echo "Enhanced getopt is not available, add it to your PATH?" 324 exit 1 325fi 326 327# Are we in a separate build tree? If so, link the Makefile 328# and shared stuff so that 'make' and run_tests.sh work. 329if test ! -e Makefile; then 330 echo "linking Makefile..." 331 ln -s "$srcdir/Makefile" . 332 333 echo "linking tests..." 334 mkdir -p $testsubdir 335 ln -sf "$srcdir/$testdir/run" $testdir/ 336 if test "$testdir" != "$testsubdir"; then 337 ln -sf "$srcdir/$testsubdir/run" $testsubdir/ 338 fi 339 ln -sf "$srcdir/$testdir/unittests.cfg" $testdir/ 340 ln -sf "$srcdir/run_tests.sh" 341 342 if [ -d "$srcdir/$testdir/snippets" ]; then 343 mkdir -p "$testdir/snippets/c" 344 fi 345 346 echo "linking scripts..." 347 ln -sf "$srcdir/scripts" 348fi 349 350# link lib/asm for the architecture 351rm -f lib/asm 352asm="asm-generic" 353if [ -d "$srcdir/lib/$arch/asm" ]; then 354 asm="$srcdir/lib/$arch/asm" 355elif [ -d "$srcdir/lib/$testdir/asm" ]; then 356 asm="$srcdir/lib/$testdir/asm" 357fi 358mkdir -p lib 359ln -sf "$asm" lib/asm 360 361 362# create the config 363cat <<EOF > config.mak 364SRCDIR=$srcdir 365PREFIX=$prefix 366HOST=$host 367ARCH=$arch 368ARCH_NAME=$arch_name 369PROCESSOR=$processor 370CC=$cross_prefix$cc 371CFLAGS=$cflags 372LD=$cross_prefix$ld 373OBJCOPY=$cross_prefix$objcopy 374OBJDUMP=$cross_prefix$objdump 375AR=$cross_prefix$ar 376ADDR2LINE=$cross_prefix$addr2line 377TEST_DIR=$testdir 378TEST_SUBDIR=$testsubdir 379FIRMWARE=$firmware 380ENDIAN=$endian 381PRETTY_PRINT_STACKS=$pretty_print_stacks 382ENVIRON_DEFAULT=$environ_default 383ERRATATXT=$erratatxt 384U32_LONG_FMT=$u32_long 385WA_DIVIDE=$wa_divide 386GENPROTIMG=${GENPROTIMG-genprotimg} 387HOST_KEY_DOCUMENT=$host_key_document 388CONFIG_EFI=$efi 389CONFIG_WERROR=$werror 390GEN_SE_HEADER=$gen_se_header 391EOF 392if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 393 echo "TARGET=$target" >> config.mak 394fi 395 396cat <<EOF > lib/config.h 397#ifndef _CONFIG_H_ 398#define _CONFIG_H_ 399/* 400 * Generated file. DO NOT MODIFY. 401 * 402 */ 403 404EOF 405if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 406cat <<EOF >> lib/config.h 407 408#define CONFIG_UART_EARLY_BASE ${arm_uart_early_addr} 409#define CONFIG_ERRATA_FORCE ${errata_force} 410#define CONFIG_PAGE_SIZE _AC(${page_size}, UL) 411 412EOF 413fi 414echo "#endif" >> lib/config.h 415