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