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

or-irq.c (4392B)


      1/*
      2 * QEMU IRQ/GPIO common code.
      3 *
      4 * Copyright (c) 2016 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/irq.h"
     27#include "hw/or-irq.h"
     28#include "hw/qdev-properties.h"
     29#include "migration/vmstate.h"
     30#include "qemu/module.h"
     31
     32static void or_irq_handler(void *opaque, int n, int level)
     33{
     34    qemu_or_irq *s = OR_IRQ(opaque);
     35    int or_level = 0;
     36    int i;
     37
     38    s->levels[n] = level;
     39
     40    for (i = 0; i < s->num_lines; i++) {
     41        or_level |= s->levels[i];
     42    }
     43
     44    qemu_set_irq(s->out_irq, or_level);
     45}
     46
     47static void or_irq_reset(DeviceState *dev)
     48{
     49    qemu_or_irq *s = OR_IRQ(dev);
     50    int i;
     51
     52    for (i = 0; i < MAX_OR_LINES; i++) {
     53        s->levels[i] = false;
     54    }
     55}
     56
     57static void or_irq_realize(DeviceState *dev, Error **errp)
     58{
     59    qemu_or_irq *s = OR_IRQ(dev);
     60
     61    assert(s->num_lines <= MAX_OR_LINES);
     62
     63    qdev_init_gpio_in(dev, or_irq_handler, s->num_lines);
     64}
     65
     66static void or_irq_init(Object *obj)
     67{
     68    qemu_or_irq *s = OR_IRQ(obj);
     69
     70    qdev_init_gpio_out(DEVICE(obj), &s->out_irq, 1);
     71}
     72
     73/* The original version of this device had a fixed 16 entries in its
     74 * VMState array; devices with more inputs than this need to
     75 * migrate the extra lines via a subsection.
     76 * The subsection migrates as much of the levels[] array as is needed
     77 * (including repeating the first 16 elements), to avoid the awkwardness
     78 * of splitting it in two to meet the requirements of VMSTATE_VARRAY_UINT16.
     79 */
     80#define OLD_MAX_OR_LINES 16
     81#if MAX_OR_LINES < OLD_MAX_OR_LINES
     82#error MAX_OR_LINES must be at least 16 for migration compatibility
     83#endif
     84
     85static bool vmstate_extras_needed(void *opaque)
     86{
     87    qemu_or_irq *s = OR_IRQ(opaque);
     88
     89    return s->num_lines >= OLD_MAX_OR_LINES;
     90}
     91
     92static const VMStateDescription vmstate_or_irq_extras = {
     93    .name = "or-irq-extras",
     94    .version_id = 1,
     95    .minimum_version_id = 1,
     96    .needed = vmstate_extras_needed,
     97    .fields = (VMStateField[]) {
     98        VMSTATE_VARRAY_UINT16_UNSAFE(levels, qemu_or_irq, num_lines, 0,
     99                                     vmstate_info_bool, bool),
    100        VMSTATE_END_OF_LIST(),
    101    },
    102};
    103
    104static const VMStateDescription vmstate_or_irq = {
    105    .name = TYPE_OR_IRQ,
    106    .version_id = 1,
    107    .minimum_version_id = 1,
    108    .fields = (VMStateField[]) {
    109        VMSTATE_BOOL_SUB_ARRAY(levels, qemu_or_irq, 0, OLD_MAX_OR_LINES),
    110        VMSTATE_END_OF_LIST(),
    111    },
    112    .subsections = (const VMStateDescription*[]) {
    113        &vmstate_or_irq_extras,
    114        NULL
    115    },
    116};
    117
    118static Property or_irq_properties[] = {
    119    DEFINE_PROP_UINT16("num-lines", qemu_or_irq, num_lines, 1),
    120    DEFINE_PROP_END_OF_LIST(),
    121};
    122
    123static void or_irq_class_init(ObjectClass *klass, void *data)
    124{
    125    DeviceClass *dc = DEVICE_CLASS(klass);
    126
    127    dc->reset = or_irq_reset;
    128    device_class_set_props(dc, or_irq_properties);
    129    dc->realize = or_irq_realize;
    130    dc->vmsd = &vmstate_or_irq;
    131
    132    /* Reason: Needs to be wired up to work, e.g. see stm32f205_soc.c */
    133    dc->user_creatable = false;
    134}
    135
    136static const TypeInfo or_irq_type_info = {
    137   .name = TYPE_OR_IRQ,
    138   .parent = TYPE_DEVICE,
    139   .instance_size = sizeof(qemu_or_irq),
    140   .instance_init = or_irq_init,
    141   .class_init = or_irq_class_init,
    142};
    143
    144static void or_irq_register_types(void)
    145{
    146    type_register_static(&or_irq_type_info);
    147}
    148
    149type_init(or_irq_register_types)