xref: /openbmc/qemu/hw/core/register.c (revision 8e6fe6b8)
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 "hw/qdev.h"
21 #include "qemu/log.h"
22 #include "qemu/module.h"
23 
24 static 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 
46 static 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; /* unreachable */
61 }
62 
63 static 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 
72 void 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     /* Create the no write mask based on the read only, write to clear and
105      * reserved bit masks.
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 
127 uint64_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     /* Mask based on the read enable size */
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 
161 void 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 
180 void 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 
191 void 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     /* Generate appropriate write enable mask */
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 
219 uint64_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     /* Generate appropriate read enable mask */
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 
250 RegisterInfoArray *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 
288 void 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 
295 static void register_class_init(ObjectClass *oc, void *data)
296 {
297     DeviceClass *dc = DEVICE_CLASS(oc);
298 
299     /* Reason: needs to be wired up to work */
300     dc->user_creatable = false;
301 }
302 
303 static const TypeInfo register_info = {
304     .name  = TYPE_REGISTER,
305     .parent = TYPE_DEVICE,
306     .class_init = register_class_init,
307 };
308 
309 static void register_register_types(void)
310 {
311     type_register_static(&register_info);
312 }
313 
314 type_init(register_register_types)
315