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