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