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(®ister_info); 328 } 329 330 type_init(register_register_types) 331