qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <aliguori@us.ibm.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Anthony Liguori <aliguori@us.ibm.com>
Subject: [Qemu-devel] [PATCH 07/10] qtest: IRQ interception infrastructure (v2)
Date: Sat, 25 Feb 2012 13:42:46 -0600	[thread overview]
Message-ID: <1330198969-27364-8-git-send-email-aliguori@us.ibm.com> (raw)
In-Reply-To: <1330198969-27364-1-git-send-email-aliguori@us.ibm.com>

From: Paolo Bonzini <pbonzini@redhat.com>

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
v1 -> v2
 - rebased to latest (aliguori)
---
 hw/irq.c     |   17 ++++++++++
 hw/irq.h     |    5 +++
 hw/pc_piix.c |    9 +++--
 qtest.c      |   97 ++++++++++++++++++++++++++++++++++++++++-----------------
 qtest.h      |    2 -
 5 files changed, 95 insertions(+), 35 deletions(-)

diff --git a/hw/irq.c b/hw/irq.c
index 62f766e..d413a0b 100644
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -104,3 +104,20 @@ qemu_irq *qemu_irq_proxy(qemu_irq **target, int n)
 {
     return qemu_allocate_irqs(proxy_irq_handler, target, n);
 }
+
+void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
+{
+    int i;
+    qemu_irq *old_irqs = qemu_allocate_irqs(NULL, NULL, n);
+    for (i = 0; i < n; i++) {
+        *old_irqs[i] = *gpio_in[i];
+        gpio_in[i]->handler = handler;
+        gpio_in[i]->opaque = old_irqs;
+    }
+}
+
+void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n)
+{
+    qemu_irq *old_irqs = *gpio_out;
+    *gpio_out = qemu_allocate_irqs(handler, old_irqs, n);
+}
diff --git a/hw/irq.h b/hw/irq.h
index 64da2fd..56c55f0 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -38,4 +38,9 @@ qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
  */
 qemu_irq *qemu_irq_proxy(qemu_irq **target, int n);
 
+/* For internal use in qtest.  Similar to qemu_irq_split, but operating
+   on an existing vector of qemu_irq.  */
+void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
+void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n);
+
 #endif
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 2c0881e..36c06d5 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -99,7 +99,7 @@ static void kvm_piix3_gsi_handler(void *opaque, int n, int level)
     }
 }
 
-static void ioapic_init(GSIState *gsi_state)
+static DeviceState *ioapic_init(GSIState *gsi_state)
 {
     DeviceState *dev;
     SysBusDevice *d;
@@ -117,6 +117,7 @@ static void ioapic_init(GSIState *gsi_state)
     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
         gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
     }
+    return dev;
 }
 
 /* PC hardware initialisation */
@@ -213,8 +214,6 @@ static void pc_init1(MemoryRegion *system_memory,
         i8259 = kvm_i8259_init(isa_bus);
     } else if (xen_enabled()) {
         i8259 = xen_interrupt_controller_init();
-    } else if (qtest_enabled()) {
-        i8259 = qtest_interrupt_controller_init();
     } else {
         cpu_irq = pc_allocate_cpu_irq();
         i8259 = i8259_init(isa_bus, cpu_irq[0]);
@@ -224,7 +223,9 @@ static void pc_init1(MemoryRegion *system_memory,
         gsi_state->i8259_irq[i] = i8259[i];
     }
     if (pci_enabled) {
-        ioapic_init(gsi_state);
+        dev = ioapic_init(gsi_state);
+        object_property_add_child(object_resolve_path("/i440fx/piix3", NULL),
+                                  "ioapic", OBJECT(dev), NULL);
     }
 
     pc_register_ferr_irq(gsi[13]);
diff --git a/qtest.c b/qtest.c
index c2fbf50..a1eca49 100644
--- a/qtest.c
+++ b/qtest.c
@@ -12,6 +12,7 @@
  */
 
 #include "qtest.h"
+#include "hw/qdev.h"
 #include "qemu-char.h"
 #include "ioport.h"
 #include "memory.h"
@@ -24,6 +25,7 @@ const char *qtest_chrdev;
 const char *qtest_log;
 int qtest_allowed = 0;
 
+static DeviceState *irq_intercept_dev;
 static FILE *qtest_log_fp;
 static CharDriverState *qtest_chr;
 static GString *inbuf;
@@ -66,18 +68,30 @@ static bool qtest_opened;
  *  > write ADDR SIZE DATA
  *  < OK
  *
- * Valid async messages:
- *
- *  IRQ raise NUM
- *  IRQ lower NUM
- *
  * ADDR, SIZE, VALUE are all integers parsed with strtoul() with a base of 0.
  *
  * DATA is an arbitrarily long hex number prefixed with '0x'.  If it's smaller
  * than the expected size, the value will be zero filled at the end of the data
  * sequence.
  *
- * NUM is an IRQ number.
+ * IRQ management:
+ *
+ *  > irq_intercept_in QOM-PATH
+ *  < OK
+ *
+ *  > irq_intercept_out QOM-PATH
+ *  < OK
+ *
+ * Attach to the gpio-in (resp. gpio-out) pins exported by the device at
+ * QOM-PATH.  When the pin is triggered, one of the following async messages
+ * will be printed to the qtest stream:
+ *
+ *  IRQ raise NUM
+ *  IRQ lower NUM
+ *
+ * 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).
  */
 
 static int hex2nib(char ch)
@@ -133,6 +147,20 @@ static void qtest_send(CharDriverState *chr, const char *fmt, ...)
     }
 }
 
