qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

register.c (9920B)


      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 RegisterInfoArray *register_init_block64(DeviceState *owner,
    304                                          const RegisterAccessInfo *rae,
    305                                          int num, RegisterInfo *ri,
    306                                          uint64_t *data,
    307                                          const MemoryRegionOps *ops,
    308                                          bool debug_enabled,
    309                                          uint64_t memory_size)
    310 {
    311     return register_init_block(owner, rae, num, ri, (void *)
    312                                data, ops, debug_enabled, memory_size, 64);
    313 }
    314 
    315 void register_finalize_block(RegisterInfoArray *r_array)
    316 {
    317     object_unparent(OBJECT(&r_array->mem));
    318     g_free(r_array->r);
    319     g_free(r_array);
    320 }
    321 
    322 static void register_class_init(ObjectClass *oc, void *data)
    323 {
    324     DeviceClass *dc = DEVICE_CLASS(oc);
    325 
    326     /* Reason: needs to be wired up to work */
    327     dc->user_creatable = false;
    328 }
    329 
    330 static const TypeInfo register_info = {
    331     .name  = TYPE_REGISTER,
    332     .parent = TYPE_DEVICE,
    333     .class_init = register_class_init,
    334     .instance_size = sizeof(RegisterInfo),
    335 };
    336 
    337 static void register_register_types(void)
    338 {
    339     type_register_static(&register_info);
    340 }
    341 
    342 type_init(register_register_types)