xref: /kvm-unit-tests/configure (revision 67b8f46291019f350cd67d67899cb34f8d3c3a50)
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, arm and
82	                           arm64 only). The specified address will overwrite the UART
83	                           address set by the --target option. EARLYCON can be one of
84	                           (case sensitive):
85	               uart[8250],mmio,ADDR
86	                           Specify an 8250 compatible UART at address ADDR. Supported
87	                           register stride is 8 bit only.
88	               pl011,ADDR
89	               pl011,mmio32,ADDR
90	                           Specify a PL011 compatible UART at address ADDR. Supported
91	                           register stride is 32 bit 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	    ;;
137	--cflags)
138	    cflags="$arg"
139	    ;;
140	--ld)
141	    ld="$arg"
142	    ;;
143	--enable-pretty-print-stacks)
144	    pretty_print_stacks=yes
145	    ;;
146	--disable-pretty-print-stacks)
147	    pretty_print_stacks=no
148	    ;;
149	--enable-default-environ)
150	    environ_default=yes
151	    ;;
152	--disable-default-environ)
153	    environ_default=no
154	    ;;
155	--erratatxt)
156	    erratatxt=
157	    [ "$arg" ] && erratatxt=$(eval realpath "$arg")
158	    ;;
159	--host-key-document)
160	    host_key_document="$arg"
161	    ;;
162	--gen-se-header)
163	    gen_se_header="$arg"
164	    ;;
165	--enable-dump)
166	    enable_dump=yes
167	    ;;
168	--disable-dump)
169	    enable_dump=no
170	    ;;
171	--page-size)
172	    page_size="$arg"
173	    ;;
174	--earlycon)
175	    earlycon="$arg"
176	    ;;
177	--enable-efi)
178	    efi=y
179	    ;;
180	--disable-efi)
181	    efi=n
182	    ;;
183	--enable-efi-direct)
184	    efi_direct=y
185	    ;;
186	--disable-efi-direct)
187	    efi_direct=n
188	    ;;
189	--enable-werror)
190	    werror=-Werror
191	    ;;
192	--disable-werror)
193	    werror=
194	    ;;
195	--help)
196	    usage
197	    ;;
198	*)
199	    echo "Unknown option '$opt'"
200	    echo
201	    usage
202	    ;;
203    esac
204done
205
206if [ -z "$efi" ] || [ "$efi" = "n" ]; then
207    [ "$efi_direct" = "y" ] && efi_direct=
208fi
209
210if [ -n "$host_key_document" ] && [ ! -f "$host_key_document" ]; then
211    echo "Host key document doesn't exist at the specified location."
212    exit 1
213fi
214
215if [ "$erratatxt" ] && [ ! -f "$erratatxt" ]; then
216    echo "erratatxt: $erratatxt does not exist or is not a regular file"
217    exit 1
218fi
219
220arch_name=$arch
221[ "$arch" = "aarch64" ] && arch="arm64"
222[ "$arch_name" = "arm64" ] && arch_name="aarch64"
223arch_libdir=$arch
224
225if [ "$arch" = "riscv" ]; then
226    echo "riscv32 or riscv64 must be specified"
227    exit 1
228fi
229
230if [ -z "$target" ]; then
231    target="qemu"
232else
233    if [ "$arch" != "arm64" ] && [ "$arch" != "arm" ]; then
234        echo "--target is not supported for $arch"
235        usage
236    fi
237fi
238
239if [ "$efi" ] && [ "$arch" != "x86_64" ] &&
240   [ "$arch" != "arm64" ] && [ "$arch" != "riscv64" ]; then
241    echo "--[enable|disable]-efi is not supported for $arch"
242    usage
243fi
244
245if [ "$efi" ] && [ "$arch" = "riscv64" ] && [ -z "$efi_direct" ]; then
246    efi_direct=y
247fi
248
249if [ -z "$page_size" ]; then
250    if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
251        page_size="4096"
252    elif [ "$arch" = "ppc64" ]; then
253        page_size="65536"
254    fi
255else
256    if [ "${page_size: -1}" = "K" ] || [ "${page_size: -1}" = "k" ]; then
257        page_size=$(( ${page_size%?} * 1024 ))
258    fi
259
260    if [ "$arch" = "arm64" ]; then
261        if [ "$page_size" != "4096" ] && [ "$page_size" != "16384" ] &&
262               [ "$page_size" != "65536" ]; then
263            echo "arm64 doesn't support page size of $page_size"
264            usage
265        fi
266        if [ "$efi" = 'y' ] && [ "$page_size" != "4096" ]; then
267            echo "efi must use 4K pages"
268            exit 1
269        fi
270    elif [ "$arch" = "ppc64" ]; then
271        if [ "$page_size" != "4096" ] && [ "$page_size" != "65536" ]; then
272            echo "ppc64 doesn't support page size of $page_size"
273            usage
274        fi
275    else
276        echo "--page-size is not supported for $arch"
277        usage
278    fi
279fi
280
281[ -z "$processor" ] && processor="$arch"
282
283if [ "$processor" = "arm64" ]; then
284    processor="cortex-a57"
285elif [ "$processor" = "arm" ]; then
286    processor="cortex-a15"
287fi
288
289if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
290    testdir=x86
291elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
292    testdir=arm
293    if [ "$target" = "qemu" ]; then
294        arm_uart_early_addr=0x09000000
295    elif [ "$target" = "kvmtool" ]; then
296        arm_uart_early_addr=0x1000000
297        errata_force=1
298    else
299        echo "--target must be one of 'qemu' or 'kvmtool'!"
300        usage
301    fi
302
303    if [ "$earlycon" ]; then
304        IFS=, read -r name type_addr addr <<<"$earlycon"
305        if [ "$name" != "uart" ] && [ "$name" != "uart8250" ] &&
306                [ "$name" != "pl011" ]; then
307            echo "unknown earlycon name: $name"
308            usage
309        fi
310
311        if [ "$name" = "pl011" ]; then
312            if [ -z "$addr" ]; then
313                addr=$type_addr
314            else
315                if [ "$type_addr" != "mmio32" ]; then
316                    echo "unknown $name earlycon type: $type_addr"
317                    usage
318                fi
319            fi
320        else
321            if [ "$type_addr" != "mmio" ]; then
322                echo "unknown $name earlycon type: $type_addr"
323                usage
324            fi
325        fi
326
327        if [ -z "$addr" ]; then
328            echo "missing $name earlycon address"
329            usage
330        fi
331        if [[ $addr =~ ^0(x|X)[0-9a-fA-F]+$ ]] ||
332                [[ $addr =~ ^[0-9]+$ ]]; then
333            arm_uart_early_addr=$addr
334        else
335            echo "invalid $name earlycon address: $addr"
336            usage
337        fi
338    fi
339elif [ "$arch" = "ppc64" ]; then
340    testdir=powerpc
341    firmware="$testdir/boot_rom.bin"
342    if [ "$endian" != "little" ] && [ "$endian" != "big" ]; then
343        echo "You must provide endianness (big or little)!"
344        usage
345    fi
346elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then
347    testdir=riscv
348    arch_libdir=riscv
349elif [ "$arch" = "s390x" ]; then
350    testdir=s390x
351else
352    echo "arch $arch is not supported!"
353    arch=
354    usage
355fi
356if [ ! -d "$srcdir/$testdir" ]; then
357    echo "$srcdir/$testdir does not exist!"
358    exit 1
359fi
360
361if [ "$efi" = "y" ] && [ -f "$srcdir/$testdir/efi/run" ]; then
362    ln -fs "$srcdir/$testdir/efi/run" $testdir-run
363elif [ -f "$srcdir/$testdir/run" ]; then
364    ln -fs "$srcdir/$testdir/run" $testdir-run
365fi
366
367testsubdir=$testdir
368if [ "$efi" = "y" ]; then
369    testsubdir=$testdir/efi
370fi
371
372# check if uint32_t needs a long format modifier
373cat << EOF > lib-test.c
374__UINT32_TYPE__
375EOF
376u32_long=$("$cross_prefix$cc" -E lib-test.c | grep -v '^#' | grep -q long && echo yes)
377rm -f lib-test.c
378
379# check if slash can be used for division
380if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
381  cat << EOF > lib-test.S
382foo:
383    movl (8 / 2), %eax
384EOF
385  wa_divide=$("$cross_prefix$cc" -c lib-test.S >/dev/null 2>&1 || echo yes)
386  rm -f lib-test.{o,S}
387fi
388
389# warn if enhanced getopt is unavailable
390getopt -T > /dev/null
391if [ $? -ne 4 ]; then
392    echo "Without enhanced getopt you won't be able to use run_tests.sh."
393    echo "Add it to your PATH?"
394fi
395
396# Are we in a separate build tree? If so, link the Makefile
397# and shared stuff so that 'make' and run_tests.sh work.
398if test ! -e Makefile; then
399    echo "linking Makefile..."
400    ln -s "$srcdir/Makefile" .
401
402    echo "linking tests..."
403    mkdir -p $testsubdir
404    ln -sf "$srcdir/$testdir/run" $testdir/
405    if test "$testdir" != "$testsubdir"; then
406        ln -sf "$srcdir/$testsubdir/run" $testsubdir/
407    fi
408    ln -sf "$srcdir/$testdir/unittests.cfg" $testdir/
409    ln -sf "$srcdir/run_tests.sh"
410
411    if [ -d "$srcdir/$testdir/snippets" ]; then
412        mkdir -p "$testdir/snippets/c"
413    fi
414
415    echo "linking scripts..."
416    ln -sf "$srcdir/scripts"
417fi
418
419# link lib/asm for the architecture
420rm -f lib/asm
421asm="asm-generic"
422if [ -d "$srcdir/lib/$arch/asm" ]; then
423	asm="$srcdir/lib/$arch/asm"
424	mkdir -p "lib/$arch"
425elif [ -d "$srcdir/lib/$arch_libdir/asm" ]; then
426	asm="$srcdir/lib/$arch_libdir/asm"
427	mkdir -p "lib/$arch_libdir"
428elif [ -d "$srcdir/lib/$testdir/asm" ]; then
429	asm="$srcdir/lib/$testdir/asm"
430	mkdir -p "lib/$testdir"
431fi
432ln -sf "$asm" lib/asm
433mkdir -p lib/generated lib/libfdt
434
435# create the config
436cat <<EOF > config.mak
437# Shellcheck does not see these are used
438# shellcheck disable=SC2034
439# Shellcheck can give pointless quoting warnings for some commands
440# shellcheck disable=SC2209
441SRCDIR=$srcdir
442PREFIX=$prefix
443HOST=$host
444ARCH=$arch
445ARCH_NAME=$arch_name
446ARCH_LIBDIR=$arch_libdir
447PROCESSOR=$processor
448CC=$cross_prefix$cc
449CFLAGS=$cflags
450LD=$cross_prefix$ld
451OBJCOPY=$cross_prefix$objcopy
452OBJDUMP=$cross_prefix$objdump
453READELF=$cross_prefix$readelf
454AR=$cross_prefix$ar
455ADDR2LINE=$cross_prefix$addr2line
456TEST_DIR=$testdir
457TEST_SUBDIR=$testsubdir
458FIRMWARE=$firmware
459ENDIAN=$endian
460PRETTY_PRINT_STACKS=$pretty_print_stacks
461ENVIRON_DEFAULT=$environ_default
462ERRATATXT=$erratatxt
463U32_LONG_FMT=$u32_long
464WA_DIVIDE=$wa_divide
465GENPROTIMG=${GENPROTIMG-genprotimg}
466HOST_KEY_DOCUMENT=$host_key_document
467CONFIG_DUMP=$enable_dump
468CONFIG_EFI=$efi
469EFI_DIRECT=$efi_direct
470CONFIG_WERROR=$werror
471GEN_SE_HEADER=$gen_se_header
472EOF
473if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
474    echo "TARGET=$target" >> config.mak
475fi
476
477cat <<EOF > lib/config.h
478#ifndef _CONFIG_H_
479#define _CONFIG_H_
480/*
481 * Generated file. DO NOT MODIFY.
482 *
483 */
484
485EOF
486if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
487cat <<EOF >> lib/config.h
488
489#define CONFIG_UART_EARLY_BASE ${arm_uart_early_addr}
490#define CONFIG_ERRATA_FORCE ${errata_force}
491
492EOF
493fi
494
495if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ] || [ "$arch" = "ppc64" ]; then
496cat <<EOF >> lib/config.h
497
498#define CONFIG_PAGE_SIZE _AC(${page_size}, UL)
499
500EOF
501elif [ "$arch" = "riscv32" ] || [ "$arch" = "riscv64" ]; then
502cat <<EOF >> lib/config.h
503
504#define CONFIG_UART_EARLY_BASE 0x10000000
505
506EOF
507fi
508echo "#endif" >> lib/config.h
509