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