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