vl: Table-based select_vgahw()
[qemu.git] / replay / replay-char.c
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 }