]> git.proxmox.com Git - mirror_qemu.git/blobdiff - qtest.c
apic_common: improve readability of apic_reset_common
[mirror_qemu.git] / qtest.c
diff --git a/qtest.c b/qtest.c
index 74f1842c1e3e16ea388813166f7399a23fa95118..8d1e66caa316581689a20af4f09b56105a5871e3 100644 (file)
--- a/qtest.c
+++ b/qtest.c
 #include "exec/ioport.h"
 #include "exec/memory.h"
 #include "hw/irq.h"
+#include "sysemu/accel.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/cpus.h"
+#include "qemu/config-file.h"
+#include "qemu/option.h"
+#include "qemu/error-report.h"
 
 #define MAX_IRQ 256
 
-const char *qtest_chrdev;
-const char *qtest_log;
 bool qtest_allowed;
 
 static DeviceState *irq_intercept_dev;
@@ -47,7 +49,7 @@ static bool qtest_opened;
  *
  * Clock management:
  *
- * The qtest client is completely in charge of the vm_clock.  qtest commands
+ * The qtest client is completely in charge of the QEMU_CLOCK_VIRTUAL.  qtest commands
  * let you adjust the value of the clock (monotonically).  All the commands
  * return the current value of the clock in nanoseconds.
  *
@@ -150,7 +152,7 @@ static int hex2nib(char ch)
     } else if (ch >= 'a' && ch <= 'f') {
         return 10 + (ch - 'a');
     } else if (ch >= 'A' && ch <= 'F') {
-        return 10 + (ch - 'a');
+        return 10 + (ch - 'A');
     } else {
         return -1;
     }
@@ -177,7 +179,7 @@ static void qtest_send_prefix(CharDriverState *chr)
 
     qtest_get_time(&tv);
     fprintf(qtest_log_fp, "[S +" FMT_timeval "] ",
-            tv.tv_sec, (long) tv.tv_usec);
+            (long) tv.tv_sec, (long) tv.tv_usec);
 }
 
 static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr,
@@ -199,8 +201,8 @@ static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr,
 
 static void qtest_irq_handler(void *opaque, int n, int level)
 {
-    qemu_irq *old_irqs = opaque;
-    qemu_set_irq(old_irqs[n], level);
+    qemu_irq old_irq = *(qemu_irq *)opaque;
+    qemu_set_irq(old_irq, level);
 
     if (irq_levels[n] != level) {
         CharDriverState *chr = qtest_chr;
@@ -225,7 +227,7 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
 
         qtest_get_time(&tv);
         fprintf(qtest_log_fp, "[R +" FMT_timeval "]",
-                tv.tv_sec, (long) tv.tv_usec);
+                (long) tv.tv_sec, (long) tv.tv_usec);
         for (i = 0; words[i]; i++) {
             fprintf(qtest_log_fp, " %s", words[i]);
         }
@@ -235,7 +237,8 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
     g_assert(command);
     if (strcmp(words[0], "irq_intercept_out") == 0
         || strcmp(words[0], "irq_intercept_in") == 0) {
-       DeviceState *dev;
+        DeviceState *dev;
+        NamedGPIOList *ngl;
 
         g_assert(words[1]);
         dev = DEVICE(object_resolve_path(words[1], NULL));
@@ -255,10 +258,25 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
            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);
+        QLIST_FOREACH(ngl, &dev->gpios, node) {
+            /* We don't support intercept of named GPIOs yet */
+            if (ngl->name) {
+                continue;
+            }
+            if (words[0][14] == 'o') {
+                int i;
+                for (i = 0; i < ngl->num_out; ++i) {
+                    qemu_irq *disconnected = g_new0(qemu_irq, 1);
+                    qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
+                                                      disconnected, i);
+
+                    *disconnected = qdev_intercept_gpio_out(dev, icpt,
+                                                            ngl->name, i);
+                }
+            } else {
+                qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
+                                      ngl->num_in);
+            }
         }
         irq_intercept_dev = dev;
         qtest_send_prefix(chr);
