From patchwork Sun Dec 16 23:56:28 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Ogilvie X-Patchwork-Id: 206761 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B02702C00A8 for ; Mon, 17 Dec 2012 12:12:46 +1100 (EST) Received: from localhost ([::1]:59247 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TkO5L-0003Ql-6u for incoming@patchwork.ozlabs.org; Sun, 16 Dec 2012 18:57:31 -0500 Received: from eggs.gnu.org ([208.118.235.92]:60752) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TkO4p-0002Yw-Ga for qemu-devel@nongnu.org; Sun, 16 Dec 2012 18:57:02 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TkO4m-0007Ip-KV for qemu-devel@nongnu.org; Sun, 16 Dec 2012 18:56:59 -0500 Received: from qmta12.emeryville.ca.mail.comcast.net ([76.96.27.227]:39864) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TkO4m-0007Ib-C2 for qemu-devel@nongnu.org; Sun, 16 Dec 2012 18:56:56 -0500 Received: from omta11.emeryville.ca.mail.comcast.net ([76.96.30.36]) by qmta12.emeryville.ca.mail.comcast.net with comcast id cPFh1k0060mlR8UACPwvsZ; Sun, 16 Dec 2012 23:56:55 +0000 Received: from mmogilvi.homeip.net ([75.70.117.91]) by omta11.emeryville.ca.mail.comcast.net with comcast id cPwt1k00W1yPlfP8XPwupK; Sun, 16 Dec 2012 23:56:54 +0000 Received: by mmogilvi.homeip.net (Postfix, from userid 501) id 7A67A1E9601B; Sun, 16 Dec 2012 16:56:53 -0700 (MST) From: Matthew Ogilvie To: qemu-devel@nongnu.org Date: Sun, 16 Dec 2012 16:56:28 -0700 Message-Id: <1355702189-6994-10-git-send-email-mmogilvi_qemu@miniinfo.net> X-Mailer: git-send-email 1.7.10.2.484.gcd07cc5 In-Reply-To: <1355702189-6994-1-git-send-email-mmogilvi_qemu@miniinfo.net> References: <1355702189-6994-1-git-send-email-mmogilvi_qemu@miniinfo.net> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcast.net; s=q20121106; t=1355702215; bh=A8mDZ5eYvZOIqZxrOWE878yWUMjgL/aOWfGqi+peTGw=; h=Received:Received:Received:From:To:Subject:Date:Message-Id; b=RaF3RZPT+frxxFN60cDDFnp3+epVahcUbfBE04gdrwqSE/nu7KYNJh0dX+zd8ysoO 0tNw0PQMNQgQHXi9pX494nQn/BfVceIUgOR4g+3aSiSOBOl+PNNv6cG6kbZmi/oh5v 8fbdo//1oWIJjBTpmX+ywDRToCfD6+Kqg4VY+OXkf5HUL4dV2FqqnPmGh8CW9aSZhO w7f9iwd4CJ9XRDoXNP6POvdZwigWH0J/7tHAesz7WP5zAs05nRqGwhW2Fnq6lkA35g yoW2vAAph+gkMAk3SRbCKVmGsKEGcS0ff+gQ7uWfJ81zJcwa3aOANGr6BKMIEPWAfC MqygxVpIPA2XQ== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 76.96.27.227 Cc: "Maciej W. Rozycki" , Jan Kiszka , Matthew Ogilvie , Gleb Natapov Subject: [Qemu-devel] [PATCH v8 09/10] qtest: add set_irq_{in, out} infrastructure for testing interrupt controllers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Matthew Ogilvie --- hw/i8259.c | 6 ++++++ qtest.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ tests/libqtest.c | 12 ++++++++++++ tests/libqtest.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) diff --git a/hw/i8259.c b/hw/i8259.c index 9b2ec40..5f09f2f 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -453,6 +453,9 @@ qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq) } isa_pic = &dev->qdev; + object_property_add_link(OBJECT(bus), + "i8259-master", TYPE_DEVICE, + (Object **)&isa_pic, NULL); dev = i8259_init_chip("isa-i8259", bus, false); @@ -462,6 +465,9 @@ qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq) } slave_pic = DO_UPCAST(PICCommonState, dev, dev); + object_property_add_link(OBJECT(bus), + "i8259-slave", TYPE_DEVICE, + (Object **)&slave_pic, NULL); return irq_set; } diff --git a/qtest.c b/qtest.c index 6965910..d4c2dd7 100644 --- a/qtest.c +++ b/qtest.c @@ -117,6 +117,21 @@ static bool qtest_opened; * where NUM is an IRQ number. For the PC, interrupts can be intercepted * simply with "irq_intercept_in ioapic" (note that IRQ0 comes out with * NUM=0 even though it is remapped to GSI 2). + * + * Testing interrupt handler chips like the i8259: + * + * > set_irq_in QOM-PATH IRQ LEVEL + * < OK + * + * > set_irq_out QOM-PATH IRQ LEVEL + * < OK + * + * Forcibly set the given interrupt pin to the given level (from the + * consumer's point of view). + * + * FUTURE: Some abstracted mechanism to initiate delivery of an + * interrupt to the CPU, returning the interrupt vector number + * that would be delivered to that CPU. */ static int hex2nib(char ch) @@ -239,7 +254,43 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) irq_intercept_dev = dev; qtest_send_prefix(chr); qtest_send(chr, "OK\n"); + } else if (strcmp(words[0], "set_irq_in") == 0 || + strcmp(words[0], "set_irq_out") == 0) { + DeviceState *dev; + qemu_irq *irqs; + int num_irqs; + int num; + int level; + + g_assert(words[1] && words[2] && words[3]); + + dev = DEVICE(object_resolve_path(words[1], NULL)); + if (!dev) { + qtest_send_prefix(chr); + qtest_send(chr, "FAIL Unknown device\n"); + return; + } + if (words[0][8] == 'o') { + irqs = dev->gpio_out; + num_irqs = dev->num_gpio_out; + } else { + irqs = dev->gpio_in; + num_irqs = dev->num_gpio_in; + } + + num = strtol(words[2], NULL, 0); + if (num < 0 || num >= num_irqs) { + qtest_send_prefix(chr); + qtest_send(chr, "FAIL Bad IRQ number\n"); + return; + } + + level = strtol(words[3], NULL, 0); + + qemu_set_irq(irqs[num], level != 0); + qtest_send_prefix(chr); + qtest_send(chr, "OK\n"); } else if (strcmp(words[0], "outb") == 0 || strcmp(words[0], "outw") == 0 || strcmp(words[0], "outl") == 0) { diff --git a/tests/libqtest.c b/tests/libqtest.c index 71b84c1..f6160ad 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -379,6 +379,18 @@ void qtest_irq_intercept_in(QTestState *s, const char *qom_path) qtest_rsp(s, 0); } +void qtest_set_irq_in(QTestState *s, const char *qom_path, int num, int level) +{ + qtest_sendf(s, "set_irq_in %s %d %d\n", qom_path, num, level); + qtest_rsp(s, 0); +} + +void qtest_set_irq_out(QTestState *s, const char *qom_path, int num, int level) +{ + qtest_sendf(s, "set_irq_out %s %d %d\n", qom_path, num, level); + qtest_rsp(s, 0); +} + static void qtest_out(QTestState *s, const char *cmd, uint16_t addr, uint32_t value) { qtest_sendf(s, "%s 0x%x 0x%x\n", cmd, addr, value); diff --git a/tests/libqtest.h b/tests/libqtest.h index c8ade85..a045fc7 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -76,6 +76,30 @@ void qtest_irq_intercept_in(QTestState *s, const char *string); void qtest_irq_intercept_out(QTestState *s, const char *string); /** + * qtest_set_irq_in: + * @s: QTestState instance to operate on. + * @string: QOM path of a device + * @irq: IRQ number + * @level: level to set it to (0 or 1) + * + * Force given device/irq GPIO-in pin to the given level. + * Mostly useful for testing interrupt controllers, rather than other devices. + */ +void qtest_set_irq_in(QTestState *s, const char *string, int irq, int level); + +/** + * qtest_set_irq_out: + * @s: QTestState instance to operate on. + * @string: QOM path of a device + * @irq: IRQ number + * @level: level to set it to (0 or 1) + * + * Force given device/irq GPIO-out pin to the given level. + * Mostly useful for testing interrupt controllers, rather than other devices. + */ +void qtest_set_irq_out(QTestState *s, const char *string, int irq, int level); + +/** * qtest_outb: * @s: QTestState instance to operate on. * @addr: I/O port to write to. @@ -250,6 +274,30 @@ void qtest_add_func(const char *str, void (*fn)); #define irq_intercept_out(string) qtest_irq_intercept_out(global_qtest, string) /** + * qtest_set_irq_in: + * @string: QOM path of a device + * @irq: IRQ number + * @level: level to set it to (0 or 1) + * + * Force given device/irq GPIO-in pin to the given level. + * Mostly useful for testing interrupt controllers, rather than other devices. + */ +#define set_irq_in(string, irq, level) \ + qtest_set_irq_in(global_qtest, string, irq, level) + +/** + * qtest_set_irq_in: + * @string: QOM path of a device + * @irq: IRQ number + * @level: level to set it to (0 or 1) + * + * Force given device/irq GPIO-in pin to the given level. + * Mostly useful for testing interrupt controllers, rather than other devices. + */ +#define set_irq_out(string, irq, level) \ + qtest_set_irq_out(global_qtest, string, irq, level) + +/** * outb: * @addr: I/O port to write to. * @value: Value being written.