tests: Add migration test for aarch64

This patch adds migration test support for aarch64. The test code, which
implements the same functionality as x86, is booted as a kernel in qemu.
Here are the design choices we make for aarch64:

 * We choose this -kernel approach because aarch64 QEMU doesn't provide a
   built-in fw like x86 does. So instead of relying on a boot loader, we
   use -kernel approach for aarch64.
 * The serial output is sent to PL011 directly.
 * The physical memory base for mach-virt machine is 0x40000000. We change
   the start_address and end_address for aarch64.

In addition to providing the binary, this patch also includes the source
code and the build script in tests/migration/aarch64. So users can change
the source and/or re-compile the binary as they wish.

Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Wei Huang <wei@redhat.com>
Message-Id: <1538669326-28135-1-git-send-email-wei@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
Wei Huang 2018-10-04 12:08:46 -04:00 committed by Dr. David Alan Gilbert
parent 75e50c80e0
commit c02b37814c
7 changed files with 145 additions and 5 deletions

View File

@ -402,6 +402,7 @@ check-qtest-arm-y += tests/hexloader-test$(EXESUF)
check-qtest-aarch64-y = tests/numa-test$(EXESUF) check-qtest-aarch64-y = tests/numa-test$(EXESUF)
check-qtest-aarch64-$(CONFIG_SDHCI) += tests/sdhci-test$(EXESUF) check-qtest-aarch64-$(CONFIG_SDHCI) += tests/sdhci-test$(EXESUF)
check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF) check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF)
check-qtest-aarch64-y += tests/migration-test$(EXESUF)
check-qtest-microblazeel-y = $(check-qtest-microblaze-y) check-qtest-microblazeel-y = $(check-qtest-microblaze-y)

View File

