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

stm32f2xx_adc.c (9339B)


      1/*
      2 * STM32F2XX ADC
      3 *
      4 * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
      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/sysbus.h"
     27#include "migration/vmstate.h"
     28#include "qemu/log.h"
     29#include "qemu/module.h"
     30#include "hw/adc/stm32f2xx_adc.h"
     31
     32#ifndef STM_ADC_ERR_DEBUG
     33#define STM_ADC_ERR_DEBUG 0
     34#endif
     35
     36#define DB_PRINT_L(lvl, fmt, args...) do { \
     37    if (STM_ADC_ERR_DEBUG >= lvl) { \
     38        qemu_log("%s: " fmt, __func__, ## args); \
     39    } \
     40} while (0)
     41
     42#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
     43
     44static void stm32f2xx_adc_reset(DeviceState *dev)
     45{
     46    STM32F2XXADCState *s = STM32F2XX_ADC(dev);
     47
     48    s->adc_sr = 0x00000000;
     49    s->adc_cr1 = 0x00000000;
     50    s->adc_cr2 = 0x00000000;
     51    s->adc_smpr1 = 0x00000000;
     52    s->adc_smpr2 = 0x00000000;
     53    s->adc_jofr[0] = 0x00000000;
     54    s->adc_jofr[1] = 0x00000000;
     55    s->adc_jofr[2] = 0x00000000;
     56    s->adc_jofr[3] = 0x00000000;
     57    s->adc_htr = 0x00000FFF;
     58    s->adc_ltr = 0x00000000;
     59    s->adc_sqr1 = 0x00000000;
     60    s->adc_sqr2 = 0x00000000;
     61    s->adc_sqr3 = 0x00000000;
     62    s->adc_jsqr = 0x00000000;
     63    s->adc_jdr[0] = 0x00000000;
     64    s->adc_jdr[1] = 0x00000000;
     65    s->adc_jdr[2] = 0x00000000;
     66    s->adc_jdr[3] = 0x00000000;
     67    s->adc_dr = 0x00000000;
     68}
     69
     70static uint32_t stm32f2xx_adc_generate_value(STM32F2XXADCState *s)
     71{
     72    /* Attempts to fake some ADC values */
     73    s->adc_dr = s->adc_dr + 7;
     74
     75    switch ((s->adc_cr1 & ADC_CR1_RES) >> 24) {
     76    case 0:
     77        /* 12-bit */
     78        s->adc_dr &= 0xFFF;
     79        break;
     80    case 1:
     81        /* 10-bit */
     82        s->adc_dr &= 0x3FF;
     83        break;
     84    case 2:
     85        /* 8-bit */
     86        s->adc_dr &= 0xFF;
     87        break;
     88    default:
     89        /* 6-bit */
     90        s->adc_dr &= 0x3F;
     91    }
     92
     93    if (s->adc_cr2 & ADC_CR2_ALIGN) {
     94        return (s->adc_dr << 1) & 0xFFF0;
     95    } else {
     96        return s->adc_dr;
     97    }
     98}
     99
    100static uint64_t stm32f2xx_adc_read(void *opaque, hwaddr addr,
    101                                     unsigned int size)
    102{
    103    STM32F2XXADCState *s = opaque;
    104
    105    DB_PRINT("Address: 0x%" HWADDR_PRIx "\n", addr);
    106
    107    if (addr >= ADC_COMMON_ADDRESS) {
    108        qemu_log_mask(LOG_UNIMP,
    109                      "%s: ADC Common Register Unsupported\n", __func__);
    110    }
    111
    112    switch (addr) {
    113    case ADC_SR:
    114        return s->adc_sr;
    115    case ADC_CR1:
    116        return s->adc_cr1;
    117    case ADC_CR2:
    118        return s->adc_cr2 & 0xFFFFFFF;
    119    case ADC_SMPR1:
    120        return s->adc_smpr1;
    121    case ADC_SMPR2:
    122        return s->adc_smpr2;
    123    case ADC_JOFR1:
    124    case ADC_JOFR2:
    125    case ADC_JOFR3:
    126    case ADC_JOFR4:
    127        qemu_log_mask(LOG_UNIMP, "%s: " \
    128                      "Injection ADC is not implemented, the registers are " \
    129                      "included for compatibility\n", __func__);
    130        return s->adc_jofr[(addr - ADC_JOFR1) / 4];
    131    case ADC_HTR:
    132        return s->adc_htr;
    133    case ADC_LTR:
    134        return s->adc_ltr;
    135    case ADC_SQR1:
    136        return s->adc_sqr1;
    137    case ADC_SQR2:
    138        return s->adc_sqr2;
    139    case ADC_SQR3:
    140        return s->adc_sqr3;
    141    case ADC_JSQR:
    142        qemu_log_mask(LOG_UNIMP, "%s: " \
    143                      "Injection ADC is not implemented, the registers are " \
    144                      "included for compatibility\n", __func__);
    145        return s->adc_jsqr;
    146    case ADC_JDR1:
    147    case ADC_JDR2:
    148    case ADC_JDR3:
    149    case ADC_JDR4:
    150        qemu_log_mask(LOG_UNIMP, "%s: " \
    151                      "Injection ADC is not implemented, the registers are " \
    152                      "included for compatibility\n", __func__);
    153        return s->adc_jdr[(addr - ADC_JDR1) / 4] -
    154               s->adc_jofr[(addr - ADC_JDR1) / 4];
    155    case ADC_DR:
    156        if ((s->adc_cr2 & ADC_CR2_ADON) && (s->adc_cr2 & ADC_CR2_SWSTART)) {
    157            s->adc_cr2 ^= ADC_CR2_SWSTART;
    158            return stm32f2xx_adc_generate_value(s);
    159        } else {
    160            return 0;
    161        }
    162    default:
    163        qemu_log_mask(LOG_GUEST_ERROR,
    164                      "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
    165    }
    166
    167    return 0;
    168}
    169
    170static void stm32f2xx_adc_write(void *opaque, hwaddr addr,
    171                       uint64_t val64, unsigned int size)
    172{
    173    STM32F2XXADCState *s = opaque;
    174    uint32_t value = (uint32_t) val64;
    175
    176    DB_PRINT("Address: 0x%" HWADDR_PRIx ", Value: 0x%x\n",
    177             addr, value);
    178
    179    if (addr >= 0x100) {
    180        qemu_log_mask(LOG_UNIMP,
    181                      "%s: ADC Common Register Unsupported\n", __func__);
    182    }
    183
    184    switch (addr) {
    185    case ADC_SR:
    186        s->adc_sr &= (value & 0x3F);
    187        break;
    188    case ADC_CR1:
    189        s->adc_cr1 = value;
    190        break;
    191    case ADC_CR2:
    192        s->adc_cr2 = value;
    193        break;
    194    case ADC_SMPR1:
    195        s->adc_smpr1 = value;
    196        break;
    197    case ADC_SMPR2:
    198        s->adc_smpr2 = value;
    199        break;
    200    case ADC_JOFR1:
    201    case ADC_JOFR2:
    202    case ADC_JOFR3:
    203    case ADC_JOFR4:
    204        s->adc_jofr[(addr - ADC_JOFR1) / 4] = (value & 0xFFF);
    205        qemu_log_mask(LOG_UNIMP, "%s: " \
    206                      "Injection ADC is not implemented, the registers are " \
    207                      "included for compatibility\n", __func__);
    208        break;
    209    case ADC_HTR:
    210        s->adc_htr = value;
    211        break;
    212    case ADC_LTR:
    213        s->adc_ltr = value;
    214        break;
    215    case ADC_SQR1:
    216        s->adc_sqr1 = value;
    217        break;
    218    case ADC_SQR2:
    219        s->adc_sqr2 = value;
    220        break;
    221    case ADC_SQR3:
    222        s->adc_sqr3 = value;
    223        break;
    224    case ADC_JSQR:
    225        s->adc_jsqr = value;
    226        qemu_log_mask(LOG_UNIMP, "%s: " \
    227                      "Injection ADC is not implemented, the registers are " \
    228                      "included for compatibility\n", __func__);
    229        break;
    230    case ADC_JDR1:
    231    case ADC_JDR2:
    232    case ADC_JDR3:
    233    case ADC_JDR4:
    234        s->adc_jdr[(addr - ADC_JDR1) / 4] = value;
    235        qemu_log_mask(LOG_UNIMP, "%s: " \
    236                      "Injection ADC is not implemented, the registers are " \
    237                      "included for compatibility\n", __func__);
    238        break;
    239    default:
    240        qemu_log_mask(LOG_GUEST_ERROR,
    241                      "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
    242    }
    243}
    244
    245static const MemoryRegionOps stm32f2xx_adc_ops = {
    246    .read = stm32f2xx_adc_read,
    247    .write = stm32f2xx_adc_write,
    248    .endianness = DEVICE_NATIVE_ENDIAN,
    249    .impl.min_access_size = 4,
    250    .impl.max_access_size = 4,
    251};
    252
    253static const VMStateDescription vmstate_stm32f2xx_adc = {
    254    .name = TYPE_STM32F2XX_ADC,
    255    .version_id = 1,
    256    .minimum_version_id = 1,
    257    .fields = (VMStateField[]) {
    258        VMSTATE_UINT32(adc_sr, STM32F2XXADCState),
    259        VMSTATE_UINT32(adc_cr1, STM32F2XXADCState),
    260        VMSTATE_UINT32(adc_cr2, STM32F2XXADCState),
    261        VMSTATE_UINT32(adc_smpr1, STM32F2XXADCState),
    262        VMSTATE_UINT32(adc_smpr2, STM32F2XXADCState),
    263        VMSTATE_UINT32_ARRAY(adc_jofr, STM32F2XXADCState, 4),
    264        VMSTATE_UINT32(adc_htr, STM32F2XXADCState),
    265        VMSTATE_UINT32(adc_ltr, STM32F2XXADCState),
    266        VMSTATE_UINT32(adc_sqr1, STM32F2XXADCState),
    267        VMSTATE_UINT32(adc_sqr2, STM32F2XXADCState),
    268        VMSTATE_UINT32(adc_sqr3, STM32F2XXADCState),
    269        VMSTATE_UINT32(adc_jsqr, STM32F2XXADCState),
    270        VMSTATE_UINT32_ARRAY(adc_jdr, STM32F2XXADCState, 4),
    271        VMSTATE_UINT32(adc_dr, STM32F2XXADCState),
    272        VMSTATE_END_OF_LIST()
    273    }
    274};
    275
    276static void stm32f2xx_adc_init(Object *obj)
    277{
    278    STM32F2XXADCState *s = STM32F2XX_ADC(obj);
    279
    280    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
    281
    282    memory_region_init_io(&s->mmio, obj, &stm32f2xx_adc_ops, s,
    283                          TYPE_STM32F2XX_ADC, 0x100);
    284    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
    285}
    286
    287static void stm32f2xx_adc_class_init(ObjectClass *klass, void *data)
    288{
    289    DeviceClass *dc = DEVICE_CLASS(klass);
    290
    291    dc->reset = stm32f2xx_adc_reset;
    292    dc->vmsd = &vmstate_stm32f2xx_adc;
    293}
    294
    295static const TypeInfo stm32f2xx_adc_info = {
    296    .name          = TYPE_STM32F2XX_ADC,
    297    .parent        = TYPE_SYS_BUS_DEVICE,
    298    .instance_size = sizeof(STM32F2XXADCState),
    299    .instance_init = stm32f2xx_adc_init,
    300    .class_init    = stm32f2xx_adc_class_init,
    301};
    302
    303static void stm32f2xx_adc_register_types(void)
    304{
    305    type_register_static(&stm32f2xx_adc_info);
    306}
    307
    308type_init(stm32f2xx_adc_register_types)