qemu/hw/core/register-dep.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-dep.h"
  16#include "qemu/log.h"
  17
  18static inline void register_write_log(DepRegisterInfo *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(DepRegisterInfo *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(DepRegisterInfo *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 dep_register_write(DepRegisterInfo *reg, uint64_t val, uint64_t we)
  68{
  69    uint64_t old_val, new_val, test, no_w_mask;
  70    const DepRegisterAccessInfo *ac;
  71    const DepRegisterAccessError *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    dep_register_refresh_gpios(reg, old_val);
 143
 144    if (ac->post_write) {
 145        ac->post_write(reg, new_val);
 146    }
 147}
 148
 149uint64_t dep_register_read(DepRegisterInfo *reg)
 150{
 151    uint64_t ret;
 152    const DepRegisterAccessInfo *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 dep_register_reset(DepRegisterInfo *reg)
 184{
 185    assert(reg);
 186    const DepRegisterAccessInfo *ac;
 187    uint64_t val;
 188
 189    if (!reg->data || !reg->access) {
 190        return;
 191    }
 192
 193    ac = reg->access;
 194
 195    val = register_read_val(reg);
 196    if (!(val & ac->inhibit_reset)) {
 197        val = reg->access->reset;
 198    }
 199    /* FIXME: move to init */
 200    /* if there are no debug msgs and no RMW requirement, mark for fast write */
 201    reg->write_lite = reg->debug || ac->ro || ac->w1c || ac->pre_write ||
 202            ((ac->ge0 || ac->ge1) && qemu_loglevel_mask(LOG_GUEST_ERROR)) ||
 203            ((ac->ui0 || ac->ui1) && qemu_loglevel_mask(LOG_UNIMP))
 204             ? false : true;
 205    /* no debug and no clear-on-read is a fast read */
 206    reg->read_lite = reg->debug || ac->cor ? false : true;
 207
 208    register_write_val(reg, val);
 209    dep_register_refresh_gpios(reg, ~val);
 210}
 211
 212void dep_register_refresh_gpios(DepRegisterInfo *reg, uint64_t old_value)
 213{
 214    const DepRegisterAccessInfo *ac;
 215    const DepRegisterGPIOMapping *gpio;
 216
 217    ac = reg->access;
 218    for (gpio = ac->gpios; gpio && gpio->name; gpio++) {
 219        int i;
 220
 221        if (gpio->input) {
 222            continue;
 223        }
 224
 225        for (i = 0; i < gpio->num; ++i) {
 226            uint64_t gpio_value, gpio_value_old;
 227
 228            qemu_irq gpo = qdev_get_gpio_out_named(DEVICE(reg), gpio->name, i);
 229            /* FIXME: do at init time, not lazily in fast path */
 230            if (!gpio->width) {
 231                ((DepRegisterGPIOMapping *)gpio)->width = 1;
 232            }
 233            gpio_value_old = extract64(old_value,
 234                                   gpio->bit_pos + i * gpio->width,
 235                                   gpio->width) ^ gpio->polarity;
 236            gpio_value = extract64(register_read_val(reg),
 237                                   gpio->bit_pos + i * gpio->width,
 238                                   gpio->width) ^ gpio->polarity;
 239            if (!(gpio_value_old ^ gpio_value)) {
 240                continue;
 241            }
 242            if (reg->debug && gpo) {
 243                qemu_log("refreshing gpio out %s to %" PRIx64 "\n",
 244                         gpio->name, gpio_value);
 245            }
 246            qemu_set_irq(gpo, gpio_value);
 247        }
 248    }
 249}
 250
 251typedef struct DeviceNamedGPIOHandlerOpaque {
 252    DeviceState *dev;
 253    const char *name;
 254} DeviceNamedGPIOHandlerOpaque;
 255
 256static void register_gpio_handler(void *opaque, int n, int level)
 257{
 258    DeviceNamedGPIOHandlerOpaque *gho = opaque;
 259    DepRegisterInfo *reg = DEP_REGISTER(gho->dev);
 260
 261    const DepRegisterAccessInfo *ac;
 262    const DepRegisterGPIOMapping *gpio;
 263
 264    ac = reg->access;
 265    for (gpio = ac->gpios; gpio && gpio->name; gpio++) {
 266        if (gpio->input && !strcmp(gho->name, gpio->name)) {
 267            /* FIXME: do at init time, not lazily in fast path */
 268            if (!gpio->width) {
 269                ((DepRegisterGPIOMapping *)gpio)->width = 1;
 270            }
 271            register_write_val(reg, deposit64(register_read_val(reg),
 272                                              gpio->bit_pos + n * gpio->width,
 273                                              gpio->width,
 274                                              level ^ gpio->polarity));
 275            return;
 276        }
 277    }
 278
 279    abort();
 280}
 281
 282/* FIXME: Convert to proper QOM init fn */
 283
 284void dep_register_init(DepRegisterInfo *reg)
 285{
 286    assert(reg);
 287    const DepRegisterAccessInfo *ac;
 288    const DepRegisterGPIOMapping *gpio;
 289
 290    if (!reg->data || !reg->access) {
 291        return;
 292    }
 293
 294    object_initialize((void *)reg, sizeof(*reg), TYPE_DEP_REGISTER);
 295
 296    ac = reg->access;
 297    for (gpio = ac->gpios; gpio && gpio->name; gpio++) {
 298        if (!gpio->num) {
 299            ((DepRegisterGPIOMapping *)gpio)->num = 1;
 300        }
 301        if (gpio->input) {
 302            DeviceNamedGPIOHandlerOpaque gho = {
 303                .name = gpio->name,
 304                .dev = DEVICE(reg),
 305            };
 306            qemu_irq irq;
 307
 308            qdev_init_gpio_in_named(DEVICE(reg), register_gpio_handler,
 309                                    gpio->name, gpio->num);
 310            /* FIXME: Pure evil, but GPIO handlers don't know their names yet */
 311            irq = qdev_get_gpio_in_named(DEVICE(reg), gpio->name, gpio->num);
 312            irq->opaque = g_memdup(&gho, sizeof(gho));
 313        } else {
 314            /* FIXME: propably ment to be freed somewhere */
 315            qemu_irq *gpos = g_new0(qemu_irq, gpio->num);
 316
 317            qdev_init_gpio_out_named(DEVICE(reg), gpos, gpio->name, gpio->num);
 318        }
 319    }
 320}
 321
 322static inline void register_write_memory(void *opaque, hwaddr addr,
 323                                         uint64_t value, unsigned size, bool be)
 324{
 325    DepRegisterInfo *reg = opaque;
 326    uint64_t we = ~0;
 327    int shift = 0;
 328
 329    if (reg->data_size != size) {
 330        we = (size == 8) ? ~0ull : (1ull << size * 8) - 1;
 331        shift = 8 * (be ? reg->data_size - size - addr : addr);
 332    }
 333
 334    assert(size + addr <= reg->data_size);
 335    dep_register_write(reg, value << shift, we << shift);
 336}
 337
 338void dep_register_write_memory_be(void *opaque, hwaddr addr, uint64_t value,
 339                              unsigned size)
 340{
 341    register_write_memory(opaque, addr, value, size, true);
 342}
 343
 344
 345void dep_register_write_memory_le(void *opaque, hwaddr addr, uint64_t value,
 346                              unsigned size)
 347{
 348    register_write_memory(opaque, addr, value, size, false);
 349}
 350
 351static inline uint64_t register_read_memory(void *opaque, hwaddr addr,
 352                                            unsigned size, bool be)
 353{
 354    DepRegisterInfo *reg = opaque;
 355    int shift = 8 * (be ? reg->data_size - size - addr : addr);
 356
 357    return dep_register_read(reg) >> shift;
 358}
 359
 360uint64_t dep_register_read_memory_be(void *opaque, hwaddr addr, unsigned size)
 361{
 362    return register_read_memory(opaque, addr, size, true);
 363}
 364
 365uint64_t dep_register_read_memory_le(void *opaque, hwaddr addr, unsigned size)
 366{
 367    return register_read_memory(opaque, addr, size, false);
 368}
 369
 370static const TypeInfo register_info = {
 371    .name  = TYPE_DEP_REGISTER,
 372    .parent = TYPE_DEVICE,
 373};
 374
 375static void register_register_types(void)
 376{
 377    type_register_static(&register_info);
 378}
 379
 380type_init(register_register_types)
 381