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

slavio_intctl.c (14379B)


      1/*
      2 * QEMU Sparc SLAVIO interrupt controller emulation
      3 *
      4 * Copyright (c) 2003-2005 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 "migration/vmstate.h"
     27#include "monitor/monitor.h"
     28#include "qemu/module.h"
     29#include "hw/sysbus.h"
     30#include "hw/intc/intc.h"
     31#include "hw/irq.h"
     32#include "trace.h"
     33#include "qom/object.h"
     34
     35//#define DEBUG_IRQ_COUNT
     36
     37/*
     38 * Registers of interrupt controller in sun4m.
     39 *
     40 * This is the interrupt controller part of chip STP2001 (Slave I/O), also
     41 * produced as NCR89C105. See
     42 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
     43 *
     44 * There is a system master controller and one for each cpu.
     45 *
     46 */
     47
     48#define MAX_CPUS 16
     49#define MAX_PILS 16
     50
     51struct SLAVIO_INTCTLState;
     52
     53typedef struct SLAVIO_CPUINTCTLState {
     54    MemoryRegion iomem;
     55    struct SLAVIO_INTCTLState *master;
     56    uint32_t intreg_pending;
     57    uint32_t cpu;
     58    uint32_t irl_out;
     59} SLAVIO_CPUINTCTLState;
     60
     61#define TYPE_SLAVIO_INTCTL "slavio_intctl"
     62OBJECT_DECLARE_SIMPLE_TYPE(SLAVIO_INTCTLState, SLAVIO_INTCTL)
     63
     64struct SLAVIO_INTCTLState {
     65    SysBusDevice parent_obj;
     66
     67    MemoryRegion iomem;
     68#ifdef DEBUG_IRQ_COUNT
     69    uint64_t irq_count[32];
     70#endif
     71    qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS];
     72    SLAVIO_CPUINTCTLState slaves[MAX_CPUS];
     73    uint32_t intregm_pending;
     74    uint32_t intregm_disabled;
     75    uint32_t target_cpu;
     76};
     77
     78#define INTCTL_MAXADDR 0xf
     79#define INTCTL_SIZE (INTCTL_MAXADDR + 1)
     80#define INTCTLM_SIZE 0x14
     81#define MASTER_IRQ_MASK ~0x0fa2007f
     82#define MASTER_DISABLE 0x80000000
     83#define CPU_SOFTIRQ_MASK 0xfffe0000
     84#define CPU_IRQ_INT15_IN (1 << 15)
     85#define CPU_IRQ_TIMER_IN (1 << 14)
     86
     87static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs);
     88
     89// per-cpu interrupt controller
     90static uint64_t slavio_intctl_mem_readl(void *opaque, hwaddr addr,
     91                                        unsigned size)
     92{
     93    SLAVIO_CPUINTCTLState *s = opaque;
     94    uint32_t saddr, ret;
     95
     96    saddr = addr >> 2;
     97    switch (saddr) {
     98    case 0:
     99        ret = s->intreg_pending;
    100        break;
    101    default:
    102        ret = 0;
    103        break;
    104    }
    105    trace_slavio_intctl_mem_readl(s->cpu, addr, ret);
    106
    107    return ret;
    108}
    109
    110static void slavio_intctl_mem_writel(void *opaque, hwaddr addr,
    111                                     uint64_t val, unsigned size)
    112{
    113    SLAVIO_CPUINTCTLState *s = opaque;
    114    uint32_t saddr;
    115
    116    saddr = addr >> 2;
    117    trace_slavio_intctl_mem_writel(s->cpu, addr, val);
    118    switch (saddr) {
    119    case 1: // clear pending softints
    120        val &= CPU_SOFTIRQ_MASK | CPU_IRQ_INT15_IN;
    121        s->intreg_pending &= ~val;
    122        slavio_check_interrupts(s->master, 1);
    123        trace_slavio_intctl_mem_writel_clear(s->cpu, val, s->intreg_pending);
    124        break;
    125    case 2: // set softint
    126        val &= CPU_SOFTIRQ_MASK;
    127        s->intreg_pending |= val;
    128        slavio_check_interrupts(s->master, 1);
    129        trace_slavio_intctl_mem_writel_set(s->cpu, val, s->intreg_pending);
    130        break;
    131    default:
    132        break;
    133    }
    134}
    135
    136static const MemoryRegionOps slavio_intctl_mem_ops = {
    137    .read = slavio_intctl_mem_readl,
    138    .write = slavio_intctl_mem_writel,
    139    .endianness = DEVICE_NATIVE_ENDIAN,
    140    .valid = {
    141        .min_access_size = 4,
    142        .max_access_size = 4,
    143    },
    144};
    145
    146// master system interrupt controller
    147static uint64_t slavio_intctlm_mem_readl(void *opaque, hwaddr addr,
    148                                         unsigned size)
    149{
    150    SLAVIO_INTCTLState *s = opaque;
    151    uint32_t saddr, ret;
    152
    153    saddr = addr >> 2;
    154    switch (saddr) {
    155    case 0:
    156        ret = s->intregm_pending & ~MASTER_DISABLE;
    157        break;
    158    case 1:
    159        ret = s->intregm_disabled & MASTER_IRQ_MASK;
    160        break;
    161    case 4:
    162        ret = s->target_cpu;
    163        break;
    164    default:
    165        ret = 0;
    166        break;
    167    }
    168    trace_slavio_intctlm_mem_readl(addr, ret);
    169
    170    return ret;
    171}
    172
    173static void slavio_intctlm_mem_writel(void *opaque, hwaddr addr,
    174                                      uint64_t val, unsigned size)
    175{
    176    SLAVIO_INTCTLState *s = opaque;
    177    uint32_t saddr;
    178
    179    saddr = addr >> 2;
    180    trace_slavio_intctlm_mem_writel(addr, val);
    181    switch (saddr) {
    182    case 2: // clear (enable)
    183        // Force clear unused bits
    184        val &= MASTER_IRQ_MASK;
    185        s->intregm_disabled &= ~val;
    186        trace_slavio_intctlm_mem_writel_enable(val, s->intregm_disabled);
    187        slavio_check_interrupts(s, 1);
    188        break;
    189    case 3: // set (disable; doesn't affect pending)
    190        // Force clear unused bits
    191        val &= MASTER_IRQ_MASK;
    192        s->intregm_disabled |= val;
    193        slavio_check_interrupts(s, 1);
    194        trace_slavio_intctlm_mem_writel_disable(val, s->intregm_disabled);
    195        break;
    196    case 4:
    197        s->target_cpu = val & (MAX_CPUS - 1);
    198        slavio_check_interrupts(s, 1);
    199        trace_slavio_intctlm_mem_writel_target(s->target_cpu);
    200        break;
    201    default:
    202        break;
    203    }
    204}
    205
    206static const MemoryRegionOps slavio_intctlm_mem_ops = {
    207    .read = slavio_intctlm_mem_readl,
    208    .write = slavio_intctlm_mem_writel,
    209    .endianness = DEVICE_NATIVE_ENDIAN,
    210    .valid = {
    211        .min_access_size = 4,
    212        .max_access_size = 4,
    213    },
    214};
    215
    216static const uint32_t intbit_to_level[] = {
    217    2, 3, 5, 7, 9, 11, 13, 2,   3, 5, 7, 9, 11, 13, 12, 12,
    218    6, 13, 4, 10, 8, 9, 11, 0,  0, 0, 0, 15, 15, 15, 15, 0,
    219};
    220
    221static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
    222{
    223    uint32_t pending = s->intregm_pending, pil_pending;
    224    unsigned int i, j;
    225
    226    pending &= ~s->intregm_disabled;
    227
    228    trace_slavio_check_interrupts(pending, s->intregm_disabled);
    229    for (i = 0; i < MAX_CPUS; i++) {
    230        pil_pending = 0;
    231
    232        /* If we are the current interrupt target, get hard interrupts */
    233        if (pending && !(s->intregm_disabled & MASTER_DISABLE) &&
    234            (i == s->target_cpu)) {
    235            for (j = 0; j < 32; j++) {
    236                if ((pending & (1 << j)) && intbit_to_level[j]) {
    237                    pil_pending |= 1 << intbit_to_level[j];
    238                }
    239            }
    240        }
    241
    242        /* Calculate current pending hard interrupts for display */
    243        s->slaves[i].intreg_pending &= CPU_SOFTIRQ_MASK | CPU_IRQ_INT15_IN |
    244            CPU_IRQ_TIMER_IN;
    245        if (i == s->target_cpu) {
    246            for (j = 0; j < 32; j++) {
    247                if ((s->intregm_pending & (1U << j)) && intbit_to_level[j]) {
    248                    s->slaves[i].intreg_pending |= 1 << intbit_to_level[j];
    249                }
    250            }
    251        }
    252
    253        /* Level 15 and CPU timer interrupts are only masked when
    254           the MASTER_DISABLE bit is set */
    255        if (!(s->intregm_disabled & MASTER_DISABLE)) {
    256            pil_pending |= s->slaves[i].intreg_pending &
    257                (CPU_IRQ_INT15_IN | CPU_IRQ_TIMER_IN);
    258        }
    259
    260        /* Add soft interrupts */
    261        pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
    262
    263        if (set_irqs) {
    264            /* Since there is not really an interrupt 0 (and pil_pending
    265             * and irl_out bit zero are thus always zero) there is no need
    266             * to do anything with cpu_irqs[i][0] and it is OK not to do
    267             * the j=0 iteration of this loop.
    268             */
    269            for (j = MAX_PILS-1; j > 0; j--) {
    270                if (pil_pending & (1 << j)) {
    271                    if (!(s->slaves[i].irl_out & (1 << j))) {
    272                        qemu_irq_raise(s->cpu_irqs[i][j]);
    273                    }
    274                } else {
    275                    if (s->slaves[i].irl_out & (1 << j)) {
    276                        qemu_irq_lower(s->cpu_irqs[i][j]);
    277                    }
    278                }
    279            }
    280        }
    281        s->slaves[i].irl_out = pil_pending;
    282    }
    283}
    284
    285/*
    286 * "irq" here is the bit number in the system interrupt register to
    287 * separate serial and keyboard interrupts sharing a level.
    288 */
    289static void slavio_set_irq(void *opaque, int irq, int level)
    290{
    291    SLAVIO_INTCTLState *s = opaque;
    292    uint32_t mask = 1 << irq;
    293    uint32_t pil = intbit_to_level[irq];
    294    unsigned int i;
    295
    296    trace_slavio_set_irq(s->target_cpu, irq, pil, level);
    297    if (pil > 0) {
    298        if (level) {
    299#ifdef DEBUG_IRQ_COUNT
    300            s->irq_count[pil]++;
    301#endif
    302            s->intregm_pending |= mask;
    303            if (pil == 15) {
    304                for (i = 0; i < MAX_CPUS; i++) {
    305                    s->slaves[i].intreg_pending |= 1 << pil;
    306                }
    307            }
    308        } else {
    309            s->intregm_pending &= ~mask;
    310            if (pil == 15) {
    311                for (i = 0; i < MAX_CPUS; i++) {
    312                    s->slaves[i].intreg_pending &= ~(1 << pil);
    313                }
    314            }
    315        }
    316        slavio_check_interrupts(s, 1);
    317    }
    318}
    319
    320static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
    321{
    322    SLAVIO_INTCTLState *s = opaque;
    323
    324    trace_slavio_set_timer_irq_cpu(cpu, level);
    325
    326    if (level) {
    327        s->slaves[cpu].intreg_pending |= CPU_IRQ_TIMER_IN;
    328    } else {
    329        s->slaves[cpu].intreg_pending &= ~CPU_IRQ_TIMER_IN;
    330    }
    331
    332    slavio_check_interrupts(s, 1);
    333}
    334
    335static void slavio_set_irq_all(void *opaque, int irq, int level)
    336{
    337    if (irq < 32) {
    338        slavio_set_irq(opaque, irq, level);
    339    } else {
    340        slavio_set_timer_irq_cpu(opaque, irq - 32, level);
    341    }
    342}
    343
    344static int vmstate_intctl_post_load(void *opaque, int version_id)
    345{
    346    SLAVIO_INTCTLState *s = opaque;
    347
    348    slavio_check_interrupts(s, 0);
    349    return 0;
    350}
    351
    352static const VMStateDescription vmstate_intctl_cpu = {
    353    .name ="slavio_intctl_cpu",
    354    .version_id = 1,
    355    .minimum_version_id = 1,
    356    .fields = (VMStateField[]) {
    357        VMSTATE_UINT32(intreg_pending, SLAVIO_CPUINTCTLState),
    358        VMSTATE_END_OF_LIST()
    359    }
    360};
    361
    362static const VMStateDescription vmstate_intctl = {
    363    .name ="slavio_intctl",
    364    .version_id = 1,
    365    .minimum_version_id = 1,
    366    .post_load = vmstate_intctl_post_load,
    367    .fields = (VMStateField[]) {
    368        VMSTATE_STRUCT_ARRAY(slaves, SLAVIO_INTCTLState, MAX_CPUS, 1,
    369                             vmstate_intctl_cpu, SLAVIO_CPUINTCTLState),
    370        VMSTATE_UINT32(intregm_pending, SLAVIO_INTCTLState),
    371        VMSTATE_UINT32(intregm_disabled, SLAVIO_INTCTLState),
    372        VMSTATE_UINT32(target_cpu, SLAVIO_INTCTLState),
    373        VMSTATE_END_OF_LIST()
    374    }
    375};
    376
    377static void slavio_intctl_reset(DeviceState *d)
    378{
    379    SLAVIO_INTCTLState *s = SLAVIO_INTCTL(d);
    380    int i;
    381
    382    for (i = 0; i < MAX_CPUS; i++) {
    383        s->slaves[i].intreg_pending = 0;
    384        s->slaves[i].irl_out = 0;
    385    }
    386    s->intregm_disabled = ~MASTER_IRQ_MASK;
    387    s->intregm_pending = 0;
    388    s->target_cpu = 0;
    389    slavio_check_interrupts(s, 0);
    390}
    391
    392#ifdef DEBUG_IRQ_COUNT
    393static bool slavio_intctl_get_statistics(InterruptStatsProvider *obj,
    394                                         uint64_t **irq_counts,
    395                                         unsigned int *nb_irqs)
    396{
    397    SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj);
    398    *irq_counts = s->irq_count;
    399    *nb_irqs = ARRAY_SIZE(s->irq_count);
    400    return true;
    401}
    402#endif
    403
    404static void slavio_intctl_print_info(InterruptStatsProvider *obj, Monitor *mon)
    405{
    406    SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj);
    407    int i;
    408
    409    for (i = 0; i < MAX_CPUS; i++) {
    410        monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i,
    411                       s->slaves[i].intreg_pending);
    412    }
    413    monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n",
    414                   s->intregm_pending, s->intregm_disabled);
    415}
    416
    417static void slavio_intctl_init(Object *obj)
    418{
    419    DeviceState *dev = DEVICE(obj);
    420    SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj);
    421    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    422    unsigned int i, j;
    423    char slave_name[45];
    424
    425    qdev_init_gpio_in(dev, slavio_set_irq_all, 32 + MAX_CPUS);
    426    memory_region_init_io(&s->iomem, obj, &slavio_intctlm_mem_ops, s,
    427                          "master-interrupt-controller", INTCTLM_SIZE);
    428    sysbus_init_mmio(sbd, &s->iomem);
    429
    430    for (i = 0; i < MAX_CPUS; i++) {
    431        snprintf(slave_name, sizeof(slave_name),
    432                 "slave-interrupt-controller-%i", i);
    433        for (j = 0; j < MAX_PILS; j++) {
    434            sysbus_init_irq(sbd, &s->cpu_irqs[i][j]);
    435        }
    436        memory_region_init_io(&s->slaves[i].iomem, OBJECT(s),
    437                              &slavio_intctl_mem_ops,
    438                              &s->slaves[i], slave_name, INTCTL_SIZE);
    439        sysbus_init_mmio(sbd, &s->slaves[i].iomem);
    440        s->slaves[i].cpu = i;
    441        s->slaves[i].master = s;
    442    }
    443}
    444
    445static void slavio_intctl_class_init(ObjectClass *klass, void *data)
    446{
    447    DeviceClass *dc = DEVICE_CLASS(klass);
    448    InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass);
    449
    450    dc->reset = slavio_intctl_reset;
    451    dc->vmsd = &vmstate_intctl;
    452#ifdef DEBUG_IRQ_COUNT
    453    ic->get_statistics = slavio_intctl_get_statistics;
    454#endif
    455    ic->print_info = slavio_intctl_print_info;
    456}
    457
    458static const TypeInfo slavio_intctl_info = {
    459    .name          = TYPE_SLAVIO_INTCTL,
    460    .parent        = TYPE_SYS_BUS_DEVICE,
    461    .instance_size = sizeof(SLAVIO_INTCTLState),
    462    .instance_init = slavio_intctl_init,
    463    .class_init    = slavio_intctl_class_init,
    464    .interfaces = (InterfaceInfo[]) {
    465        { TYPE_INTERRUPT_STATS_PROVIDER },
    466        { }
    467    },
    468};
    469
    470static void slavio_intctl_register_types(void)
    471{
    472    type_register_static(&slavio_intctl_info);
    473}
    474
    475type_init(slavio_intctl_register_types)