qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

tests: add RTAS command in the protocol

Add a first test to validate the protocol:

- rtas/get-time-of-day compares the time
from the guest with the time from the host.

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

authored by

Laurent Vivier and committed by
David Gibson
eeddd59f 8d6ef7c9

+197
+19
hw/ppc/spapr_rtas.c
··· 37 37 38 38 #include "hw/ppc/spapr.h" 39 39 #include "hw/ppc/spapr_vio.h" 40 + #include "hw/ppc/spapr_rtas.h" 40 41 #include "hw/ppc/ppc.h" 41 42 #include "qapi-event.h" 42 43 #include "hw/boards.h" ··· 689 690 690 691 hcall_dprintf("Unknown RTAS token 0x%x\n", token); 691 692 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 693 + return H_PARAMETER; 694 + } 695 + 696 + uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args, 697 + uint32_t nret, uint64_t rets) 698 + { 699 + int token; 700 + 701 + for (token = 0; token < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; token++) { 702 + if (strcmp(cmd, rtas_table[token].name) == 0) { 703 + sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 704 + PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 705 + 706 + rtas_table[token].fn(cpu, spapr, token + RTAS_TOKEN_BASE, 707 + nargs, args, nret, rets); 708 + return H_SUCCESS; 709 + } 710 + } 692 711 return H_PARAMETER; 693 712 } 694 713
+10
include/hw/ppc/spapr_rtas.h
··· 1 + #ifndef HW_SPAPR_RTAS_H 2 + #define HW_SPAPR_RTAS_H 3 + /* 4 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 5 + * See the COPYING file in the top-level directory. 6 + */ 7 + 8 + uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args, 9 + uint32_t nret, uint64_t rets); 10 + #endif /* HW_SPAPR_RTAS_H */
+17
qtest.c
··· 28 28 #include "qemu/option.h" 29 29 #include "qemu/error-report.h" 30 30 #include "qemu/cutils.h" 31 + #ifdef TARGET_PPC64 32 + #include "hw/ppc/spapr_rtas.h" 33 + #endif 31 34 32 35 #define MAX_IRQ 256 33 36 ··· 534 537 535 538 qtest_send_prefix(chr); 536 539 qtest_send(chr, "OK\n"); 540 + #ifdef TARGET_PPC64 541 + } else if (strcmp(words[0], "rtas") == 0) { 542 + uint64_t res, args, ret; 543 + unsigned long nargs, nret; 544 + 545 + g_assert(qemu_strtoul(words[2], NULL, 0, &nargs) == 0); 546 + g_assert(qemu_strtoull(words[3], NULL, 0, &args) == 0); 547 + g_assert(qemu_strtoul(words[4], NULL, 0, &nret) == 0); 548 + g_assert(qemu_strtoull(words[5], NULL, 0, &ret) == 0); 549 + res = qtest_rtas_call(words[1], nargs, args, nret, ret); 550 + 551 + qtest_send_prefix(chr); 552 + qtest_sendf(chr, "OK %"PRIu64"\n", res); 553 + #endif 537 554 } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) { 538 555 int64_t ns; 539 556
+3
tests/Makefile.include
··· 268 268 check-qtest-ppc64-y += tests/drive_del-test$(EXESUF) 269 269 check-qtest-ppc64-y += tests/postcopy-test$(EXESUF) 270 270 check-qtest-ppc64-y += tests/boot-serial-test$(EXESUF) 271 + check-qtest-ppc64-y += tests/rtas-test$(EXESUF) 271 272 272 273 check-qtest-sh4-y = tests/endianness-test$(EXESUF) 273 274 ··· 585 586 libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o 586 587 libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o 587 588 libqos-spapr-obj-y += tests/libqos/libqos-spapr.o 589 + libqos-spapr-obj-y += tests/libqos/rtas.o 588 590 libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o 589 591 libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o 590 592 libqos-pc-obj-y += tests/libqos/ahci.o ··· 599 601 tests/endianness-test$(EXESUF): tests/endianness-test.o 600 602 tests/spapr-phb-test$(EXESUF): tests/spapr-phb-test.o $(libqos-obj-y) 601 603 tests/prom-env-test$(EXESUF): tests/prom-env-test.o $(libqos-obj-y) 604 + tests/rtas-test$(EXESUF): tests/rtas-test.o $(libqos-spapr-obj-y) 602 605 tests/fdc-test$(EXESUF): tests/fdc-test.o 603 606 tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y) 604 607 tests/ahci-test$(EXESUF): tests/ahci-test.o $(libqos-pc-obj-y)
+71
tests/libqos/rtas.c
··· 1 + /* 2 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 3 + * See the COPYING file in the top-level directory. 4 + */ 5 + 6 + #include "qemu/osdep.h" 7 + #include "libqtest.h" 8 + #include "libqos/rtas.h" 9 + 10 + static void qrtas_copy_args(uint64_t target_args, uint32_t nargs, 11 + uint32_t *args) 12 + { 13 + int i; 14 + 15 + for (i = 0; i < nargs; i++) { 16 + writel(target_args + i * sizeof(uint32_t), args[i]); 17 + } 18 + } 19 + 20 + static void qrtas_copy_ret(uint64_t target_ret, uint32_t nret, uint32_t *ret) 21 + { 22 + int i; 23 + 24 + for (i = 0; i < nret; i++) { 25 + ret[i] = readl(target_ret + i * sizeof(uint32_t)); 26 + } 27 + } 28 + 29 + static uint64_t qrtas_call(QGuestAllocator *alloc, const char *name, 30 + uint32_t nargs, uint32_t *args, 31 + uint32_t nret, uint32_t *ret) 32 + { 33 + uint64_t res; 34 + uint64_t target_args, target_ret; 35 + 36 + target_args = guest_alloc(alloc, nargs * sizeof(uint32_t)); 37 + target_ret = guest_alloc(alloc, nret * sizeof(uint32_t)); 38 + 39 + qrtas_copy_args(target_args, nargs, args); 40 + res = qtest_rtas_call(global_qtest, name, 41 + nargs, target_args, nret, target_ret); 42 + qrtas_copy_ret(target_ret, nret, ret); 43 + 44 + guest_free(alloc, target_ret); 45 + guest_free(alloc, target_args); 46 + 47 + return res; 48 + } 49 + 50 + int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns) 51 + { 52 + int res; 53 + uint32_t ret[8]; 54 + 55 + res = qrtas_call(alloc, "get-time-of-day", 0, NULL, 8, ret); 56 + if (res != 0) { 57 + return res; 58 + } 59 + 60 + res = ret[0]; 61 + memset(tm, 0, sizeof(*tm)); 62 + tm->tm_year = ret[1] - 1900; 63 + tm->tm_mon = ret[2] - 1; 64 + tm->tm_mday = ret[3]; 65 + tm->tm_hour = ret[4]; 66 + tm->tm_min = ret[5]; 67 + tm->tm_sec = ret[6]; 68 + *ns = ret[7]; 69 + 70 + return res; 71 + }
+11
tests/libqos/rtas.h
··· 1 + /* 2 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 3 + * See the COPYING file in the top-level directory. 4 + */ 5 + 6 + #ifndef LIBQOS_RTAS_H 7 + #define LIBQOS_RTAS_H 8 + #include "libqos/malloc.h" 9 + 10 + int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns); 11 + #endif /* LIBQOS_RTAS_H */
+10
tests/libqtest.c
··· 751 751 g_strfreev(args); 752 752 } 753 753 754 + uint64_t qtest_rtas_call(QTestState *s, const char *name, 755 + uint32_t nargs, uint64_t args, 756 + uint32_t nret, uint64_t ret) 757 + { 758 + qtest_sendf(s, "rtas %s %u 0x%"PRIx64" %u 0x%"PRIx64"\n", 759 + name, nargs, args, nret, ret); 760 + qtest_rsp(s, 0); 761 + return 0; 762 + } 763 + 754 764 void qtest_add_func(const char *str, void (*fn)(void)) 755 765 { 756 766 gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
+15
tests/libqtest.h
··· 318 318 void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size); 319 319 320 320 /** 321 + * qtest_rtas_call: 322 + * @s: #QTestState instance to operate on. 323 + * @name: name of the command to call. 324 + * @nargs: Number of args. 325 + * @args: Guest address to read args from. 326 + * @nret: Number of return value. 327 + * @ret: Guest address to write return values to. 328 + * 329 + * Call an RTAS function 330 + */ 331 + uint64_t qtest_rtas_call(QTestState *s, const char *name, 332 + uint32_t nargs, uint64_t args, 333 + uint32_t nret, uint64_t ret); 334 + 335 + /** 321 336 * qtest_bufread: 322 337 * @s: #QTestState instance to operate on. 323 338 * @addr: Guest address to read from.
+41
tests/rtas-test.c
··· 1 + #include "qemu/osdep.h" 2 + #include "qemu/cutils.h" 3 + #include "libqtest.h" 4 + 5 + #include "libqos/libqos-spapr.h" 6 + #include "libqos/rtas.h" 7 + 8 + static void test_rtas_get_time_of_day(void) 9 + { 10 + QOSState *qs; 11 + struct tm tm; 12 + uint32_t ns; 13 + uint64_t ret; 14 + time_t t1, t2; 15 + 16 + qs = qtest_spapr_boot("-machine pseries"); 17 + g_assert(qs != NULL); 18 + 19 + t1 = time(NULL); 20 + ret = qrtas_get_time_of_day(qs->alloc, &tm, &ns); 21 + g_assert_cmpint(ret, ==, 0); 22 + t2 = mktimegm(&tm); 23 + g_assert(t2 - t1 < 5); /* 5 sec max to run the test */ 24 + 25 + qtest_spapr_shutdown(qs); 26 + } 27 + 28 + int main(int argc, char *argv[]) 29 + { 30 + const char *arch = qtest_get_arch(); 31 + 32 + g_test_init(&argc, &argv, NULL); 33 + 34 + if (strcmp(arch, "ppc64")) { 35 + g_printerr("RTAS requires ppc64-softmmu/qemu-system-ppc64\n"); 36 + exit(EXIT_FAILURE); 37 + } 38 + qtest_add_func("rtas/get-time-of-day", test_rtas_get_time_of_day); 39 + 40 + return g_test_run(); 41 + }