From patchwork Thu Oct 6 18:56:58 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 679033 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sqhkH22j6z9s9Y for ; Fri, 7 Oct 2016 05:58:12 +1100 (AEDT) Received: from localhost ([::1]:58874 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bsDrq-0002FM-0R for incoming@patchwork.ozlabs.org; Thu, 06 Oct 2016 14:58:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46147) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bsDr5-0001sK-R2 for qemu-devel@nongnu.org; Thu, 06 Oct 2016 14:57:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bsDr1-00034T-MU for qemu-devel@nongnu.org; Thu, 06 Oct 2016 14:57:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48862) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bsDr1-00034I-C7 for qemu-devel@nongnu.org; Thu, 06 Oct 2016 14:57:15 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 339C6837; Thu, 6 Oct 2016 18:57:13 +0000 (UTC) Received: from thinkpad.redhat.com (ovpn-112-46.ams2.redhat.com [10.36.112.46]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u96Iv8sF022188; Thu, 6 Oct 2016 14:57:09 -0400 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Thu, 6 Oct 2016 20:56:58 +0200 Message-Id: <1475780218-26393-1-git-send-email-lvivier@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 06 Oct 2016 18:57:14 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH] qtest: ask endianness of the target in qtest_init() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Laurent Vivier , Peter Maydell , Greg Kurz , David Gibson Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The target endianness is not deduced anymore from the architecture name but asked directly to the guest, using a new qtest command: "endianness". As it can't change (this is the value of TARGET_WORDS_BIGENDIAN), we store it to not have to ask every time we want to know if we have to byte-swap a value. Signed-off-by: Laurent Vivier CC: Greg Kurz CC: David Gibson CC: Peter Maydell Reviewed-by: Greg Kurz --- Note: this patch can be seen as a v2 of "qtest: evaluate endianness of the target in qtest_init()" from the patch series "tests: enable virtio tests on SPAPR" in which I have added the idea from Peter to ask the endianness directly to the guest using a new qtest command. qtest.c | 7 ++ tests/libqos/virtio-pci.c | 2 +- tests/libqtest.c | 224 ++++++++++++++++++++-------------------------- tests/libqtest.h | 16 +++- tests/virtio-blk-test.c | 2 +- 5 files changed, 118 insertions(+), 133 deletions(-) diff --git a/qtest.c b/qtest.c index 22482cc..b53b39c 100644 --- a/qtest.c +++ b/qtest.c @@ -537,6 +537,13 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) qtest_send_prefix(chr); qtest_send(chr, "OK\n"); + } else if (strcmp(words[0], "endianness") == 0) { + qtest_send_prefix(chr); +#if defined(TARGET_WORDS_BIGENDIAN) + qtest_sendf(chr, "OK big\n"); +#else + qtest_sendf(chr, "OK little\n"); +#endif #ifdef TARGET_PPC64 } else if (strcmp(words[0], "rtas") == 0) { uint64_t res, args, ret; diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c index 18b92b9..6e005c1 100644 --- a/tests/libqos/virtio-pci.c +++ b/tests/libqos/virtio-pci.c @@ -86,7 +86,7 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr) int i; uint64_t u64 = 0; - if (qtest_big_endian()) { + if (target_big_endian()) { for (i = 0; i < 8; ++i) { u64 |= (uint64_t)qpci_io_readb(dev->pdev, (void *)(uintptr_t)addr + i) << (7 - i) * 8; diff --git a/tests/libqtest.c b/tests/libqtest.c index 6f6bdf1..27cf6b1 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -37,6 +37,7 @@ struct QTestState bool irq_level[MAX_IRQ]; GString *rx; pid_t qemu_pid; /* our child QEMU process */ + bool big_endian; }; static GHookList abrt_hooks; @@ -146,89 +147,6 @@ void qtest_add_abrt_handler(GHookFunc fn, const void *data) g_hook_prepend(&abrt_hooks, hook); } -QTestState *qtest_init(const char *extra_args) -{ - QTestState *s; - int sock, qmpsock, i; - gchar *socket_path; - gchar *qmp_socket_path; - gchar *command; - const char *qemu_binary; - - qemu_binary = getenv("QTEST_QEMU_BINARY"); - g_assert(qemu_binary != NULL); - - s = g_malloc(sizeof(*s)); - - socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid()); - qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid()); - - sock = init_socket(socket_path); - qmpsock = init_socket(qmp_socket_path); - - qtest_add_abrt_handler(kill_qemu_hook_func, s); - - s->qemu_pid = fork(); - if (s->qemu_pid == 0) { - setenv("QEMU_AUDIO_DRV", "none", true); - command = g_strdup_printf("exec %s " - "-qtest unix:%s,nowait " - "-qtest-log %s " - "-qmp unix:%s,nowait " - "-machine accel=qtest " - "-display none " - "%s", qemu_binary, socket_path, - getenv("QTEST_LOG") ? "/dev/fd/2" : "/dev/null", - qmp_socket_path, - extra_args ?: ""); - execlp("/bin/sh", "sh", "-c", command, NULL); - exit(1); - } - - s->fd = socket_accept(sock); - if (s->fd >= 0) { - s->qmp_fd = socket_accept(qmpsock); - } - unlink(socket_path); - unlink(qmp_socket_path); - g_free(socket_path); - g_free(qmp_socket_path); - - g_assert(s->fd >= 0 && s->qmp_fd >= 0); - - s->rx = g_string_new(""); - for (i = 0; i < MAX_IRQ; i++) { - s->irq_level[i] = false; - } - - /* Read the QMP greeting and then do the handshake */ - qtest_qmp_discard_response(s, ""); - qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }"); - - if (getenv("QTEST_STOP")) { - kill(s->qemu_pid, SIGSTOP); - } - - return s; -} - -void qtest_quit(QTestState *s) -{ - qtest_instances = g_list_remove(qtest_instances, s); - g_hook_destroy_link(&abrt_hooks, g_hook_find_data(&abrt_hooks, TRUE, s)); - - /* Uninstall SIGABRT handler on last instance */ - if (!qtest_instances) { - cleanup_sigabrt_handler(); - } - - kill_qemu(s); - close(s->fd); - close(s->qmp_fd); - g_string_free(s->rx, true); - g_free(s); -} - static void socket_send(int fd, const char *buf, size_t size) { size_t offset; @@ -347,6 +265,99 @@ typedef struct { QDict *response; } QMPResponseParser; +QTestState *qtest_init(const char *extra_args) +{ + QTestState *s; + int sock, qmpsock, i; + gchar *socket_path; + gchar *qmp_socket_path; + gchar *command; + const char *qemu_binary; + gchar **args; + + qemu_binary = getenv("QTEST_QEMU_BINARY"); + g_assert(qemu_binary != NULL); + + s = g_malloc(sizeof(*s)); + + socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid()); + qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid()); + + sock = init_socket(socket_path); + qmpsock = init_socket(qmp_socket_path); + + qtest_add_abrt_handler(kill_qemu_hook_func, s); + + s->qemu_pid = fork(); + if (s->qemu_pid == 0) { + setenv("QEMU_AUDIO_DRV", "none", true); + command = g_strdup_printf("exec %s " + "-qtest unix:%s,nowait " + "-qtest-log %s " + "-qmp unix:%s,nowait " + "-machine accel=qtest " + "-display none " + "%s", qemu_binary, socket_path, + getenv("QTEST_LOG") ? "/dev/fd/2" + : "/dev/null", + qmp_socket_path, + extra_args ?: ""); + execlp("/bin/sh", "sh", "-c", command, NULL); + exit(1); + } + + s->fd = socket_accept(sock); + if (s->fd >= 0) { + s->qmp_fd = socket_accept(qmpsock); + } + unlink(socket_path); + unlink(qmp_socket_path); + g_free(socket_path); + g_free(qmp_socket_path); + + g_assert(s->fd >= 0 && s->qmp_fd >= 0); + + s->rx = g_string_new(""); + for (i = 0; i < MAX_IRQ; i++) { + s->irq_level[i] = false; + } + + /* Read the QMP greeting and then do the handshake */ + qtest_qmp_discard_response(s, ""); + qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }"); + + if (getenv("QTEST_STOP")) { + kill(s->qemu_pid, SIGSTOP); + } + + /* ask endianness of the target */ + + qtest_sendf(s, "endianness\n"); + args = qtest_rsp(s, 1); + g_assert(strcmp(args[1], "big") == 0 || strcmp(args[1], "little") == 0); + s->big_endian = strcmp(args[1], "big") == 0; + g_strfreev(args); + + return s; +} + +void qtest_quit(QTestState *s) +{ + qtest_instances = g_list_remove(qtest_instances, s); + g_hook_destroy_link(&abrt_hooks, g_hook_find_data(&abrt_hooks, TRUE, s)); + + /* Uninstall SIGABRT handler on last instance */ + if (!qtest_instances) { + cleanup_sigabrt_handler(); + } + + kill_qemu(s); + close(s->fd); + close(s->qmp_fd); + g_string_free(s->rx, true); + g_free(s); +} + static void qmp_response(JSONMessageParser *parser, GQueue *tokens) { QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser); @@ -886,50 +897,7 @@ char *hmp(const char *fmt, ...) return ret; } -bool qtest_big_endian(void) +bool qtest_big_endian(QTestState *s) { - const char *arch = qtest_get_arch(); - int i; - - static const struct { - const char *arch; - bool big_endian; - } endianness[] = { - { "aarch64", false }, - { "alpha", false }, - { "arm", false }, - { "cris", false }, - { "i386", false }, - { "lm32", true }, - { "m68k", true }, - { "microblaze", true }, - { "microblazeel", false }, - { "mips", true }, - { "mips64", true }, - { "mips64el", false }, - { "mipsel", false }, - { "moxie", true }, - { "or32", true }, - { "ppc", true }, - { "ppc64", true }, - { "ppcemb", true }, - { "s390x", true }, - { "sh4", false }, - { "sh4eb", true }, - { "sparc", true }, - { "sparc64", true }, - { "unicore32", false }, - { "x86_64", false }, - { "xtensa", false }, - { "xtensaeb", true }, - {}, - }; - - for (i = 0; endianness[i].arch; i++) { - if (strcmp(endianness[i].arch, arch) == 0) { - return endianness[i].big_endian; - } - } - - return false; + return s->big_endian; } diff --git a/tests/libqtest.h b/tests/libqtest.h index f7402e0..4be1f77 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -410,6 +410,14 @@ int64_t qtest_clock_step(QTestState *s, int64_t step); int64_t qtest_clock_set(QTestState *s, int64_t val); /** + * qtest_big_endian: + * @s: QTestState instance to operate on. + * + * Returns: True if the architecture under test has a big endian configuration. + */ +bool qtest_big_endian(QTestState *s); + +/** * qtest_get_arch: * * Returns: The architecture for the QEMU executable under test. @@ -874,12 +882,14 @@ static inline int64_t clock_set(int64_t val) } /** - * qtest_big_endian: + * target_big_endian: * * Returns: True if the architecture under test has a big endian configuration. */ -bool qtest_big_endian(void); - +static inline bool target_big_endian(void) +{ + return qtest_big_endian(global_qtest); +} QDict *qmp_fd_receive(int fd); void qmp_fd_sendv(int fd, const char *fmt, va_list ap); diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index 3c4fecc..0506917 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -125,7 +125,7 @@ static inline void virtio_blk_fix_request(QVirtioBlkReq *req) bool host_endian = false; #endif - if (qtest_big_endian() != host_endian) { + if (target_big_endian() != host_endian) { req->type = bswap32(req->type); req->ioprio = bswap32(req->ioprio); req->sector = bswap64(req->sector);