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 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" != "arm64" ] && [ "$arch" != "arm" ]; then 288 echo "--target is not supported for $arch" 289 usage 290 fi 291fi 292 293if [ "$efi" ] && [ "$arch" != "x86_64" ] && 294 [ "$arch" != "arm64" ] && [ "$arch" != "riscv64" ]; then 295 echo "--[enable|disable]-efi is not supported for $arch" 296 usage 297fi 298 299if [ "$efi" ] && [ "$arch" = "riscv64" ] && [ -z "$efi_direct" ]; then 300 efi_direct=y 301fi 302 303if [ -z "$page_size" ]; then 304 if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 305 page_size="4096" 306 elif [ "$arch" = "ppc64" ]; then 307 page_size="65536" 308 fi 309else 310 if [ "${page_size: -1}" = "K" ] || [ "${page_size: -1}" = "k" ]; then 311 page_size=$(( ${page_size%?} * 1024 )) 312 fi 313 314 if [ "$arch" = "arm64" ]; then 315 if [ "$page_size" != "4096" ] && [ "$page_size" != "16384" ] && 316 [ "$page_size" != "65536" ]; then 317 echo "arm64 doesn't support page size of $page_size" 318 usage 319 fi 320 if [ "$efi" = 'y' ] && [ "$page_size" != "4096" ]; then 321 echo "efi must use 4K pages" 322 exit 1 323 fi 324 elif [ "$arch" = "ppc64" ]; then 325 if [ "$page_size" != "4096" ] && [ "$page_size" != "65536" ]; then 326 echo "ppc64 doesn't support page size of $page_size" 327 usage 328 fi 329 else 330 echo "--page-size is not supported for $arch" 331 usage 332 fi 333fi 334 335if [ "$earlycon" ]; then 336 IFS=, read -r name type_addr addr <<<"$earlycon" 337 if [ "$name" != "uart" ] && [ "$name" != "uart8250" ] && [ "$name" != "pl011" ]; then 338 echo "unknown earlycon name: $name" 339 usage 340 fi 341 342 if [ "$name" = "pl011" ]; then 343 if [ -z "$addr" ]; then 344 addr=$type_addr 345 else 346 if [ "$type_addr" != "mmio32" ]; then 347 echo "unknown $name earlycon type: $type_addr" 348 usage 349 fi 350 fi 351 else 352 if [ "$type_addr" != "mmio" ]; then 353 echo "unknown $name earlycon type: $type_addr" 354 usage 355 fi 356 fi 357 358 if [ -z "$addr" ]; then 359 echo "missing $name earlycon address" 360 usage 361 fi 362 if [[ $addr =~ ^0(x|X)[0-9a-fA-F]+$ ]] || [[ $addr =~ ^[0-9]+$ ]]; then 363 uart_early_addr=$addr 364 else 365 echo "invalid $name earlycon address: $addr" 366 usage 367 fi 368fi 369 370# $arch will have changed when cross-compiling. 371[ -z "$processor" ] && processor=$(get_default_processor $arch) 372 373if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then 374 testdir=x86 375elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 376 testdir=arm 377 if [ "$target" = "qemu" ]; then 378 : "${uart_early_addr:=0x9000000}" 379 elif [ "$target" = "kvmtool" ]; then 380 : "${uart_early_addr:=0x1000000}" 381 else 382 echo "--target must be one of 'qemu' or 'kvmtool'!" 383 usage 384 fi 385elif [ "$arch" = "ppc64" ]; then 386 testdir=powerpc 387 firmware="$testdir/boot_rom.bin" 388 if [ "$endian" != "little" ] && [ "$endian" != "big" ]; then 389 echo "You must provide endianness (big or little)!" 390 usage 391 fi 392elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then 393 testdir=riscv 394 arch_libdir=riscv 395 : "${uart_early_addr:=0x10000000}" 396elif [ "$arch" = "s390x" ]; then 397 testdir=s390x 398else 399 echo "arch $arch is not supported!" 400 arch= 401 usage 402fi 403if [ ! -d "$srcdir/$testdir" ]; then 404 echo "$srcdir/$testdir does not exist!" 405 exit 1 406fi 407 408if [ "$efi" = "y" ] && [ -f "$srcdir/$testdir/efi/run" ]; then 409 ln -fs "$srcdir/$testdir/efi/run" $testdir-run 410elif [ -f "$srcdir/$testdir/run" ]; then 411 ln -fs "$srcdir/$testdir/run" $testdir-run 412fi 413 414testsubdir=$testdir 415if [ "$efi" = "y" ]; then 416 testsubdir=$testdir/efi 417fi 418 419# check if uint32_t needs a long format modifier 420cat << EOF > lib-test.c 421__UINT32_TYPE__ 422EOF 423u32_long=$("$cc" $cflags -E lib-test.c | grep -v '^#' | grep -q long && echo yes) 424rm -f lib-test.c 425 426# check if slash can be used for division 427if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then 428 cat << EOF > lib-test.S 429foo: 430 movl (8 / 2), %eax 431EOF 432 wa_divide=$("$cc" $cflags -c lib-test.S >/dev/null 2>&1 || echo yes) 433 rm -f lib-test.{o,S} 434fi 435 436# warn if enhanced getopt is unavailable 437getopt -T > /dev/null 438if [ $? -ne 4 ]; then 439 echo "Without enhanced getopt you won't be able to use run_tests.sh." 440 echo "Add it to your PATH?" 441fi 442 443# Are we in a separate build tree? If so, link the Makefile 444# and shared stuff so that 'make' and run_tests.sh work. 445if test ! -e Makefile; then 446 echo "linking Makefile..." 447 ln -s "$srcdir/Makefile" . 448 449 echo "linking tests..." 450 mkdir -p $testsubdir 451 ln -sf "$srcdir/$testdir/run" $testdir/ 452 if test "$testdir" != "$testsubdir"; then 453 ln -sf "$srcdir/$testsubdir/run" $testsubdir/ 454 fi 455 ln -sf "$srcdir/$testdir/unittests.cfg" $testdir/ 456 ln -sf "$srcdir/run_tests.sh" 457 458 if [ -d "$srcdir/$testdir/snippets" ]; then 459 mkdir -p "$testdir/snippets/c" 460 fi 461 462 echo "linking scripts..." 463 ln -sf "$srcdir/scripts" 464fi 465 466# link lib/asm for the architecture 467rm -f lib/asm 468asm="asm-generic" 469if [ -d "$srcdir/lib/$arch/asm" ]; then 470 asm="$srcdir/lib/$arch/asm" 471 mkdir -p "lib/$arch" 472elif [ -d "$srcdir/lib/$arch_libdir/asm" ]; then 473 asm="$srcdir/lib/$arch_libdir/asm" 474 mkdir -p "lib/$arch_libdir" 475elif [ -d "$srcdir/lib/$testdir/asm" ]; then 476 asm="$srcdir/lib/$testdir/asm" 477 mkdir -p "lib/$testdir" 478fi 479ln -sf "$asm" lib/asm 480mkdir -p lib/generated lib/libfdt 481 482# create the config 483cat <<EOF > config.mak 484# Shellcheck does not see these are used 485# shellcheck disable=SC2034 486# Shellcheck can give pointless quoting warnings for some commands 487# shellcheck disable=SC2209 488SRCDIR=$srcdir 489PREFIX=$prefix 490HOST=$host 491ARCH=$arch 492ARCH_NAME=$arch_name 493ARCH_LIBDIR=$arch_libdir 494PROCESSOR=$processor 495TARGET_CPU=$target_cpu 496DEFAULT_QEMU_CPU=$(get_default_qemu_cpu $arch) 497CC=$cc 498CFLAGS=$cflags 499LD=$cross_prefix$ld 500OBJCOPY=$cross_prefix$objcopy 501OBJDUMP=$cross_prefix$objdump 502READELF=$cross_prefix$readelf 503AR=$cross_prefix$ar 504ADDR2LINE=$cross_prefix$addr2line 505TEST_DIR=$testdir 506TEST_SUBDIR=$testsubdir 507FIRMWARE=$firmware 508ENDIAN=$endian 509PRETTY_PRINT_STACKS=$pretty_print_stacks 510ENVIRON_DEFAULT=$environ_default 511ERRATATXT=$erratatxt 512U32_LONG_FMT=$u32_long 513WA_DIVIDE=$wa_divide 514GENPROTIMG=${GENPROTIMG-genprotimg} 515HOST_KEY_DOCUMENT=$host_key_document 516CONFIG_DUMP=$enable_dump 517CONFIG_EFI=$efi 518EFI_DIRECT=$efi_direct 519CONFIG_WERROR=$werror 520GEN_SE_HEADER=$gen_se_header 521EOF 522if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 523 echo "TARGET=$target" >> config.mak 524fi 525 526cat <<EOF > lib/config.h 527#ifndef _CONFIG_H_ 528#define _CONFIG_H_ 529/* 530 * Generated file. DO NOT MODIFY. 531 * 532 */ 533 534EOF 535if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 536cat <<EOF >> lib/config.h 537 538#define CONFIG_UART_EARLY_BASE ${uart_early_addr} 539#define CONFIG_ERRATA_FORCE ${errata_force} 540 541EOF 542fi 543 544if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ] || [ "$arch" = "ppc64" ]; then 545cat <<EOF >> lib/config.h 546 547#define CONFIG_PAGE_SIZE _AC(${page_size}, UL) 548 549EOF 550elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then 551 echo "#define CONFIG_UART_EARLY_BASE ${uart_early_addr}" >> lib/config.h 552 [ "$console" = "sbi" ] && echo "#define CONFIG_SBI_CONSOLE" >> lib/config.h 553 echo >> lib/config.h 554fi 555echo "#endif" >> lib/config.h 556