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