blob: f8d764b7190f9eff2beec102a500d0827addf250 [file] [log] [blame]
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +02001/*
2 * Test Server
3 *
4 * Copyright IBM, Corp. 2011
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 *
12 */
13
Peter Maydelld38ea872016-01-29 17:50:05 +000014#include "qemu/osdep.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010015#include "qapi/error.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010016#include "sysemu/qtest.h"
Markus Armbruster54d31232019-08-12 07:23:59 +020017#include "sysemu/runstate.h"
Marc-André Lureau4d43a602017-01-26 18:26:44 +040018#include "chardev/char-fe.h"
Paolo Bonzini022c62c2012-12-17 18:19:49 +010019#include "exec/ioport.h"
20#include "exec/memory.h"
Thomas Huth09637ed2023-04-11 20:34:18 +020021#include "exec/tswap.h"
Philippe Mathieu-Daudé496bde82022-02-07 09:27:51 +010022#include "hw/qdev-core.h"
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020023#include "hw/irq.h"
Claudio Fontana940e43a2021-02-04 17:39:24 +010024#include "qemu/accel.h"
Claudio Fontana740b1752020-08-19 13:17:19 +020025#include "sysemu/cpu-timers.h"
Sebastian Tanase1ad95802014-07-25 11:56:28 +020026#include "qemu/config-file.h"
27#include "qemu/option.h"
28#include "qemu/error-report.h"
Markus Armbruster0b8fa322019-05-23 16:35:07 +020029#include "qemu/module.h"
Laurent Vivieraa15f492016-09-13 14:52:43 +020030#include "qemu/cutils.h"
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -050031#include "qom/object_interfaces.h"
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020032
33#define MAX_IRQ 256
34
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -050035#define TYPE_QTEST "qtest"
36
37OBJECT_DECLARE_SIMPLE_TYPE(QTest, QTEST)
38
39struct QTest {
40 Object parent;
41
42 bool has_machine_link;
43 char *chr_name;
44 Chardev *chr;
45 CharBackend qtest_chr;
46 char *log;
47};
48
liguangd5286af2013-01-24 13:03:27 +080049bool qtest_allowed;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020050
Paolo Bonzini20288342012-03-28 15:42:03 +020051static DeviceState *irq_intercept_dev;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020052static FILE *qtest_log_fp;
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -050053static QTest *qtest;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020054static GString *inbuf;
55static int irq_levels[MAX_IRQ];
Marc-André Lureau20e4ae12022-03-07 11:03:58 +040056static GTimer *timer;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020057static bool qtest_opened;
Alexander Bulekove731d082020-02-19 23:11:01 -050058static void (*qtest_server_send)(void*, const char*);
59static void *qtest_server_send_opaque;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020060
Marc-André Lureau20e4ae12022-03-07 11:03:58 +040061#define FMT_timeval "%.06f"
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020062
63/**
Eduardo Habkostf59c6de2020-10-05 16:52:27 -040064 * DOC: QTest Protocol
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020065 *
66 * Line based protocol, request/response based. Server can send async messages
67 * so clients should always handle many async messages before the response
68 * comes in.
69 *
70 * Valid requests
Eduardo Habkostf59c6de2020-10-05 16:52:27 -040071 * ^^^^^^^^^^^^^^
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020072 *
Paolo Bonzini8156be52012-03-28 15:42:04 +020073 * Clock management:
Eduardo Habkostf59c6de2020-10-05 16:52:27 -040074 * """""""""""""""""
Paolo Bonzini8156be52012-03-28 15:42:04 +020075 *
Alex Blighbc72ad62013-08-21 16:03:08 +010076 * The qtest client is completely in charge of the QEMU_CLOCK_VIRTUAL. qtest commands
Paolo Bonzini8156be52012-03-28 15:42:04 +020077 * let you adjust the value of the clock (monotonically). All the commands
78 * return the current value of the clock in nanoseconds.
79 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -040080 * .. code-block:: none
81 *
Paolo Bonzini8156be52012-03-28 15:42:04 +020082 * > clock_step
83 * < OK VALUE
84 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -040085 * Advance the clock to the next deadline. Useful when waiting for
86 * asynchronous events.
87 *
88 * .. code-block:: none
Paolo Bonzini8156be52012-03-28 15:42:04 +020089 *
90 * > clock_step NS
91 * < OK VALUE
92 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -040093 * Advance the clock by NS nanoseconds.
94 *
95 * .. code-block:: none
Paolo Bonzini8156be52012-03-28 15:42:04 +020096 *
97 * > clock_set NS
98 * < OK VALUE
99 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400100 * Advance the clock to NS nanoseconds (do nothing if it's already past).
Paolo Bonzini8156be52012-03-28 15:42:04 +0200101 *
102 * PIO and memory access:
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400103 * """"""""""""""""""""""
104 *
105 * .. code-block:: none
Paolo Bonzini8156be52012-03-28 15:42:04 +0200106 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200107 * > outb ADDR VALUE
108 * < OK
109 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400110 * .. code-block:: none
111 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200112 * > outw ADDR VALUE
113 * < OK
114 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400115 * .. code-block:: none
116 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200117 * > outl ADDR VALUE
118 * < OK
119 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400120 * .. code-block:: none
121 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200122 * > inb ADDR
123 * < OK VALUE
124 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400125 * .. code-block:: none
126 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200127 * > inw ADDR
128 * < OK VALUE
129 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400130 * .. code-block:: none
131 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200132 * > inl ADDR
133 * < OK VALUE
134 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400135 * .. code-block:: none
136 *
Andreas Färber872536b2013-02-16 22:44:03 +0100137 * > writeb ADDR VALUE
138 * < OK
139 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400140 * .. code-block:: none
141 *
Andreas Färber872536b2013-02-16 22:44:03 +0100142 * > writew ADDR VALUE
143 * < OK
144 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400145 * .. code-block:: none
146 *
Andreas Färber872536b2013-02-16 22:44:03 +0100147 * > writel ADDR VALUE
148 * < OK
149 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400150 * .. code-block:: none
151 *
Andreas Färber872536b2013-02-16 22:44:03 +0100152 * > writeq ADDR VALUE
153 * < OK
154 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400155 * .. code-block:: none
156 *
Andreas Färber872536b2013-02-16 22:44:03 +0100157 * > readb ADDR
158 * < OK VALUE
159 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400160 * .. code-block:: none
161 *
Andreas Färber872536b2013-02-16 22:44:03 +0100162 * > readw ADDR
163 * < OK VALUE
164 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400165 * .. code-block:: none
166 *
Andreas Färber872536b2013-02-16 22:44:03 +0100167 * > readl ADDR
168 * < OK VALUE
169 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400170 * .. code-block:: none
171 *
Andreas Färber872536b2013-02-16 22:44:03 +0100172 * > readq ADDR
173 * < OK VALUE
174 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400175 * .. code-block:: none
176 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200177 * > read ADDR SIZE
178 * < OK DATA
179 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400180 * .. code-block:: none
181 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200182 * > write ADDR SIZE DATA
183 * < OK
184 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400185 * .. code-block:: none
186 *
John Snow7a6a7402015-05-22 14:13:44 -0400187 * > b64read ADDR SIZE
188 * < OK B64_DATA
189 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400190 * .. code-block:: none
191 *
John Snow7a6a7402015-05-22 14:13:44 -0400192 * > b64write ADDR SIZE B64_DATA
193 * < OK
194 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400195 * .. code-block:: none
196 *
John Snow4d007962015-05-22 14:13:44 -0400197 * > memset ADDR SIZE VALUE
198 * < OK
199 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200200 * ADDR, SIZE, VALUE are all integers parsed with strtoul() with a base of 0.
Peter Maydell5f31bbf2016-08-05 11:43:20 +0100201 * For 'memset' a zero size is permitted and does nothing.
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200202 *
203 * DATA is an arbitrarily long hex number prefixed with '0x'. If it's smaller
204 * than the expected size, the value will be zero filled at the end of the data
205 * sequence.
206 *
John Snow7a6a7402015-05-22 14:13:44 -0400207 * B64_DATA is an arbitrarily long base64 encoded string.
208 * If the sizes do not match, the data will be truncated.
209 *
Paolo Bonzini20288342012-03-28 15:42:03 +0200210 * IRQ management:
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400211 * """""""""""""""
212 *
213 * .. code-block:: none
Paolo Bonzini20288342012-03-28 15:42:03 +0200214 *
215 * > irq_intercept_in QOM-PATH
216 * < OK
217 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400218 * .. code-block:: none
219 *
Paolo Bonzini20288342012-03-28 15:42:03 +0200220 * > irq_intercept_out QOM-PATH
221 * < OK
222 *
223 * Attach to the gpio-in (resp. gpio-out) pins exported by the device at
224 * QOM-PATH. When the pin is triggered, one of the following async messages
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400225 * will be printed to the qtest stream::
Paolo Bonzini20288342012-03-28 15:42:03 +0200226 *
227 * IRQ raise NUM
228 * IRQ lower NUM
229 *
230 * where NUM is an IRQ number. For the PC, interrupts can be intercepted
231 * simply with "irq_intercept_in ioapic" (note that IRQ0 comes out with
232 * NUM=0 even though it is remapped to GSI 2).
Steffen Görtz9813dc62019-01-07 15:23:47 +0000233 *
234 * Setting interrupt level:
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400235 * """"""""""""""""""""""""
236 *
237 * .. code-block:: none
Steffen Görtz9813dc62019-01-07 15:23:47 +0000238 *
239 * > set_irq_in QOM-PATH NAME NUM LEVEL
240 * < OK
241 *
Eduardo Habkostf59c6de2020-10-05 16:52:27 -0400242 * where NAME is the name of the irq/gpio list, NUM is an IRQ number and
243 * LEVEL is an signed integer IRQ level.
Steffen Görtz9813dc62019-01-07 15:23:47 +0000244 *
245 * Forcibly set the given interrupt pin to the given level.
246 *
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200247 */
248
249static int hex2nib(char ch)
250{
251 if (ch >= '0' && ch <= '9') {
252 return ch - '0';
253 } else if (ch >= 'a' && ch <= 'f') {
254 return 10 + (ch - 'a');
255 } else if (ch >= 'A' && ch <= 'F') {
Sergey Fedorov2a802aa2014-05-27 16:15:20 +0400256 return 10 + (ch - 'A');
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200257 } else {
258 return -1;
259 }
260}
261
Thomas Huthc7a6bf52023-04-11 20:34:16 +0200262void qtest_send_prefix(CharBackend *chr)
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200263{
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200264 if (!qtest_log_fp || !qtest_opened) {
265 return;
266 }
267
Marc-André Lureau20e4ae12022-03-07 11:03:58 +0400268 fprintf(qtest_log_fp, "[S +" FMT_timeval "] ", g_timer_elapsed(timer, NULL));
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200269}
270
Marc-André Lureau9edc6312022-02-20 20:39:25 +0400271static void G_GNUC_PRINTF(1, 2) qtest_log_send(const char *fmt, ...)
John Snow7a6a7402015-05-22 14:13:44 -0400272{
273 va_list ap;
274
275 if (!qtest_log_fp || !qtest_opened) {
276 return;
277 }
278
279 qtest_send_prefix(NULL);
280
281 va_start(ap, fmt);
282 vfprintf(qtest_log_fp, fmt, ap);
283 va_end(ap);
284}
285
Alexander Bulekove731d082020-02-19 23:11:01 -0500286static void qtest_server_char_be_send(void *opaque, const char *str)
John Snow332cc7e2015-05-22 14:13:43 -0400287{
Alexander Bulekove731d082020-02-19 23:11:01 -0500288 size_t len = strlen(str);
289 CharBackend* chr = (CharBackend *)opaque;
John Snow332cc7e2015-05-22 14:13:43 -0400290 qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
291 if (qtest_log_fp && qtest_opened) {
292 fprintf(qtest_log_fp, "%s", str);
293 }
294}
295
Marc-André Lureau5345fdb2016-10-22 12:52:55 +0300296static void qtest_send(CharBackend *chr, const char *str)
John Snow332cc7e2015-05-22 14:13:43 -0400297{
Alexander Bulekove731d082020-02-19 23:11:01 -0500298 qtest_server_send(qtest_server_send_opaque, str);
John Snow332cc7e2015-05-22 14:13:43 -0400299}
300
Thomas Huthc7a6bf52023-04-11 20:34:16 +0200301void qtest_sendf(CharBackend *chr, const char *fmt, ...)
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200302{
303 va_list ap;
John Snow332cc7e2015-05-22 14:13:43 -0400304 gchar *buffer;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200305
306 va_start(ap, fmt);
John Snow332cc7e2015-05-22 14:13:43 -0400307 buffer = g_strdup_vprintf(fmt, ap);
308 qtest_send(chr, buffer);
Marc-André Lureaufc340592016-11-10 12:25:00 +0400309 g_free(buffer);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200310 va_end(ap);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200311}
312
Paolo Bonzini20288342012-03-28 15:42:03 +0200313static void qtest_irq_handler(void *opaque, int n, int level)
314{
Peter Crosthwaite60a79012014-09-25 22:21:31 -0700315 qemu_irq old_irq = *(qemu_irq *)opaque;
316 qemu_set_irq(old_irq, level);
Paolo Bonzini20288342012-03-28 15:42:03 +0200317
318 if (irq_levels[n] != level) {
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500319 CharBackend *chr = &qtest->qtest_chr;
Paolo Bonzini20288342012-03-28 15:42:03 +0200320 irq_levels[n] = level;
321 qtest_send_prefix(chr);
John Snow332cc7e2015-05-22 14:13:43 -0400322 qtest_sendf(chr, "IRQ %s %d\n",
323 level ? "raise" : "lower", n);
Paolo Bonzini20288342012-03-28 15:42:03 +0200324 }
325}
326
Claudio Fontana740b1752020-08-19 13:17:19 +0200327static int64_t qtest_clock_counter;
328
329int64_t qtest_get_virtual_clock(void)
330{
331 return qatomic_read_i64(&qtest_clock_counter);
332}
333
334static void qtest_set_virtual_clock(int64_t count)
335{
336 qatomic_set_i64(&qtest_clock_counter, count);
337}
338
339static void qtest_clock_warp(int64_t dest)
340{
341 int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
342 AioContext *aio_context;
343 assert(qtest_enabled());
344 aio_context = qemu_get_aio_context();
345 while (clock < dest) {
346 int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
347 QEMU_TIMER_ATTR_ALL);
348 int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
349
350 qtest_set_virtual_clock(qtest_get_virtual_clock() + warp);
351
352 qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
353 timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]);
354 clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
355 }
356 qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
357}
358
Thomas Huthc7a6bf52023-04-11 20:34:16 +0200359static bool (*process_command_cb)(CharBackend *chr, gchar **words);
360
361void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words))
362{
363 assert(!process_command_cb); /* Switch to a list if we need more than one */
364
365 process_command_cb = pc_cb;
366}
367
Marc-André Lureau5345fdb2016-10-22 12:52:55 +0300368static void qtest_process_command(CharBackend *chr, gchar **words)
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200369{
370 const gchar *command;
371
372 g_assert(words);
373
374 command = words[0];
375
376 if (qtest_log_fp) {
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200377 int i;
378
Marc-André Lureau20e4ae12022-03-07 11:03:58 +0400379 fprintf(qtest_log_fp, "[R +" FMT_timeval "]", g_timer_elapsed(timer, NULL));
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200380 for (i = 0; words[i]; i++) {
381 fprintf(qtest_log_fp, " %s", words[i]);
382 }
383 fprintf(qtest_log_fp, "\n");
384 }
385
386 g_assert(command);
Paolo Bonzini20288342012-03-28 15:42:03 +0200387 if (strcmp(words[0], "irq_intercept_out") == 0
388 || strcmp(words[0], "irq_intercept_in") == 0) {
Peter Crosthwaitea5f54292014-05-19 23:30:58 -0700389 DeviceState *dev;
390 NamedGPIOList *ngl;
Paolo Bonzini20288342012-03-28 15:42:03 +0200391
392 g_assert(words[1]);
393 dev = DEVICE(object_resolve_path(words[1], NULL));
394 if (!dev) {
395 qtest_send_prefix(chr);
396 qtest_send(chr, "FAIL Unknown device\n");
Paolo Bonzini7d374352018-12-13 23:37:37 +0100397 return;
Paolo Bonzini20288342012-03-28 15:42:03 +0200398 }
399
400 if (irq_intercept_dev) {
401 qtest_send_prefix(chr);
402 if (irq_intercept_dev != dev) {
403 qtest_send(chr, "FAIL IRQ intercept already enabled\n");
404 } else {
405 qtest_send(chr, "OK\n");
406 }
Paolo Bonzini7d374352018-12-13 23:37:37 +0100407 return;
Paolo Bonzini20288342012-03-28 15:42:03 +0200408 }
409
Peter Crosthwaitea5f54292014-05-19 23:30:58 -0700410 QLIST_FOREACH(ngl, &dev->gpios, node) {
411 /* We don't support intercept of named GPIOs yet */
412 if (ngl->name) {
413 continue;
414 }
415 if (words[0][14] == 'o') {
Peter Crosthwaite60a79012014-09-25 22:21:31 -0700416 int i;
417 for (i = 0; i < ngl->num_out; ++i) {
418 qemu_irq *disconnected = g_new0(qemu_irq, 1);
419 qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
420 disconnected, i);
421
422 *disconnected = qdev_intercept_gpio_out(dev, icpt,
423 ngl->name, i);
424 }
Peter Crosthwaitea5f54292014-05-19 23:30:58 -0700425 } else {
426 qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
427 ngl->num_in);
428 }
Paolo Bonzini20288342012-03-28 15:42:03 +0200429 }
430 irq_intercept_dev = dev;
431 qtest_send_prefix(chr);
432 qtest_send(chr, "OK\n");
Steffen Görtz9813dc62019-01-07 15:23:47 +0000433 } else if (strcmp(words[0], "set_irq_in") == 0) {
434 DeviceState *dev;
435 qemu_irq irq;
436 char *name;
437 int ret;
438 int num;
439 int level;
Paolo Bonzini20288342012-03-28 15:42:03 +0200440
Steffen Görtz9813dc62019-01-07 15:23:47 +0000441 g_assert(words[1] && words[2] && words[3] && words[4]);
442
443 dev = DEVICE(object_resolve_path(words[1], NULL));
444 if (!dev) {
445 qtest_send_prefix(chr);
446 qtest_send(chr, "FAIL Unknown device\n");
447 return;
448 }
449
450 if (strcmp(words[2], "unnamed-gpio-in") == 0) {
451 name = NULL;
452 } else {
453 name = words[2];
454 }
455
456 ret = qemu_strtoi(words[3], NULL, 0, &num);
457 g_assert(!ret);
458 ret = qemu_strtoi(words[4], NULL, 0, &level);
459 g_assert(!ret);
460
461 irq = qdev_get_gpio_in_named(dev, name, num);
462
463 qemu_set_irq(irq, level);
464 qtest_send_prefix(chr);
465 qtest_send(chr, "OK\n");
Paolo Bonzini20288342012-03-28 15:42:03 +0200466 } else if (strcmp(words[0], "outb") == 0 ||
467 strcmp(words[0], "outw") == 0 ||
468 strcmp(words[0], "outl") == 0) {
Laurent Vivieraa15f492016-09-13 14:52:43 +0200469 unsigned long addr;
470 unsigned long value;
Eric Blake14773122017-09-11 12:19:46 -0500471 int ret;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200472
473 g_assert(words[1] && words[2]);
Eric Blake14773122017-09-11 12:19:46 -0500474 ret = qemu_strtoul(words[1], NULL, 0, &addr);
475 g_assert(ret == 0);
476 ret = qemu_strtoul(words[2], NULL, 0, &value);
477 g_assert(ret == 0);
Laurent Vivieraa15f492016-09-13 14:52:43 +0200478 g_assert(addr <= 0xffff);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200479
480 if (words[0][3] == 'b') {
481 cpu_outb(addr, value);
482 } else if (words[0][3] == 'w') {
483 cpu_outw(addr, value);
484 } else if (words[0][3] == 'l') {
485 cpu_outl(addr, value);
486 }
487 qtest_send_prefix(chr);
488 qtest_send(chr, "OK\n");
489 } else if (strcmp(words[0], "inb") == 0 ||
490 strcmp(words[0], "inw") == 0 ||
491 strcmp(words[0], "inl") == 0) {
Laurent Vivieraa15f492016-09-13 14:52:43 +0200492 unsigned long addr;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200493 uint32_t value = -1U;
Eric Blake14773122017-09-11 12:19:46 -0500494 int ret;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200495
496 g_assert(words[1]);
Eric Blake14773122017-09-11 12:19:46 -0500497 ret = qemu_strtoul(words[1], NULL, 0, &addr);
498 g_assert(ret == 0);
Laurent Vivieraa15f492016-09-13 14:52:43 +0200499 g_assert(addr <= 0xffff);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200500
501 if (words[0][2] == 'b') {
502 value = cpu_inb(addr);
503 } else if (words[0][2] == 'w') {
504 value = cpu_inw(addr);
505 } else if (words[0][2] == 'l') {
506 value = cpu_inl(addr);
507 }
508 qtest_send_prefix(chr);
John Snow332cc7e2015-05-22 14:13:43 -0400509 qtest_sendf(chr, "OK 0x%04x\n", value);
Andreas Färber872536b2013-02-16 22:44:03 +0100510 } else if (strcmp(words[0], "writeb") == 0 ||
511 strcmp(words[0], "writew") == 0 ||
512 strcmp(words[0], "writel") == 0 ||
513 strcmp(words[0], "writeq") == 0) {
514 uint64_t addr;
515 uint64_t value;
Eric Blake14773122017-09-11 12:19:46 -0500516 int ret;
Andreas Färber872536b2013-02-16 22:44:03 +0100517
518 g_assert(words[1] && words[2]);
Eric Blake14773122017-09-11 12:19:46 -0500519 ret = qemu_strtou64(words[1], NULL, 0, &addr);
520 g_assert(ret == 0);
521 ret = qemu_strtou64(words[2], NULL, 0, &value);
522 g_assert(ret == 0);
Andreas Färber872536b2013-02-16 22:44:03 +0100523
524 if (words[0][5] == 'b') {
525 uint8_t data = value;
Peter Maydell19f70342020-02-18 11:24:57 +0000526 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
527 &data, 1);
Andreas Färber872536b2013-02-16 22:44:03 +0100528 } else if (words[0][5] == 'w') {
529 uint16_t data = value;
530 tswap16s(&data);
Peter Maydell19f70342020-02-18 11:24:57 +0000531 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
532 &data, 2);
Andreas Färber872536b2013-02-16 22:44:03 +0100533 } else if (words[0][5] == 'l') {
534 uint32_t data = value;
535 tswap32s(&data);
Peter Maydell19f70342020-02-18 11:24:57 +0000536 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
537 &data, 4);
Andreas Färber872536b2013-02-16 22:44:03 +0100538 } else if (words[0][5] == 'q') {
539 uint64_t data = value;
540 tswap64s(&data);
Peter Maydell19f70342020-02-18 11:24:57 +0000541 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
542 &data, 8);
Andreas Färber872536b2013-02-16 22:44:03 +0100543 }
544 qtest_send_prefix(chr);
545 qtest_send(chr, "OK\n");
546 } else if (strcmp(words[0], "readb") == 0 ||
547 strcmp(words[0], "readw") == 0 ||
548 strcmp(words[0], "readl") == 0 ||
549 strcmp(words[0], "readq") == 0) {
550 uint64_t addr;
551 uint64_t value = UINT64_C(-1);
Eric Blake14773122017-09-11 12:19:46 -0500552 int ret;
Andreas Färber872536b2013-02-16 22:44:03 +0100553
554 g_assert(words[1]);
Eric Blake14773122017-09-11 12:19:46 -0500555 ret = qemu_strtou64(words[1], NULL, 0, &addr);
556 g_assert(ret == 0);
Andreas Färber872536b2013-02-16 22:44:03 +0100557
558 if (words[0][4] == 'b') {
559 uint8_t data;
Peter Maydell19f70342020-02-18 11:24:57 +0000560 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
561 &data, 1);
Andreas Färber872536b2013-02-16 22:44:03 +0100562 value = data;
563 } else if (words[0][4] == 'w') {
564 uint16_t data;
Peter Maydell19f70342020-02-18 11:24:57 +0000565 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
566 &data, 2);
Andreas Färber872536b2013-02-16 22:44:03 +0100567 value = tswap16(data);
568 } else if (words[0][4] == 'l') {
569 uint32_t data;
Peter Maydell19f70342020-02-18 11:24:57 +0000570 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
571 &data, 4);
Andreas Färber872536b2013-02-16 22:44:03 +0100572 value = tswap32(data);
573 } else if (words[0][4] == 'q') {
Peter Maydell19f70342020-02-18 11:24:57 +0000574 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
575 &value, 8);
Andreas Färber872536b2013-02-16 22:44:03 +0100576 tswap64s(&value);
577 }
578 qtest_send_prefix(chr);
John Snow332cc7e2015-05-22 14:13:43 -0400579 qtest_sendf(chr, "OK 0x%016" PRIx64 "\n", value);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200580 } else if (strcmp(words[0], "read") == 0) {
581 uint64_t addr, len, i;
582 uint8_t *data;
John Snow5560b852015-05-22 14:13:44 -0400583 char *enc;
Eric Blake14773122017-09-11 12:19:46 -0500584 int ret;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200585
586 g_assert(words[1] && words[2]);
Eric Blake14773122017-09-11 12:19:46 -0500587 ret = qemu_strtou64(words[1], NULL, 0, &addr);
588 g_assert(ret == 0);
589 ret = qemu_strtou64(words[2], NULL, 0, &len);
590 g_assert(ret == 0);
Greg Kurz204febd2017-01-11 09:49:32 +0100591 /* We'd send garbage to libqtest if len is 0 */
592 g_assert(len);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200593
594 data = g_malloc(len);
Peter Maydell19f70342020-02-18 11:24:57 +0000595 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
596 len);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200597
John Snow5560b852015-05-22 14:13:44 -0400598 enc = g_malloc(2 * len + 1);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200599 for (i = 0; i < len; i++) {
John Snow5560b852015-05-22 14:13:44 -0400600 sprintf(&enc[i * 2], "%02x", data[i]);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200601 }
John Snow5560b852015-05-22 14:13:44 -0400602
603 qtest_send_prefix(chr);
604 qtest_sendf(chr, "OK 0x%s\n", enc);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200605
606 g_free(data);
John Snow5560b852015-05-22 14:13:44 -0400607 g_free(enc);
John Snow7a6a7402015-05-22 14:13:44 -0400608 } else if (strcmp(words[0], "b64read") == 0) {
609 uint64_t addr, len;
610 uint8_t *data;
611 gchar *b64_data;
Eric Blake14773122017-09-11 12:19:46 -0500612 int ret;
John Snow7a6a7402015-05-22 14:13:44 -0400613
614 g_assert(words[1] && words[2]);
Eric Blake14773122017-09-11 12:19:46 -0500615 ret = qemu_strtou64(words[1], NULL, 0, &addr);
616 g_assert(ret == 0);
617 ret = qemu_strtou64(words[2], NULL, 0, &len);
618 g_assert(ret == 0);
John Snow7a6a7402015-05-22 14:13:44 -0400619
620 data = g_malloc(len);
Peter Maydell19f70342020-02-18 11:24:57 +0000621 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
622 len);
John Snow7a6a7402015-05-22 14:13:44 -0400623 b64_data = g_base64_encode(data, len);
624 qtest_send_prefix(chr);
625 qtest_sendf(chr, "OK %s\n", b64_data);
626
627 g_free(data);
628 g_free(b64_data);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200629 } else if (strcmp(words[0], "write") == 0) {
630 uint64_t addr, len, i;
631 uint8_t *data;
632 size_t data_len;
Eric Blake14773122017-09-11 12:19:46 -0500633 int ret;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200634
635 g_assert(words[1] && words[2] && words[3]);
Eric Blake14773122017-09-11 12:19:46 -0500636 ret = qemu_strtou64(words[1], NULL, 0, &addr);
637 g_assert(ret == 0);
638 ret = qemu_strtou64(words[2], NULL, 0, &len);
639 g_assert(ret == 0);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200640
641 data_len = strlen(words[3]);
642 if (data_len < 3) {
643 qtest_send(chr, "ERR invalid argument size\n");
644 return;
645 }
646
647 data = g_malloc(len);
648 for (i = 0; i < len; i++) {
649 if ((i * 2 + 4) <= data_len) {
650 data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
651 data[i] |= hex2nib(words[3][i * 2 + 3]);
652 } else {
653 data[i] = 0;
654 }
655 }
Peter Maydell19f70342020-02-18 11:24:57 +0000656 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
657 len);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200658 g_free(data);
659
660 qtest_send_prefix(chr);
661 qtest_send(chr, "OK\n");
John Snow4d007962015-05-22 14:13:44 -0400662 } else if (strcmp(words[0], "memset") == 0) {
663 uint64_t addr, len;
664 uint8_t *data;
Laurent Vivieraa15f492016-09-13 14:52:43 +0200665 unsigned long pattern;
Eric Blake14773122017-09-11 12:19:46 -0500666 int ret;
John Snow4d007962015-05-22 14:13:44 -0400667
668 g_assert(words[1] && words[2] && words[3]);
Eric Blake14773122017-09-11 12:19:46 -0500669 ret = qemu_strtou64(words[1], NULL, 0, &addr);
670 g_assert(ret == 0);
671 ret = qemu_strtou64(words[2], NULL, 0, &len);
672 g_assert(ret == 0);
673 ret = qemu_strtoul(words[3], NULL, 0, &pattern);
674 g_assert(ret == 0);
John Snow4d007962015-05-22 14:13:44 -0400675
Peter Maydell5f31bbf2016-08-05 11:43:20 +0100676 if (len) {
677 data = g_malloc(len);
678 memset(data, pattern, len);
Peter Maydell19f70342020-02-18 11:24:57 +0000679 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
680 data, len);
Peter Maydell5f31bbf2016-08-05 11:43:20 +0100681 g_free(data);
682 }
John Snow4d007962015-05-22 14:13:44 -0400683
684 qtest_send_prefix(chr);
685 qtest_send(chr, "OK\n");
John Snow7a6a7402015-05-22 14:13:44 -0400686 } else if (strcmp(words[0], "b64write") == 0) {
687 uint64_t addr, len;
688 uint8_t *data;
689 size_t data_len;
690 gsize out_len;
Eric Blake14773122017-09-11 12:19:46 -0500691 int ret;
John Snow7a6a7402015-05-22 14:13:44 -0400692
693 g_assert(words[1] && words[2] && words[3]);
Eric Blake14773122017-09-11 12:19:46 -0500694 ret = qemu_strtou64(words[1], NULL, 0, &addr);
695 g_assert(ret == 0);
696 ret = qemu_strtou64(words[2], NULL, 0, &len);
697 g_assert(ret == 0);
John Snow7a6a7402015-05-22 14:13:44 -0400698
699 data_len = strlen(words[3]);
700 if (data_len < 3) {
701 qtest_send(chr, "ERR invalid argument size\n");
702 return;
703 }
704
705 data = g_base64_decode_inplace(words[3], &out_len);
706 if (out_len != len) {
707 qtest_log_send("b64write: data length mismatch (told %"PRIu64", "
708 "found %zu)\n",
709 len, out_len);
710 out_len = MIN(out_len, len);
711 }
712
Peter Maydell19f70342020-02-18 11:24:57 +0000713 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
714 len);
John Snow7a6a7402015-05-22 14:13:44 -0400715
716 qtest_send_prefix(chr);
717 qtest_send(chr, "OK\n");
Laurent Vivier54ce6f22016-10-07 12:14:27 +0200718 } else if (strcmp(words[0], "endianness") == 0) {
719 qtest_send_prefix(chr);
Thomas Huth09637ed2023-04-11 20:34:18 +0200720 if (target_words_bigendian()) {
721 qtest_sendf(chr, "OK big\n");
722 } else {
723 qtest_sendf(chr, "OK little\n");
724 }
Paolo Bonzinid4fce242013-10-18 13:51:11 +0200725 } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
Paolo Bonzini8156be52012-03-28 15:42:04 +0200726 int64_t ns;
727
728 if (words[1]) {
Eric Blake14773122017-09-11 12:19:46 -0500729 int ret = qemu_strtoi64(words[1], NULL, 0, &ns);
730 g_assert(ret == 0);
Paolo Bonzini8156be52012-03-28 15:42:04 +0200731 } else {
Pavel Dovgalyukdcb15782019-07-25 11:44:26 +0300732 ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
733 QEMU_TIMER_ATTR_ALL);
Paolo Bonzini8156be52012-03-28 15:42:04 +0200734 }
Alex Blighbc72ad62013-08-21 16:03:08 +0100735 qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
Paolo Bonzini8156be52012-03-28 15:42:04 +0200736 qtest_send_prefix(chr);
John Snow332cc7e2015-05-22 14:13:43 -0400737 qtest_sendf(chr, "OK %"PRIi64"\n",
738 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
Marc-André Lureaueb062cf2019-07-22 22:51:40 +0400739 } else if (strcmp(words[0], "module_load") == 0) {
Claudio Fontanac551fb02022-09-29 11:30:33 +0200740 Error *local_err = NULL;
741 int rv;
Marc-André Lureaueb062cf2019-07-22 22:51:40 +0400742 g_assert(words[1] && words[2]);
743
744 qtest_send_prefix(chr);
Claudio Fontanac551fb02022-09-29 11:30:33 +0200745 rv = module_load(words[1], words[2], &local_err);
746 if (rv > 0) {
Marc-André Lureaueb062cf2019-07-22 22:51:40 +0400747 qtest_sendf(chr, "OK\n");
748 } else {
Claudio Fontanac551fb02022-09-29 11:30:33 +0200749 if (rv < 0) {
750 error_report_err(local_err);
751 }
Marc-André Lureaueb062cf2019-07-22 22:51:40 +0400752 qtest_sendf(chr, "FAIL\n");
753 }
Paolo Bonzinid4fce242013-10-18 13:51:11 +0200754 } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
Paolo Bonzini8156be52012-03-28 15:42:04 +0200755 int64_t ns;
Eric Blake14773122017-09-11 12:19:46 -0500756 int ret;
Paolo Bonzini8156be52012-03-28 15:42:04 +0200757
758 g_assert(words[1]);
Eric Blake14773122017-09-11 12:19:46 -0500759 ret = qemu_strtoi64(words[1], NULL, 0, &ns);
760 g_assert(ret == 0);
Paolo Bonzini8156be52012-03-28 15:42:04 +0200761 qtest_clock_warp(ns);
762 qtest_send_prefix(chr);
John Snow332cc7e2015-05-22 14:13:43 -0400763 qtest_sendf(chr, "OK %"PRIi64"\n",
764 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
Thomas Huthc7a6bf52023-04-11 20:34:16 +0200765 } else if (process_command_cb && process_command_cb(chr, words)) {
766 /* Command got consumed by the callback handler */
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200767 } else {
768 qtest_send_prefix(chr);
John Snow332cc7e2015-05-22 14:13:43 -0400769 qtest_sendf(chr, "FAIL Unknown command '%s'\n", words[0]);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200770 }
771}
772
Marc-André Lureau5345fdb2016-10-22 12:52:55 +0300773static void qtest_process_inbuf(CharBackend *chr, GString *inbuf)
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200774{
775 char *end;
776
777 while ((end = strchr(inbuf->str, '\n')) != NULL) {
778 size_t offset;
779 GString *cmd;
780 gchar **words;
781
782 offset = end - inbuf->str;
783
784 cmd = g_string_new_len(inbuf->str, offset);
785 g_string_erase(inbuf, 0, offset + 1);
786
787 words = g_strsplit(cmd->str, " ", 0);
788 qtest_process_command(chr, words);
789 g_strfreev(words);
790
791 g_string_free(cmd, TRUE);
792 }
793}
794
795static void qtest_read(void *opaque, const uint8_t *buf, int size)
796{
Marc-André Lureau5345fdb2016-10-22 12:52:55 +0300797 CharBackend *chr = opaque;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200798
799 g_string_append_len(inbuf, (const gchar *)buf, size);
800 qtest_process_inbuf(chr, inbuf);
801}
802
803static int qtest_can_read(void *opaque)
804{
805 return 1024;
806}
807
Philippe Mathieu-Daudé083b2662019-12-18 18:20:09 +0100808static void qtest_event(void *opaque, QEMUChrEvent event)
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200809{
810 int i;
811
812 switch (event) {
813 case CHR_EVENT_OPENED:
Markus Armbrusterba646ff2013-06-26 15:52:12 +0200814 /*
815 * We used to call qemu_system_reset() here, hoping we could
816 * use the same process for multiple tests that way. Never
817 * used. Injects an extra reset even when it's not used, and
818 * that can mess up tests, e.g. -boot once.
819 */
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200820 for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
821 irq_levels[i] = 0;
822 }
Marc-André Lureau20e4ae12022-03-07 11:03:58 +0400823
824 g_clear_pointer(&timer, g_timer_destroy);
825 timer = g_timer_new();
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200826 qtest_opened = true;
827 if (qtest_log_fp) {
Marc-André Lureau20e4ae12022-03-07 11:03:58 +0400828 fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n", g_timer_elapsed(timer, NULL));
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200829 }
830 break;
831 case CHR_EVENT_CLOSED:
832 qtest_opened = false;
833 if (qtest_log_fp) {
Marc-André Lureau20e4ae12022-03-07 11:03:58 +0400834 fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n", g_timer_elapsed(timer, NULL));
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200835 }
Marc-André Lureau20e4ae12022-03-07 11:03:58 +0400836 g_clear_pointer(&timer, g_timer_destroy);
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200837 break;
838 default:
839 break;
840 }
841}
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500842
Oleinik, Alexander2b8985f2019-08-05 03:13:01 +0000843void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200844{
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500845 ERRP_GUARD();
Marc-André Lureau0ec7b3e2016-12-07 16:20:22 +0300846 Chardev *chr;
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500847 Object *qtest;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200848
Paolo Bonzini4ad6f6c2019-02-13 14:18:13 +0100849 chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
Fam Zheng23802b42014-02-10 09:28:02 +0800850 if (chr == NULL) {
851 error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
852 qtest_chrdev);
853 return;
854 }
855
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500856 qtest = object_new(TYPE_QTEST);
Peter Maydell537a1382023-04-13 16:07:23 +0100857 object_property_set_str(qtest, "chardev", chr->label, &error_abort);
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500858 if (qtest_log) {
859 object_property_set_str(qtest, "log", qtest_log, &error_abort);
860 }
861 object_property_add_child(qdev_get_machine(), "qtest", qtest);
862 user_creatable_complete(USER_CREATABLE(qtest), errp);
863 if (*errp) {
864 object_unparent(qtest);
865 }
866 object_unref(OBJECT(chr));
867 object_unref(qtest);
868}
869
870static bool qtest_server_start(QTest *q, Error **errp)
871{
872 Chardev *chr = q->chr;
873 const char *qtest_log = q->log;
874
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200875 if (qtest_log) {
876 if (strcmp(qtest_log, "none") != 0) {
877 qtest_log_fp = fopen(qtest_log, "w+");
878 }
879 } else {
880 qtest_log_fp = stderr;
881 }
882
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500883 if (!qemu_chr_fe_init(&q->qtest_chr, chr, errp)) {
884 return false;
885 }
886 qemu_chr_fe_set_handlers(&q->qtest_chr, qtest_can_read, qtest_read,
887 qtest_event, NULL, &q->qtest_chr, NULL, true);
888 qemu_chr_fe_set_echo(&q->qtest_chr, true);
Li Liu107684c2014-10-22 10:26:47 +0800889
890 inbuf = g_string_new("");
Alexander Bulekove731d082020-02-19 23:11:01 -0500891
892 if (!qtest_server_send) {
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500893 qtest_server_set_send_handler(qtest_server_char_be_send, &q->qtest_chr);
Alexander Bulekove731d082020-02-19 23:11:01 -0500894 }
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500895 qtest = q;
896 return true;
Alexander Bulekove731d082020-02-19 23:11:01 -0500897}
898
Alexander Bulekov3fc92f82020-02-26 22:14:39 -0500899void qtest_server_set_send_handler(void (*send)(void*, const char*),
900 void *opaque)
Alexander Bulekove731d082020-02-19 23:11:01 -0500901{
902 qtest_server_send = send;
903 qtest_server_send_opaque = opaque;
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +0200904}
Michael S. Tsirkinb3be57c2014-02-04 20:06:47 +0200905
906bool qtest_driver(void)
907{
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500908 return qtest && qtest->qtest_chr.chr != NULL;
Michael S. Tsirkinb3be57c2014-02-04 20:06:47 +0200909}
Alexander Bulekov0bd9aef2020-02-19 23:11:04 -0500910
911void qtest_server_inproc_recv(void *dummy, const char *buf)
912{
913 static GString *gstr;
914 if (!gstr) {
915 gstr = g_string_new(NULL);
916 }
917 g_string_append(gstr, buf);
918 if (gstr->str[gstr->len - 1] == '\n') {
919 qtest_process_inbuf(NULL, gstr);
920 g_string_truncate(gstr, 0);
921 }
922}
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500923
924static void qtest_complete(UserCreatable *uc, Error **errp)
925{
926 QTest *q = QTEST(uc);
927 if (qtest) {
928 error_setg(errp, "Only one instance of qtest can be created");
929 return;
930 }
931 if (!q->chr_name) {
932 error_setg(errp, "No backend specified");
933 return;
934 }
935
936 if (OBJECT(uc)->parent != qdev_get_machine()) {
937 q->has_machine_link = true;
938 object_property_add_const_link(qdev_get_machine(), "qtest", OBJECT(uc));
939 } else {
940 /* -qtest was used. */
941 }
942
943 qtest_server_start(q, errp);
944}
945
946static void qtest_unparent(Object *obj)
947{
948 QTest *q = QTEST(obj);
949
950 if (qtest == q) {
951 qemu_chr_fe_disconnect(&q->qtest_chr);
952 assert(!qtest_opened);
953 qemu_chr_fe_deinit(&q->qtest_chr, false);
954 if (qtest_log_fp) {
955 fclose(qtest_log_fp);
956 qtest_log_fp = NULL;
957 }
958 qtest = NULL;
959 }
960
961 if (q->has_machine_link) {
962 object_property_del(qdev_get_machine(), "qtest");
963 q->has_machine_link = false;
964 }
965}
966
967static void qtest_set_log(Object *obj, const char *value, Error **errp)
968{
969 QTest *q = QTEST(obj);
970
971 if (qtest == q) {
Markus Armbruster8d095932022-10-12 17:38:00 +0200972 error_setg(errp, "Property 'log' can not be set now");
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500973 } else {
974 g_free(q->log);
975 q->log = g_strdup(value);
976 }
977}
978
979static char *qtest_get_log(Object *obj, Error **errp)
980{
981 QTest *q = QTEST(obj);
982
983 return g_strdup(q->log);
984}
985
986static void qtest_set_chardev(Object *obj, const char *value, Error **errp)
987{
988 QTest *q = QTEST(obj);
989 Chardev *chr;
990
991 if (qtest == q) {
Markus Armbruster8d095932022-10-12 17:38:00 +0200992 error_setg(errp, "Property 'chardev' can not be set now");
Paolo Bonzini6ba7ada2020-11-09 10:13:30 -0500993 return;
994 }
995
996 chr = qemu_chr_find(value);
997 if (!chr) {
998 error_setg(errp, "Cannot find character device '%s'", value);
999 return;
1000 }
1001
1002 g_free(q->chr_name);
1003 q->chr_name = g_strdup(value);
1004
1005 if (q->chr) {
1006 object_unref(q->chr);
1007 }
1008 q->chr = chr;
1009 object_ref(chr);
1010}
1011
1012static char *qtest_get_chardev(Object *obj, Error **errp)
1013{
1014 QTest *q = QTEST(obj);
1015
1016 return g_strdup(q->chr_name);
1017}
1018
1019static void qtest_class_init(ObjectClass *oc, void *data)
1020{
1021 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
1022
1023 oc->unparent = qtest_unparent;
1024 ucc->complete = qtest_complete;
1025
1026 object_class_property_add_str(oc, "chardev",
1027 qtest_get_chardev, qtest_set_chardev);
1028 object_class_property_add_str(oc, "log",
1029 qtest_get_log, qtest_set_log);
1030}
1031
1032static const TypeInfo qtest_info = {
1033 .name = TYPE_QTEST,
1034 .parent = TYPE_OBJECT,
1035 .class_init = qtest_class_init,
1036 .instance_size = sizeof(QTest),
1037 .interfaces = (InterfaceInfo[]) {
1038 { TYPE_USER_CREATABLE },
1039 { }
1040 }
1041};
1042
1043static void register_types(void)
1044{
1045 type_register_static(&qtest_info);
1046}
1047
1048type_init(register_types);