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