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 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: %#" 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: %#" PRIx64 ")\n", prefix, test); 93 } 94 95 test = val & ac->unimp; 96 if (test) { 97 qemu_log_mask(LOG_UNIMP, 98 "%s:%s writing %#" PRIx64 " to unimplemented bits:" \ 99 " %#" PRIx64 "", 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 %#" 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 %#" PRIx64 "\n", prefix, 154 ac->name, ret); 155 } 156 157 return ret; 158 } 159 160 void register_reset(RegisterInfo *reg) 161 { 162 g_assert(reg); 163 164 if (!reg->data || !reg->access) { 165 return; 166 } 167 168 register_write_val(reg, reg->access->reset); 169 } 170 171 void register_init(RegisterInfo *reg) 172 { 173 assert(reg); 174 175 if (!reg->data || !reg->access) { 176 return; 177 } 178 179 object_initialize((void *)reg, sizeof(*reg), TYPE_REGISTER); 180 } 181 182 void register_write_memory(void *opaque, hwaddr addr, 183 uint64_t value, unsigned size) 184 { 185 RegisterInfoArray *reg_array = opaque; 186 RegisterInfo *reg = NULL; 187 uint64_t we; 188 int i; 189 190 for (i = 0; i < reg_array->num_elements; i++) { 191 if (reg_array->r[i]->access->addr == addr) { 192 reg = reg_array->r[i]; 193 break; 194 } 195 } 196 197 if (!reg) { 198 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \ 199 "at address: %#" PRIx64 "\n", reg_array->prefix, addr); 200 return; 201 } 202 203 /* Generate appropriate write enable mask */ 204 we = register_enabled_mask(reg->data_size, size); 205 206 register_write(reg, value, we, reg_array->prefix, 207 reg_array->debug); 208 } 209 210 uint64_t register_read_memory(void *opaque, hwaddr addr, 211 unsigned size) 212 { 213 RegisterInfoArray *reg_array = opaque; 214 RegisterInfo *reg = NULL; 215 uint64_t read_val; 216 uint64_t re; 217 int i; 218 219 for (i = 0; i < reg_array->num_elements; i++) { 220 if (reg_array->r[i]->access->addr == addr) { 221 reg = reg_array->r[i]; 222 break; 223 } 224 } 225 226 if (!reg) { 227 qemu_log_mask(LOG_GUEST_ERROR, "%s: read to unimplemented register " \ 228 "at address: %#" PRIx64 "\n", reg_array->prefix, addr); 229 return 0; 230 } 231 232 /* Generate appropriate read enable mask */ 233 re = register_enabled_mask(reg->data_size, size); 234 235 read_val = register_read(reg, re, reg_array->prefix, 236 reg_array->debug); 237 238 return extract64(read_val, 0, size * 8); 239 } 240 241 RegisterInfoArray *register_init_block32(DeviceState *owner, 242 const RegisterAccessInfo *rae, 243 int num, RegisterInfo *ri, 244 uint32_t *data, 245 const MemoryRegionOps *ops, 246 bool debug_enabled, 247 uint64_t memory_size) 248 { 249 const char *device_prefix = object_get_typename(OBJECT(owner)); 250 RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1); 251 int i; 252 253 r_array->r = g_new0(RegisterInfo *, num); 254 r_array->num_elements = num; 255 r_array->debug = debug_enabled; 256 r_array->prefix = device_prefix; 257 258 for (i = 0; i < num; i++) { 259 int index = rae[i].addr / 4; 260 RegisterInfo *r = &ri[index]; 261 262 *r = (RegisterInfo) { 263 .data = &data[index], 264 .data_size = sizeof(uint32_t), 265 .access = &rae[i], 266 .opaque = owner, 267 }; 268 register_init(r); 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 void register_finalize_block(RegisterInfoArray *r_array) 280 { 281 object_unparent(OBJECT(&r_array->mem)); 282 g_free(r_array->r); 283 g_free(r_array); 284 } 285 286 static void register_class_init(ObjectClass *oc, void *data) 287 { 288 DeviceClass *dc = DEVICE_CLASS(oc); 289 290 /* Reason: needs to be wired up to work */ 291 dc->user_creatable = false; 292 } 293 294 static const TypeInfo register_info = { 295 .name = TYPE_REGISTER, 296 .parent = TYPE_DEVICE, 297 .class_init = register_class_init, 298 }; 299 300 static void register_register_types(void) 301 { 302 type_register_static(®ister_info); 303 } 304 305 type_init(register_register_types) 306