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