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