xref: /kvm-unit-tests/configure (revision dc0a3a769728a3345b0fc6d9c29bc62ab3ae1587)
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
15readelf=readelf
16ar=ar
17addr2line=addr2line
18arch=$(uname -m | sed -e 's/i.86/i386/;s/arm64/aarch64/;s/arm.*/arm/;s/ppc64.*/ppc64/')
19host=$arch
20cross_prefix=
21endian=""
22pretty_print_stacks=yes
23environ_default=yes
24u32_long=
25wa_divide=
26target=
27errata_force=0
28erratatxt="$srcdir/errata.txt"
29host_key_document=
30gen_se_header=
31enable_dump=no
32page_size=
33earlycon=
34efi=
35efi_direct=
36
37# Enable -Werror by default for git repositories only (i.e. developer builds)
38if [ -e "$srcdir"/.git ]; then
39    werror=-Werror
40else
41    werror=
42fi
43
44usage() {
45    cat <<-EOF
46	Usage: $0 [options]
47
48	Options include:
49	    --arch=ARCH            architecture to compile for ($arch). ARCH can be one of:
50	                           arm, arm64, i386, ppc64, riscv32, riscv64, s390x, x86_64
51	    --processor=PROCESSOR  processor to compile for ($arch)
52	    --target=TARGET        target platform that the tests will be running on (qemu or
53	                           kvmtool, default is qemu) (arm/arm64 only)
54	    --cross-prefix=PREFIX  cross compiler prefix
55	    --cc=CC                c compiler to use ($cc)
56	    --cflags=FLAGS         extra options to be passed to the c compiler
57	    --ld=LD                ld linker to use ($ld)
58	    --prefix=PREFIX        where to install things ($prefix)
59	    --endian=ENDIAN        endianness to compile for (little or big, ppc64 only)
60	    --[enable|disable]-pretty-print-stacks
61	                           enable or disable pretty stack printing (enabled by default)
62	    --[enable|disable]-default-environ
63	                           enable or disable the generation of a default environ when
64	                           no environ is provided by the user (enabled by default)
65	    --erratatxt=FILE       specify a file to use instead of errata.txt. Use
66	                           '--erratatxt=' to ensure no file is used.
67	    --host-key-document=HOST_KEY_DOCUMENT
68	                           Specify the machine-specific host-key document for creating
69	                           a PVM image with 'genprotimg' (s390x only)
70	    --gen-se-header=GEN_SE_HEADER
71	                           Provide an executable to generate a PV header
72	                           requires --host-key-document. (s390x-snippets only)
73	    --[enable|disable]-dump
74	                           Allow PV guests to be dumped. Requires at least z16.
75	                           (s390x only)
76	    --page-size=PAGE_SIZE
77	                           Specify the page size (translation granule). PAGE_SIZE can be
78	                           4k [default], 16k, 64k for arm64.
79	                           4k [default], 64k for ppc64.
80	    --earlycon=EARLYCON
81	                           Specify the UART name, type and address (optional, arm and
82	                           arm64 only). The specified address will overwrite the UART
83	                           address set by the --target option. EARLYCON can be one of
84	                           (case sensitive):
85	               uart[8250],mmio,ADDR
86	                           Specify an 8250 compatible UART at address ADDR. Supported
87	                           register stride is 8 bit only.
88	               pl011,ADDR
89	               pl011,mmio32,ADDR
90	                           Specify a PL011 compatible UART at address ADDR. Supported
91	                           register stride is 32 bit only.
92	    --[enable|disable]-efi Boot and run from UEFI (disabled by default, x86_64 and arm64 only)
93	    --[enable|disable]-werror
94	                           Select whether to compile with the -Werror compiler flag
95	    --[enable|disable]-efi-direct
96	                           Select whether to run EFI tests directly with QEMU's -kernel
97	                           option. When not enabled, tests will be placed in an EFI file
98	                           system and run from the UEFI shell. Ignored when efi isn't enabled
99	                           and defaults to enabled when efi is enabled for riscv64.
100	                           (arm64 and riscv64 only)
101EOF
102    exit 1
103}
104
105while [[ "$1" = -* ]]; do
106    opt="$1"; shift
107    arg=
108    if [[ "$opt" = *=* ]]; then
109	arg="${opt#*=}"
110	opt="${opt%%=*}"
111    fi
112    case "$opt" in
113	--prefix)
114	    prefix="$arg"
115	    ;;
116        --arch)
117	    arch="$arg"
118	    ;;
119        --processor)
120	    processor="$arg"
121	    ;;
122	--target)
123	    target="$arg"
124	    ;;
125	--cross-prefix)
126	    cross_prefix="$arg"
127	    ;;
128	--endian)
129	    endian="$arg"
130	    ;;
131	--cc)
132	    cc="$arg"
133	    ;;
134	--cflags)
135	    cflags="$arg"
136	    ;;
137	--ld)
138	    ld="$arg"
139	    ;;
140	--enable-pretty-print-stacks)
141	    pretty_print_stacks=yes
142	    ;;
143	--disable-pretty-print-stacks)
144	    pretty_print_stacks=no
145	    ;;
146	--enable-default-environ)
147	    environ_default=yes
148	    ;;
149	--disable-default-environ)
150	    environ_default=no
151	    ;;
152	--erratatxt)
153	    erratatxt=
154	    [ "$arg" ] && erratatxt=$(eval realpath "$arg")
155	    ;;
156	--host-key-document)
157	    host_key_document="$arg"
158	    ;;
159	--gen-se-header)
160	    gen_se_header="$arg"
161	    ;;
162	--enable-dump)
163	    enable_dump=yes
164	    ;;
165	--disable-dump)
166	    enable_dump=no
167	    ;;
168	--page-size)
169	    page_size="$arg"
170	    ;;
171	--earlycon)
172	    earlycon="$arg"
173	    ;;
174	--enable-efi)
175	    efi=y
176	    ;;
177	--disable-efi)
178	    efi=n
179	    ;;
180	--enable-efi-direct)
181	    efi_direct=y
182	    ;;
183	--disable-efi-direct)
184	    efi_direct=n
185	    ;;
186	--enable-werror)
187	    werror=-Werror
188	    ;;
189	--disable-werror)
190	    werror=
191	    ;;
192	--help)
193	    usage
194	    ;;
195	*)
196	    echo "Unknown option '$opt'"
197	    echo
198	    usage
199	    ;;
200    esac
201done
202
203if [ -z "$efi" ] || [ "$efi" = "n" ]; then
204    [ "$efi_direct" = "y" ] && efi_direct=
205fi
206
207if [ -n "$host_key_document" ] && [ ! -f "$host_key_document" ]; then
208    echo "Host key document doesn't exist at the specified location."
209    exit 1
210fi
211
212if [ "$erratatxt" ] && [ ! -f "$erratatxt" ]; then
213    echo "erratatxt: $erratatxt does not exist or is not a regular file"
214    exit 1
215fi
216
217arch_name=$arch
218[ "$arch" = "aarch64" ] && arch="arm64"
219[ "$arch_name" = "arm64" ] && arch_name="aarch64"
220arch_libdir=$arch
221
222if [ "$arch" = "riscv" ]; then
223    echo "riscv32 or riscv64 must be specified"
224    exit 1
225fi
226
227if [ -z "$target" ]; then
228    target="qemu"
229else
230    if [ "$arch" != "arm64" ] && [ "$arch" != "arm" ]; then
231        echo "--target is not supported for $arch"
232        usage
233    fi
234fi
235
236if [ "$efi" ] && [ "$arch" != "x86_64" ] &&
237   [ "$arch" != "arm64" ] && [ "$arch" != "riscv64" ]; then
238    echo "--[enable|disable]-efi is not supported for $arch"
239    usage
240fi
241
242if [ "$efi" ] && [ "$arch" = "riscv64" ] && [ -z "$efi_direct" ]; then
243    efi_direct=y
244fi
245
246if [ -z "$page_size" ]; then
247    if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
248        page_size="4096"
249    elif [ "$arch" = "ppc64" ]; then
250        page_size="65536"
251    fi
252else
253    if [ "${page_size: -1}" = "K" ] || [ "${page_size: -1}" = "k" ]; then
254        page_size=$(( ${page_size%?} * 1024 ))
255    fi
256
257    if [ "$arch" = "arm64" ]; then
258        if [ "$page_size" != "4096" ] && [ "$page_size" != "16384" ] &&
259               [ "$page_size" != "65536" ]; then
260            echo "arm64 doesn't support page size of $page_size"
261            usage
262        fi
263        if [ "$efi" = 'y' ] && [ "$page_size" != "4096" ]; then
264            echo "efi must use 4K pages"
265            exit 1
266        fi
267    elif [ "$arch" = "ppc64" ]; then
268        if [ "$page_size" != "4096" ] && [ "$page_size" != "65536" ]; then
269            echo "ppc64 doesn't support page size of $page_size"
270            usage
271        fi
272    else
273        echo "--page-size is not supported for $arch"
274        usage
275    fi
276fi
277
278[ -z "$processor" ] && processor="$arch"
279
280if [ "$processor" = "arm64" ]; then
281    processor="cortex-a57"
282elif [ "$processor" = "arm" ]; then
283    processor="cortex-a15"
284fi
285
286if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
287    testdir=x86
288elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
289    testdir=arm
290    if [ "$target" = "qemu" ]; then
291        arm_uart_early_addr=0x09000000
292    elif [ "$target" = "kvmtool" ]; then
293        arm_uart_early_addr=0x1000000
294        errata_force=1
295    else
296        echo "--target must be one of 'qemu' or 'kvmtool'!"
297        usage
298    fi
299
300    if [ "$earlycon" ]; then
301        IFS=, read -r name type_addr addr <<<"$earlycon"
302        if [ "$name" != "uart" ] && [ "$name" != "uart8250" ] &&
303                [ "$name" != "pl011" ]; then
304            echo "unknown earlycon name: $name"
305            usage
306        fi
307
308        if [ "$name" = "pl011" ]; then
309            if [ -z "$addr" ]; then
310                addr=$type_addr
311            else
312                if [ "$type_addr" != "mmio32" ]; then
313                    echo "unknown $name earlycon type: $type_addr"
314                    usage
315                fi
316            fi
317        else
318            if [ "$type_addr" != "mmio" ]; then
319                echo "unknown $name earlycon type: $type_addr"
320                usage
321            fi
322        fi
323
324        if [ -z "$addr" ]; then
325            echo "missing $name earlycon address"
326            usage
327        fi
328        if [[ $addr =~ ^0(x|X)[0-9a-fA-F]+$ ]] ||
329                [[ $addr =~ ^[0-9]+$ ]]; then
330            arm_uart_early_addr=$addr
331        else
332            echo "invalid $name earlycon address: $addr"
333            usage
334        fi
335    fi
336elif [ "$arch" = "ppc64" ]; then
337    testdir=powerpc
338    firmware="$testdir/boot_rom.bin"
339    if [ "$endian" != "little" ] && [ "$endian" != "big" ]; then
340        echo "You must provide endianness (big or little)!"
341        usage
342    fi
343elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then
344    testdir=riscv
345    arch_libdir=riscv
346elif [ "$arch" = "s390x" ]; then
347    testdir=s390x
348else
349    echo "arch $arch is not supported!"
350    arch=
351    usage
352fi
353if [ ! -d "$srcdir/$testdir" ]; then
354    echo "$srcdir/$testdir does not exist!"
355    exit 1
356fi
357
358if [ "$efi" = "y" ] && [ -f "$srcdir/$testdir/efi/run" ]; then
359    ln -fs "$srcdir/$testdir/efi/run" $testdir-run
360elif [ -f "$srcdir/$testdir/run" ]; then
361    ln -fs "$srcdir/$testdir/run" $testdir-run
362fi
363
364testsubdir=$testdir
365if [ "$efi" = "y" ]; then
366    testsubdir=$testdir/efi
367fi
368
369# check if uint32_t needs a long format modifier
370cat << EOF > lib-test.c
371__UINT32_TYPE__
372EOF
373u32_long=$("$cross_prefix$cc" -E lib-test.c | grep -v '^#' | grep -q long && echo yes)
374rm -f lib-test.c
375
376# check if slash can be used for division
377if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
378  cat << EOF > lib-test.S
379foo:
380    movl (8 / 2), %eax
381EOF
382  wa_divide=$("$cross_prefix$cc" -c lib-test.S >/dev/null 2>&1 || echo yes)
383  rm -f lib-test.{o,S}
384fi
385
386# warn if enhanced getopt is unavailable
387getopt -T > /dev/null
388if [ $? -ne 4 ]; then
389    echo "Without enhanced getopt you won't be able to use run_tests.sh."
390    echo "Add it to your PATH?"
391fi
392
393# Are we in a separate build tree? If so, link the Makefile
394# and shared stuff so that 'make' and run_tests.sh work.
395if test ! -e Makefile; then
396    echo "linking Makefile..."
397    ln -s "$srcdir/Makefile" .
398
399    echo "linking tests..."
400    mkdir -p $testsubdir
401    ln -sf "$srcdir/$testdir/run" $testdir/
402    if test "$testdir" != "$testsubdir"; then
403        ln -sf "$srcdir/$testsubdir/run" $testsubdir/
404    fi
405    ln -sf "$srcdir/$testdir/unittests.cfg" $testdir/
406    ln -sf "$srcdir/run_tests.sh"
407
408    if [ -d "$srcdir/$testdir/snippets" ]; then
409        mkdir -p "$testdir/snippets/c"
410    fi
411
412    echo "linking scripts..."
413    ln -sf "$srcdir/scripts"
414fi
415
416# link lib/asm for the architecture
417rm -f lib/asm
418asm="asm-generic"
419if [ -d "$srcdir/lib/$arch/asm" ]; then
420	asm="$srcdir/lib/$arch/asm"
421elif [ -d "$srcdir/lib/$testdir/asm" ]; then
422	asm="$srcdir/lib/$testdir/asm"
423fi
424mkdir -p lib
425ln -sf "$asm" lib/asm
426
427
428# create the config
429cat <<EOF > config.mak
430# Shellcheck does not see these are used
431# shellcheck disable=SC2034
432# Shellcheck can give pointless quoting warnings for some commands
433# shellcheck disable=SC2209
434SRCDIR=$srcdir
435PREFIX=$prefix
436HOST=$host
437ARCH=$arch
438ARCH_NAME=$arch_name
439ARCH_LIBDIR=$arch_libdir
440PROCESSOR=$processor
441CC=$cross_prefix$cc
442CFLAGS=$cflags
443LD=$cross_prefix$ld
444OBJCOPY=$cross_prefix$objcopy
445OBJDUMP=$cross_prefix$objdump
446READELF=$cross_prefix$readelf
447AR=$cross_prefix$ar
448ADDR2LINE=$cross_prefix$addr2line
449TEST_DIR=$testdir
450TEST_SUBDIR=$testsubdir
451FIRMWARE=$firmware
452ENDIAN=$endian
453PRETTY_PRINT_STACKS=$pretty_print_stacks
454ENVIRON_DEFAULT=$environ_default
455ERRATATXT=$erratatxt
456U32_LONG_FMT=$u32_long
457WA_DIVIDE=$wa_divide
458GENPROTIMG=${GENPROTIMG-genprotimg}
459HOST_KEY_DOCUMENT=$host_key_document
460CONFIG_DUMP=$enable_dump
461CONFIG_EFI=$efi
462EFI_DIRECT=$efi_direct
463CONFIG_WERROR=$werror
464GEN_SE_HEADER=$gen_se_header
465EOF
466if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
467    echo "TARGET=$target" >> config.mak
468fi
469
470cat <<EOF > lib/config.h
471#ifndef _CONFIG_H_
472#define _CONFIG_H_
473/*
474 * Generated file. DO NOT MODIFY.
475 *
476 */
477
478EOF
479if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
480cat <<EOF >> lib/config.h
481
482#define CONFIG_UART_EARLY_BASE ${arm_uart_early_addr}
483#define CONFIG_ERRATA_FORCE ${errata_force}
484
485EOF
486fi
487
488if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ] || [ "$arch" = "ppc64" ]; then
489cat <<EOF >> lib/config.h
490
491#define CONFIG_PAGE_SIZE _AC(${page_size}, UL)
492
493EOF
494elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then
495cat <<EOF >> lib/config.h
496
497#define CONFIG_UART_EARLY_BASE 0x10000000
498
499EOF
500fi
501echo "#endif" >> lib/config.h
502