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

i8259.c (4449B)


      1/*
      2 * KVM in-kernel PIC (i8259) support
      3 *
      4 * Copyright (c) 2011 Siemens AG
      5 *
      6 * Authors:
      7 *  Jan Kiszka          <jan.kiszka@siemens.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL version 2.
     10 * See the COPYING file in the top-level directory.
     11 */
     12
     13#include "qemu/osdep.h"
     14#include "hw/isa/i8259_internal.h"
     15#include "hw/intc/i8259.h"
     16#include "qemu/module.h"
     17#include "hw/i386/apic_internal.h"
     18#include "hw/irq.h"
     19#include "sysemu/kvm.h"
     20#include "qom/object.h"
     21
     22#define TYPE_KVM_I8259 "kvm-i8259"
     23typedef struct KVMPICClass KVMPICClass;
     24DECLARE_CLASS_CHECKERS(KVMPICClass, KVM_PIC,
     25                       TYPE_KVM_I8259)
     26
     27/**
     28 * KVMPICClass:
     29 * @parent_realize: The parent's realizefn.
     30 */
     31struct KVMPICClass {
     32    PICCommonClass parent_class;
     33
     34    DeviceRealize parent_realize;
     35};
     36
     37static void kvm_pic_get(PICCommonState *s)
     38{
     39    struct kvm_irqchip chip;
     40    struct kvm_pic_state *kpic;
     41    int ret;
     42
     43    chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE;
     44    ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip);
     45    if (ret < 0) {
     46        fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(-ret));
     47        abort();
     48    }
     49
     50    kpic = &chip.chip.pic;
     51
     52    s->last_irr = kpic->last_irr;
     53    s->irr = kpic->irr;
     54    s->imr = kpic->imr;
     55    s->isr = kpic->isr;
     56    s->priority_add = kpic->priority_add;
     57    s->irq_base = kpic->irq_base;
     58    s->read_reg_select = kpic->read_reg_select;
     59    s->poll = kpic->poll;
     60    s->special_mask = kpic->special_mask;
     61    s->init_state = kpic->init_state;
     62    s->auto_eoi = kpic->auto_eoi;
     63    s->rotate_on_auto_eoi = kpic->rotate_on_auto_eoi;
     64    s->special_fully_nested_mode = kpic->special_fully_nested_mode;
     65    s->init4 = kpic->init4;
     66    s->elcr = kpic->elcr;
     67    s->elcr_mask = kpic->elcr_mask;
     68}
     69
     70static void kvm_pic_put(PICCommonState *s)
     71{
     72    struct kvm_irqchip chip;
     73    struct kvm_pic_state *kpic;
     74    int ret;
     75
     76    chip.chip_id = s->master ? KVM_IRQCHIP_PIC_MASTER : KVM_IRQCHIP_PIC_SLAVE;
     77
     78    kpic = &chip.chip.pic;
     79
     80    kpic->last_irr = s->last_irr;
     81    kpic->irr = s->irr;
     82    kpic->imr = s->imr;
     83    kpic->isr = s->isr;
     84    kpic->priority_add = s->priority_add;
     85    kpic->irq_base = s->irq_base;
     86    kpic->read_reg_select = s->read_reg_select;
     87    kpic->poll = s->poll;
     88    kpic->special_mask = s->special_mask;
     89    kpic->init_state = s->init_state;
     90    kpic->auto_eoi = s->auto_eoi;
     91    kpic->rotate_on_auto_eoi = s->rotate_on_auto_eoi;
     92    kpic->special_fully_nested_mode = s->special_fully_nested_mode;
     93    kpic->init4 = s->init4;
     94    kpic->elcr = s->elcr;
     95    kpic->elcr_mask = s->elcr_mask;
     96
     97    ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip);
     98    if (ret < 0) {
     99        fprintf(stderr, "KVM_SET_IRQCHIP failed: %s\n", strerror(-ret));
    100        abort();
    101    }
    102}
    103
    104static void kvm_pic_reset(DeviceState *dev)
    105{
    106    PICCommonState *s = PIC_COMMON(dev);
    107
    108    s->elcr = 0;
    109    pic_reset_common(s);
    110
    111    kvm_pic_put(s);
    112}
    113
    114static void kvm_pic_set_irq(void *opaque, int irq, int level)
    115{
    116    int delivered;
    117
    118    pic_stat_update_irq(irq, level);
    119    delivered = kvm_set_irq(kvm_state, irq, level);
    120    apic_report_irq_delivered(delivered);
    121}
    122
    123static void kvm_pic_realize(DeviceState *dev, Error **errp)
    124{
    125    PICCommonState *s = PIC_COMMON(dev);
    126    KVMPICClass *kpc = KVM_PIC_GET_CLASS(dev);
    127
    128    memory_region_init_io(&s->base_io, OBJECT(dev), NULL, NULL, "kvm-pic", 2);
    129    memory_region_init_io(&s->elcr_io, OBJECT(dev), NULL, NULL, "kvm-elcr", 1);
    130
    131    kpc->parent_realize(dev, errp);
    132}
    133
    134qemu_irq *kvm_i8259_init(ISABus *bus)
    135{
    136    i8259_init_chip(TYPE_KVM_I8259, bus, true);
    137    i8259_init_chip(TYPE_KVM_I8259, bus, false);
    138
    139    return qemu_allocate_irqs(kvm_pic_set_irq, NULL, ISA_NUM_IRQS);
    140}
    141
    142static void kvm_i8259_class_init(ObjectClass *klass, void *data)
    143{
    144    KVMPICClass *kpc = KVM_PIC_CLASS(klass);
    145    PICCommonClass *k = PIC_COMMON_CLASS(klass);
    146    DeviceClass *dc = DEVICE_CLASS(klass);
    147
    148    dc->reset     = kvm_pic_reset;
    149    device_class_set_parent_realize(dc, kvm_pic_realize, &kpc->parent_realize);
    150    k->pre_save   = kvm_pic_get;
    151    k->post_load  = kvm_pic_put;
    152}
    153
    154static const TypeInfo kvm_i8259_info = {
    155    .name = TYPE_KVM_I8259,
    156    .parent = TYPE_PIC_COMMON,
    157    .instance_size = sizeof(PICCommonState),
    158    .class_init = kvm_i8259_class_init,
    159    .class_size = sizeof(KVMPICClass),
    160};
    161
    162static void kvm_pic_register_types(void)
    163{
    164    type_register_static(&kvm_i8259_info);
    165}
    166
    167type_init(kvm_pic_register_types)