1 /* 2 * Test Open-Firmware-based machines. 3 * 4 * Copyright (c) 2016, 2017 Red Hat Inc. 5 * 6 * Author: 7 * Thomas Huth <thuth@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 10 * or later. See the COPYING file in the top-level directory. 11 * 12 * This test is used to check that some Open Firmware based machines (i.e. 13 * OpenBIOS or SLOF) can be started successfully in TCG mode. To do this, we 14 * first put some Forth code into the "boot-command" Open Firmware environment 15 * variable. This Forth code writes a well-known magic value to a known location 16 * in memory. Then we start the guest so that the firmware can boot and finally 17 * run the Forth code. 18 * The testing code here then can finally check whether the value has been 19 * successfully written into the guest memory. 20 */ 21 22 #include "qemu/osdep.h" 23 #include "libqtest.h" 24 25 #define MAGIC 0xcafec0de 26 #define ADDRESS 0x4000 27 28 static void check_guest_memory(QTestState *qts) 29 { 30 uint32_t signature; 31 int i; 32 33 /* Poll until code has run and modified memory. Wait at most 600 seconds */ 34 for (i = 0; i < 60000; ++i) { 35 signature = qtest_readl(qts, ADDRESS); 36 if (signature == MAGIC) { 37 break; 38 } 39 g_usleep(10000); 40 } 41 42 g_assert_cmphex(signature, ==, MAGIC); 43 } 44 45 static void test_machine(const void *machine) 46 { 47 const char *extra_args = ""; 48 QTestState *qts; 49 50 /* 51 * The pseries firmware boots much faster without the default 52 * devices, it also needs Spectre/Meltdown workarounds disabled to 53 * avoid warnings with TCG 54 */ 55 if (strcmp(machine, "pseries") == 0) { 56 extra_args = "-nodefaults" 57 " -machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken"; 58 } 59 60 qts = qtest_initf("-M %s -accel tcg %s -prom-env 'use-nvramrc?=true' " 61 "-prom-env 'nvramrc=%x %x l!' ", (const char *)machine, 62 extra_args, MAGIC, ADDRESS); 63 check_guest_memory(qts); 64 qtest_quit(qts); 65 } 66 67 static void add_tests(const char *machines[]) 68 { 69 int i; 70 char *name; 71 72 for (i = 0; machines[i] != NULL; i++) { 73 name = g_strdup_printf("prom-env/%s", machines[i]); 74 qtest_add_data_func(name, machines[i], test_machine); 75 g_free(name); 76 } 77 } 78 79 int main(int argc, char *argv[]) 80 { 81 const char *sparc_machines[] = { "SPARCbook", "Voyager", "SS-20", NULL }; 82 const char *sparc64_machines[] = { "sun4u", NULL }; 83 const char *ppc_machines[] = { "mac99", "g3beige", NULL }; 84 const char *arch = qtest_get_arch(); 85 86 g_test_init(&argc, &argv, NULL); 87 88 if (!strcmp(arch, "ppc")) { 89 add_tests(ppc_machines); 90 } else if (!strcmp(arch, "ppc64")) { 91 add_tests(ppc_machines); 92 if (g_test_slow()) { 93 qtest_add_data_func("prom-env/pseries", "pseries", test_machine); 94 } 95 } else if (!strcmp(arch, "sparc")) { 96 add_tests(sparc_machines); 97 } else if (!strcmp(arch, "sparc64")) { 98 add_tests(sparc64_machines); 99 } else { 100 g_assert_not_reached(); 101 } 102 103 return g_test_run(); 104 } 105