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