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