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

nrf51_uart.c (8685B)


      1/*
      2 * nRF51 SoC UART emulation
      3 *
      4 * See nRF51 Series Reference Manual, "29 Universal Asynchronous
      5 * Receiver/Transmitter" for hardware specifications:
      6 * http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
      7 *
      8 * Copyright (c) 2018 Julia Suvorova <jusual@mail.ru>
      9 *
     10 * This program is free software; you can redistribute it and/or modify
     11 * it under the terms of the GNU General Public License version 2 or
     12 * (at your option) any later version.
     13 */
     14
     15#include "qemu/osdep.h"
     16#include "qemu/log.h"
     17#include "qemu/module.h"
     18#include "hw/char/nrf51_uart.h"
     19#include "hw/irq.h"
     20#include "hw/qdev-properties.h"
     21#include "hw/qdev-properties-system.h"
     22#include "migration/vmstate.h"
     23#include "trace.h"
     24
     25static void nrf51_uart_update_irq(NRF51UARTState *s)
     26{
     27    bool irq = false;
     28
     29    irq |= (s->reg[R_UART_RXDRDY] &&
     30            (s->reg[R_UART_INTEN] & R_UART_INTEN_RXDRDY_MASK));
     31    irq |= (s->reg[R_UART_TXDRDY] &&
     32            (s->reg[R_UART_INTEN] & R_UART_INTEN_TXDRDY_MASK));
     33    irq |= (s->reg[R_UART_ERROR]  &&
     34            (s->reg[R_UART_INTEN] & R_UART_INTEN_ERROR_MASK));
     35    irq |= (s->reg[R_UART_RXTO]   &&
     36            (s->reg[R_UART_INTEN] & R_UART_INTEN_RXTO_MASK));
     37
     38    qemu_set_irq(s->irq, irq);
     39}
     40
     41static uint64_t uart_read(void *opaque, hwaddr addr, unsigned int size)
     42{
     43    NRF51UARTState *s = NRF51_UART(opaque);
     44    uint64_t r;
     45
     46    if (!s->enabled) {
     47        return 0;
     48    }
     49
     50    switch (addr) {
     51    case A_UART_RXD:
     52        r = s->rx_fifo[s->rx_fifo_pos];
     53        if (s->rx_started && s->rx_fifo_len) {
     54            s->rx_fifo_pos = (s->rx_fifo_pos + 1) % UART_FIFO_LENGTH;
     55            s->rx_fifo_len--;
     56            if (s->rx_fifo_len) {
     57                s->reg[R_UART_RXDRDY] = 1;
     58                nrf51_uart_update_irq(s);
     59            }
     60            qemu_chr_fe_accept_input(&s->chr);
     61        }
     62        break;
     63    case A_UART_INTENSET:
     64    case A_UART_INTENCLR:
     65    case A_UART_INTEN:
     66        r = s->reg[R_UART_INTEN];
     67        break;
     68    default:
     69        r = s->reg[addr / 4];
     70        break;
     71    }
     72
     73    trace_nrf51_uart_read(addr, r, size);
     74
     75    return r;
     76}
     77
     78static gboolean uart_transmit(void *do_not_use, GIOCondition cond, void *opaque)
     79{
     80    NRF51UARTState *s = NRF51_UART(opaque);
     81    int r;
     82    uint8_t c = s->reg[R_UART_TXD];
     83
     84    s->watch_tag = 0;
     85
     86    r = qemu_chr_fe_write(&s->chr, &c, 1);
     87    if (r <= 0) {
     88        s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
     89                                             uart_transmit, s);
     90        if (!s->watch_tag) {
     91            /* The hardware has no transmit error reporting,
     92             * so silently drop the byte
     93             */
     94            goto buffer_drained;
     95        }
     96        return FALSE;
     97    }
     98
     99buffer_drained:
    100    s->reg[R_UART_TXDRDY] = 1;
    101    s->pending_tx_byte = false;
    102    return FALSE;
    103}
    104
    105static void uart_cancel_transmit(NRF51UARTState *s)
    106{
    107    if (s->watch_tag) {
    108        g_source_remove(s->watch_tag);
    109        s->watch_tag = 0;
    110    }
    111}
    112
    113static void uart_write(void *opaque, hwaddr addr,
    114                       uint64_t value, unsigned int size)
    115{
    116    NRF51UARTState *s = NRF51_UART(opaque);
    117
    118    trace_nrf51_uart_write(addr, value, size);
    119
    120    if (!s->enabled && (addr != A_UART_ENABLE)) {
    121        return;
    122    }
    123
    124    switch (addr) {
    125    case A_UART_TXD:
    126        if (!s->pending_tx_byte && s->tx_started) {
    127            s->reg[R_UART_TXD] = value;
    128            s->pending_tx_byte = true;
    129            uart_transmit(NULL, G_IO_OUT, s);
    130        }
    131        break;
    132    case A_UART_INTEN:
    133        s->reg[R_UART_INTEN] = value;
    134        break;
    135    case A_UART_INTENSET:
    136        s->reg[R_UART_INTEN] |= value;
    137        break;
    138    case A_UART_INTENCLR:
    139        s->reg[R_UART_INTEN] &= ~value;
    140        break;
    141    case A_UART_TXDRDY ... A_UART_RXTO:
    142        s->reg[addr / 4] = value;
    143        break;
    144    case A_UART_ERRORSRC:
    145        s->reg[addr / 4] &= ~value;
    146        break;
    147    case A_UART_RXD:
    148        break;
    149    case A_UART_RXDRDY:
    150        if (value == 0) {
    151            s->reg[R_UART_RXDRDY] = 0;
    152        }
    153        break;
    154    case A_UART_STARTTX:
    155        if (value == 1) {
    156            s->tx_started = true;
    157        }
    158        break;
    159    case A_UART_STARTRX:
    160        if (value == 1) {
    161            s->rx_started = true;
    162        }
    163        break;
    164    case A_UART_ENABLE:
    165        if (value) {
    166            if (value == 4) {
    167                s->enabled = true;
    168            }
    169            break;
    170        }
    171        s->enabled = false;
    172        value = 1;
    173        /* fall through */
    174    case A_UART_SUSPEND:
    175    case A_UART_STOPTX:
    176        if (value == 1) {
    177            s->tx_started = false;
    178        }
    179        /* fall through */
    180    case A_UART_STOPRX:
    181        if (addr != A_UART_STOPTX && value == 1) {
    182            s->rx_started = false;
    183            s->reg[R_UART_RXTO] = 1;
    184        }
    185        break;
    186    default:
    187        s->reg[addr / 4] = value;
    188        break;
    189    }
    190    nrf51_uart_update_irq(s);
    191}
    192
    193static const MemoryRegionOps uart_ops = {
    194    .read =  uart_read,
    195    .write = uart_write,
    196    .endianness = DEVICE_LITTLE_ENDIAN,
    197};
    198
    199static void nrf51_uart_reset(DeviceState *dev)
    200{
    201    NRF51UARTState *s = NRF51_UART(dev);
    202
    203    s->pending_tx_byte = 0;
    204
    205    uart_cancel_transmit(s);
    206
    207    memset(s->reg, 0, sizeof(s->reg));
    208
    209    s->reg[R_UART_PSELRTS] = 0xFFFFFFFF;
    210    s->reg[R_UART_PSELTXD] = 0xFFFFFFFF;
    211    s->reg[R_UART_PSELCTS] = 0xFFFFFFFF;
    212    s->reg[R_UART_PSELRXD] = 0xFFFFFFFF;
    213    s->reg[R_UART_BAUDRATE] = 0x4000000;
    214
    215    s->rx_fifo_len = 0;
    216    s->rx_fifo_pos = 0;
    217    s->rx_started = false;
    218    s->tx_started = false;
    219    s->enabled = false;
    220}
    221
    222static void uart_receive(void *opaque, const uint8_t *buf, int size)
    223{
    224
    225    NRF51UARTState *s = NRF51_UART(opaque);
    226    int i;
    227
    228    if (size == 0 || s->rx_fifo_len >= UART_FIFO_LENGTH) {
    229        return;
    230    }
    231
    232    for (i = 0; i < size; i++) {
    233        uint32_t pos = (s->rx_fifo_pos + s->rx_fifo_len) % UART_FIFO_LENGTH;
    234        s->rx_fifo[pos] = buf[i];
    235        s->rx_fifo_len++;
    236    }
    237
    238    s->reg[R_UART_RXDRDY] = 1;
    239    nrf51_uart_update_irq(s);
    240}
    241
    242static int uart_can_receive(void *opaque)
    243{
    244    NRF51UARTState *s = NRF51_UART(opaque);
    245
    246    return s->rx_started ? (UART_FIFO_LENGTH - s->rx_fifo_len) : 0;
    247}
    248
    249static void uart_event(void *opaque, QEMUChrEvent event)
    250{
    251    NRF51UARTState *s = NRF51_UART(opaque);
    252
    253    if (event == CHR_EVENT_BREAK) {
    254        s->reg[R_UART_ERRORSRC] |= 3;
    255        s->reg[R_UART_ERROR] = 1;
    256        nrf51_uart_update_irq(s);
    257    }
    258}
    259
    260static void nrf51_uart_realize(DeviceState *dev, Error **errp)
    261{
    262    NRF51UARTState *s = NRF51_UART(dev);
    263
    264    qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
    265                             uart_event, NULL, s, NULL, true);
    266}
    267
    268static void nrf51_uart_init(Object *obj)
    269{
    270    NRF51UARTState *s = NRF51_UART(obj);
    271    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    272
    273    memory_region_init_io(&s->iomem, obj, &uart_ops, s,
    274                          "nrf51_soc.uart", UART_SIZE);
    275    sysbus_init_mmio(sbd, &s->iomem);
    276    sysbus_init_irq(sbd, &s->irq);
    277}
    278
    279static int nrf51_uart_post_load(void *opaque, int version_id)
    280{
    281    NRF51UARTState *s = NRF51_UART(opaque);
    282
    283    if (s->pending_tx_byte) {
    284        s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
    285                                             uart_transmit, s);
    286    }
    287
    288    return 0;
    289}
    290
    291static const VMStateDescription nrf51_uart_vmstate = {
    292    .name = "nrf51_soc.uart",
    293    .post_load = nrf51_uart_post_load,
    294    .fields = (VMStateField[]) {
    295        VMSTATE_UINT32_ARRAY(reg, NRF51UARTState, 0x56C),
    296        VMSTATE_UINT8_ARRAY(rx_fifo, NRF51UARTState, UART_FIFO_LENGTH),
    297        VMSTATE_UINT32(rx_fifo_pos, NRF51UARTState),
    298        VMSTATE_UINT32(rx_fifo_len, NRF51UARTState),
    299        VMSTATE_BOOL(rx_started, NRF51UARTState),
    300        VMSTATE_BOOL(tx_started, NRF51UARTState),
    301        VMSTATE_BOOL(pending_tx_byte, NRF51UARTState),
    302        VMSTATE_BOOL(enabled, NRF51UARTState),
    303        VMSTATE_END_OF_LIST()
    304    }
    305};
    306
    307static Property nrf51_uart_properties[] = {
    308    DEFINE_PROP_CHR("chardev", NRF51UARTState, chr),
    309    DEFINE_PROP_END_OF_LIST(),
    310};
    311
    312static void nrf51_uart_class_init(ObjectClass *klass, void *data)
    313{
    314    DeviceClass *dc = DEVICE_CLASS(klass);
    315
    316    dc->reset = nrf51_uart_reset;
    317    dc->realize = nrf51_uart_realize;
    318    device_class_set_props(dc, nrf51_uart_properties);
    319    dc->vmsd = &nrf51_uart_vmstate;
    320}
    321
    322static const TypeInfo nrf51_uart_info = {
    323    .name = TYPE_NRF51_UART,
    324    .parent = TYPE_SYS_BUS_DEVICE,
    325    .instance_size = sizeof(NRF51UARTState),
    326    .instance_init = nrf51_uart_init,
    327    .class_init = nrf51_uart_class_init
    328};
    329
    330static void nrf51_uart_register_types(void)
    331{
    332    type_register_static(&nrf51_uart_info);
    333}
    334
    335type_init(nrf51_uart_register_types)