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