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