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