qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

replay-char.c (3854B)


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