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(®ister_info); 312 } 313 314 type_init(register_register_types) 315