]> git.proxmox.com Git - mirror_qemu.git/blame - hw/core/register.c
hw/arm/smmuv3: Include missing 'hw/registerfields.h' header
[mirror_qemu.git] / hw / core / register.c
CommitLineData
1599121b
AF
1/*
2 * Register Definition API
3 *
4 * Copyright (c) 2016 Xilinx Inc.
5 * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18#include "qemu/osdep.h"
19#include "hw/register.h"
1599121b 20#include "qemu/log.h"
0b8fa32f 21#include "qemu/module.h"
1599121b
AF
22
23static inline void register_write_val(RegisterInfo *reg, uint64_t val)
24{
25 g_assert(reg->data);
26
27 switch (reg->data_size) {
28 case 1:
29 *(uint8_t *)reg->data = val;
30 break;
31 case 2:
32 *(uint16_t *)reg->data = val;
33 break;
34 case 4:
35 *(uint32_t *)reg->data = val;
36 break;
37 case 8:
38 *(uint64_t *)reg->data = val;
39 break;
40 default:
41 g_assert_not_reached();
42 }
43}
44
45static inline uint64_t register_read_val(RegisterInfo *reg)
46{
47 switch (reg->data_size) {
48 case 1:
49 return *(uint8_t *)reg->data;
50 case 2:
51 return *(uint16_t *)reg->data;
52 case 4:
53 return *(uint32_t *)reg->data;
54 case 8:
55 return *(uint64_t *)reg->data;
56 default:
57 g_assert_not_reached();
58 }
59 return 0; /* unreachable */
60}
61
4729b3a4
PMD
62static inline uint64_t register_enabled_mask(int data_size, unsigned size)
63{
64 if (data_size < size) {
65 size = data_size;
66 }
67
68 return MAKE_64BIT_MASK(0, size * 8);
69}
70
1599121b
AF
71void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
72 const char *prefix, bool debug)
73{
74 uint64_t old_val, new_val, test, no_w_mask;
75 const RegisterAccessInfo *ac;
76
77 assert(reg);
78
79 ac = reg->access;
80
81 if (!ac || !ac->name) {
82 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
b3d2a429 83 "(written value: 0x%" PRIx64 ")\n", prefix, val);
1599121b
AF
84 return;
85 }
86
87 old_val = reg->data ? register_read_val(reg) : ac->reset;
88
89 test = (old_val ^ val) & ac->rsvd;
90 if (test) {
91 qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit"
b3d2a429 92 "fields: 0x%" PRIx64 ")\n", prefix, test);
1599121b
AF
93 }
94
95 test = val & ac->unimp;
96 if (test) {
97 qemu_log_mask(LOG_UNIMP,
b3d2a429
XZ
98 "%s:%s writing 0x%" PRIx64 " to unimplemented bits:" \
99 " 0x%" PRIx64 "\n",
1599121b
AF
100 prefix, reg->access->name, val, ac->unimp);
101 }
102
103 /* Create the no write mask based on the read only, write to clear and
104 * reserved bit masks.
105 */
106 no_w_mask = ac->ro | ac->w1c | ac->rsvd | ~we;
107 new_val = (val & ~no_w_mask) | (old_val & no_w_mask);
108 new_val &= ~(val & ac->w1c);
109
110 if (ac->pre_write) {
111 new_val = ac->pre_write(reg, new_val);
112 }
113
114 if (debug) {
b3d2a429 115 qemu_log("%s:%s: write of value 0x%" PRIx64 "\n", prefix, ac->name,
1599121b
AF
116 new_val);
117 }
118
119 register_write_val(reg, new_val);
120
121 if (ac->post_write) {
122 ac->post_write(reg, new_val);
123 }
124}
125
126uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
127 bool debug)
128{
129 uint64_t ret;
130 const RegisterAccessInfo *ac;
131
132 assert(reg);
133
134 ac = reg->access;
135 if (!ac || !ac->name) {
136 qemu_log_mask(LOG_GUEST_ERROR, "%s: read from undefined device state\n",
137 prefix);
138 return 0;
139 }
140
141 ret = reg->data ? register_read_val(reg) : ac->reset;
142
143 register_write_val(reg, ret & ~(ac->cor & re));
144
145 /* Mask based on the read enable size */
146 ret &= re;
147
148 if (ac->post_read) {
149 ret = ac->post_read(reg, ret);
150 }
151
152 if (debug) {
b3d2a429 153 qemu_log("%s:%s: read of value 0x%" PRIx64 "\n", prefix,
1599121b
AF
154 ac->name, ret);
155 }
156
157 return ret;
158}
159
160void register_reset(RegisterInfo *reg)
161{
4e5f0fb7
AF
162 const RegisterAccessInfo *ac;
163
1599121b
AF
164 g_assert(reg);
165
166 if (!reg->data || !reg->access) {
167 return;
168 }
169
4e5f0fb7
AF
170 ac = reg->access;
171
1599121b 172 register_write_val(reg, reg->access->reset);
4e5f0fb7
AF
173
174 if (ac->post_write) {
175 ac->post_write(reg, reg->access->reset);
176 }
1599121b 177}
0b73c9bb
AF
178
179void register_write_memory(void *opaque, hwaddr addr,
180 uint64_t value, unsigned size)
181{
182 RegisterInfoArray *reg_array = opaque;
183 RegisterInfo *reg = NULL;
184 uint64_t we;
185 int i;
186
187 for (i = 0; i < reg_array->num_elements; i++) {
188 if (reg_array->r[i]->access->addr == addr) {
189 reg = reg_array->r[i];
190 break;
191 }
192 }
193
194 if (!reg) {
016b4a93 195 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \
b3d2a429 196 "at address: 0x%" PRIx64 "\n", reg_array->prefix, addr);
0b73c9bb
AF
197 return;
198 }
199
200 /* Generate appropriate write enable mask */
4729b3a4 201 we = register_enabled_mask(reg->data_size, size);
0b73c9bb
AF
202
203 register_write(reg, value, we, reg_array->prefix,
204 reg_array->debug);
205}
206
207uint64_t register_read_memory(void *opaque, hwaddr addr,
208 unsigned size)
209{
210 RegisterInfoArray *reg_array = opaque;
211 RegisterInfo *reg = NULL;
212 uint64_t read_val;
4729b3a4 213 uint64_t re;
0b73c9bb
AF
214 int i;
215
216 for (i = 0; i < reg_array->num_elements; i++) {
217 if (reg_array->r[i]->access->addr == addr) {
218 reg = reg_array->r[i];
219 break;
220 }
221 }
222
223 if (!reg) {
016b4a93 224 qemu_log_mask(LOG_GUEST_ERROR, "%s: read to unimplemented register " \
b3d2a429 225 "at address: 0x%" PRIx64 "\n", reg_array->prefix, addr);
0b73c9bb
AF
226 return 0;
227 }
228
4729b3a4
PMD
229 /* Generate appropriate read enable mask */
230 re = register_enabled_mask(reg->data_size, size);
231
232 read_val = register_read(reg, re, reg_array->prefix,
0b73c9bb
AF
233 reg_array->debug);
234
235 return extract64(read_val, 0, size * 8);
236}
49e14ddb 237
f08085f4
JA
238static RegisterInfoArray *register_init_block(DeviceState *owner,
239 const RegisterAccessInfo *rae,
240 int num, RegisterInfo *ri,
241 void *data,
242 const MemoryRegionOps *ops,
243 bool debug_enabled,
244 uint64_t memory_size,
245 size_t data_size_bits)
a7422959
PC
246{
247 const char *device_prefix = object_get_typename(OBJECT(owner));
248 RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
f08085f4 249 int data_size = data_size_bits >> 3;
a7422959
PC
250 int i;
251
252 r_array->r = g_new0(RegisterInfo *, num);
253 r_array->num_elements = num;
254 r_array->debug = debug_enabled;
255 r_array->prefix = device_prefix;
256
257 for (i = 0; i < num; i++) {
f08085f4 258 int index = rae[i].addr / data_size;
a7422959
PC
259 RegisterInfo *r = &ri[index];
260
e8a612b7
AF
261 /* Init the register, this will zero it. */
262 object_initialize((void *)r, sizeof(*r), TYPE_REGISTER);
263
264 /* Set the properties of the register */
265 r->data = data + data_size * index;
266 r->data_size = data_size;
267 r->access = &rae[i];
268 r->opaque = owner;
a7422959
PC
269
270 r_array->r[i] = r;
271 }
272
273 memory_region_init_io(&r_array->mem, OBJECT(owner), ops, r_array,
274 device_prefix, memory_size);
275
276 return r_array;
277}
278
f08085f4
JA
279RegisterInfoArray *register_init_block8(DeviceState *owner,
280 const RegisterAccessInfo *rae,
281 int num, RegisterInfo *ri,
282 uint8_t *data,
283 const MemoryRegionOps *ops,
284 bool debug_enabled,
285 uint64_t memory_size)
286{
287 return register_init_block(owner, rae, num, ri, (void *)
288 data, ops, debug_enabled, memory_size, 8);
289}
290
291RegisterInfoArray *register_init_block32(DeviceState *owner,
292 const RegisterAccessInfo *rae,
293 int num, RegisterInfo *ri,
294 uint32_t *data,
295 const MemoryRegionOps *ops,
296 bool debug_enabled,
297 uint64_t memory_size)
298{
299 return register_init_block(owner, rae, num, ri, (void *)
300 data, ops, debug_enabled, memory_size, 32);
301}
302
4d63ef20
JK
303RegisterInfoArray *register_init_block64(DeviceState *owner,
304 const RegisterAccessInfo *rae,
305 int num, RegisterInfo *ri,
306 uint64_t *data,
307 const MemoryRegionOps *ops,
308 bool debug_enabled,
309 uint64_t memory_size)
310{
311 return register_init_block(owner, rae, num, ri, (void *)
312 data, ops, debug_enabled, memory_size, 64);
313}
314
a7422959
PC
315void register_finalize_block(RegisterInfoArray *r_array)
316{
317 object_unparent(OBJECT(&r_array->mem));
318 g_free(r_array->r);
319 g_free(r_array);
320}
321
a6e3707e
TH
322static void register_class_init(ObjectClass *oc, void *data)
323{
324 DeviceClass *dc = DEVICE_CLASS(oc);
325
326 /* Reason: needs to be wired up to work */
e90f2a8c 327 dc->user_creatable = false;
a6e3707e
TH
328}
329
49e14ddb
PC
330static const TypeInfo register_info = {
331 .name = TYPE_REGISTER,
332 .parent = TYPE_DEVICE,
a6e3707e 333 .class_init = register_class_init,
e8a612b7 334 .instance_size = sizeof(RegisterInfo),
49e14ddb
PC
335};
336
337static void register_register_types(void)
338{
339 type_register_static(&register_info);
340}
341
342type_init(register_register_types)