xref: /openbmc/qemu/replay/replay-char.c (revision b917da4c)
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. */
25 static CharDriverState **char_drivers;
26 static int drivers_count;
27 
28 /* Char event attributes. */
29 typedef struct CharEvent {
30     int id;
31     uint8_t *buf;
32     size_t len;
33 } CharEvent;
34 
35 static 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 
46 void 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 
56 void 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 
72 void 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 
83 void 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 
91 void *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 
101 void 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 
111 void 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 
127 int 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 
151 void 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 
161 void 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