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 #include "ppc-util.h" 25 26 #define MAGIC 0xcafec0de 27 #define ADDRESS 0x4000 28 29 static void check_guest_memory(QTestState *qts) 30 { 31 uint32_t signature; 32 int i; 33 34 /* Poll until code has run and modified memory. Wait at most 600 seconds */ 35 for (i = 0; i < 60000; ++i) { 36 signature = qtest_readl(qts, ADDRESS); 37 if (signature == MAGIC) { 38 break; 39 } 40 g_usleep(10000); 41 } 42 43 g_assert_cmphex(signature, ==, MAGIC); 44 } 45 46 static void test_machine(const void *machine) 47 { 48 const char *extra_args = ""; 49 QTestState *qts; 50 51 /* 52 * The pseries firmware boots much faster without the default 53 * devices, it also needs Spectre/Meltdown workarounds disabled to 54 * avoid warnings with TCG 55 */ 56 if (strcmp(machine, "pseries") == 0) { 57 extra_args = "-nodefaults" 58 " -machine " PSERIES_DEFAULT_CAPABILITIES; 59 } 60 61 qts = qtest_initf("-M %s -accel tcg %s -prom-env \"use-nvramrc?=true\" " 62 "-prom-env \"nvramrc=%x %x l!\" ", (const char *)machine, 63 extra_args, MAGIC, ADDRESS); 64 check_guest_memory(qts); 65 qtest_quit(qts); 66 } 67 68 static void add_tests(const char *machines[]) 69 { 70 int i; 71 char *name; 72 73 for (i = 0; machines[i] != NULL; i++) { 74 if (qtest_has_machine(machines[i])) { 75 name = g_strdup_printf("prom-env/%s", machines[i]); 76 qtest_add_data_func(name, machines[i], test_machine); 77 g_free(name); 78 } 79 } 80 } 81 82 int main(int argc, char *argv[]) 83 { 84 const char *sparc_machines[] = { "SPARCbook", "Voyager", "SS-20", NULL }; 85 const char *sparc64_machines[] = { "sun4u", NULL }; 86 const char *ppc_machines[] = { "mac99", "g3beige", NULL }; 87 const char *arch = qtest_get_arch(); 88 89 g_test_init(&argc, &argv, NULL); 90 91 if (!strcmp(arch, "ppc")) { 92 add_tests(ppc_machines); 93 } else if (!strcmp(arch, "ppc64")) { 94 add_tests(ppc_machines); 95 if (g_test_slow()) { 96 qtest_add_data_func("prom-env/pseries", "pseries", test_machine); 97 } 98 } else if (!strcmp(arch, "sparc")) { 99 add_tests(sparc_machines); 100 } else if (!strcmp(arch, "sparc64")) { 101 add_tests(sparc64_machines); 102 } else { 103 g_assert_not_reached(); 104 } 105 106 return g_test_run(); 107 } 108