qemu/hw/core/register.c
<<
>>
Prefs
   1/*
   2 * Register Definition API
   3 *
   4 * Copyright (c) 2013 Xilinx Inc.
   5 * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
   6 *
   7 * This work is licensed under the terms of the GNU GPL, version 2.  See
   8 * the COPYING file in the top-level directory.
   9 */
  10
  11#include "qemu/osdep.h"
  12#include "hw/hw.h"
  13#include "qapi/error.h"
  14#include "qemu/error-report.h"
  15#include "hw/register.h"
  16#include "qemu/log.h"
  17
  18static inline void register_write_log(RegisterInfo *reg, int dir, uint64_t val,
  19                                      int mask, const char *msg,
  20                                      const char *reason)
  21{
  22    qemu_log_mask(mask, "%s:%s bits %#" PRIx64 " %s write of %d%s%s\n",
  23                  reg->prefix, reg->access->name, val, msg, dir,
  24                  reason ? ": " : "", reason ? reason : "");
  25}
  26
  27static inline void register_write_val(RegisterInfo *reg, uint64_t val)
  28{
  29    if (!reg->data) {
  30        return;
  31    }
  32    switch (reg->data_size) {
  33    case 1:
  34        *(uint8_t *)reg->data = val;
  35        break;
  36    case 2:
  37        *(uint16_t *)reg->data = val;
  38        break;
  39    case 4:
  40        *(uint32_t *)reg->data = val;
  41        break;
  42    case 8:
  43        *(uint64_t *)reg->data = val;
  44        break;
  45    default:
  46        abort();
  47    }
  48}
  49
  50static inline uint64_t register_read_val(RegisterInfo *reg)
  51{
  52    switch (reg->data_size) {
  53    case 1:
  54        return *(uint8_t *)reg->data;
  55    case 2:
  56        return *(uint16_t *)reg->data;
  57    case 4:
  58        return *(uint32_t *)reg->data;
  59    case 8:
  60        return *(uint64_t *)reg->data;
  61    default:
  62        abort();
  63    }
  64    return 0; /* unreachable */
  65}
  66
  67void register_write(RegisterInfo *reg, uint64_t val, uint64_t we)
  68{
  69    uint64_t old_val, new_val, test, no_w_mask;
  70    const RegisterAccessInfo *ac;
  71    const RegisterAccessError *rae;
  72
  73    assert(reg);
  74
  75    ac = reg->access;
  76    old_val = reg->data ? register_read_val(reg) : ac->reset;
  77    if (reg->write_lite && !~we) { /* fast path!! */
  78        new_val = val;
  79        goto register_write_fast;
  80    }
  81
  82    if (!ac || !ac->name) {
  83        qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
  84                      "(written value: %#" PRIx64 ")\n", reg->prefix, val);
  85        return;
  86    }
  87
  88    no_w_mask = ac->ro | ac->w1c | ~we;
  89
  90    if (reg->debug) {
  91        qemu_log("%s:%s: write of value %#" PRIx64 "\n", reg->prefix, ac->name,
  92                 val);
  93    }
  94
  95    if (qemu_loglevel_mask(LOG_GUEST_ERROR)) {
  96        test = (old_val ^ val) & ac->rsvd;
  97        if (test) {
  98            qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit"
  99                          "fields: %#" PRIx64 ")\n", reg->prefix, test);
 100        }
 101        for (rae = ac->ge1; rae && rae->mask; rae++) {
 102            test = val & rae->mask;
 103            if (test) {
 104                register_write_log(reg, 1, test, LOG_GUEST_ERROR,
 105                                   "invalid", rae->reason);
 106            }
 107        }
 108        for (rae = ac->ge0; rae && rae->mask; rae++) {
 109            test = ~val & rae->mask;
 110            if (test) {
 111                register_write_log(reg, 0, test, LOG_GUEST_ERROR,
 112                                   "invalid", rae->reason);
 113            }
 114        }
 115    }
 116
 117    if (qemu_loglevel_mask(LOG_UNIMP)) {
 118        for (rae = ac->ui1; rae && rae->mask; rae++) {
 119            test = val & rae->mask;
 120            if (test) {
 121                register_write_log(reg, 1, test, LOG_GUEST_ERROR,
 122                                   "unimplmented", rae->reason);
 123            }
 124        }
 125        for (rae = ac->ui0; rae && rae->mask; rae++) {
 126            test = ~val & rae->mask;
 127            if (test) {
 128                register_write_log(reg, 0, test, LOG_GUEST_ERROR,
 129                                   "unimplemented", rae->reason);
 130            }
 131        }
 132    }
 133
 134    new_val = (val & ~no_w_mask) | (old_val & no_w_mask);
 135    new_val &= ~(val & ac->w1c);
 136
 137    if (ac->pre_write) {
 138        new_val = ac->pre_write(reg, new_val);
 139    }
 140register_write_fast:
 141    register_write_val(reg, new_val);
 142    register_refresh_gpios(reg, old_val);
 143
 144    if (ac->post_write) {
 145        ac->post_write(reg, new_val);
 146    }
 147}
 148
 149uint64_t register_read(RegisterInfo *reg)
 150{
 151    uint64_t ret;
 152    const RegisterAccessInfo *ac;
 153
 154    assert(reg);
 155
 156    ac = reg->access;
 157    if (!ac || !ac->name) {
 158        qemu_log_mask(LOG_GUEST_ERROR, "%s: read from undefined device state\n",
 159                      reg->prefix);
 160        return 0;
 161    }
 162
 163    ret = reg->data ? register_read_val(reg) : ac->reset;
 164
 165    if (!reg->read_lite) {
 166        register_write_val(reg, ret & ~ac->cor);
 167    }
 168
 169    if (ac->post_read) {
 170        ret = ac->post_read(reg, ret);
 171    }
 172
 173    if (!reg->read_lite) {
 174        if (reg->debug) {
 175            qemu_log("%s:%s: read of value %#" PRIx64 "\n", reg->prefix,
 176                     ac->name, ret);
 177        }
 178    }
 179
 180    return ret;
 181}
 182
 183void register_reset(RegisterInfo *reg)
 184{
 185    assert(reg);
 186    const RegisterAccessInfo *ac;
 187    uint64_t val, old_val;
 188
 189    if (!reg->data || !reg->access) {
 190        return;
 191    }
 192
 193    ac = reg->access;
 194
 195    /* FIXME: Not cool */
 196    val = old_val = register_read_val(reg);
 197    if (!(val & ac->inhibit_reset)) {
 198        val = reg->access->reset;
 199    }
 200    /* FIXME: move to init */
 201    /* if there are no debug msgs and no RMW requirement, mark for fast write */
 202    reg->write_lite = reg->debug || ac->ro || ac->w1c || ac->pre_write ||
 203            ((ac->ge0 || ac->ge1) && qemu_loglevel_mask(LOG_GUEST_ERROR)) ||
 204            ((ac->ui0 || ac->ui1) && qemu_loglevel_mask(LOG_UNIMP))
 205             ? false : true;
 206    /* no debug and no clear-on-read is a fast read */
 207    reg->read_lite = reg->debug || ac->cor ? false : true;
 208
 209    register_write_val(reg, val);
 210    register_refresh_gpios(reg, old_val);
 211}
 212
 213void register_refresh_gpios(RegisterInfo *reg, uint64_t old_value)
 214{
 215    const RegisterAccessInfo *ac;
 216    const RegisterGPIOMapping *gpio;
 217
 218    ac = reg->access;
 219    for (gpio = ac->gpios; gpio && gpio->name; gpio++) {
 220        int i;
 221
 222        if (gpio->input) {
 223            continue;
 224        }
 225
 226        for (i = 0; i < gpio->num; ++i) {
 227            uint64_t gpio_value, gpio_value_old;
 228
 229            qemu_irq gpo = qdev_get_gpio_out_named(DEVICE(reg), gpio->name, i);
 230            /* FIXME: do at init time, not lazily in fast path */
 231            if (!gpio->width) {
 232                ((RegisterGPIOMapping *)gpio)->width = 1;
 233            }
 234            gpio_value_old = extract64(old_value,
 235                                   gpio->bit_pos + i * gpio->width,
 236                                   gpio->width) ^ gpio->polarity;
 237            gpio_value = extract64(register_read_val(reg),
 238                                   gpio->bit_pos + i * gpio->width,
 239                                   gpio->width) ^ gpio->polarity;
 240            if (!(gpio_value_old ^ gpio_value)) {
 241                continue;
 242            }
 243            if (reg->debug && gpo) {
 244                qemu_log("refreshing gpio out %s to %" PRIx64 "\n",
 245                         gpio->name, gpio_value);
 246            }
 247            qemu_set_irq(gpo, gpio_value);
 248        }
 249    }
 250}
 251
 252typedef struct DeviceNamedGPIOHandlerOpaque {
 253    DeviceState *dev;
 254    const char *name;
 255} DeviceNamedGPIOHandlerOpaque;
 256
 257static void register_gpio_handler(void *opaque, int n, int level)
 258{
 259    DeviceNamedGPIOHandlerOpaque *gho = opaque;
 260    RegisterInfo *reg = REGISTER(gho->dev);
 261
 262    const RegisterAccessInfo *ac;
 263    const RegisterGPIOMapping *gpio;
 264
 265    ac = reg->access;
 266    for (gpio = ac->gpios; gpio && gpio->name; gpio++) {
 267        if (gpio->input && !strcmp(gho->name, gpio->name)) {
 268            /* FIXME: do at init time, not lazily in fast path */
 269            if (!gpio->width) {
 270                ((RegisterGPIOMapping *)gpio)->width = 1;
 271            }
 272            register_write_val(reg, deposit64(register_read_val(reg),
 273                                              gpio->bit_pos + n * gpio->width,
 274                                              gpio->width,
 275                                              level ^ gpio->polarity));
 276            return;
 277        }
 278    }
 279
 280    abort();
 281}
 282
 283/* FIXME: Convert to proper QOM init fn */
 284
 285void register_init(RegisterInfo *reg)
 286{
 287    assert(reg);
 288    const RegisterAccessInfo *ac;
 289    const RegisterGPIOMapping *gpio;
 290
 291    if (!reg->data || !reg->access) {
 292        return;
 293    }
 294
 295    object_initialize((void *)reg, sizeof(*reg), TYPE_REGISTER);
 296
 297    ac = reg->access;
 298    for (gpio = ac->gpios; gpio && gpio->name; gpio++) {
 299        if (!gpio->num) {
 300            ((RegisterGPIOMapping *)gpio)->num = 1;
 301        }
 302        if (gpio->input) {
 303            DeviceNamedGPIOHandlerOpaque gho = {
 304                .name = gpio->name,
 305                .dev = DEVICE(reg),
 306            };
 307            qemu_irq irq;
 308
 309            qdev_init_gpio_in_named(DEVICE(reg), register_gpio_handler,
 310                                    gpio->name, gpio->num);
 311            /* FIXME: Pure evil, but GPIO handlers don't know their names yet */
 312            irq = qdev_get_gpio_in_named(DEVICE(reg), gpio->name, gpio->num);
 313            irq->opaque = g_memdup(&gho, sizeof(gho));
 314        } else {
 315            /* FIXME: propably ment to be freed somewhere */
 316            qemu_irq *gpos = g_new0(qemu_irq, gpio->num);
 317
 318            qdev_init_gpio_out_named(DEVICE(reg), gpos, gpio->name, gpio->num);
 319        }
 320    }
 321}
 322
 323static inline void register_write_memory(void *opaque, hwaddr addr,
 324                                         uint64_t value, unsigned size, bool be)
 325{
 326    RegisterInfo *reg = opaque;
 327    uint64_t we = ~0;
 328    int shift = 0;
 329
 330    if (reg->data_size != size) {
 331        we = (size == 8) ? ~0ull : (1ull << size * 8) - 1;
 332        shift = 8 * (be ? reg->data_size - size - addr : addr);
 333    }
 334
 335    assert(size + addr <= reg->data_size);
 336    register_write(reg, value << shift, we << shift);
 337}
 338
 339void register_write_memory_be(void *opaque, hwaddr addr, uint64_t value,
 340                              unsigned size)
 341{
 342    register_write_memory(opaque, addr, value, size, true);
 343}
 344
 345
 346void register_write_memory_le(void *opaque, hwaddr addr, uint64_t value,
 347                              unsigned size)
 348{
 349    register_write_memory(opaque, addr, value, size, false);
 350}
 351
 352static inline uint64_t register_read_memory(void *opaque, hwaddr addr,
 353                                            unsigned size, bool be)
 354{
 355    RegisterInfo *reg = opaque;
 356    int shift = 8 * (be ? reg->data_size - size - addr : addr);
 357
 358    return register_read(reg) >> shift;
 359}
 360
 361uint64_t register_read_memory_be(void *opaque, hwaddr addr, unsigned size)
 362{
 363    return register_read_memory(opaque, addr, size, true);
 364}
 365
 366uint64_t register_read_memory_le(void *opaque, hwaddr addr, unsigned size)
 367{
 368    return register_read_memory(opaque, addr, size, false);
 369}
 370
 371static const TypeInfo register_info = {
 372    .name  = TYPE_REGISTER,
 373    .parent = TYPE_DEVICE,
 374};
 375
 376static void register_register_types(void)
 377{
 378    type_register_static(&register_info);
 379}
 380
 381type_init(register_register_types)
 382