xref: /openbmc/qemu/hw/core/register.c (revision b3c818a4)
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"
20 #include "qemu/log.h"
21 #include "qemu/module.h"
22 
23 static 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 
45 static 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 
62 static 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 
71 void 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 "
83                       "(written value: 0x%" PRIx64 ")\n", prefix, val);
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"
92                       "fields: 0x%" PRIx64 ")\n", prefix, test);
93     }
94 
95     test = val & ac->unimp;
96     if (test) {
97         qemu_log_mask(LOG_UNIMP,
98                       "%s:%s writing 0x%" PRIx64 " to unimplemented bits:" \
99                       " 0x%" PRIx64 "\n",
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) {
115         qemu_log("%s:%s: write of value 0x%" PRIx64 "\n", prefix, ac->name,
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 
126 uint64_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) {
153         qemu_log("%s:%s: read of value 0x%" PRIx64 "\n", prefix,
154                  ac->name, ret);
155     }
156 
157     return ret;
158 }
159 
160 void register_reset(RegisterInfo *reg)
161 {
162     const RegisterAccessInfo *ac;
163 
164     g_assert(reg);
165 
166     if (!reg->data || !reg->access) {
167         return;
168     }
169 
170     ac = reg->access;
171 
172     register_write_val(reg, reg->access->reset);
173 
174     if (ac->post_write) {
175         ac->post_write(reg, reg->access->reset);
176     }
177 }
178 
179 void 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) {
195         qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \
196                       "at address: 0x%" PRIx64 "\n", reg_array->prefix, addr);
197         return;
198     }
199 
200     /* Generate appropriate write enable mask */
201     we = register_enabled_mask(reg->data_size, size);
202 
203     register_write(reg, value, we, reg_array->prefix,
204                    reg_array->debug);
205 }
206 
207 uint64_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;
213     uint64_t re;
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) {
224         qemu_log_mask(LOG_GUEST_ERROR, "%s:  read to unimplemented register " \
225                       "at address: 0x%" PRIx64 "\n", reg_array->prefix, addr);
226         return 0;
227     }
228 
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,
233                              reg_array->debug);
234 
235     return extract64(read_val, 0, size * 8);
236 }
237 
238 static 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)
246 {
247     const char *device_prefix = object_get_typename(OBJECT(owner));
248     RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
249     int data_size = data_size_bits >> 3;
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++) {
258         int index = rae[i].addr / data_size;
259         RegisterInfo *r = &ri[index];
260 
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;
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 
279 RegisterInfoArray *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 
291 RegisterInfoArray *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 
303 void register_finalize_block(RegisterInfoArray *r_array)
304 {
305     object_unparent(OBJECT(&r_array->mem));
306     g_free(r_array->r);
307     g_free(r_array);
308 }
309 
310 static void register_class_init(ObjectClass *oc, void *data)
311 {
312     DeviceClass *dc = DEVICE_CLASS(oc);
313 
314     /* Reason: needs to be wired up to work */
315     dc->user_creatable = false;
316 }
317 
318 static const TypeInfo register_info = {
319     .name  = TYPE_REGISTER,
320     .parent = TYPE_DEVICE,
321     .class_init = register_class_init,
322     .instance_size = sizeof(RegisterInfo),
323 };
324 
325 static void register_register_types(void)
326 {
327     type_register_static(&register_info);
328 }
329 
330 type_init(register_register_types)
331