cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

adb.c (8846B)


      1/*
      2 * QEMU ADB support
      3 *
      4 * Copyright (c) 2004 Fabrice Bellard
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "hw/input/adb.h"
     27#include "hw/qdev-properties.h"
     28#include "migration/vmstate.h"
     29#include "qemu/module.h"
     30#include "qemu/timer.h"
     31#include "adb-internal.h"
     32#include "trace.h"
     33
     34/* error codes */
     35#define ADB_RET_NOTPRESENT (-2)
     36
     37static const char *adb_commands[] = {
     38    "RESET", "FLUSH", "(Reserved 0x2)", "(Reserved 0x3)",
     39    "Reserved (0x4)", "(Reserved 0x5)", "(Reserved 0x6)", "(Reserved 0x7)",
     40    "LISTEN r0", "LISTEN r1", "LISTEN r2", "LISTEN r3",
     41    "TALK r0", "TALK r1", "TALK r2", "TALK r3",
     42};
     43
     44static void adb_device_reset(ADBDevice *d)
     45{
     46    qdev_reset_all(DEVICE(d));
     47}
     48
     49static int do_adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf,
     50                          int len)
     51{
     52    ADBDevice *d;
     53    ADBDeviceClass *adc;
     54    int devaddr, cmd, olen, i;
     55
     56    cmd = buf[0] & 0xf;
     57    if (cmd == ADB_BUSRESET) {
     58        for (i = 0; i < s->nb_devices; i++) {
     59            d = s->devices[i];
     60            adb_device_reset(d);
     61        }
     62        s->status = 0;
     63        return 0;
     64    }
     65
     66    s->pending = 0;
     67    for (i = 0; i < s->nb_devices; i++) {
     68        d = s->devices[i];
     69        adc = ADB_DEVICE_GET_CLASS(d);
     70
     71        if (adc->devhasdata(d)) {
     72            s->pending |= (1 << d->devaddr);
     73        }
     74    }
     75
     76    s->status = 0;
     77    devaddr = buf[0] >> 4;
     78    for (i = 0; i < s->nb_devices; i++) {
     79        d = s->devices[i];
     80        adc = ADB_DEVICE_GET_CLASS(d);
     81
     82        if (d->devaddr == devaddr) {
     83            olen = adc->devreq(d, obuf, buf, len);
     84            if (!olen) {
     85                s->status |= ADB_STATUS_BUSTIMEOUT;
     86            }
     87            return olen;
     88        }
     89    }
     90
     91    s->status |= ADB_STATUS_BUSTIMEOUT;
     92    return ADB_RET_NOTPRESENT;
     93}
     94
     95int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
     96{
     97    int ret;
     98
     99    trace_adb_bus_request(buf[0] >> 4, adb_commands[buf[0] & 0xf], len);
    100
    101    assert(s->autopoll_blocked);
    102
    103    ret = do_adb_request(s, obuf, buf, len);
    104
    105    trace_adb_bus_request_done(buf[0] >> 4, adb_commands[buf[0] & 0xf], ret);
    106    return ret;
    107}
    108
    109int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask)
    110{
    111    ADBDevice *d;
    112    int olen, i;
    113    uint8_t buf[1];
    114
    115    olen = 0;
    116    for (i = 0; i < s->nb_devices; i++) {
    117        if (s->poll_index >= s->nb_devices) {
    118            s->poll_index = 0;
    119        }
    120        d = s->devices[s->poll_index];
    121        if ((1 << d->devaddr) & poll_mask) {
    122            buf[0] = ADB_READREG | (d->devaddr << 4);
    123            olen = do_adb_request(s, obuf + 1, buf, 1);
    124            /* if there is data, we poll again the same device */
    125            if (olen > 0) {
    126                s->status |= ADB_STATUS_POLLREPLY;
    127                obuf[0] = buf[0];
    128                olen++;
    129                return olen;
    130            }
    131        }
    132        s->poll_index++;
    133    }
    134    return olen;
    135}
    136
    137void adb_set_autopoll_enabled(ADBBusState *s, bool enabled)
    138{
    139    if (s->autopoll_enabled != enabled) {
    140        s->autopoll_enabled = enabled;
    141        if (s->autopoll_enabled) {
    142            timer_mod(s->autopoll_timer,
    143                      qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
    144                      s->autopoll_rate_ms);
    145        } else {
    146            timer_del(s->autopoll_timer);
    147        }
    148    }
    149}
    150
    151void adb_set_autopoll_rate_ms(ADBBusState *s, int rate_ms)
    152{
    153    s->autopoll_rate_ms = rate_ms;
    154
    155    if (s->autopoll_enabled) {
    156        timer_mod(s->autopoll_timer,
    157                  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
    158                  s->autopoll_rate_ms);
    159    }
    160}
    161
    162void adb_set_autopoll_mask(ADBBusState *s, uint16_t mask)
    163{
    164    if (s->autopoll_mask != mask) {
    165        s->autopoll_mask = mask;
    166        if (s->autopoll_enabled && s->autopoll_mask) {
    167            timer_mod(s->autopoll_timer,
    168                      qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
    169                      s->autopoll_rate_ms);
    170        } else {
    171            timer_del(s->autopoll_timer);
    172        }
    173    }
    174}
    175
    176void adb_autopoll_block(ADBBusState *s)
    177{
    178    s->autopoll_blocked = true;
    179    trace_adb_bus_autopoll_block(s->autopoll_blocked);
    180
    181    if (s->autopoll_enabled) {
    182        timer_del(s->autopoll_timer);
    183    }
    184}
    185
    186void adb_autopoll_unblock(ADBBusState *s)
    187{
    188    s->autopoll_blocked = false;
    189    trace_adb_bus_autopoll_block(s->autopoll_blocked);
    190
    191    if (s->autopoll_enabled) {
    192        timer_mod(s->autopoll_timer,
    193                  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
    194                  s->autopoll_rate_ms);
    195    }
    196}
    197
    198static void adb_autopoll(void *opaque)
    199{
    200    ADBBusState *s = opaque;
    201
    202    if (!s->autopoll_blocked) {
    203        trace_adb_bus_autopoll_cb(s->autopoll_mask);
    204        s->autopoll_cb(s->autopoll_cb_opaque);
    205        trace_adb_bus_autopoll_cb_done(s->autopoll_mask);
    206    }
    207
    208    timer_mod(s->autopoll_timer,
    209              qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
    210              s->autopoll_rate_ms);
    211}
    212
    213void adb_register_autopoll_callback(ADBBusState *s, void (*cb)(void *opaque),
    214                                    void *opaque)
    215{
    216    s->autopoll_cb = cb;
    217    s->autopoll_cb_opaque = opaque;
    218}
    219
    220static const VMStateDescription vmstate_adb_bus = {
    221    .name = "adb_bus",
    222    .version_id = 0,
    223    .minimum_version_id = 0,
    224    .fields = (VMStateField[]) {
    225        VMSTATE_TIMER_PTR(autopoll_timer, ADBBusState),
    226        VMSTATE_BOOL(autopoll_enabled, ADBBusState),
    227        VMSTATE_UINT8(autopoll_rate_ms, ADBBusState),
    228        VMSTATE_UINT16(autopoll_mask, ADBBusState),
    229        VMSTATE_BOOL(autopoll_blocked, ADBBusState),
    230        VMSTATE_END_OF_LIST()
    231    }
    232};
    233
    234static void adb_bus_reset(BusState *qbus)
    235{
    236    ADBBusState *adb_bus = ADB_BUS(qbus);
    237
    238    adb_bus->autopoll_enabled = false;
    239    adb_bus->autopoll_mask = 0xffff;
    240    adb_bus->autopoll_rate_ms = 20;
    241}
    242
    243static void adb_bus_realize(BusState *qbus, Error **errp)
    244{
    245    ADBBusState *adb_bus = ADB_BUS(qbus);
    246
    247    adb_bus->autopoll_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, adb_autopoll,
    248                                           adb_bus);
    249
    250    vmstate_register(NULL, -1, &vmstate_adb_bus, adb_bus);
    251}
    252
    253static void adb_bus_unrealize(BusState *qbus)
    254{
    255    ADBBusState *adb_bus = ADB_BUS(qbus);
    256
    257    timer_del(adb_bus->autopoll_timer);
    258
    259    vmstate_unregister(NULL, &vmstate_adb_bus, adb_bus);
    260}
    261
    262static void adb_bus_class_init(ObjectClass *klass, void *data)
    263{
    264    BusClass *k = BUS_CLASS(klass);
    265
    266    k->realize = adb_bus_realize;
    267    k->unrealize = adb_bus_unrealize;
    268    k->reset = adb_bus_reset;
    269}
    270
    271static const TypeInfo adb_bus_type_info = {
    272    .name = TYPE_ADB_BUS,
    273    .parent = TYPE_BUS,
    274    .instance_size = sizeof(ADBBusState),
    275    .class_init = adb_bus_class_init,
    276};
    277
    278const VMStateDescription vmstate_adb_device = {
    279    .name = "adb_device",
    280    .version_id = 0,
    281    .minimum_version_id = 0,
    282    .fields = (VMStateField[]) {
    283        VMSTATE_INT32(devaddr, ADBDevice),
    284        VMSTATE_INT32(handler, ADBDevice),
    285        VMSTATE_END_OF_LIST()
    286    }
    287};
    288
    289static void adb_device_realizefn(DeviceState *dev, Error **errp)
    290{
    291    ADBDevice *d = ADB_DEVICE(dev);
    292    ADBBusState *bus = ADB_BUS(qdev_get_parent_bus(dev));
    293
    294    if (bus->nb_devices >= MAX_ADB_DEVICES) {
    295        return;
    296    }
    297
    298    bus->devices[bus->nb_devices++] = d;
    299}
    300
    301static void adb_device_class_init(ObjectClass *oc, void *data)
    302{
    303    DeviceClass *dc = DEVICE_CLASS(oc);
    304
    305    dc->realize = adb_device_realizefn;
    306    dc->bus_type = TYPE_ADB_BUS;
    307}
    308
    309static const TypeInfo adb_device_type_info = {
    310    .name = TYPE_ADB_DEVICE,
    311    .parent = TYPE_DEVICE,
    312    .class_size = sizeof(ADBDeviceClass),
    313    .instance_size = sizeof(ADBDevice),
    314    .abstract = true,
    315    .class_init = adb_device_class_init,
    316};
    317
    318static void adb_register_types(void)
    319{
    320    type_register_static(&adb_bus_type_info);
    321    type_register_static(&adb_device_type_info);
    322}
    323
    324type_init(adb_register_types)