xref: /kvm-unit-tests/configure (revision 0cc3a351b925928827baa4b69cf0e46ff5837083)
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).
82	                           The specified address will overwrite the UART address set by
83	                           the --target option. EARLYCON can be one of (case sensitive):
84	               uart[8250],mmio,ADDR
85	                           Specify an 8250 compatible UART at address ADDR. Supported
86	                           register stride is 8 bit only.
87	               pl011,ADDR
88	               pl011,mmio32,ADDR
89	                           Specify a PL011 compatible UART at address ADDR. Supported
90	                           register stride is 32 bit only.
91	                           (arm/arm64 and riscv32/riscv64 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
286if [ "$earlycon" ]; then
287    IFS=, read -r name type_addr addr <<<"$earlycon"
288    if [ "$name" != "uart" ] && [ "$name" != "uart8250" ] && [ "$name" != "pl011" ]; then
289        echo "unknown earlycon name: $name"
290        usage
291    fi
292
293    if [ "$name" = "pl011" ]; then
294        if [ -z "$addr" ]; then
295            addr=$type_addr
296        else
297            if [ "$type_addr" != "mmio32" ]; then
298                echo "unknown $name earlycon type: $type_addr"
299                usage
300            fi
301        fi
302    else
303        if [ "$type_addr" != "mmio" ]; then
304            echo "unknown $name earlycon type: $type_addr"
305            usage
306        fi
307    fi
308
309    if [ -z "$addr" ]; then
310        echo "missing $name earlycon address"
311        usage
312    fi
313    if [[ $addr =~ ^0(x|X)[0-9a-fA-F]+$ ]] || [[ $addr =~ ^[0-9]+$ ]]; then
314        uart_early_addr=$addr
315    else
316        echo "invalid $name earlycon address: $addr"
317        usage
318    fi
319fi
320
321[ -z "$processor" ] && processor="$arch"
322
323if [ "$processor" = "arm64" ]; then
324    processor="cortex-a57"
325elif [ "$processor" = "arm" ]; then
326    processor="cortex-a15"
327fi
328
329if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
330    testdir=x86
331elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
332    testdir=arm
333    if [ "$target" = "qemu" ]; then
334        : "${uart_early_addr:=0x9000000}"
335    elif [ "$target" = "kvmtool" ]; then
336        : "${uart_early_addr:=0x1000000}"
337        errata_force=1
338    else
339        echo "--target must be one of 'qemu' or 'kvmtool'!"
340        usage
341    fi
342elif [ "$arch" = "ppc64" ]; then
343    testdir=powerpc
344    firmware="$testdir/boot_rom.bin"
345    if [ "$endian" != "little" ] && [ "$endian" != "big" ]; then
346        echo "You must provide endianness (big or little)!"
347        usage
348    fi
349elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then
350    testdir=riscv
351    arch_libdir=riscv
352    : "${uart_early_addr:=0x10000000}"
353elif [ "$arch" = "s390x" ]; then
354    testdir=s390x
355else
356    echo "arch $arch is not supported!"
357    arch=
358    usage
359fi
360if [ ! -d "$srcdir/$testdir" ]; then
361    echo "$srcdir/$testdir does not exist!"
362    exit 1
363fi
364
365if [ "$efi" = "y" ] && [ -f "$srcdir/$testdir/efi/run" ]; then
366    ln -fs "$srcdir/$testdir/efi/run" $testdir-run
367elif [ -f "$srcdir/$testdir/run" ]; then
368    ln -fs "$srcdir/$testdir/run" $testdir-run
369fi
370
371testsubdir=$testdir
372if [ "$efi" = "y" ]; then
373    testsubdir=$testdir/efi
374fi
375
376# check if uint32_t needs a long format modifier
377cat << EOF > lib-test.c
378__UINT32_TYPE__
379EOF
380u32_long=$("$cc" $cflags -E lib-test.c | grep -v '^#' | grep -q long && echo yes)
381rm -f lib-test.c
382
383# check if slash can be used for division
384if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
385  cat << EOF > lib-test.S
386foo:
387    movl (8 / 2), %eax
388EOF
389  wa_divide=$("$cc" $cflags -c lib-test.S >/dev/null 2>&1 || echo yes)
390  rm -f lib-test.{o,S}
391fi
392
393# warn if enhanced getopt is unavailable
394getopt -T > /dev/null
395if [ $? -ne 4 ]; then
396    echo "Without enhanced getopt you won't be able to use run_tests.sh."
397    echo "Add it to your PATH?"
398fi
399
400# Are we in a separate build tree? If so, link the Makefile
401# and shared stuff so that 'make' and run_tests.sh work.
402if test ! -e Makefile; then
403    echo "linking Makefile..."
404    ln -s "$srcdir/Makefile" .
405
406    echo "linking tests..."
407    mkdir -p $testsubdir
408    ln -sf "$srcdir/$testdir/run" $testdir/
409    if test "$testdir" != "$testsubdir"; then
410        ln -sf "$srcdir/$testsubdir/run" $testsubdir/
411    fi
412    ln -sf "$srcdir/$testdir/unittests.cfg" $testdir/
413    ln -sf "$srcdir/run_tests.sh"
414
415    if [ -d "$srcdir/$testdir/snippets" ]; then
416        mkdir -p "$testdir/snippets/c"
417    fi
418
419    echo "linking scripts..."
420    ln -sf "$srcdir/scripts"
421fi
422
423# link lib/asm for the architecture
424rm -f lib/asm
425asm="asm-generic"
426if [ -d "$srcdir/lib/$arch/asm" ]; then
427	asm="$srcdir/lib/$arch/asm"
428	mkdir -p "lib/$arch"
429elif [ -d "$srcdir/lib/$arch_libdir/asm" ]; then
430	asm="$srcdir/lib/$arch_libdir/asm"
431	mkdir -p "lib/$arch_libdir"
432elif [ -d "$srcdir/lib/$testdir/asm" ]; then
433	asm="$srcdir/lib/$testdir/asm"
434	mkdir -p "lib/$testdir"
435fi
436ln -sf "$asm" lib/asm
437mkdir -p lib/generated lib/libfdt
438
439# create the config
440cat <<EOF > config.mak
441# Shellcheck does not see these are used
442# shellcheck disable=SC2034
443# Shellcheck can give pointless quoting warnings for some commands
444# shellcheck disable=SC2209
445SRCDIR=$srcdir
446PREFIX=$prefix
447HOST=$host
448ARCH=$arch
449ARCH_NAME=$arch_name
450ARCH_LIBDIR=$arch_libdir
451PROCESSOR=$processor
452CC=$cc
453CFLAGS=$cflags
454LD=$cross_prefix$ld
455OBJCOPY=$cross_prefix$objcopy
456OBJDUMP=$cross_prefix$objdump
457READELF=$cross_prefix$readelf
458AR=$cross_prefix$ar
459ADDR2LINE=$cross_prefix$addr2line
460TEST_DIR=$testdir
461TEST_SUBDIR=$testsubdir
462FIRMWARE=$firmware
463ENDIAN=$endian
464PRETTY_PRINT_STACKS=$pretty_print_stacks
465ENVIRON_DEFAULT=$environ_default
466ERRATATXT=$erratatxt
467U32_LONG_FMT=$u32_long
468WA_DIVIDE=$wa_divide
469GENPROTIMG=${GENPROTIMG-genprotimg}
470HOST_KEY_DOCUMENT=$host_key_document
471CONFIG_DUMP=$enable_dump
472CONFIG_EFI=$efi
473EFI_DIRECT=$efi_direct
474CONFIG_WERROR=$werror
475GEN_SE_HEADER=$gen_se_header
476EOF
477if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
478    echo "TARGET=$target" >> config.mak
479fi
480
481cat <<EOF > lib/config.h
482#ifndef _CONFIG_H_
483#define _CONFIG_H_
484/*
485 * Generated file. DO NOT MODIFY.
486 *
487 */
488
489EOF
490if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
491cat <<EOF >> lib/config.h
492
493#define CONFIG_UART_EARLY_BASE ${uart_early_addr}
494#define CONFIG_ERRATA_FORCE ${errata_force}
495
496EOF
497fi
498
499if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ] || [ "$arch" = "ppc64" ]; then
500cat <<EOF >> lib/config.h
501
502#define CONFIG_PAGE_SIZE _AC(${page_size}, UL)
503
504EOF
505elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then
506cat <<EOF >> lib/config.h
507
508#define CONFIG_UART_EARLY_BASE ${uart_early_addr}
509
510EOF
511fi
512echo "#endif" >> lib/config.h
513