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