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 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" ]; then 212 echo "--[enable|disable]-efi is not supported for $arch" 213 usage 214fi 215 216if [ -z "$page_size" ]; then 217 [ "$arch" = "arm64" ] && page_size="65536" 218 [ "$arch" = "arm" ] && page_size="4096" 219else 220 if [ "$arch" != "arm64" ]; then 221 echo "--page-size is not supported for $arch" 222 usage 223 fi 224 225 if [ "${page_size: -1}" = "K" ] || [ "${page_size: -1}" = "k" ]; then 226 page_size=$(( ${page_size%?} * 1024 )) 227 fi 228 if [ "$page_size" != "4096" ] && [ "$page_size" != "16384" ] && 229 [ "$page_size" != "65536" ]; then 230 echo "arm64 doesn't support page size of $page_size" 231 usage 232 fi 233fi 234 235[ -z "$processor" ] && processor="$arch" 236 237if [ "$processor" = "arm64" ]; then 238 processor="cortex-a57" 239elif [ "$processor" = "arm" ]; then 240 processor="cortex-a15" 241fi 242 243if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then 244 testdir=x86 245elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 246 testdir=arm 247 if [ "$target" = "qemu" ]; then 248 arm_uart_early_addr=0x09000000 249 elif [ "$target" = "kvmtool" ]; then 250 arm_uart_early_addr=0x1000000 251 errata_force=1 252 else 253 echo "--target must be one of 'qemu' or 'kvmtool'!" 254 usage 255 fi 256 257 if [ "$earlycon" ]; then 258 IFS=, read -r name type_addr addr <<<"$earlycon" 259 if [ "$name" != "uart" ] && [ "$name" != "uart8250" ] && 260 [ "$name" != "pl011" ]; then 261 echo "unknown earlycon name: $name" 262 usage 263 fi 264 265 if [ "$name" = "pl011" ]; then 266 if [ -z "$addr" ]; then 267 addr=$type_addr 268 else 269 if [ "$type_addr" != "mmio32" ]; then 270 echo "unknown $name earlycon type: $type_addr" 271 usage 272 fi 273 fi 274 else 275 if [ "$type_addr" != "mmio" ]; then 276 echo "unknown $name earlycon type: $type_addr" 277 usage 278 fi 279 fi 280 281 if [ -z "$addr" ]; then 282 echo "missing $name earlycon address" 283 usage 284 fi 285 if [[ $addr =~ ^0(x|X)[0-9a-fA-F]+$ ]] || 286 [[ $addr =~ ^[0-9]+$ ]]; then 287 arm_uart_early_addr=$addr 288 else 289 echo "invalid $name earlycon address: $addr" 290 usage 291 fi 292 fi 293elif [ "$arch" = "ppc64" ]; then 294 testdir=powerpc 295 firmware="$testdir/boot_rom.bin" 296 if [ "$endian" != "little" ] && [ "$endian" != "big" ]; then 297 echo "You must provide endianness (big or little)!" 298 usage 299 fi 300else 301 testdir=$arch 302fi 303if [ ! -d "$srcdir/$testdir" ]; then 304 echo "$testdir does not exist!" 305 exit 1 306fi 307if [ -f "$srcdir/$testdir/run" ]; then 308 ln -fs "$srcdir/$testdir/run" $testdir-run 309fi 310 311testsubdir=$testdir 312if [ "$efi" = "y" ]; then 313 testsubdir=$testdir/efi 314fi 315 316# check if uint32_t needs a long format modifier 317cat << EOF > lib-test.c 318__UINT32_TYPE__ 319EOF 320u32_long=$("$cross_prefix$cc" -E lib-test.c | grep -v '^#' | grep -q long && echo yes) 321rm -f lib-test.c 322 323# check if slash can be used for division 324if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then 325 cat << EOF > lib-test.S 326foo: 327 movl (8 / 2), %eax 328EOF 329 wa_divide=$("$cross_prefix$cc" -c lib-test.S >/dev/null 2>&1 || echo yes) 330 rm -f lib-test.{o,S} 331fi 332 333# warn if enhanced getopt is unavailable 334getopt -T > /dev/null 335if [ $? -ne 4 ]; then 336 echo "Without enhanced getopt you won't be able to use run_tests.sh." 337 echo "Add it to your PATH?" 338fi 339 340# Are we in a separate build tree? If so, link the Makefile 341# and shared stuff so that 'make' and run_tests.sh work. 342if test ! -e Makefile; then 343 echo "linking Makefile..." 344 ln -s "$srcdir/Makefile" . 345 346 echo "linking tests..." 347 mkdir -p $testsubdir 348 ln -sf "$srcdir/$testdir/run" $testdir/ 349 if test "$testdir" != "$testsubdir"; then 350 ln -sf "$srcdir/$testsubdir/run" $testsubdir/ 351 fi 352 ln -sf "$srcdir/$testdir/unittests.cfg" $testdir/ 353 ln -sf "$srcdir/run_tests.sh" 354 355 if [ -d "$srcdir/$testdir/snippets" ]; then 356 mkdir -p "$testdir/snippets/c" 357 fi 358 359 echo "linking scripts..." 360 ln -sf "$srcdir/scripts" 361fi 362 363# link lib/asm for the architecture 364rm -f lib/asm 365asm="asm-generic" 366if [ -d "$srcdir/lib/$arch/asm" ]; then 367 asm="$srcdir/lib/$arch/asm" 368elif [ -d "$srcdir/lib/$testdir/asm" ]; then 369 asm="$srcdir/lib/$testdir/asm" 370fi 371mkdir -p lib 372ln -sf "$asm" lib/asm 373 374 375# create the config 376cat <<EOF > config.mak 377SRCDIR=$srcdir 378PREFIX=$prefix 379HOST=$host 380ARCH=$arch 381ARCH_NAME=$arch_name 382PROCESSOR=$processor 383CC=$cross_prefix$cc 384CFLAGS=$cflags 385LD=$cross_prefix$ld 386OBJCOPY=$cross_prefix$objcopy 387OBJDUMP=$cross_prefix$objdump 388READELF=$cross_prefix$readelf 389AR=$cross_prefix$ar 390ADDR2LINE=$cross_prefix$addr2line 391TEST_DIR=$testdir 392TEST_SUBDIR=$testsubdir 393FIRMWARE=$firmware 394ENDIAN=$endian 395PRETTY_PRINT_STACKS=$pretty_print_stacks 396ENVIRON_DEFAULT=$environ_default 397ERRATATXT=$erratatxt 398U32_LONG_FMT=$u32_long 399WA_DIVIDE=$wa_divide 400GENPROTIMG=${GENPROTIMG-genprotimg} 401HOST_KEY_DOCUMENT=$host_key_document 402CONFIG_DUMP=$enable_dump 403CONFIG_EFI=$efi 404CONFIG_WERROR=$werror 405GEN_SE_HEADER=$gen_se_header 406EOF 407if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 408 echo "TARGET=$target" >> config.mak 409fi 410 411cat <<EOF > lib/config.h 412#ifndef _CONFIG_H_ 413#define _CONFIG_H_ 414/* 415 * Generated file. DO NOT MODIFY. 416 * 417 */ 418 419EOF 420if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then 421cat <<EOF >> lib/config.h 422 423#define CONFIG_UART_EARLY_BASE ${arm_uart_early_addr} 424#define CONFIG_ERRATA_FORCE ${errata_force} 425#define CONFIG_PAGE_SIZE _AC(${page_size}, UL) 426 427EOF 428fi 429echo "#endif" >> lib/config.h 430