xref: /kvm-unit-tests/configure (revision 08db0f5cfbca16b36f200b7bc54a78fa4941bcce)
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        errata_force=1
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}"
397elif [ "$arch" = "s390x" ]; then
398    testdir=s390x
399else
400    echo "arch $arch is not supported!"
401    arch=
402    usage
403fi
404if [ ! -d "$srcdir/$testdir" ]; then
405    echo "$srcdir/$testdir does not exist!"
406    exit 1
407fi
408
409if [ "$efi" = "y" ] && [ -f "$srcdir/$testdir/efi/run" ]; then
410    ln -fs "$srcdir/$testdir/efi/run" $testdir-run
411elif [ -f "$srcdir/$testdir/run" ]; then
412    ln -fs "$srcdir/$testdir/run" $testdir-run
413fi
414
415testsubdir=$testdir
416if [ "$efi" = "y" ]; then
417    testsubdir=$testdir/efi
418fi
419
420# check if uint32_t needs a long format modifier
421cat << EOF > lib-test.c
422__UINT32_TYPE__
423EOF
424u32_long=$("$cc" $cflags -E lib-test.c | grep -v '^#' | grep -q long && echo yes)
425rm -f lib-test.c
426
427# check if slash can be used for division
428if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
429  cat << EOF > lib-test.S
430foo:
431    movl (8 / 2), %eax
432EOF
433  wa_divide=$("$cc" $cflags -c lib-test.S >/dev/null 2>&1 || echo yes)
434  rm -f lib-test.{o,S}
435fi
436
437# warn if enhanced getopt is unavailable
438getopt -T > /dev/null
439if [ $? -ne 4 ]; then
440    echo "Without enhanced getopt you won't be able to use run_tests.sh."
441    echo "Add it to your PATH?"
442fi
443
444# Are we in a separate build tree? If so, link the Makefile
445# and shared stuff so that 'make' and run_tests.sh work.
446if test ! -e Makefile; then
447    echo "linking Makefile..."
448    ln -s "$srcdir/Makefile" .
449
450    echo "linking tests..."
451    mkdir -p $testsubdir
452    ln -sf "$srcdir/$testdir/run" $testdir/
453    if test "$testdir" != "$testsubdir"; then
454        ln -sf "$srcdir/$testsubdir/run" $testsubdir/
455    fi
456    ln -sf "$srcdir/$testdir/unittests.cfg" $testdir/
457    ln -sf "$srcdir/run_tests.sh"
458
459    if [ -d "$srcdir/$testdir/snippets" ]; then
460        mkdir -p "$testdir/snippets/c"
461    fi
462
463    echo "linking scripts..."
464    ln -sf "$srcdir/scripts"
465fi
466
467# link lib/asm for the architecture
468rm -f lib/asm
469asm="asm-generic"
470if [ -d "$srcdir/lib/$arch/asm" ]; then
471	asm="$srcdir/lib/$arch/asm"
472	mkdir -p "lib/$arch"
473elif [ -d "$srcdir/lib/$arch_libdir/asm" ]; then
474	asm="$srcdir/lib/$arch_libdir/asm"
475	mkdir -p "lib/$arch_libdir"
476elif [ -d "$srcdir/lib/$testdir/asm" ]; then
477	asm="$srcdir/lib/$testdir/asm"
478	mkdir -p "lib/$testdir"
479fi
480ln -sf "$asm" lib/asm
481mkdir -p lib/generated lib/libfdt
482
483# create the config
484cat <<EOF > config.mak
485# Shellcheck does not see these are used
486# shellcheck disable=SC2034
487# Shellcheck can give pointless quoting warnings for some commands
488# shellcheck disable=SC2209
489SRCDIR=$srcdir
490PREFIX=$prefix
491HOST=$host
492ARCH=$arch
493ARCH_NAME=$arch_name
494ARCH_LIBDIR=$arch_libdir
495PROCESSOR=$processor
496TARGET_CPU=$target_cpu
497DEFAULT_QEMU_CPU=$(get_default_qemu_cpu $arch)
498CC=$cc
499CFLAGS=$cflags
500LD=$cross_prefix$ld
501OBJCOPY=$cross_prefix$objcopy
502OBJDUMP=$cross_prefix$objdump
503READELF=$cross_prefix$readelf
504AR=$cross_prefix$ar
505ADDR2LINE=$cross_prefix$addr2line
506TEST_DIR=$testdir
507TEST_SUBDIR=$testsubdir
508FIRMWARE=$firmware
509ENDIAN=$endian
510PRETTY_PRINT_STACKS=$pretty_print_stacks
511ENVIRON_DEFAULT=$environ_default
512ERRATATXT=$erratatxt
513U32_LONG_FMT=$u32_long
514WA_DIVIDE=$wa_divide
515GENPROTIMG=${GENPROTIMG-genprotimg}
516HOST_KEY_DOCUMENT=$host_key_document
517CONFIG_DUMP=$enable_dump
518CONFIG_EFI=$efi
519EFI_DIRECT=$efi_direct
520CONFIG_WERROR=$werror
521GEN_SE_HEADER=$gen_se_header
522EOF
523if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
524    echo "TARGET=$target" >> config.mak
525fi
526
527cat <<EOF > lib/config.h
528#ifndef _CONFIG_H_
529#define _CONFIG_H_
530/*
531 * Generated file. DO NOT MODIFY.
532 *
533 */
534
535EOF
536if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
537cat <<EOF >> lib/config.h
538
539#define CONFIG_UART_EARLY_BASE ${uart_early_addr}
540#define CONFIG_ERRATA_FORCE ${errata_force}
541
542EOF
543fi
544
545if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ] || [ "$arch" = "ppc64" ]; then
546cat <<EOF >> lib/config.h
547
548#define CONFIG_PAGE_SIZE _AC(${page_size}, UL)
549
550EOF
551elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then
552    echo "#define CONFIG_UART_EARLY_BASE ${uart_early_addr}" >> lib/config.h
553    [ "$console" = "sbi" ] && echo "#define CONFIG_SBI_CONSOLE" >> lib/config.h
554    echo >> lib/config.h
555fi
556echo "#endif" >> lib/config.h
557