1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "qemu/osdep.h"
19#include "hw/register.h"
20#include "hw/qdev.h"
21#include "qemu/log.h"
22#include "qemu/module.h"
23
24static inline void register_write_val(RegisterInfo *reg, uint64_t val)
25{
26 g_assert(reg->data);
27
28 switch (reg->data_size) {
29 case 1:
30 *(uint8_t *)reg->data = val;
31 break;
32 case 2:
33 *(uint16_t *)reg->data = val;
34 break;
35 case 4:
36 *(uint32_t *)reg->data = val;
37 break;
38 case 8:
39 *(uint64_t *)reg->data = val;
40 break;
41 default:
42 g_assert_not_reached();
43 }
44}
45
46static inline uint64_t register_read_val(RegisterInfo *reg)
47{
48 switch (reg->data_size) {
49 case 1:
50 return *(uint8_t *)reg->data;
51 case 2:
52 return *(uint16_t *)reg->data;
53 case 4:
54 return *(uint32_t *)reg->data;
55 case 8:
56 return *(uint64_t *)reg->data;
57 default:
58 g_assert_not_reached();
59 }
60 return 0;
61}
62
63static inline uint64_t register_enabled_mask(int data_size, unsigned size)
64{
65 if (data_size < size) {
66 size = data_size;
67 }
68
69 return MAKE_64BIT_MASK(0, size * 8);
70}
71
72void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
73 const char *prefix, bool debug)
74{
75 uint64_t old_val, new_val, test, no_w_mask;
76 const RegisterAccessInfo *ac;
77
78 assert(reg);
79
80 ac = reg->access;
81
82 if (!ac || !ac->name) {
83 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
84 "(written value: %#" PRIx64 ")\n", prefix, val);
85 return;
86 }
87
88 old_val = reg->data ? register_read_val(reg) : ac->reset;
89
90 test = (old_val ^ val) & ac->rsvd;
91 if (test) {
92 qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit"
93 "fields: %#" PRIx64 ")\n", prefix, test);
94 }
95
96 test = val & ac->unimp;
97 if (test) {
98 qemu_log_mask(LOG_UNIMP,
99 "%s:%s writing %#" PRIx64 " to unimplemented bits:" \
100 " %#" PRIx64 "\n",
101 prefix, reg->access->name, val, ac->unimp);
102 }
103
104
105
106
107 no_w_mask = ac->ro | ac->w1c | ac->rsvd | ~we;
108 new_val = (val & ~no_w_mask) | (old_val & no_w_mask);
109 new_val &= ~(val & ac->w1c);
110
111 if (ac->pre_write) {
112 new_val = ac->pre_write(reg, new_val);
113 }
114
115 if (debug) {
116 qemu_log("%s:%s: write of value %#" PRIx64 "\n", prefix, ac->name,
117 new_val);
118 }
119
120 register_write_val(reg, new_val);
121
122 if (ac->post_write) {
123 ac->post_write(reg, new_val);
124 }
125}
126
127uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
128 bool debug)
129{
130 uint64_t ret;
131 const RegisterAccessInfo *ac;
132
133 assert(reg);
134
135 ac = reg->access;
136 if (!ac || !ac->name) {
137 qemu_log_mask(LOG_GUEST_ERROR, "%s: read from undefined device state\n",
138 prefix);
139 return 0;
140 }
141
142 ret = reg->data ? register_read_val(reg) : ac->reset;
143
144 register_write_val(reg, ret & ~(ac->cor & re));
145
146
147 ret &= re;
148
149 if (ac->post_read) {
150 ret = ac->post_read(reg, ret);
151 }
152
153 if (debug) {
154 qemu_log("%s:%s: read of value %#" PRIx64 "\n", prefix,
155 ac->name, ret);
156 }
157
158 return ret;
159}
160
161void register_reset(RegisterInfo *reg)
162{
163 const RegisterAccessInfo *ac;
164
165 g_assert(reg);
166
167 if (!reg->data || !reg->access) {
168 return;
169 }
170
171 ac = reg->access;
172
173 register_write_val(reg, reg->access->reset);
174
175 if (ac->post_write) {
176 ac->post_write(reg, reg->access->reset);
177 }
178}
179
180void register_init(RegisterInfo *reg)
181{
182 assert(reg);
183
184 if (!reg->data || !reg->access) {
185 return;
186 }
187
188 object_initialize((void *)reg, sizeof(*reg), TYPE_REGISTER);
189}
190
191void register_write_memory(void *opaque, hwaddr addr,
192 uint64_t value, unsigned size)
193{
194 RegisterInfoArray *reg_array = opaque;
195 RegisterInfo *reg = NULL;
196 uint64_t we;
197 int i;
198
199 for (i = 0; i < reg_array->num_elements; i++) {
200 if (reg_array->r[i]->access->addr == addr) {
201 reg = reg_array->r[i];
202 break;
203 }
204 }
205
206 if (!reg) {
207 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \
208 "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
209 return;
210 }
211
212
213 we = register_enabled_mask(reg->data_size, size);
214
215 register_write(reg, value, we, reg_array->prefix,
216 reg_array->debug);
217}
218
219uint64_t register_read_memory(void *opaque, hwaddr addr,
220 unsigned size)
221{
222 RegisterInfoArray *reg_array = opaque;
223 RegisterInfo *reg = NULL;
224 uint64_t read_val;
225 uint64_t re;
226 int i;
227
228 for (i = 0; i < reg_array->num_elements; i++) {
229 if (reg_array->r[i]->access->addr == addr) {
230 reg = reg_array->r[i];
231 break;
232 }
233 }
234
235 if (!reg) {
236 qemu_log_mask(LOG_GUEST_ERROR, "%s: read to unimplemented register " \
237 "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
238 return 0;
239 }
240
241
242 re = register_enabled_mask(reg->data_size, size);
243
244 read_val = register_read(reg, re, reg_array->prefix,
245 reg_array->debug);
246
247 return extract64(read_val, 0, size * 8);
248}
249
250RegisterInfoArray *register_init_block32(DeviceState *owner,
251 const RegisterAccessInfo *rae,
252 int num, RegisterInfo *ri,
253 uint32_t *data,
254 const MemoryRegionOps *ops,
255 bool debug_enabled,
256 uint64_t memory_size)
257{
258 const char *device_prefix = object_get_typename(OBJECT(owner));
259 RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
260 int i;
261
262 r_array->r = g_new0(RegisterInfo *, num);
263 r_array->num_elements = num;
264 r_array->debug = debug_enabled;
265 r_array->prefix = device_prefix;
266
267 for (i = 0; i < num; i++) {
268 int index = rae[i].addr / 4;
269 RegisterInfo *r = &ri[index];
270
271 *r = (RegisterInfo) {
272 .data = &data[index],
273 .data_size = sizeof(uint32_t),
274 .access = &rae[i],
275 .opaque = owner,
276 };
277 register_init(r);
278
279 r_array->r[i] = r;
280 }
281
282 memory_region_init_io(&r_array->mem, OBJECT(owner), ops, r_array,
283 device_prefix, memory_size);
284
285 return r_array;
286}
287
288void register_finalize_block(RegisterInfoArray *r_array)
289{
290 object_unparent(OBJECT(&r_array->mem));
291 g_free(r_array->r);
292 g_free(r_array);
293}
294
295static void register_class_init(ObjectClass *oc, void *data)
296{
297 DeviceClass *dc = DEVICE_CLASS(oc);
298
299
300 dc->user_creatable = false;
301}
302
303static const TypeInfo register_info = {
304 .name = TYPE_REGISTER,
305 .parent = TYPE_DEVICE,
306 .class_init = register_class_init,
307};
308
309static void register_register_types(void)
310{
311 type_register_static(®ister_info);
312}
313
314type_init(register_register_types)
315