@@ -406,25 +424,25 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
 
         qtest_send_prefix(chr);
         qtest_send(chr, "OK\n");
-    } else if (strcmp(words[0], "clock_step") == 0) {
+    } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
         int64_t ns;
 
         if (words[1]) {
             ns = strtoll(words[1], NULL, 0);
         } else {
-            ns = qemu_clock_deadline(vm_clock);
+            ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
         }
-        qtest_clock_warp(qemu_get_clock_ns(vm_clock) + ns);
+        qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
         qtest_send_prefix(chr);
-        qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_get_clock_ns(vm_clock));
-    } else if (strcmp(words[0], "clock_set") == 0) {
+        qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+    } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
         int64_t ns;
 
         g_assert(words[1]);
         ns = strtoll(words[1], NULL, 0);
         qtest_clock_warp(ns);
         qtest_send_prefix(chr);
-        qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_get_clock_ns(vm_clock));
+        qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
     } else {
         qtest_send_prefix(chr);
         qtest_send(chr, "FAIL Unknown command `%s'\n", words[0]);
@@ -485,7 +503,7 @@ static void qtest_event(void *opaque, int event)
         qtest_opened = true;
         if (qtest_log_fp) {
             fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
-                    start_time.tv_sec, (long) start_time.tv_usec);
+                    (long) start_time.tv_sec, (long) start_time.tv_usec);
         }
         break;
     case CHR_EVENT_CLOSED:
@@ -494,7 +512,7 @@ static void qtest_event(void *opaque, int event)
             qemu_timeval tv;
             qtest_get_time(&tv);
             fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
-                    tv.tv_sec, (long) tv.tv_usec);
+                    (long) tv.tv_sec, (long) tv.tv_usec);
         }
         break;
     default:
@@ -502,19 +520,27 @@ static void qtest_event(void *opaque, int event)
     }
 }
 
-int qtest_init(void)
+static int qtest_init_accel(MachineState *ms)
 {
-    CharDriverState *chr;
+    QemuOpts *opts = qemu_opts_create(qemu_find_opts("icount"), NULL, 0,
+                                      &error_abort);
+    qemu_opt_set(opts, "shift", "0", &error_abort);
+    configure_icount(opts, &error_abort);
+    qemu_opts_del(opts);
+    return 0;
+}
 
-    g_assert(qtest_chrdev != NULL);
+void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
+{
+    CharDriverState *chr;
 
-    configure_icount("0");
     chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
 
-    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
-    qemu_chr_fe_set_echo(chr, true);
-
-    inbuf = g_string_new("");
+    if (chr == NULL) {
+        error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
+                   qtest_chrdev);
+        return;
+    }
 
     if (qtest_log) {
         if (strcmp(qtest_log, "none") != 0) {
@@ -524,7 +550,38 @@ int qtest_init(void)
         qtest_log_fp = stderr;
     }
 
+    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
+    qemu_chr_fe_set_echo(chr, true);
+
+    inbuf = g_string_new("");
     qtest_chr = chr;
+}
 
-    return 0;
+bool qtest_driver(void)
+{
+    return qtest_chr;
+}
+
+static void qtest_accel_class_init(ObjectClass *oc, void *data)
+{
+    AccelClass *ac = ACCEL_CLASS(oc);
+    ac->name = "QTest";
+    ac->available = qtest_available;
+    ac->init_machine = qtest_init_accel;
+    ac->allowed = &qtest_allowed;
+}
+
+#define TYPE_QTEST_ACCEL ACCEL_CLASS_NAME("qtest")
+
+static const TypeInfo qtest_accel_type = {
+    .name = TYPE_QTEST_ACCEL,
+    .parent = TYPE_ACCEL,
+    .class_init = qtest_accel_class_init,
+};
+
+static void qtest_type_init(void)
+{
+    type_register_static(&qtest_accel_type);
 }
+
+type_init(qtest_type_init);