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