summaryrefslogtreecommitdiffstats
path: root/qemu/replay
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/replay')
-rw-r--r--qemu/replay/Makefile.objs6
-rwxr-xr-xqemu/replay/replay-char.c168
-rw-r--r--qemu/replay/replay-events.c311
-rw-r--r--qemu/replay/replay-input.c169
-rw-r--r--qemu/replay/replay-internal.c207
-rw-r--r--qemu/replay/replay-internal.h158
-rw-r--r--qemu/replay/replay-time.c65
-rw-r--r--qemu/replay/replay.c354
8 files changed, 0 insertions, 1438 deletions
diff --git a/qemu/replay/Makefile.objs b/qemu/replay/Makefile.objs
deleted file mode 100644
index fcb3f74d6..000000000
--- a/qemu/replay/Makefile.objs
+++ /dev/null
@@ -1,6 +0,0 @@
-common-obj-y += replay.o
-common-obj-y += replay-internal.o
-common-obj-y += replay-events.o
-common-obj-y += replay-time.o
-common-obj-y += replay-input.o
-common-obj-y += replay-char.o
diff --git a/qemu/replay/replay-char.c b/qemu/replay/replay-char.c
deleted file mode 100755
index 23b692297..000000000
--- a/qemu/replay/replay-char.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * replay-char.c
- *
- * Copyright (c) 2010-2016 Institute for System Programming
- * of the Russian Academy of Sciences.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "qemu/osdep.h"
-#include "qemu/error-report.h"
-#include "sysemu/replay.h"
-#include "replay-internal.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/char.h"
-
-/* Char drivers that generate qemu_chr_be_write events
- that should be saved into the log. */
-static CharDriverState **char_drivers;
-static int drivers_count;
-
-/* Char event attributes. */
-typedef struct CharEvent {
- int id;
- uint8_t *buf;
- size_t len;
-} CharEvent;
-
-static int find_char_driver(CharDriverState *chr)
-{
- int i = 0;
- for ( ; i < drivers_count ; ++i) {
- if (char_drivers[i] == chr) {
- return i;
- }
- }
- return -1;
-}
-
-void replay_register_char_driver(CharDriverState *chr)
-{
- if (replay_mode == REPLAY_MODE_NONE) {
- return;
- }
- char_drivers = g_realloc(char_drivers,
- sizeof(*char_drivers) * (drivers_count + 1));
- char_drivers[drivers_count++] = chr;
-}
-
-void replay_chr_be_write(CharDriverState *s, uint8_t *buf, int len)
-{
- CharEvent *event = g_malloc0(sizeof(CharEvent));
-
- event->id = find_char_driver(s);
- if (event->id < 0) {
- fprintf(stderr, "Replay: cannot find char driver\n");
- exit(1);
- }
- event->buf = g_malloc(len);
- memcpy(event->buf, buf, len);
- event->len = len;
-
- replay_add_event(REPLAY_ASYNC_EVENT_CHAR_READ, event, NULL, 0);
-}
-
-void replay_event_char_read_run(void *opaque)
-{
- CharEvent *event = (CharEvent *)opaque;
-
- qemu_chr_be_write_impl(char_drivers[event->id], event->buf,
- (int)event->len);
-
- g_free(event->buf);
- g_free(event);
-}
-
-void replay_event_char_read_save(void *opaque)
-{
- CharEvent *event = (CharEvent *)opaque;
-
- replay_put_byte(event->id);
- replay_put_array(event->buf, event->len);
-}
-
-void *replay_event_char_read_load(void)
-{
- CharEvent *event = g_malloc0(sizeof(CharEvent));
-
- event->id = replay_get_byte();
- replay_get_array_alloc(&event->buf, &event->len);
-
- return event;
-}
-
-void replay_char_write_event_save(int res, int offset)
-{
- replay_save_instructions();
- replay_mutex_lock();
- replay_put_event(EVENT_CHAR_WRITE);
- replay_put_dword(res);
- replay_put_dword(offset);
- replay_mutex_unlock();
-}
-
-void replay_char_write_event_load(int *res, int *offset)
-{
- replay_account_executed_instructions();
- replay_mutex_lock();
- if (replay_next_event_is(EVENT_CHAR_WRITE)) {
- *res = replay_get_dword();
- *offset = replay_get_dword();
- replay_finish_event();
- replay_mutex_unlock();
- } else {
- replay_mutex_unlock();
- error_report("Missing character write event in the replay log");
- exit(1);
- }
-}
-
-int replay_char_read_all_load(uint8_t *buf)
-{
- replay_mutex_lock();
- if (replay_next_event_is(EVENT_CHAR_READ_ALL)) {
- size_t size;
- int res;
- replay_get_array(buf, &size);
- replay_finish_event();
- replay_mutex_unlock();
- res = (int)size;
- assert(res >= 0);
- return res;
- } else if (replay_next_event_is(EVENT_CHAR_READ_ALL_ERROR)) {
- int res = replay_get_dword();
- replay_finish_event();
- replay_mutex_unlock();
- return res;
- } else {
- replay_mutex_unlock();
- error_report("Missing character read all event in the replay log");
- exit(1);
- }
-}
-
-void replay_char_read_all_save_error(int res)
-{
- assert(res < 0);
- replay_save_instructions();
- replay_mutex_lock();
- replay_put_event(EVENT_CHAR_READ_ALL_ERROR);
- replay_put_dword(res);
- replay_mutex_unlock();
-}
-
-void replay_char_read_all_save_buf(uint8_t *buf, int offset)
-{
- replay_save_instructions();
- replay_mutex_lock();
- replay_put_event(EVENT_CHAR_READ_ALL);
- replay_put_array(buf, offset);
- replay_mutex_unlock();
-}
diff --git a/qemu/replay/replay-events.c b/qemu/replay/replay-events.c
deleted file mode 100644
index 3807245ae..000000000
--- a/qemu/replay/replay-events.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * replay-events.c
- *
- * Copyright (c) 2010-2015 Institute for System Programming
- * of the Russian Academy of Sciences.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qemu/error-report.h"
-#include "sysemu/replay.h"
-#include "replay-internal.h"
-#include "block/aio.h"
-#include "ui/input.h"
-
-typedef struct Event {
- ReplayAsyncEventKind event_kind;
- void *opaque;
- void *opaque2;
- uint64_t id;
-
- QTAILQ_ENTRY(Event) events;
-} Event;
-
-static QTAILQ_HEAD(, Event) events_list = QTAILQ_HEAD_INITIALIZER(events_list);
-static unsigned int read_event_kind = -1;
-static uint64_t read_id = -1;
-static int read_checkpoint = -1;
-
-static bool events_enabled;
-
-/* Functions */
-
-static void replay_run_event(Event *event)
-{
- switch (event->event_kind) {
- case REPLAY_ASYNC_EVENT_BH:
- aio_bh_call(event->opaque);
- break;
- case REPLAY_ASYNC_EVENT_INPUT:
- qemu_input_event_send_impl(NULL, (InputEvent *)event->opaque);
- qapi_free_InputEvent((InputEvent *)event->opaque);
- break;
- case REPLAY_ASYNC_EVENT_INPUT_SYNC:
- qemu_input_event_sync_impl();
- break;
- case REPLAY_ASYNC_EVENT_CHAR_READ:
- replay_event_char_read_run(event->opaque);
- break;
- case REPLAY_ASYNC_EVENT_BLOCK:
- aio_bh_call(event->opaque);
- break;
- default:
- error_report("Replay: invalid async event ID (%d) in the queue",
- event->event_kind);
- exit(1);
- break;
- }
-}
-
-void replay_enable_events(void)
-{
- events_enabled = true;
-}
-
-bool replay_has_events(void)
-{
- return !QTAILQ_EMPTY(&events_list);
-}
-
-void replay_flush_events(void)
-{
- replay_mutex_lock();
- while (!QTAILQ_EMPTY(&events_list)) {
- Event *event = QTAILQ_FIRST(&events_list);
- replay_mutex_unlock();
- replay_run_event(event);
- replay_mutex_lock();
- QTAILQ_REMOVE(&events_list, event, events);
- g_free(event);
- }
- replay_mutex_unlock();
-}
-
-void replay_disable_events(void)
-{
- if (replay_mode != REPLAY_MODE_NONE) {
- events_enabled = false;
- /* Flush events queue before waiting of completion */
- replay_flush_events();
- }
-}
-
-void replay_clear_events(void)
-{
- replay_mutex_lock();
- while (!QTAILQ_EMPTY(&events_list)) {
- Event *event = QTAILQ_FIRST(&events_list);
- QTAILQ_REMOVE(&events_list, event, events);
-
- g_free(event);
- }
- replay_mutex_unlock();
-}
-
-/*! Adds specified async event to the queue */
-void replay_add_event(ReplayAsyncEventKind event_kind,
- void *opaque,
- void *opaque2, uint64_t id)
-{
- assert(event_kind < REPLAY_ASYNC_COUNT);
-
- if (!replay_file || replay_mode == REPLAY_MODE_NONE
- || !events_enabled) {
- Event e;
- e.event_kind = event_kind;
- e.opaque = opaque;
- e.opaque2 = opaque2;
- e.id = id;
- replay_run_event(&e);
- return;
- }
-
- Event *event = g_malloc0(sizeof(Event));
- event->event_kind = event_kind;
- event->opaque = opaque;
- event->opaque2 = opaque2;
- event->id = id;
-
- replay_mutex_lock();
- QTAILQ_INSERT_TAIL(&events_list, event, events);
- replay_mutex_unlock();
-}
-
-void replay_bh_schedule_event(QEMUBH *bh)
-{
- if (replay_mode != REPLAY_MODE_NONE && events_enabled) {
- uint64_t id = replay_get_current_step();
- replay_add_event(REPLAY_ASYNC_EVENT_BH, bh, NULL, id);
- } else {
- qemu_bh_schedule(bh);
- }
-}
-
-void replay_add_input_event(struct InputEvent *event)
-{
- replay_add_event(REPLAY_ASYNC_EVENT_INPUT, event, NULL, 0);
-}
-
-void replay_add_input_sync_event(void)
-{
- replay_add_event(REPLAY_ASYNC_EVENT_INPUT_SYNC, NULL, NULL, 0);
-}
-
-void replay_block_event(QEMUBH *bh, uint64_t id)
-{
- if (replay_mode != REPLAY_MODE_NONE && events_enabled) {
- replay_add_event(REPLAY_ASYNC_EVENT_BLOCK, bh, NULL, id);
- } else {
- qemu_bh_schedule(bh);
- }
-}
-
-static void replay_save_event(Event *event, int checkpoint)
-{
- if (replay_mode != REPLAY_MODE_PLAY) {
- /* put the event into the file */
- replay_put_event(EVENT_ASYNC);
- replay_put_byte(checkpoint);
- replay_put_byte(event->event_kind);
-
- /* save event-specific data */
- switch (event->event_kind) {
- case REPLAY_ASYNC_EVENT_BH:
- replay_put_qword(event->id);
- break;
- case REPLAY_ASYNC_EVENT_INPUT:
- replay_save_input_event(event->opaque);
- break;
- case REPLAY_ASYNC_EVENT_INPUT_SYNC:
- break;
- case REPLAY_ASYNC_EVENT_CHAR_READ:
- replay_event_char_read_save(event->opaque);
- break;
- case REPLAY_ASYNC_EVENT_BLOCK:
- replay_put_qword(event->id);
- break;
- default:
- error_report("Unknown ID %" PRId64 " of replay event", event->id);
- exit(1);
- }
- }
-}
-
-/* Called with replay mutex locked */
-void replay_save_events(int checkpoint)
-{
- while (!QTAILQ_EMPTY(&events_list)) {
- Event *event = QTAILQ_FIRST(&events_list);
- replay_save_event(event, checkpoint);
-
- replay_mutex_unlock();
- replay_run_event(event);
- replay_mutex_lock();
- QTAILQ_REMOVE(&events_list, event, events);
- g_free(event);
- }
-}
-
-static Event *replay_read_event(int checkpoint)
-{
- Event *event;
- if (read_event_kind == -1) {
- read_checkpoint = replay_get_byte();
- read_event_kind = replay_get_byte();
- read_id = -1;
- replay_check_error();
- }
-
- if (checkpoint != read_checkpoint) {
- return NULL;
- }
-
- /* Events that has not to be in the queue */
- switch (read_event_kind) {
- case REPLAY_ASYNC_EVENT_BH:
- if (read_id == -1) {
- read_id = replay_get_qword();
- }
- break;
- case REPLAY_ASYNC_EVENT_INPUT:
- event = g_malloc0(sizeof(Event));
- event->event_kind = read_event_kind;
- event->opaque = replay_read_input_event();
- return event;
- case REPLAY_ASYNC_EVENT_INPUT_SYNC:
- event = g_malloc0(sizeof(Event));
- event->event_kind = read_event_kind;
- event->opaque = 0;
- return event;
- case REPLAY_ASYNC_EVENT_CHAR_READ:
- event = g_malloc0(sizeof(Event));
- event->event_kind = read_event_kind;
- event->opaque = replay_event_char_read_load();
- return event;
- case REPLAY_ASYNC_EVENT_BLOCK:
- if (read_id == -1) {
- read_id = replay_get_qword();
- }
- break;
- default:
- error_report("Unknown ID %d of replay event", read_event_kind);
- exit(1);
- break;
- }
-
- QTAILQ_FOREACH(event, &events_list, events) {
- if (event->event_kind == read_event_kind
- && (read_id == -1 || read_id == event->id)) {
- break;
- }
- }
-
- if (event) {
- QTAILQ_REMOVE(&events_list, event, events);
- } else {
- return NULL;
- }
-
- /* Read event-specific data */
-
- return event;
-}
-
-/* Called with replay mutex locked */
-void replay_read_events(int checkpoint)
-{
- while (replay_data_kind == EVENT_ASYNC) {
- Event *event = replay_read_event(checkpoint);
- if (!event) {
- break;
- }
- replay_mutex_unlock();
- replay_run_event(event);
- replay_mutex_lock();
-
- g_free(event);
- replay_finish_event();
- read_event_kind = -1;
- }
-}
-
-void replay_init_events(void)
-{
- read_event_kind = -1;
-}
-
-void replay_finish_events(void)
-{
- events_enabled = false;
- replay_clear_events();
-}
-
-bool replay_events_enabled(void)
-{
- return events_enabled;
-}
diff --git a/qemu/replay/replay-input.c b/qemu/replay/replay-input.c
deleted file mode 100644
index 06babe0ec..000000000
--- a/qemu/replay/replay-input.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * replay-input.c
- *
- * Copyright (c) 2010-2015 Institute for System Programming
- * of the Russian Academy of Sciences.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu-common.h"
-#include "sysemu/replay.h"
-#include "replay-internal.h"
-#include "qemu/notify.h"
-#include "ui/input.h"
-#include "qapi/qmp-output-visitor.h"
-#include "qapi/qmp-input-visitor.h"
-#include "qapi-visit.h"
-
-static InputEvent *qapi_clone_InputEvent(InputEvent *src)
-{
- QmpOutputVisitor *qov;
- QmpInputVisitor *qiv;
- Visitor *ov, *iv;
- QObject *obj;
- InputEvent *dst = NULL;
-
- qov = qmp_output_visitor_new();
- ov = qmp_output_get_visitor(qov);
- visit_type_InputEvent(ov, NULL, &src, &error_abort);
- obj = qmp_output_get_qobject(qov);
- qmp_output_visitor_cleanup(qov);
- if (!obj) {
- return NULL;
- }
-
- qiv = qmp_input_visitor_new(obj);
- iv = qmp_input_get_visitor(qiv);
- visit_type_InputEvent(iv, NULL, &dst, &error_abort);
- qmp_input_visitor_cleanup(qiv);
- qobject_decref(obj);
-
- return dst;
-}
-
-void replay_save_input_event(InputEvent *evt)
-{
- InputKeyEvent *key;
- InputBtnEvent *btn;
- InputMoveEvent *move;
- replay_put_dword(evt->type);
-
- switch (evt->type) {
- case INPUT_EVENT_KIND_KEY:
- key = evt->u.key.data;
- replay_put_dword(key->key->type);
-
- switch (key->key->type) {
- case KEY_VALUE_KIND_NUMBER:
- replay_put_qword(key->key->u.number.data);
- replay_put_byte(key->down);
- break;
- case KEY_VALUE_KIND_QCODE:
- replay_put_dword(key->key->u.qcode.data);
- replay_put_byte(key->down);
- break;
- case KEY_VALUE_KIND__MAX:
- /* keep gcc happy */
- break;
- }
- break;
- case INPUT_EVENT_KIND_BTN:
- btn = evt->u.btn.data;
- replay_put_dword(btn->button);
- replay_put_byte(btn->down);
- break;
- case INPUT_EVENT_KIND_REL:
- move = evt->u.rel.data;
- replay_put_dword(move->axis);
- replay_put_qword(move->value);
- break;
- case INPUT_EVENT_KIND_ABS:
- move = evt->u.abs.data;
- replay_put_dword(move->axis);
- replay_put_qword(move->value);
- break;
- case INPUT_EVENT_KIND__MAX:
- /* keep gcc happy */
- break;
- }
-}
-
-InputEvent *replay_read_input_event(void)
-{
- InputEvent evt;
- KeyValue keyValue;
- InputKeyEvent key;
- key.key = &keyValue;
- InputBtnEvent btn;
- InputMoveEvent rel;
- InputMoveEvent abs;
-
- evt.type = replay_get_dword();
- switch (evt.type) {
- case INPUT_EVENT_KIND_KEY:
- evt.u.key.data = &key;
- evt.u.key.data->key->type = replay_get_dword();
-
- switch (evt.u.key.data->key->type) {
- case KEY_VALUE_KIND_NUMBER:
- evt.u.key.data->key->u.number.data = replay_get_qword();
- evt.u.key.data->down = replay_get_byte();
- break;
- case KEY_VALUE_KIND_QCODE:
- evt.u.key.data->key->u.qcode.data = (QKeyCode)replay_get_dword();
- evt.u.key.data->down = replay_get_byte();
- break;
- case KEY_VALUE_KIND__MAX:
- /* keep gcc happy */
- break;
- }
- break;
- case INPUT_EVENT_KIND_BTN:
- evt.u.btn.data = &btn;
- evt.u.btn.data->button = (InputButton)replay_get_dword();
- evt.u.btn.data->down = replay_get_byte();
- break;
- case INPUT_EVENT_KIND_REL:
- evt.u.rel.data = &rel;
- evt.u.rel.data->axis = (InputAxis)replay_get_dword();
- evt.u.rel.data->value = replay_get_qword();
- break;
- case INPUT_EVENT_KIND_ABS:
- evt.u.abs.data = &abs;
- evt.u.abs.data->axis = (InputAxis)replay_get_dword();
- evt.u.abs.data->value = replay_get_qword();
- break;
- case INPUT_EVENT_KIND__MAX:
- /* keep gcc happy */
- break;
- }
-
- return qapi_clone_InputEvent(&evt);
-}
-
-void replay_input_event(QemuConsole *src, InputEvent *evt)
-{
- if (replay_mode == REPLAY_MODE_PLAY) {
- /* Nothing */
- } else if (replay_mode == REPLAY_MODE_RECORD) {
- replay_add_input_event(qapi_clone_InputEvent(evt));
- } else {
- qemu_input_event_send_impl(src, evt);
- }
-}
-
-void replay_input_sync_event(void)
-{
- if (replay_mode == REPLAY_MODE_PLAY) {
- /* Nothing */
- } else if (replay_mode == REPLAY_MODE_RECORD) {
- replay_add_input_sync_event();
- } else {
- qemu_input_event_sync_impl();
- }
-}
diff --git a/qemu/replay/replay-internal.c b/qemu/replay/replay-internal.c
deleted file mode 100644
index 5835e8def..000000000
--- a/qemu/replay/replay-internal.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * replay-internal.c
- *
- * Copyright (c) 2010-2015 Institute for System Programming
- * of the Russian Academy of Sciences.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/replay.h"
-#include "replay-internal.h"
-#include "qemu/error-report.h"
-#include "sysemu/sysemu.h"
-
-unsigned int replay_data_kind = -1;
-static unsigned int replay_has_unread_data;
-
-/* Mutex to protect reading and writing events to the log.
- replay_data_kind and replay_has_unread_data are also protected
- by this mutex.
- It also protects replay events queue which stores events to be
- written or read to the log. */
-static QemuMutex lock;
-
-/* File for replay writing */
-FILE *replay_file;
-
-void replay_put_byte(uint8_t byte)
-{
- if (replay_file) {
- putc(byte, replay_file);
- }
-}
-
-void replay_put_event(uint8_t event)
-{
- assert(event < EVENT_COUNT);
- replay_put_byte(event);
-}
-
-
-void replay_put_word(uint16_t word)
-{
- replay_put_byte(word >> 8);
- replay_put_byte(word);
-}
-
-void replay_put_dword(uint32_t dword)
-{
- replay_put_word(dword >> 16);
- replay_put_word(dword);
-}
-
-void replay_put_qword(int64_t qword)
-{
- replay_put_dword(qword >> 32);
- replay_put_dword(qword);
-}
-
-void replay_put_array(const uint8_t *buf, size_t size)
-{
- if (replay_file) {
- replay_put_dword(size);
- fwrite(buf, 1, size, replay_file);
- }
-}
-
-uint8_t replay_get_byte(void)
-{
- uint8_t byte = 0;
- if (replay_file) {
- byte = getc(replay_file);
- }
- return byte;
-}
-
-uint16_t replay_get_word(void)
-{
- uint16_t word = 0;
- if (replay_file) {
- word = replay_get_byte();
- word = (word << 8) + replay_get_byte();
- }
-
- return word;
-}
-
-uint32_t replay_get_dword(void)
-{
- uint32_t dword = 0;
- if (replay_file) {
- dword = replay_get_word();
- dword = (dword << 16) + replay_get_word();
- }
-
- return dword;
-}
-
-int64_t replay_get_qword(void)
-{
- int64_t qword = 0;
- if (replay_file) {
- qword = replay_get_dword();
- qword = (qword << 32) + replay_get_dword();
- }
-
- return qword;
-}
-
-void replay_get_array(uint8_t *buf, size_t *size)
-{
- if (replay_file) {
- *size = replay_get_dword();
- if (fread(buf, 1, *size, replay_file) != *size) {
- error_report("replay read error");
- }
- }
-}
-
-void replay_get_array_alloc(uint8_t **buf, size_t *size)
-{
- if (replay_file) {
- *size = replay_get_dword();
- *buf = g_malloc(*size);
- if (fread(*buf, 1, *size, replay_file) != *size) {
- error_report("replay read error");
- }
- }
-}
-
-void replay_check_error(void)
-{
- if (replay_file) {
- if (feof(replay_file)) {
- error_report("replay file is over");
- qemu_system_vmstop_request_prepare();
- qemu_system_vmstop_request(RUN_STATE_PAUSED);
- } else if (ferror(replay_file)) {
- error_report("replay file is over or something goes wrong");
- qemu_system_vmstop_request_prepare();
- qemu_system_vmstop_request(RUN_STATE_INTERNAL_ERROR);
- }
- }
-}
-
-void replay_fetch_data_kind(void)
-{
- if (replay_file) {
- if (!replay_has_unread_data) {
- replay_data_kind = replay_get_byte();
- if (replay_data_kind == EVENT_INSTRUCTION) {
- replay_state.instructions_count = replay_get_dword();
- }
- replay_check_error();
- replay_has_unread_data = 1;
- if (replay_data_kind >= EVENT_COUNT) {
- error_report("Replay: unknown event kind %d", replay_data_kind);
- exit(1);
- }
- }
- }
-}
-
-void replay_finish_event(void)
-{
- replay_has_unread_data = 0;
- replay_fetch_data_kind();
-}
-
-void replay_mutex_init(void)
-{
- qemu_mutex_init(&lock);
-}
-
-void replay_mutex_destroy(void)
-{
- qemu_mutex_destroy(&lock);
-}
-
-void replay_mutex_lock(void)
-{
- qemu_mutex_lock(&lock);
-}
-
-void replay_mutex_unlock(void)
-{
- qemu_mutex_unlock(&lock);
-}
-
-/*! Saves cached instructions. */
-void replay_save_instructions(void)
-{
- if (replay_file && replay_mode == REPLAY_MODE_RECORD) {
- replay_mutex_lock();
- int diff = (int)(replay_get_current_step() - replay_state.current_step);
- if (diff > 0) {
- replay_put_event(EVENT_INSTRUCTION);
- replay_put_dword(diff);
- replay_state.current_step += diff;
- }
- replay_mutex_unlock();
- }
-}
diff --git a/qemu/replay/replay-internal.h b/qemu/replay/replay-internal.h
deleted file mode 100644
index efbf14c8a..000000000
--- a/qemu/replay/replay-internal.h
+++ /dev/null
@@ -1,158 +0,0 @@
-#ifndef REPLAY_INTERNAL_H
-#define REPLAY_INTERNAL_H
-
-/*
- * replay-internal.h
- *
- * Copyright (c) 2010-2015 Institute for System Programming
- * of the Russian Academy of Sciences.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-
-enum ReplayEvents {
- /* for instruction event */
- EVENT_INSTRUCTION,
- /* for software interrupt */
- EVENT_INTERRUPT,
- /* for emulated exceptions */
- EVENT_EXCEPTION,
- /* for async events */
- EVENT_ASYNC,
- /* for shutdown request */
- EVENT_SHUTDOWN,
- /* for character device write event */
- EVENT_CHAR_WRITE,
- /* for character device read all event */
- EVENT_CHAR_READ_ALL,
- EVENT_CHAR_READ_ALL_ERROR,
- /* for clock read/writes */
- /* some of greater codes are reserved for clocks */
- EVENT_CLOCK,
- EVENT_CLOCK_LAST = EVENT_CLOCK + REPLAY_CLOCK_COUNT - 1,
- /* for checkpoint event */
- /* some of greater codes are reserved for checkpoints */
- EVENT_CHECKPOINT,
- EVENT_CHECKPOINT_LAST = EVENT_CHECKPOINT + CHECKPOINT_COUNT - 1,
- /* end of log event */
- EVENT_END,
- EVENT_COUNT
-};
-
-/* Asynchronous events IDs */
-
-enum ReplayAsyncEventKind {
- REPLAY_ASYNC_EVENT_BH,
- REPLAY_ASYNC_EVENT_INPUT,
- REPLAY_ASYNC_EVENT_INPUT_SYNC,
- REPLAY_ASYNC_EVENT_CHAR_READ,
- REPLAY_ASYNC_EVENT_BLOCK,
- REPLAY_ASYNC_COUNT
-};
-
-typedef enum ReplayAsyncEventKind ReplayAsyncEventKind;
-
-typedef struct ReplayState {
- /*! Cached clock values. */
- int64_t cached_clock[REPLAY_CLOCK_COUNT];
- /*! Current step - number of processed instructions and timer events. */
- uint64_t current_step;
- /*! Number of instructions to be executed before other events happen. */
- int instructions_count;
-} ReplayState;
-extern ReplayState replay_state;
-
-extern unsigned int replay_data_kind;
-
-/* File for replay writing */
-extern FILE *replay_file;
-
-void replay_put_byte(uint8_t byte);
-void replay_put_event(uint8_t event);
-void replay_put_word(uint16_t word);
-void replay_put_dword(uint32_t dword);
-void replay_put_qword(int64_t qword);
-void replay_put_array(const uint8_t *buf, size_t size);
-
-uint8_t replay_get_byte(void);
-uint16_t replay_get_word(void);
-uint32_t replay_get_dword(void);
-int64_t replay_get_qword(void);
-void replay_get_array(uint8_t *buf, size_t *size);
-void replay_get_array_alloc(uint8_t **buf, size_t *size);
-
-/* Mutex functions for protecting replay log file */
-
-void replay_mutex_init(void);
-void replay_mutex_destroy(void);
-void replay_mutex_lock(void);
-void replay_mutex_unlock(void);
-
-/*! Checks error status of the file. */
-void replay_check_error(void);
-
-/*! Finishes processing of the replayed event and fetches
- the next event from the log. */
-void replay_finish_event(void);
-/*! Reads data type from the file and stores it in the
- replay_data_kind variable. */
-void replay_fetch_data_kind(void);
-
-/*! Saves queued events (like instructions and sound). */
-void replay_save_instructions(void);
-
-/*! Skips async events until some sync event will be found.
- \return true, if event was found */
-bool replay_next_event_is(int event);
-
-/*! Reads next clock value from the file.
- If clock kind read from the file is different from the parameter,
- the value is not used. */
-void replay_read_next_clock(unsigned int kind);
-
-/* Asynchronous events queue */
-
-/*! Initializes events' processing internals */
-void replay_init_events(void);
-/*! Clears internal data structures for events handling */
-void replay_finish_events(void);
-/*! Enables storing events in the queue */
-void replay_enable_events(void);
-/*! Flushes events queue */
-void replay_flush_events(void);
-/*! Clears events list before loading new VM state */
-void replay_clear_events(void);
-/*! Returns true if there are any unsaved events in the queue */
-bool replay_has_events(void);
-/*! Saves events from queue into the file */
-void replay_save_events(int checkpoint);
-/*! Read events from the file into the input queue */
-void replay_read_events(int checkpoint);
-/*! Adds specified async event to the queue */
-void replay_add_event(ReplayAsyncEventKind event_kind, void *opaque,
- void *opaque2, uint64_t id);
-
-/* Input events */
-
-/*! Saves input event to the log */
-void replay_save_input_event(InputEvent *evt);
-/*! Reads input event from the log */
-InputEvent *replay_read_input_event(void);
-/*! Adds input event to the queue */
-void replay_add_input_event(struct InputEvent *event);
-/*! Adds input sync event to the queue */
-void replay_add_input_sync_event(void);
-
-/* Character devices */
-
-/*! Called to run char device read event. */
-void replay_event_char_read_run(void *opaque);
-/*! Writes char read event to the file. */
-void replay_event_char_read_save(void *opaque);
-/*! Reads char event read from the file. */
-void *replay_event_char_read_load(void);
-
-#endif
diff --git a/qemu/replay/replay-time.c b/qemu/replay/replay-time.c
deleted file mode 100644
index fffe072c5..000000000
--- a/qemu/replay/replay-time.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * replay-time.c
- *
- * Copyright (c) 2010-2015 Institute for System Programming
- * of the Russian Academy of Sciences.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "sysemu/replay.h"
-#include "replay-internal.h"
-#include "qemu/error-report.h"
-
-int64_t replay_save_clock(ReplayClockKind kind, int64_t clock)
-{
- replay_save_instructions();
-
- if (replay_file) {
- replay_mutex_lock();
- replay_put_event(EVENT_CLOCK + kind);
- replay_put_qword(clock);
- replay_mutex_unlock();
- }
-
- return clock;
-}
-
-void replay_read_next_clock(ReplayClockKind kind)
-{
- unsigned int read_kind = replay_data_kind - EVENT_CLOCK;
-
- assert(read_kind == kind);
-
- int64_t clock = replay_get_qword();
-
- replay_check_error();
- replay_finish_event();
-
- replay_state.cached_clock[read_kind] = clock;
-}
-
-/*! Reads next clock event from the input. */
-int64_t replay_read_clock(ReplayClockKind kind)
-{
- replay_account_executed_instructions();
-
- if (replay_file) {
- int64_t ret;
- replay_mutex_lock();
- if (replay_next_event_is(EVENT_CLOCK + kind)) {
- replay_read_next_clock(kind);
- }
- ret = replay_state.cached_clock[kind];
- replay_mutex_unlock();
-
- return ret;
- }
-
- error_report("REPLAY INTERNAL ERROR %d", __LINE__);
- exit(1);
-}
diff --git a/qemu/replay/replay.c b/qemu/replay/replay.c
deleted file mode 100644
index 167fd2942..000000000
--- a/qemu/replay/replay.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * replay.c
- *
- * Copyright (c) 2010-2015 Institute for System Programming
- * of the Russian Academy of Sciences.
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qemu-common.h"
-#include "sysemu/replay.h"
-#include "replay-internal.h"
-#include "qemu/timer.h"
-#include "qemu/main-loop.h"
-#include "sysemu/sysemu.h"
-#include "qemu/error-report.h"
-
-/* Current version of the replay mechanism.
- Increase it when file format changes. */
-#define REPLAY_VERSION 0xe02004
-/* Size of replay log header */
-#define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t))
-
-ReplayMode replay_mode = REPLAY_MODE_NONE;
-
-/* Name of replay file */
-static char *replay_filename;
-ReplayState replay_state;
-static GSList *replay_blockers;
-
-bool replay_next_event_is(int event)
-{
- bool res = false;
-
- /* nothing to skip - not all instructions used */
- if (replay_state.instructions_count != 0) {
- assert(replay_data_kind == EVENT_INSTRUCTION);
- return event == EVENT_INSTRUCTION;
- }
-
- while (true) {
- if (event == replay_data_kind) {
- res = true;
- }
- switch (replay_data_kind) {
- case EVENT_SHUTDOWN:
- replay_finish_event();
- qemu_system_shutdown_request();
- break;
- default:
- /* clock, time_t, checkpoint and other events */
- return res;
- }
- }
- return res;
-}
-
-uint64_t replay_get_current_step(void)
-{
- return cpu_get_icount_raw();
-}
-
-int replay_get_instructions(void)
-{
- int res = 0;
- replay_mutex_lock();
- if (replay_next_event_is(EVENT_INSTRUCTION)) {
- res = replay_state.instructions_count;
- }
- replay_mutex_unlock();
- return res;
-}
-
-void replay_account_executed_instructions(void)
-{
- if (replay_mode == REPLAY_MODE_PLAY) {
- replay_mutex_lock();
- if (replay_state.instructions_count > 0) {
- int count = (int)(replay_get_current_step()
- - replay_state.current_step);
- replay_state.instructions_count -= count;
- replay_state.current_step += count;
- if (replay_state.instructions_count == 0) {
- assert(replay_data_kind == EVENT_INSTRUCTION);
- replay_finish_event();
- /* Wake up iothread. This is required because
- timers will not expire until clock counters
- will be read from the log. */
- qemu_notify_event();
- }
- }
- replay_mutex_unlock();
- }
-}
-
-bool replay_exception(void)
-{
- if (replay_mode == REPLAY_MODE_RECORD) {
- replay_save_instructions();
- replay_mutex_lock();
- replay_put_event(EVENT_EXCEPTION);
- replay_mutex_unlock();
- return true;
- } else if (replay_mode == REPLAY_MODE_PLAY) {
- bool res = replay_has_exception();
- if (res) {
- replay_mutex_lock();
- replay_finish_event();
- replay_mutex_unlock();
- }
- return res;
- }
-
- return true;
-}
-
-bool replay_has_exception(void)
-{
- bool res = false;
- if (replay_mode == REPLAY_MODE_PLAY) {
- replay_account_executed_instructions();
- replay_mutex_lock();
- res = replay_next_event_is(EVENT_EXCEPTION);
- replay_mutex_unlock();
- }
-
- return res;
-}
-
-bool replay_interrupt(void)
-{
- if (replay_mode == REPLAY_MODE_RECORD) {
- replay_save_instructions();
- replay_mutex_lock();
- replay_put_event(EVENT_INTERRUPT);
- replay_mutex_unlock();
- return true;
- } else if (replay_mode == REPLAY_MODE_PLAY) {
- bool res = replay_has_interrupt();
- if (res) {
- replay_mutex_lock();
- replay_finish_event();
- replay_mutex_unlock();
- }
- return res;
- }
-
- return true;
-}
-
-bool replay_has_interrupt(void)
-{
- bool res = false;
- if (replay_mode == REPLAY_MODE_PLAY) {
- replay_account_executed_instructions();
- replay_mutex_lock();
- res = replay_next_event_is(EVENT_INTERRUPT);
- replay_mutex_unlock();
- }
- return res;
-}
-
-void replay_shutdown_request(void)
-{
- if (replay_mode == REPLAY_MODE_RECORD) {
- replay_mutex_lock();
- replay_put_event(EVENT_SHUTDOWN);
- replay_mutex_unlock();
- }
-}
-
-bool replay_checkpoint(ReplayCheckpoint checkpoint)
-{
- bool res = false;
- assert(EVENT_CHECKPOINT + checkpoint <= EVENT_CHECKPOINT_LAST);
- replay_save_instructions();
-
- if (!replay_file) {
- return true;
- }
-
- replay_mutex_lock();
-
- if (replay_mode == REPLAY_MODE_PLAY) {
- if (replay_next_event_is(EVENT_CHECKPOINT + checkpoint)) {
- replay_finish_event();
- } else if (replay_data_kind != EVENT_ASYNC) {
- res = false;
- goto out;
- }
- replay_read_events(checkpoint);
- /* replay_read_events may leave some unread events.
- Return false if not all of the events associated with
- checkpoint were processed */
- res = replay_data_kind != EVENT_ASYNC;
- } else if (replay_mode == REPLAY_MODE_RECORD) {
- replay_put_event(EVENT_CHECKPOINT + checkpoint);
- replay_save_events(checkpoint);
- res = true;
- }
-out:
- replay_mutex_unlock();
- return res;
-}
-
-static void replay_enable(const char *fname, int mode)
-{
- const char *fmode = NULL;
- assert(!replay_file);
-
- switch (mode) {
- case REPLAY_MODE_RECORD:
- fmode = "wb";
- break;
- case REPLAY_MODE_PLAY:
- fmode = "rb";
- break;
- default:
- fprintf(stderr, "Replay: internal error: invalid replay mode\n");
- exit(1);
- }
-
- atexit(replay_finish);
-
- replay_mutex_init();
-
- replay_file = fopen(fname, fmode);
- if (replay_file == NULL) {
- fprintf(stderr, "Replay: open %s: %s\n", fname, strerror(errno));
- exit(1);
- }
-
- replay_filename = g_strdup(fname);
-
- replay_mode = mode;
- replay_data_kind = -1;
- replay_state.instructions_count = 0;
- replay_state.current_step = 0;
-
- /* skip file header for RECORD and check it for PLAY */
- if (replay_mode == REPLAY_MODE_RECORD) {
- fseek(replay_file, HEADER_SIZE, SEEK_SET);
- } else if (replay_mode == REPLAY_MODE_PLAY) {
- unsigned int version = replay_get_dword();
- if (version != REPLAY_VERSION) {
- fprintf(stderr, "Replay: invalid input log file version\n");
- exit(1);
- }
- /* go to the beginning */
- fseek(replay_file, HEADER_SIZE, SEEK_SET);
- replay_fetch_data_kind();
- }
-
- replay_init_events();
-}
-
-void replay_configure(QemuOpts *opts)
-{
- const char *fname;
- const char *rr;
- ReplayMode mode = REPLAY_MODE_NONE;
- Location loc;
-
- if (!opts) {
- return;
- }
-
- loc_push_none(&loc);
- qemu_opts_loc_restore(opts);
-
- rr = qemu_opt_get(opts, "rr");
- if (!rr) {
- /* Just enabling icount */
- goto out;
- } else if (!strcmp(rr, "record")) {
- mode = REPLAY_MODE_RECORD;
- } else if (!strcmp(rr, "replay")) {
- mode = REPLAY_MODE_PLAY;
- } else {
- error_report("Invalid icount rr option: %s", rr);
- exit(1);
- }
-
- fname = qemu_opt_get(opts, "rrfile");
- if (!fname) {
- error_report("File name not specified for replay");
- exit(1);
- }
-
- replay_enable(fname, mode);
-
-out:
- loc_pop(&loc);
-}
-
-void replay_start(void)
-{
- if (replay_mode == REPLAY_MODE_NONE) {
- return;
- }
-
- if (replay_blockers) {
- error_reportf_err(replay_blockers->data, "Record/replay: ");
- exit(1);
- }
- if (!use_icount) {
- error_report("Please enable icount to use record/replay");
- exit(1);
- }
-
- /* Timer for snapshotting will be set up here. */
-
- replay_enable_events();
-}
-
-void replay_finish(void)
-{
- if (replay_mode == REPLAY_MODE_NONE) {
- return;
- }
-
- replay_save_instructions();
-
- /* finalize the file */
- if (replay_file) {
- if (replay_mode == REPLAY_MODE_RECORD) {
- /* write end event */
- replay_put_event(EVENT_END);
-
- /* write header */
- fseek(replay_file, 0, SEEK_SET);
- replay_put_dword(REPLAY_VERSION);
- }
-
- fclose(replay_file);
- replay_file = NULL;
- }
- if (replay_filename) {
- g_free(replay_filename);
- replay_filename = NULL;
- }
-
- replay_finish_events();
- replay_mutex_destroy();
-}
-
-void replay_add_blocker(Error *reason)
-{
- replay_blockers = g_slist_prepend(replay_blockers, reason);
-}