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