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