xref: /kvm-unit-tests/configure (revision f372d35fb1bea99e401cc6eafc798aecfce29a07)
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
105optno=1
106argc=$#
107while [[ $optno -le $argc ]]; do
108    opt="$1"; shift
109    optno=$(( $optno + 1 ))
110    arg=
111    if [[ "$opt" = *=* ]]; then
112	arg="${opt#*=}"
113	opt="${opt%%=*}"
114    fi
115    case "$opt" in
116	--prefix)
117	    prefix="$arg"
118	    ;;
119        --arch)
120	    arch="$arg"
121	    ;;
122        --processor)
123	    processor="$arg"
124	    ;;
125	--target)
126	    target="$arg"
127	    ;;
128	--cross-prefix)
129	    cross_prefix="$arg"
130	    ;;
131	--endian)
132	    endian="$arg"
133	    ;;
134	--cc)
135	    cc="$arg"
136	    cc_selected=yes
137	    ;;
138	--cflags)
139	    cflags="$arg"
140	    ;;
141	--ld)
142	    ld="$arg"
143	    ;;
144	--enable-pretty-print-stacks)
145	    pretty_print_stacks=yes
146	    ;;
147	--disable-pretty-print-stacks)
148	    pretty_print_stacks=no
149	    ;;
150	--enable-default-environ)
151	    environ_default=yes
152	    ;;
153	--disable-default-environ)
154	    environ_default=no
155	    ;;
156	--erratatxt)
157	    erratatxt=
158	    [ "$arg" ] && erratatxt=$(eval realpath "$arg")
159	    ;;
160	--host-key-document)
161	    host_key_document="$arg"
162	    ;;
163	--gen-se-header)
164	    gen_se_header="$arg"
165	    ;;
166	--enable-dump)
167	    enable_dump=yes
168	    ;;
169	--disable-dump)
170	    enable_dump=no
171	    ;;
172	--page-size)
173	    page_size="$arg"
174	    ;;
175	--earlycon)
176	    earlycon="$arg"
177	    ;;
178	--enable-efi)
179	    efi=y
180	    ;;
181	--disable-efi)
182	    efi=n
183	    ;;
184	--enable-efi-direct)
185	    efi_direct=y
186	    ;;
187	--disable-efi-direct)
188	    efi_direct=n
189	    ;;
190	--enable-werror)
191	    werror=-Werror
192	    ;;
193	--disable-werror)
194	    werror=
195	    ;;
196	--help)
197	    usage
198	    ;;
199	*)
200	    echo "Unknown option '$opt'"
201	    echo
202	    usage
203	    ;;
204    esac
205done
206
207if [ -z "$cc_selected" ] && [ "$cross_prefix" ]; then
208    cc="$cross_prefix$cc"
209fi
210
211if [ -z "$efi" ] || [ "$efi" = "n" ]; then
212    [ "$efi_direct" = "y" ] && efi_direct=
213fi
214
215if [ -n "$host_key_document" ] && [ ! -f "$host_key_document" ]; then
216    echo "Host key document doesn't exist at the specified location."
217    exit 1
218fi
219
220if [ "$erratatxt" ] && [ ! -f "$erratatxt" ]; then
221    echo "erratatxt: $erratatxt does not exist or is not a regular file"
222    exit 1
223fi
224
225arch_name=$arch
226[ "$arch" = "aarch64" ] && arch="arm64"
227[ "$arch_name" = "arm64" ] && arch_name="aarch64"
228arch_libdir=$arch
229
230if [ "$arch" = "riscv" ]; then
231    echo "riscv32 or riscv64 must be specified"
232    exit 1
233fi
234
235if [ -z "$target" ]; then
236    target="qemu"
237else
238    if [ "$arch" != "arm64" ] && [ "$arch" != "arm" ]; then
239        echo "--target is not supported for $arch"
240        usage
241    fi
242fi
243
244if [ "$efi" ] && [ "$arch" != "x86_64" ] &&
245   [ "$arch" != "arm64" ] && [ "$arch" != "riscv64" ]; then
246    echo "--[enable|disable]-efi is not supported for $arch"
247    usage
248fi
249
250if [ "$efi" ] && [ "$arch" = "riscv64" ] && [ -z "$efi_direct" ]; then
251    efi_direct=y
252fi
253
254if [ -z "$page_size" ]; then
255    if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
256        page_size="4096"
257    elif [ "$arch" = "ppc64" ]; then
258        page_size="65536"
259    fi
260else
261    if [ "${page_size: -1}" = "K" ] || [ "${page_size: -1}" = "k" ]; then
262        page_size=$(( ${page_size%?} * 1024 ))
263    fi
264
265    if [ "$arch" = "arm64" ]; then
266        if [ "$page_size" != "4096" ] && [ "$page_size" != "16384" ] &&
267               [ "$page_size" != "65536" ]; then
268            echo "arm64 doesn't support page size of $page_size"
269            usage
270        fi
271        if [ "$efi" = 'y' ] && [ "$page_size" != "4096" ]; then
272            echo "efi must use 4K pages"
273            exit 1
274        fi
275    elif [ "$arch" = "ppc64" ]; then
276        if [ "$page_size" != "4096" ] && [ "$page_size" != "65536" ]; then
277            echo "ppc64 doesn't support page size of $page_size"
278            usage
279        fi
280    else
281        echo "--page-size is not supported for $arch"
282        usage
283    fi
284fi
285
286[ -z "$processor" ] && processor="$arch"
287
288if [ "$processor" = "arm64" ]; then
289    processor="cortex-a57"
290elif [ "$processor" = "arm" ]; then
291    processor="cortex-a15"
292fi
293
294if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
295    testdir=x86
296elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
297    testdir=arm
298    if [ "$target" = "qemu" ]; then
299        arm_uart_early_addr=0x09000000
300    elif [ "$target" = "kvmtool" ]; then
301        arm_uart_early_addr=0x1000000
302        errata_force=1
303    else
304        echo "--target must be one of 'qemu' or 'kvmtool'!"
305        usage
306    fi
307
308    if [ "$earlycon" ]; then
309        IFS=, read -r name type_addr addr <<<"$earlycon"
310        if [ "$name" != "uart" ] && [ "$name" != "uart8250" ] &&
311                [ "$name" != "pl011" ]; then
312            echo "unknown earlycon name: $name"
313            usage
314        fi
315
316        if [ "$name" = "pl011" ]; then
317            if [ -z "$addr" ]; then
318                addr=$type_addr
319            else
320                if [ "$type_addr" != "mmio32" ]; then
321                    echo "unknown $name earlycon type: $type_addr"
322                    usage
323                fi
324            fi
325        else
326            if [ "$type_addr" != "mmio" ]; then
327                echo "unknown $name earlycon type: $type_addr"
328                usage
329            fi
330        fi
331
332        if [ -z "$addr" ]; then
333            echo "missing $name earlycon address"
334            usage
335        fi
336        if [[ $addr =~ ^0(x|X)[0-9a-fA-F]+$ ]] ||
337                [[ $addr =~ ^[0-9]+$ ]]; then
338            arm_uart_early_addr=$addr
339        else
340            echo "invalid $name earlycon address: $addr"
341            usage
342        fi
343    fi
344elif [ "$arch" = "ppc64" ]; then
345    testdir=powerpc
346    firmware="$testdir/boot_rom.bin"
347    if [ "$endian" != "little" ] && [ "$endian" != "big" ]; then
348        echo "You must provide endianness (big or little)!"
349        usage
350    fi
351elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then
352    testdir=riscv
353    arch_libdir=riscv
354elif [ "$arch" = "s390x" ]; then
355    testdir=s390x
356else
357    echo "arch $arch is not supported!"
358    arch=
359    usage
360fi
361if [ ! -d "$srcdir/$testdir" ]; then
362    echo "$srcdir/$testdir does not exist!"
363    exit 1
364fi
365
366if [ "$efi" = "y" ] && [ -f "$srcdir/$testdir/efi/run" ]; then
367    ln -fs "$srcdir/$testdir/efi/run" $testdir-run
368elif [ -f "$srcdir/$testdir/run" ]; then
369    ln -fs "$srcdir/$testdir/run" $testdir-run
370fi
371
372testsubdir=$testdir
373if [ "$efi" = "y" ]; then
374    testsubdir=$testdir/efi
375fi
376
377# check if uint32_t needs a long format modifier
378cat << EOF > lib-test.c
379__UINT32_TYPE__
380EOF
381u32_long=$("$cc" $cflags -E lib-test.c | grep -v '^#' | grep -q long && echo yes)
382rm -f lib-test.c
383
384# check if slash can be used for division
385if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
386  cat << EOF > lib-test.S
387foo:
388    movl (8 / 2), %eax
389EOF
390  wa_divide=$("$cc" $cflags -c lib-test.S >/dev/null 2>&1 || echo yes)
391  rm -f lib-test.{o,S}
392fi
393
394# warn if enhanced getopt is unavailable
395getopt -T > /dev/null
396if [ $? -ne 4 ]; then
397    echo "Without enhanced getopt you won't be able to use run_tests.sh."
398    echo "Add it to your PATH?"
399fi
400
401# Are we in a separate build tree? If so, link the Makefile
402# and shared stuff so that 'make' and run_tests.sh work.
403if test ! -e Makefile; then
404    echo "linking Makefile..."
405    ln -s "$srcdir/Makefile" .
406
407    echo "linking tests..."
408    mkdir -p $testsubdir
409    ln -sf "$srcdir/$testdir/run" $testdir/
410    if test "$testdir" != "$testsubdir"; then
411        ln -sf "$srcdir/$testsubdir/run" $testsubdir/
412    fi
413    ln -sf "$srcdir/$testdir/unittests.cfg" $testdir/
414    ln -sf "$srcdir/run_tests.sh"
415
416    if [ -d "$srcdir/$testdir/snippets" ]; then
417        mkdir -p "$testdir/snippets/c"
418    fi
419
420    echo "linking scripts..."
421    ln -sf "$srcdir/scripts"
422fi
423
424# link lib/asm for the architecture
425rm -f lib/asm
426asm="asm-generic"
427if [ -d "$srcdir/lib/$arch/asm" ]; then
428	asm="$srcdir/lib/$arch/asm"
429	mkdir -p "lib/$arch"
430elif [ -d "$srcdir/lib/$arch_libdir/asm" ]; then
431	asm="$srcdir/lib/$arch_libdir/asm"
432	mkdir -p "lib/$arch_libdir"
433elif [ -d "$srcdir/lib/$testdir/asm" ]; then
434	asm="$srcdir/lib/$testdir/asm"
435	mkdir -p "lib/$testdir"
436fi
437ln -sf "$asm" lib/asm
438mkdir -p lib/generated lib/libfdt
439
440# create the config
441cat <<EOF > config.mak
442# Shellcheck does not see these are used
443# shellcheck disable=SC2034
444# Shellcheck can give pointless quoting warnings for some commands
445# shellcheck disable=SC2209
446SRCDIR=$srcdir
447PREFIX=$prefix
448HOST=$host
449ARCH=$arch
450ARCH_NAME=$arch_name
451ARCH_LIBDIR=$arch_libdir
452PROCESSOR=$processor
453CC=$cc
454CFLAGS=$cflags
455LD=$cross_prefix$ld
456OBJCOPY=$cross_prefix$objcopy
457OBJDUMP=$cross_prefix$objdump
458READELF=$cross_prefix$readelf
459AR=$cross_prefix$ar
460ADDR2LINE=$cross_prefix$addr2line
461TEST_DIR=$testdir
462TEST_SUBDIR=$testsubdir
463FIRMWARE=$firmware
464ENDIAN=$endian
465PRETTY_PRINT_STACKS=$pretty_print_stacks
466ENVIRON_DEFAULT=$environ_default
467ERRATATXT=$erratatxt
468U32_LONG_FMT=$u32_long
469WA_DIVIDE=$wa_divide
470GENPROTIMG=${GENPROTIMG-genprotimg}
471HOST_KEY_DOCUMENT=$host_key_document
472CONFIG_DUMP=$enable_dump
473CONFIG_EFI=$efi
474EFI_DIRECT=$efi_direct
475CONFIG_WERROR=$werror
476GEN_SE_HEADER=$gen_se_header
477EOF
478if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
479    echo "TARGET=$target" >> config.mak
480fi
481
482cat <<EOF > lib/config.h
483#ifndef _CONFIG_H_
484#define _CONFIG_H_
485/*
486 * Generated file. DO NOT MODIFY.
487 *
488 */
489
490EOF
491if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
492cat <<EOF >> lib/config.h
493
494#define CONFIG_UART_EARLY_BASE ${arm_uart_early_addr}
495#define CONFIG_ERRATA_FORCE ${errata_force}
496
497EOF
498fi
499
500if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ] || [ "$arch" = "ppc64" ]; then
501cat <<EOF >> lib/config.h
502
503#define CONFIG_PAGE_SIZE _AC(${page_size}, UL)
504
505EOF
506elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then
507cat <<EOF >> lib/config.h
508
509#define CONFIG_UART_EARLY_BASE 0x10000000
510
511EOF
512fi
513echo "#endif" >> lib/config.h
514