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