@ -86,12 +86,13 @@ static const char *tmpfs;
* repeatedly. It outputs a 'B' at a fixed rate while it's still running. * repeatedly. It outputs a 'B' at a fixed rate while it's still running.
*/ */
#include "tests/migration/i386/a-b-bootblock.h" #include "tests/migration/i386/a-b-bootblock.h"
#include "tests/migration/aarch64/a-b-kernel.h"
static void init_bootfile_x86(const char *bootpath) static void init_bootfile(const char *bootpath, void *content)
{ {
FILE *bootfile = fopen(bootpath, "wb"); FILE *bootfile = fopen(bootpath, "wb");
g_assert_cmpint(fwrite(x86_bootsect, 512, 1, bootfile), ==, 1); g_assert_cmpint(fwrite(content, 512, 1, bootfile), ==, 1);
fclose(bootfile); fclose(bootfile);
} }
@ -428,7 +429,7 @@ static int test_migrate_start(QTestState **from, QTestState **to,
got_stop = false; got_stop = false;
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
init_bootfile_x86(bootpath); init_bootfile(bootpath, x86_bootsect);
cmd_src = g_strdup_printf("-machine accel=%s -m 150M" cmd_src = g_strdup_printf("-machine accel=%s -m 150M"
" -name source,debug-threads=on" " -name source,debug-threads=on"
" -serial file:%s/src_serial" " -serial file:%s/src_serial"
@ -459,6 +460,24 @@ static int test_migrate_start(QTestState **from, QTestState **to,
start_address = PPC_TEST_MEM_START; start_address = PPC_TEST_MEM_START;
end_address = PPC_TEST_MEM_END; end_address = PPC_TEST_MEM_END;
} else if (strcmp(arch, "aarch64") == 0) {
init_bootfile(bootpath, aarch64_kernel);
cmd_src = g_strdup_printf("-machine virt,accel=%s,gic-version=max "
"-name vmsource,debug-threads=on -cpu max "
"-m 150M -serial file:%s/src_serial "
"-kernel %s ",
accel, tmpfs, bootpath);
cmd_dst = g_strdup_printf("-machine virt,accel=%s,gic-version=max "
"-name vmdest,debug-threads=on -cpu max "
"-m 150M -serial file:%s/dest_serial "
"-kernel %s "
"-incoming %s ",
accel, tmpfs, bootpath, uri);
start_address = ARM_TEST_MEM_START;
end_address = ARM_TEST_MEM_END;
g_assert(sizeof(aarch64_kernel) <= ARM_TEST_MAX_KERNEL_SIZE);
} else { } else {
g_assert_not_reached(); g_assert_not_reached();
} }
@ -545,7 +564,7 @@ static void test_deprecated(void)
{ {
QTestState *from; QTestState *from;
from = qtest_start(""); from = qtest_start("-machine none");
deprecated_set_downtime(from, 0.12345); deprecated_set_downtime(from, 0.12345);
deprecated_set_speed(from, 12345); deprecated_set_speed(from, 12345);

View File

@ -5,7 +5,7 @@
# See the COPYING file in the top-level directory. # See the COPYING file in the top-level directory.
# #
TARGET_LIST = i386 TARGET_LIST = i386 aarch64
SRC_PATH = ../.. SRC_PATH = ../..

View File

@ -0,0 +1,18 @@
# To specify cross compiler prefix, use CROSS_PREFIX=
# $ make CROSS_PREFIX=aarch64-linux-gnu-
.PHONY: all clean
all: a-b-kernel.h
a-b-kernel.h: aarch64.kernel
echo "$$__note" > $@
xxd -i $< | sed -e 's/.*int.*//' >> $@
aarch64.kernel: aarch64.elf
$(CROSS_PREFIX)objcopy -O binary $< $@
aarch64.elf: a-b-kernel.S
$(CROSS_PREFIX)gcc -o $@ -nostdlib -Wl,--build-id=none $<
clean:
$(RM) *.kernel *.elf

View File

@ -0,0 +1,75 @@
#
# Copyright (c) 2018 Red Hat, Inc. and/or its affiliates
#
# Author:
# Wei Huang <wei@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2 or later.
# See the COPYING file in the top-level directory.
#
# Note: Please make sure the compiler compiles the assembly code below with
# pc-relative address. Also the branch instructions should use relative
# addresses only.
#include "../migration-test.h"
.section .text
.globl _start
_start:
/* disable MMU to use phys mem address */
mrs x0, sctlr_el1
bic x0, x0, #(1<<0)
msr sctlr_el1, x0
isb
/* traverse test memory region */
mov x0, #ARM_TEST_MEM_START
mov x1, #ARM_TEST_MEM_END
/* output char 'A' to PL011 */
mov w3, 'A'
mov x2, #ARM_MACH_VIRT_UART
strb w3, [x2]
/* clean up memory */
mov w3, #0
mov x4, x0
clean:
strb w3, [x4]
add x4, x4, #TEST_MEM_PAGE_SIZE
cmp x4, x1
ble clean
/* w5 keeps a counter so we can limit the output speed */
mov w5, #0
/* main body */
mainloop:
mov x4, x0
innerloop:
/* increment the first byte of each page by 1 */
ldrb w3, [x4]
add w3, w3, #1
and w3, w3, #0xff
strb w3, [x4]
/* make sure QEMU user space can see consistent data as MMU is off */
dc civac, x4
add x4, x4, #TEST_MEM_PAGE_SIZE
cmp x4, x1
blt innerloop
add w5, w5, #1
and w5, w5, #0xff
cmp w5, #0
bne mainloop
/* output char 'B' to PL011 */
mov w3, 'B'
strb w3, [x2]
b mainloop

View File

@ -0,0 +1,18 @@
/* This file is automatically generated from the assembly file in
* tests/migration/aarch64. Edit that file and then run "make all"
* inside tests/migration to update, and then remember to send both
* the header and the assembler differences in your patch submission.
*/
unsigned char aarch64_kernel[] = {
0x00, 0x10, 0x38, 0xd5, 0x00, 0xf8, 0x7f, 0x92, 0x00, 0x10, 0x18, 0xd5,
0xdf, 0x3f, 0x03, 0xd5, 0x00, 0x02, 0xa8, 0xd2, 0x01, 0xc8, 0xa8, 0xd2,
0x23, 0x08, 0x80, 0x52, 0x02, 0x20, 0xa1, 0xd2, 0x43, 0x00, 0x00, 0x39,
0x03, 0x00, 0x80, 0x52, 0xe4, 0x03, 0x00, 0xaa, 0x83, 0x00, 0x00, 0x39,
0x84, 0x04, 0x40, 0x91, 0x9f, 0x00, 0x01, 0xeb, 0xad, 0xff, 0xff, 0x54,
0x05, 0x00, 0x80, 0x52, 0xe4, 0x03, 0x00, 0xaa, 0x83, 0x00, 0x40, 0x39,
0x63, 0x04, 0x00, 0x11, 0x63, 0x1c, 0x00, 0x12, 0x83, 0x00, 0x00, 0x39,
0x24, 0x7e, 0x0b, 0xd5, 0x84, 0x04, 0x40, 0x91, 0x9f, 0x00, 0x01, 0xeb,
0x2b, 0xff, 0xff, 0x54, 0xa5, 0x04, 0x00, 0x11, 0xa5, 0x1c, 0x00, 0x12,
0xbf, 0x00, 0x00, 0x71, 0x81, 0xfe, 0xff, 0x54, 0x43, 0x08, 0x80, 0x52,
0x43, 0x00, 0x00, 0x39, 0xf1, 0xff, 0xff, 0x17
};

View File

@ -18,4 +18,13 @@
#define PPC_TEST_MEM_START (1 * 1024 * 1024) #define PPC_TEST_MEM_START (1 * 1024 * 1024)
#define PPC_TEST_MEM_END (100 * 1024 * 1024) #define PPC_TEST_MEM_END (100 * 1024 * 1024)
/* ARM */
#define ARM_TEST_MEM_START (0x40000000 + 1 * 1024 * 1024)
#define ARM_TEST_MEM_END (0x40000000 + 100 * 1024 * 1024)
#define ARM_MACH_VIRT_UART 0x09000000
/* AArch64 kernel load address is 0x40080000, and the test memory starts at
* 0x40100000. So the maximum allowable kernel size is 512KB.
*/
#define ARM_TEST_MAX_KERNEL_SIZE (512 * 1024)
#endif /* _TEST_MIGRATION_H_ */ #endif /* _TEST_MIGRATION_H_ */