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 void register_write(RegisterInfo *reg, uint64_t val, uint64_t we, 63 const char *prefix, bool debug) 64 { 65 uint64_t old_val, new_val, test, no_w_mask; 66 const RegisterAccessInfo *ac; 67 68 assert(reg); 69 70 ac = reg->access; 71 72 if (!ac || !ac->name) { 73 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state " 74 "(written value: %#" PRIx64 ")\n", prefix, val); 75 return; 76 } 77 78 old_val = reg->data ? register_read_val(reg) : ac->reset; 79 80 test = (old_val ^ val) & ac->rsvd; 81 if (test) { 82 qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit" 83 "fields: %#" PRIx64 ")\n", prefix, test); 84 } 85 86 test = val & ac->unimp; 87 if (test) { 88 qemu_log_mask(LOG_UNIMP, 89 "%s:%s writing %#" PRIx64 " to unimplemented bits:" \ 90 " %#" PRIx64 "", 91 prefix, reg->access->name, val, ac->unimp); 92 } 93 94 /* Create the no write mask based on the read only, write to clear and 95 * reserved bit masks. 96 */ 97 no_w_mask = ac->ro | ac->w1c | ac->rsvd | ~we; 98 new_val = (val & ~no_w_mask) | (old_val & no_w_mask); 99 new_val &= ~(val & ac->w1c); 100 101 if (ac->pre_write) { 102 new_val = ac->pre_write(reg, new_val); 103 } 104 105 if (debug) { 106 qemu_log("%s:%s: write of value %#" PRIx64 "\n", prefix, ac->name, 107 new_val); 108 } 109 110 register_write_val(reg, new_val); 111 112 if (ac->post_write) { 113 ac->post_write(reg, new_val); 114 } 115 } 116 117 uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix, 118 bool debug) 119 { 120 uint64_t ret; 121 const RegisterAccessInfo *ac; 122 123 assert(reg); 124 125 ac = reg->access; 126 if (!ac || !ac->name) { 127 qemu_log_mask(LOG_GUEST_ERROR, "%s: read from undefined device state\n", 128 prefix); 129 return 0; 130 } 131 132 ret = reg->data ? register_read_val(reg) : ac->reset; 133 134 register_write_val(reg, ret & ~(ac->cor & re)); 135 136 /* Mask based on the read enable size */ 137 ret &= re; 138 139 if (ac->post_read) { 140 ret = ac->post_read(reg, ret); 141 } 142 143 if (debug) { 144 qemu_log("%s:%s: read of value %#" PRIx64 "\n", prefix, 145 ac->name, ret); 146 } 147 148 return ret; 149 } 150 151 void register_reset(RegisterInfo *reg) 152 { 153 g_assert(reg); 154 155 if (!reg->data || !reg->access) { 156 return; 157 } 158 159 register_write_val(reg, reg->access->reset); 160 } 161 162 void register_init(RegisterInfo *reg) 163 { 164 assert(reg); 165 166 if (!reg->data || !reg->access) { 167 return; 168 } 169 170 object_initialize((void *)reg, sizeof(*reg), TYPE_REGISTER); 171 } 172 173 void register_write_memory(void *opaque, hwaddr addr, 174 uint64_t value, unsigned size) 175 { 176 RegisterInfoArray *reg_array = opaque; 177 RegisterInfo *reg = NULL; 178 uint64_t we; 179 int i; 180 181 for (i = 0; i < reg_array->num_elements; i++) { 182 if (reg_array->r[i]->access->addr == addr) { 183 reg = reg_array->r[i]; 184 break; 185 } 186 } 187 188 if (!reg) { 189 qemu_log_mask(LOG_GUEST_ERROR, "Write to unimplemented register at " \ 190 "address: %#" PRIx64 "\n", addr); 191 return; 192 } 193 194 /* Generate appropriate write enable mask */ 195 if (reg->data_size < size) { 196 we = MAKE_64BIT_MASK(0, reg->data_size * 8); 197 } else { 198 we = MAKE_64BIT_MASK(0, size * 8); 199 } 200 201 register_write(reg, value, we, reg_array->prefix, 202 reg_array->debug); 203 } 204 205 uint64_t register_read_memory(void *opaque, hwaddr addr, 206 unsigned size) 207 { 208 RegisterInfoArray *reg_array = opaque; 209 RegisterInfo *reg = NULL; 210 uint64_t read_val; 211 int i; 212 213 for (i = 0; i < reg_array->num_elements; i++) { 214 if (reg_array->r[i]->access->addr == addr) { 215 reg = reg_array->r[i]; 216 break; 217 } 218 } 219 220 if (!reg) { 221 qemu_log_mask(LOG_GUEST_ERROR, "Read to unimplemented register at " \ 222 "address: %#" PRIx64 "\n", addr); 223 return 0; 224 } 225 226 read_val = register_read(reg, size * 8, reg_array->prefix, 227 reg_array->debug); 228 229 return extract64(read_val, 0, size * 8); 230 } 231 232 RegisterInfoArray *register_init_block32(DeviceState *owner, 233 const RegisterAccessInfo *rae, 234 int num, RegisterInfo *ri, 235 uint32_t *data, 236 const MemoryRegionOps *ops, 237 bool debug_enabled, 238 uint64_t memory_size) 239 { 240 const char *device_prefix = object_get_typename(OBJECT(owner)); 241 RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1); 242 int i; 243 244 r_array->r = g_new0(RegisterInfo *, num); 245 r_array->num_elements = num; 246 r_array->debug = debug_enabled; 247 r_array->prefix = device_prefix; 248 249 for (i = 0; i < num; i++) { 250 int index = rae[i].addr / 4; 251 RegisterInfo *r = &ri[index]; 252 253 *r = (RegisterInfo) { 254 .data = &data[index], 255 .data_size = sizeof(uint32_t), 256 .access = &rae[i], 257 .opaque = owner, 258 }; 259 register_init(r); 260 261 r_array->r[i] = r; 262 } 263 264 memory_region_init_io(&r_array->mem, OBJECT(owner), ops, r_array, 265 device_prefix, memory_size); 266 267 return r_array; 268 } 269 270 void register_finalize_block(RegisterInfoArray *r_array) 271 { 272 object_unparent(OBJECT(&r_array->mem)); 273 g_free(r_array->r); 274 g_free(r_array); 275 } 276 277 static const TypeInfo register_info = { 278 .name = TYPE_REGISTER, 279 .parent = TYPE_DEVICE, 280 }; 281 282 static void register_register_types(void) 283 { 284 type_register_static(®ister_info); 285 } 286 287 type_init(register_register_types) 288