+static void qtest_irq_handler(void *opaque, int n, int level)
+{
+    qemu_irq *old_irqs = opaque;
+    qemu_set_irq(old_irqs[n], level);
+
+    if (irq_levels[n] != level) {
+        CharDriverState *chr = qtest_chr;
+        irq_levels[n] = level;
+        qtest_send_prefix(chr);
+        qtest_send(chr, "IRQ %s %d\n",
+                   level ? "raise" : "lower", n);
+    }
+}
+
 static void qtest_process_command(CharDriverState *chr, gchar **words)
 {
     const gchar *command;
@@ -155,9 +183,40 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
     }
 
     g_assert(command);
-    if (strcmp(words[0], "outb") == 0 ||
-        strcmp(words[0], "outw") == 0 ||
-        strcmp(words[0], "outl") == 0) {
+    if (strcmp(words[0], "irq_intercept_out") == 0
+        || strcmp(words[0], "irq_intercept_in") == 0) {
+	DeviceState *dev;
+
+        g_assert(words[1]);
+        dev = DEVICE(object_resolve_path(words[1], NULL));
+        if (!dev) {
+            qtest_send_prefix(chr);
+            qtest_send(chr, "FAIL Unknown device\n");
+	    return;
+        }
+
+        if (irq_intercept_dev) {
+            qtest_send_prefix(chr);
+            if (irq_intercept_dev != dev) {
+                qtest_send(chr, "FAIL IRQ intercept already enabled\n");
+            } else {
+                qtest_send(chr, "OK\n");
+            }
+	    return;
+        }
+
+        if (words[0][14] == 'o') {
+            qemu_irq_intercept_out(&dev->gpio_out, qtest_irq_handler, dev->num_gpio_out);
+        } else {
+            qemu_irq_intercept_in(dev->gpio_in, qtest_irq_handler, dev->num_gpio_in);
+        }
+        irq_intercept_dev = dev;
+        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) {
         uint16_t addr;
         uint32_t value;
 
@@ -312,26 +371,6 @@ static void qtest_event(void *opaque, int event)
     }
 }
 
-static void qtest_set_irq(void *opaque, int irq, int level)
-{
-    CharDriverState *chr = qtest_chr;
-    bool changed;
-
-    changed = (irq_levels[irq] != level);
-    irq_levels[irq] = level;
-
-    if (changed) {
-        qtest_send_prefix(chr);
-        qtest_send(chr, "IRQ %s %d\n",
-                   level ? "raise" : "lower", irq);
-    }
-}
-
-qemu_irq *qtest_interrupt_controller_init(void)
-{
-    return qemu_allocate_irqs(qtest_set_irq, NULL, MAX_IRQ);
-}
-
 int qtest_init(void)
 {
     CharDriverState *chr;
diff --git a/qtest.h b/qtest.h
index f0e1377..1478343 100644
--- a/qtest.h
+++ b/qtest.h
@@ -32,6 +32,4 @@ static inline int qtest_available(void)
 
 int qtest_init(void);
 
-qemu_irq *qtest_interrupt_controller_init(void);
-
 #endif
-- 
1.7.4.1

  parent reply	other threads:[~2012-02-25 19:43 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-25 19:42 [Qemu-devel] [PATCH 00/10] qtest: a testing framework for devices (v2) Anthony Liguori
2012-02-25 19:42 ` [Qemu-devel] [PATCH 01/10] qtest: add test framework (v2) Anthony Liguori
2012-02-25 20:19   ` Paolo Bonzini
2012-02-25 19:42 ` [Qemu-devel] [PATCH 02/10] qtest: add support for -M pc Anthony Liguori
2012-02-25 20:19   ` Paolo Bonzini
2012-02-25 21:12     ` Anthony Liguori
2012-02-25 21:21       ` Andreas Färber
2012-02-25 21:29         ` Anthony Liguori
2012-02-25 21:39       ` Paolo Bonzini
2012-02-25 19:42 ` [Qemu-devel] [PATCH 03/10] qtest: add C version of test infrastructure Anthony Liguori
2012-03-02 22:17   ` Eduardo Habkost
2012-02-25 19:42 ` [Qemu-devel] [PATCH 04/10] make: add check targets based on gtester (v2) Anthony Liguori
2012-02-25 19:42 ` [Qemu-devel] [PATCH 05/10] rtc: split out macros into a header file and use in test case Anthony Liguori
2012-02-25 19:42 ` [Qemu-devel] [PATCH 06/10] qtest: add rtc-test test-case (v2) Anthony Liguori
2012-02-25 20:20   ` Paolo Bonzini
2012-02-25 20:41   ` Stefan Weil
2012-02-25 19:42 ` Anthony Liguori [this message]
2012-02-25 20:20   ` [Qemu-devel] [PATCH 07/10] qtest: IRQ interception infrastructure (v2) Paolo Bonzini
2012-02-25 21:16     ` Anthony Liguori
2012-02-26  1:31       ` Andreas Färber
2012-02-26  1:34         ` Anthony Liguori
2012-02-25 19:42 ` [Qemu-devel] [PATCH 08/10] libqtest: add IRQ intercept commands Anthony Liguori
2012-02-25 19:42 ` [Qemu-devel] [PATCH 09/10] rtc-test: add IRQ intercept Anthony Liguori
2012-02-25 19:42 ` [Qemu-devel] [PATCH 10/10] qtest: add clock management Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1330198969-27364-8-git-send-email-aliguori@us.ibm.com \
    --to=aliguori@us.ibm.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).