| /* |
| * Test Open-Firmware-based machines. |
| * |
| * Copyright (c) 2016, 2017 Red Hat Inc. |
| * |
| * Author: |
| * Thomas Huth <thuth@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. |
| * |
| * This test is used to check that some Open Firmware based machines (i.e. |
| * OpenBIOS or SLOF) can be started successfully in TCG mode. To do this, we |
| * first put some Forth code into the "boot-command" Open Firmware environment |
| * variable. This Forth code writes a well-known magic value to a known location |
| * in memory. Then we start the guest so that the firmware can boot and finally |
| * run the Forth code. |
| * The testing code here then can finally check whether the value has been |
| * successfully written into the guest memory. |
| */ |
| |
| #include "qemu/osdep.h" |
| #include "libqtest.h" |
| |
| #define MAGIC 0xcafec0de |
| #define ADDRESS 0x4000 |
| |
| static void check_guest_memory(QTestState *qts) |
| { |
| uint32_t signature; |
| int i; |
| |
| /* Poll until code has run and modified memory. Wait at most 600 seconds */ |
| for (i = 0; i < 60000; ++i) { |
| signature = qtest_readl(qts, ADDRESS); |
| if (signature == MAGIC) { |
| break; |
| } |
| g_usleep(10000); |
| } |
| |
| g_assert_cmphex(signature, ==, MAGIC); |
| } |
| |
| static void test_machine(const void *machine) |
| { |
| const char *extra_args = ""; |
| QTestState *qts; |
| |
| /* |
| * The pseries firmware boots much faster without the default |
| * devices, it also needs Spectre/Meltdown workarounds disabled to |
| * avoid warnings with TCG |
| */ |
| if (strcmp(machine, "pseries") == 0) { |
| extra_args = "-nodefaults" |
| " -machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken"; |
| } |
| |
| qts = qtest_initf("-M %s,accel=tcg %s -prom-env 'use-nvramrc?=true' " |
| "-prom-env 'nvramrc=%x %x l!' ", (const char *)machine, |
| extra_args, MAGIC, ADDRESS); |
| check_guest_memory(qts); |
| qtest_quit(qts); |
| } |
| |
| static void add_tests(const char *machines[]) |
| { |
| int i; |
| char *name; |
| |
| for (i = 0; machines[i] != NULL; i++) { |
| name = g_strdup_printf("prom-env/%s", machines[i]); |
| qtest_add_data_func(name, machines[i], test_machine); |
| g_free(name); |
| } |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| const char *sparc_machines[] = { "SPARCbook", "Voyager", "SS-20", NULL }; |
| const char *sparc64_machines[] = { "sun4u", NULL }; |
| const char *ppc_machines[] = { "mac99", "g3beige", NULL }; |
| const char *arch = qtest_get_arch(); |
| |
| g_test_init(&argc, &argv, NULL); |
| |
| if (!strcmp(arch, "ppc")) { |
| add_tests(ppc_machines); |
| } else if (!strcmp(arch, "ppc64")) { |
| add_tests(ppc_machines); |
| if (g_test_slow()) { |
| qtest_add_data_func("prom-env/pseries", "pseries", test_machine); |
| } |
| } else if (!strcmp(arch, "sparc")) { |
| add_tests(sparc_machines); |
| } else if (!strcmp(arch, "sparc64")) { |
| add_tests(sparc64_machines); |
| } else { |
| g_assert_not_reached(); |
| } |
| |
| return g_test_run(); |
| } |