qemu/replay/replay-char.c
<<
>>
Prefs
   1/*
   2 * replay-char.c
   3 *
   4 * Copyright (c) 2010-2016 Institute for System Programming
   5 *                         of the Russian Academy of Sciences.
   6 *
   7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   8 * See the COPYING file in the top-level directory.
   9 *
  10 */
  11
  12#include <stdio.h>
  13#include <stdlib.h>
  14#include <string.h>
  15
  16#include "qemu/osdep.h"
  17#include "qemu/error-report.h"
  18#include "sysemu/replay.h"
  19#include "replay-internal.h"
  20#include "sysemu/sysemu.h"
  21#include "sysemu/char.h"
  22
  23/* Char drivers that generate qemu_chr_be_write events
  24   that should be saved into the log. */
  25static CharDriverState **char_drivers;
  26static int drivers_count;
  27
  28/* Char event attributes. */
  29typedef struct CharEvent {
  30    int id;
  31    uint8_t *buf;
  32    size_t len;
  33} CharEvent;
  34
  35static int find_char_driver(CharDriverState *chr)
  36{
  37    int i = 0;
  38    for ( ; i < drivers_count ; ++i) {
  39        if (char_drivers[i] == chr) {
  40            return i;
  41        }
  42    }
  43    return -1;
  44}
  45
  46void replay_register_char_driver(CharDriverState *chr)
  47{
  48    if (replay_mode == REPLAY_MODE_NONE) {
  49        return;
  50    }
  51    char_drivers = g_realloc(char_drivers,
  52                             sizeof(*char_drivers) * (drivers_count + 1));
  53    char_drivers[drivers_count++] = chr;
  54}
  55
  56void replay_chr_be_write(CharDriverState *s, uint8_t *buf, int len)
  57{
  58    CharEvent *event = g_malloc0(sizeof(CharEvent));
  59
  60    event->id = find_char_driver(s);
  61    if (event->id < 0) {
  62        fprintf(stderr, "Replay: cannot find char driver\n");
  63        exit(1);
  64    }
  65    event->buf = g_malloc(len);
  66    memcpy(event->buf, buf, len);
  67    event->len = len;
  68
  69    replay_add_event(REPLAY_ASYNC_EVENT_CHAR_READ, event, NULL, 0);
  70}
  71
  72void replay_event_char_read_run(void *opaque)
  73{
  74    CharEvent *event = (CharEvent *)opaque;
  75
  76    qemu_chr_be_write_impl(char_drivers[event->id], event->buf,
  77                           (int)event->len);
  78
  79    g_free(event->buf);
  80    g_free(event);
  81}
  82
  83void replay_event_char_read_save(void *opaque)
  84{
  85    CharEvent *event = (CharEvent *)opaque;
  86
  87    replay_put_byte(event->id);
  88    replay_put_array(event->buf, event->len);
  89}
  90
  91void *replay_event_char_read_load(void)
  92{
  93    CharEvent *event = g_malloc0(sizeof(CharEvent));
  94
  95    event->id = replay_get_byte();
  96    replay_get_array_alloc(&event->buf, &event->len);
  97
  98    return event;
  99}
 100
 101void replay_char_write_event_save(int res, int offset)
 102{
 103    replay_save_instructions();
 104    replay_mutex_lock();
 105    replay_put_event(EVENT_CHAR_WRITE);
 106    replay_put_dword(res);
 107    replay_put_dword(offset);
 108    replay_mutex_unlock();
 109}
 110
 111void replay_char_write_event_load(int *res, int *offset)
 112{
 113    replay_account_executed_instructions();
 114    replay_mutex_lock();
 115    if (replay_next_event_is(EVENT_CHAR_WRITE)) {
 116        *res = replay_get_dword();
 117        *offset = replay_get_dword();
 118        replay_finish_event();
 119        replay_mutex_unlock();
 120    } else {
 121        replay_mutex_unlock();
 122        error_report("Missing character write event in the replay log");
 123        exit(1);
 124    }
 125}
 126
 127int replay_char_read_all_load(uint8_t *buf)
 128{
 129    replay_mutex_lock();
 130    if (replay_next_event_is(EVENT_CHAR_READ_ALL)) {
 131        size_t size;
 132        int res;
 133        replay_get_array(buf, &size);
 134        replay_finish_event();
 135        replay_mutex_unlock();
 136        res = (int)size;
 137        assert(res >= 0);
 138        return res;
 139    } else if (replay_next_event_is(EVENT_CHAR_READ_ALL_ERROR)) {
 140        int res = replay_get_dword();
 141        replay_finish_event();
 142        replay_mutex_unlock();
 143        return res;
 144    } else {
 145        replay_mutex_unlock();
 146        error_report("Missing character read all event in the replay log");
 147        exit(1);
 148    }
 149}
 150
 151void replay_char_read_all_save_error(int res)
 152{
 153    assert(res < 0);
 154    replay_save_instructions();
 155    replay_mutex_lock();
 156    replay_put_event(EVENT_CHAR_READ_ALL_ERROR);
 157    replay_put_dword(res);
 158    replay_mutex_unlock();
 159}
 160
 161void replay_char_read_all_save_buf(uint8_t *buf, int offset)
 162{
 163    replay_save_instructions();
 164    replay_mutex_lock();
 165    replay_put_event(EVENT_CHAR_READ_ALL);
 166    replay_put_array(buf, offset);
 167    replay_mutex_unlock();
 168}
 169