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