#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "cpu.h"
#include "sysemu/qtest.h"
#include "sysemu/runstate.h"
#include "chardev/char-fe.h"
#include "exec/ioport.h"
#include "exec/memory.h"
+#include "exec/tswap.h"
#include "hw/qdev-core.h"
#include "hw/irq.h"
#include "qemu/accel.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "qemu/cutils.h"
-#include "qapi/qmp/qerror.h"
#include "qom/object_interfaces.h"
-#include CONFIG_DEVICES
-#ifdef CONFIG_PSERIES
-#include "hw/ppc/spapr_rtas.h"
-#endif
#define MAX_IRQ 256
}
}
-static void qtest_send_prefix(CharBackend *chr)
+void qtest_send_prefix(CharBackend *chr)
{
if (!qtest_log_fp || !qtest_opened) {
return;
qtest_server_send(qtest_server_send_opaque, str);
}
-static void G_GNUC_PRINTF(2, 3) qtest_sendf(CharBackend *chr,
- const char *fmt, ...)
+void qtest_sendf(CharBackend *chr, const char *fmt, ...)
{
va_list ap;
gchar *buffer;
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
}
+static bool (*process_command_cb)(CharBackend *chr, gchar **words);
+
+void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words))
+{
+ assert(!process_command_cb); /* Switch to a list if we need more than one */
+
+ process_command_cb = pc_cb;
+}
+
+static void qtest_install_gpio_out_intercept(DeviceState *dev, const char *name, int n)
+{
+ qemu_irq *disconnected = g_new0(qemu_irq, 1);
+ qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
+ disconnected, n);
+
+ *disconnected = qdev_intercept_gpio_out(dev, icpt, name, n);
+}
+
static void qtest_process_command(CharBackend *chr, gchar **words)
{
const gchar *command;
|| strcmp(words[0], "irq_intercept_in") == 0) {
DeviceState *dev;
NamedGPIOList *ngl;
+ bool is_named;
+ bool is_outbound;
+ bool interception_succeeded = false;
g_assert(words[1]);
+ is_named = words[2] != NULL;
+ is_outbound = words[0][14] == 'o';
dev = DEVICE(object_resolve_path(words[1], NULL));
if (!dev) {
qtest_send_prefix(chr);
return;
}
+ if (is_named && !is_outbound) {
+ qtest_send_prefix(chr);
+ qtest_send(chr, "FAIL Interception of named in-GPIOs not yet supported\n");
+ return;
+ }
+
if (irq_intercept_dev) {
qtest_send_prefix(chr);
if (irq_intercept_dev != dev) {
}
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);
+ /* We don't support inbound interception of named GPIOs yet */
+ if (is_outbound) {
+ /* NULL is valid and matchable, for "unnamed GPIO" */
+ if (g_strcmp0(ngl->name, words[2]) == 0) {
+ int i;
+ for (i = 0; i < ngl->num_out; ++i) {
+ qtest_install_gpio_out_intercept(dev, ngl->name, i);
+ }
+ interception_succeeded = true;
}
} else {
qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
ngl->num_in);
+ interception_succeeded = true;
}
}
- irq_intercept_dev = dev;
+
qtest_send_prefix(chr);
- qtest_send(chr, "OK\n");
+ if (interception_succeeded) {
+ irq_intercept_dev = dev;
+ qtest_send(chr, "OK\n");
+ } else {
+ qtest_send(chr, "FAIL No intercepts installed\n");
+ }
} else if (strcmp(words[0], "set_irq_in") == 0) {
DeviceState *dev;
qemu_irq irq;
qtest_send(chr, "OK\n");
} else if (strcmp(words[0], "endianness") == 0) {
qtest_send_prefix(chr);
-#if TARGET_BIG_ENDIAN
- qtest_sendf(chr, "OK big\n");
-#else
- qtest_sendf(chr, "OK little\n");
-#endif
-#ifdef CONFIG_PSERIES
- } else if (strcmp(words[0], "rtas") == 0) {
- uint64_t res, args, ret;
- unsigned long nargs, nret;
- int rc;
-
- rc = qemu_strtoul(words[2], NULL, 0, &nargs);
- g_assert(rc == 0);
- rc = qemu_strtou64(words[3], NULL, 0, &args);
- g_assert(rc == 0);
- rc = qemu_strtoul(words[4], NULL, 0, &nret);
- g_assert(rc == 0);
- rc = qemu_strtou64(words[5], NULL, 0, &ret);
- g_assert(rc == 0);
- res = qtest_rtas_call(words[1], nargs, args, nret, ret);
-
- qtest_send_prefix(chr);
- qtest_sendf(chr, "OK %"PRIu64"\n", res);
-#endif
+ if (target_words_bigendian()) {
+ qtest_sendf(chr, "OK big\n");
+ } else {
+ qtest_sendf(chr, "OK little\n");
+ }
} else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
int64_t ns;
qtest_send_prefix(chr);
qtest_sendf(chr, "OK %"PRIi64"\n",
(int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+ } else if (process_command_cb && process_command_cb(chr, words)) {
+ /* Command got consumed by the callback handler */
} else {
qtest_send_prefix(chr);
qtest_sendf(chr, "FAIL Unknown command '%s'\n", words[0]);
}
qtest = object_new(TYPE_QTEST);
- object_property_set_str(qtest, "chardev", "qtest", &error_abort);
+ object_property_set_str(qtest, "chardev", chr->label, &error_abort);
if (qtest_log) {
object_property_set_str(qtest, "log", qtest_log, &error_abort);
}