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

xics.c (18569B)


      1/*
      2 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
      3 *
      4 * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
      5 *
      6 * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
      7 *
      8 * Permission is hereby granted, free of charge, to any person obtaining a copy
      9 * of this software and associated documentation files (the "Software"), to deal
     10 * in the Software without restriction, including without limitation the rights
     11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     12 * copies of the Software, and to permit persons to whom the Software is
     13 * furnished to do so, subject to the following conditions:
     14 *
     15 * The above copyright notice and this permission notice shall be included in
     16 * all copies or substantial portions of the Software.
     17 *
     18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     24 * THE SOFTWARE.
     25 *
     26 */
     27
     28#include "qemu/osdep.h"
     29#include "qapi/error.h"
     30#include "trace.h"
     31#include "qemu/timer.h"
     32#include "hw/ppc/xics.h"
     33#include "hw/qdev-properties.h"
     34#include "qemu/error-report.h"
     35#include "qemu/module.h"
     36#include "qapi/visitor.h"
     37#include "migration/vmstate.h"
     38#include "monitor/monitor.h"
     39#include "hw/intc/intc.h"
     40#include "hw/irq.h"
     41#include "sysemu/kvm.h"
     42#include "sysemu/reset.h"
     43
     44void icp_pic_print_info(ICPState *icp, Monitor *mon)
     45{
     46    int cpu_index;
     47
     48    /* Skip partially initialized vCPUs. This can happen on sPAPR when vCPUs
     49     * are hot plugged or unplugged.
     50     */
     51    if (!icp) {
     52        return;
     53    }
     54
     55    cpu_index = icp->cs ? icp->cs->cpu_index : -1;
     56
     57    if (!icp->output) {
     58        return;
     59    }
     60
     61    if (kvm_irqchip_in_kernel()) {
     62        icp_synchronize_state(icp);
     63    }
     64
     65    monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n",
     66                   cpu_index, icp->xirr, icp->xirr_owner,
     67                   icp->pending_priority, icp->mfrr);
     68}
     69
     70void ics_pic_print_info(ICSState *ics, Monitor *mon)
     71{
     72    uint32_t i;
     73
     74    monitor_printf(mon, "ICS %4x..%4x %p\n",
     75                   ics->offset, ics->offset + ics->nr_irqs - 1, ics);
     76
     77    if (!ics->irqs) {
     78        return;
     79    }
     80
     81    if (kvm_irqchip_in_kernel()) {
     82        ics_synchronize_state(ics);
     83    }
     84
     85    for (i = 0; i < ics->nr_irqs; i++) {
     86        ICSIRQState *irq = ics->irqs + i;
     87
     88        if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) {
     89            continue;
     90        }
     91        monitor_printf(mon, "  %4x %s %02x %02x\n",
     92                       ics->offset + i,
     93                       (irq->flags & XICS_FLAGS_IRQ_LSI) ?
     94                       "LSI" : "MSI",
     95                       irq->priority, irq->status);
     96    }
     97}
     98
     99/*
    100 * ICP: Presentation layer
    101 */
    102
    103#define XISR_MASK  0x00ffffff
    104#define CPPR_MASK  0xff000000
    105
    106#define XISR(icp)   (((icp)->xirr) & XISR_MASK)
    107#define CPPR(icp)   (((icp)->xirr) >> 24)
    108
    109static void ics_reject(ICSState *ics, uint32_t nr);
    110static void ics_eoi(ICSState *ics, uint32_t nr);
    111
    112static void icp_check_ipi(ICPState *icp)
    113{
    114    if (XISR(icp) && (icp->pending_priority <= icp->mfrr)) {
    115        return;
    116    }
    117
    118    trace_xics_icp_check_ipi(icp->cs->cpu_index, icp->mfrr);
    119
    120    if (XISR(icp) && icp->xirr_owner) {
    121        ics_reject(icp->xirr_owner, XISR(icp));
    122    }
    123
    124    icp->xirr = (icp->xirr & ~XISR_MASK) | XICS_IPI;
    125    icp->pending_priority = icp->mfrr;
    126    icp->xirr_owner = NULL;
    127    qemu_irq_raise(icp->output);
    128}
    129
    130void icp_resend(ICPState *icp)
    131{
    132    XICSFabric *xi = icp->xics;
    133    XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(xi);
    134
    135    if (icp->mfrr < CPPR(icp)) {
    136        icp_check_ipi(icp);
    137    }
    138
    139    xic->ics_resend(xi);
    140}
    141
    142void icp_set_cppr(ICPState *icp, uint8_t cppr)
    143{
    144    uint8_t old_cppr;
    145    uint32_t old_xisr;
    146
    147    old_cppr = CPPR(icp);
    148    icp->xirr = (icp->xirr & ~CPPR_MASK) | (cppr << 24);
    149
    150    if (cppr < old_cppr) {
    151        if (XISR(icp) && (cppr <= icp->pending_priority)) {
    152            old_xisr = XISR(icp);
    153            icp->xirr &= ~XISR_MASK; /* Clear XISR */
    154            icp->pending_priority = 0xff;
    155            qemu_irq_lower(icp->output);
    156            if (icp->xirr_owner) {
    157                ics_reject(icp->xirr_owner, old_xisr);
    158                icp->xirr_owner = NULL;
    159            }
    160        }
    161    } else {
    162        if (!XISR(icp)) {
    163            icp_resend(icp);
    164        }
    165    }
    166}
    167
    168void icp_set_mfrr(ICPState *icp, uint8_t mfrr)
    169{
    170    icp->mfrr = mfrr;
    171    if (mfrr < CPPR(icp)) {
    172        icp_check_ipi(icp);
    173    }
    174}
    175
    176uint32_t icp_accept(ICPState *icp)
    177{
    178    uint32_t xirr = icp->xirr;
    179
    180    qemu_irq_lower(icp->output);
    181    icp->xirr = icp->pending_priority << 24;
    182    icp->pending_priority = 0xff;
    183    icp->xirr_owner = NULL;
    184
    185    trace_xics_icp_accept(xirr, icp->xirr);
    186
    187    return xirr;
    188}
    189
    190uint32_t icp_ipoll(ICPState *icp, uint32_t *mfrr)
    191{
    192    if (mfrr) {
    193        *mfrr = icp->mfrr;
    194    }
    195    return icp->xirr;
    196}
    197
    198void icp_eoi(ICPState *icp, uint32_t xirr)
    199{
    200    XICSFabric *xi = icp->xics;
    201    XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(xi);
    202    ICSState *ics;
    203    uint32_t irq;
    204
    205    /* Send EOI -> ICS */
    206    icp->xirr = (icp->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
    207    trace_xics_icp_eoi(icp->cs->cpu_index, xirr, icp->xirr);
    208    irq = xirr & XISR_MASK;
    209
    210    ics = xic->ics_get(xi, irq);
    211    if (ics) {
    212        ics_eoi(ics, irq);
    213    }
    214    if (!XISR(icp)) {
    215        icp_resend(icp);
    216    }
    217}
    218
    219void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
    220{
    221    ICPState *icp = xics_icp_get(ics->xics, server);
    222
    223    trace_xics_icp_irq(server, nr, priority);
    224
    225    if ((priority >= CPPR(icp))
    226        || (XISR(icp) && (icp->pending_priority <= priority))) {
    227        ics_reject(ics, nr);
    228    } else {
    229        if (XISR(icp) && icp->xirr_owner) {
    230            ics_reject(icp->xirr_owner, XISR(icp));
    231            icp->xirr_owner = NULL;
    232        }
    233        icp->xirr = (icp->xirr & ~XISR_MASK) | (nr & XISR_MASK);
    234        icp->xirr_owner = ics;
    235        icp->pending_priority = priority;
    236        trace_xics_icp_raise(icp->xirr, icp->pending_priority);
    237        qemu_irq_raise(icp->output);
    238    }
    239}
    240
    241static int icp_pre_save(void *opaque)
    242{
    243    ICPState *icp = opaque;
    244
    245    if (kvm_irqchip_in_kernel()) {
    246        icp_get_kvm_state(icp);
    247    }
    248
    249    return 0;
    250}
    251
    252static int icp_post_load(void *opaque, int version_id)
    253{
    254    ICPState *icp = opaque;
    255
    256    if (kvm_irqchip_in_kernel()) {
    257        Error *local_err = NULL;
    258        int ret;
    259
    260        ret = icp_set_kvm_state(icp, &local_err);
    261        if (ret < 0) {
    262            error_report_err(local_err);
    263            return ret;
    264        }
    265    }
    266
    267    return 0;
    268}
    269
    270static const VMStateDescription vmstate_icp_server = {
    271    .name = "icp/server",
    272    .version_id = 1,
    273    .minimum_version_id = 1,
    274    .pre_save = icp_pre_save,
    275    .post_load = icp_post_load,
    276    .fields = (VMStateField[]) {
    277        /* Sanity check */
    278        VMSTATE_UINT32(xirr, ICPState),
    279        VMSTATE_UINT8(pending_priority, ICPState),
    280        VMSTATE_UINT8(mfrr, ICPState),
    281        VMSTATE_END_OF_LIST()
    282    },
    283};
    284
    285void icp_reset(ICPState *icp)
    286{
    287    icp->xirr = 0;
    288    icp->pending_priority = 0xff;
    289    icp->mfrr = 0xff;
    290
    291    if (kvm_irqchip_in_kernel()) {
    292        Error *local_err = NULL;
    293
    294        icp_set_kvm_state(icp, &local_err);
    295        if (local_err) {
    296            error_report_err(local_err);
    297        }
    298    }
    299}
    300
    301static void icp_realize(DeviceState *dev, Error **errp)
    302{
    303    ICPState *icp = ICP(dev);
    304    CPUPPCState *env;
    305    Error *err = NULL;
    306
    307    assert(icp->xics);
    308    assert(icp->cs);
    309
    310    env = &POWERPC_CPU(icp->cs)->env;
    311    switch (PPC_INPUT(env)) {
    312    case PPC_FLAGS_INPUT_POWER7:
    313        icp->output = env->irq_inputs[POWER7_INPUT_INT];
    314        break;
    315    case PPC_FLAGS_INPUT_POWER9: /* For SPAPR xics emulation */
    316        icp->output = env->irq_inputs[POWER9_INPUT_INT];
    317        break;
    318
    319    case PPC_FLAGS_INPUT_970:
    320        icp->output = env->irq_inputs[PPC970_INPUT_INT];
    321        break;
    322
    323    default:
    324        error_setg(errp, "XICS interrupt controller does not support this CPU bus model");
    325        return;
    326    }
    327
    328    /* Connect the presenter to the VCPU (required for CPU hotplug) */
    329    if (kvm_irqchip_in_kernel()) {
    330        icp_kvm_realize(dev, &err);
    331        if (err) {
    332            error_propagate(errp, err);
    333            return;
    334        }
    335    }
    336
    337    vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp);
    338}
    339
    340static void icp_unrealize(DeviceState *dev)
    341{
    342    ICPState *icp = ICP(dev);
    343
    344    vmstate_unregister(NULL, &vmstate_icp_server, icp);
    345}
    346
    347static Property icp_properties[] = {
    348    DEFINE_PROP_LINK(ICP_PROP_XICS, ICPState, xics, TYPE_XICS_FABRIC,
    349                     XICSFabric *),
    350    DEFINE_PROP_LINK(ICP_PROP_CPU, ICPState, cs, TYPE_CPU, CPUState *),
    351    DEFINE_PROP_END_OF_LIST(),
    352};
    353
    354static void icp_class_init(ObjectClass *klass, void *data)
    355{
    356    DeviceClass *dc = DEVICE_CLASS(klass);
    357
    358    dc->realize = icp_realize;
    359    dc->unrealize = icp_unrealize;
    360    device_class_set_props(dc, icp_properties);
    361    /*
    362     * Reason: part of XICS interrupt controller, needs to be wired up
    363     * by icp_create().
    364     */
    365    dc->user_creatable = false;
    366}
    367
    368static const TypeInfo icp_info = {
    369    .name = TYPE_ICP,
    370    .parent = TYPE_DEVICE,
    371    .instance_size = sizeof(ICPState),
    372    .class_init = icp_class_init,
    373    .class_size = sizeof(ICPStateClass),
    374};
    375
    376Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp)
    377{
    378    Object *obj;
    379
    380    obj = object_new(type);
    381    object_property_add_child(cpu, type, obj);
    382    object_unref(obj);
    383    object_property_set_link(obj, ICP_PROP_XICS, OBJECT(xi), &error_abort);
    384    object_property_set_link(obj, ICP_PROP_CPU, cpu, &error_abort);
    385    if (!qdev_realize(DEVICE(obj), NULL, errp)) {
    386        object_unparent(obj);
    387        obj = NULL;
    388    }
    389
    390    return obj;
    391}
    392
    393void icp_destroy(ICPState *icp)
    394{
    395    Object *obj = OBJECT(icp);
    396
    397    object_unparent(obj);
    398}
    399
    400/*
    401 * ICS: Source layer
    402 */
    403static void ics_resend_msi(ICSState *ics, int srcno)
    404{
    405    ICSIRQState *irq = ics->irqs + srcno;
    406
    407    /* FIXME: filter by server#? */
    408    if (irq->status & XICS_STATUS_REJECTED) {
    409        irq->status &= ~XICS_STATUS_REJECTED;
    410        if (irq->priority != 0xff) {
    411            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
    412        }
    413    }
    414}
    415
    416static void ics_resend_lsi(ICSState *ics, int srcno)
    417{
    418    ICSIRQState *irq = ics->irqs + srcno;
    419
    420    if ((irq->priority != 0xff)
    421        && (irq->status & XICS_STATUS_ASSERTED)
    422        && !(irq->status & XICS_STATUS_SENT)) {
    423        irq->status |= XICS_STATUS_SENT;
    424        icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
    425    }
    426}
    427
    428static void ics_set_irq_msi(ICSState *ics, int srcno, int val)
    429{
    430    ICSIRQState *irq = ics->irqs + srcno;
    431
    432    trace_xics_ics_set_irq_msi(srcno, srcno + ics->offset);
    433
    434    if (val) {
    435        if (irq->priority == 0xff) {
    436            irq->status |= XICS_STATUS_MASKED_PENDING;
    437            trace_xics_masked_pending();
    438        } else  {
    439            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
    440        }
    441    }
    442}
    443
    444static void ics_set_irq_lsi(ICSState *ics, int srcno, int val)
    445{
    446    ICSIRQState *irq = ics->irqs + srcno;
    447
    448    trace_xics_ics_set_irq_lsi(srcno, srcno + ics->offset);
    449    if (val) {
    450        irq->status |= XICS_STATUS_ASSERTED;
    451    } else {
    452        irq->status &= ~XICS_STATUS_ASSERTED;
    453    }
    454    ics_resend_lsi(ics, srcno);
    455}
    456
    457void ics_set_irq(void *opaque, int srcno, int val)
    458{
    459    ICSState *ics = (ICSState *)opaque;
    460
    461    if (kvm_irqchip_in_kernel()) {
    462        ics_kvm_set_irq(ics, srcno, val);
    463        return;
    464    }
    465
    466    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
    467        ics_set_irq_lsi(ics, srcno, val);
    468    } else {
    469        ics_set_irq_msi(ics, srcno, val);
    470    }
    471}
    472
    473static void ics_write_xive_msi(ICSState *ics, int srcno)
    474{
    475    ICSIRQState *irq = ics->irqs + srcno;
    476
    477    if (!(irq->status & XICS_STATUS_MASKED_PENDING)
    478        || (irq->priority == 0xff)) {
    479        return;
    480    }
    481
    482    irq->status &= ~XICS_STATUS_MASKED_PENDING;
    483    icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
    484}
    485
    486static void ics_write_xive_lsi(ICSState *ics, int srcno)
    487{
    488    ics_resend_lsi(ics, srcno);
    489}
    490
    491void ics_write_xive(ICSState *ics, int srcno, int server,
    492                    uint8_t priority, uint8_t saved_priority)
    493{
    494    ICSIRQState *irq = ics->irqs + srcno;
    495
    496    irq->server = server;
    497    irq->priority = priority;
    498    irq->saved_priority = saved_priority;
    499
    500    trace_xics_ics_write_xive(ics->offset + srcno, srcno, server, priority);
    501
    502    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
    503        ics_write_xive_lsi(ics, srcno);
    504    } else {
    505        ics_write_xive_msi(ics, srcno);
    506    }
    507}
    508
    509static void ics_reject(ICSState *ics, uint32_t nr)
    510{
    511    ICSStateClass *isc = ICS_GET_CLASS(ics);
    512    ICSIRQState *irq = ics->irqs + nr - ics->offset;
    513
    514    if (isc->reject) {
    515        isc->reject(ics, nr);
    516        return;
    517    }
    518
    519    trace_xics_ics_reject(nr, nr - ics->offset);
    520    if (irq->flags & XICS_FLAGS_IRQ_MSI) {
    521        irq->status |= XICS_STATUS_REJECTED;
    522    } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
    523        irq->status &= ~XICS_STATUS_SENT;
    524    }
    525}
    526
    527void ics_resend(ICSState *ics)
    528{
    529    ICSStateClass *isc = ICS_GET_CLASS(ics);
    530    int i;
    531
    532    if (isc->resend) {
    533        isc->resend(ics);
    534        return;
    535    }
    536
    537    for (i = 0; i < ics->nr_irqs; i++) {
    538        /* FIXME: filter by server#? */
    539        if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
    540            ics_resend_lsi(ics, i);
    541        } else {
    542            ics_resend_msi(ics, i);
    543        }
    544    }
    545}
    546
    547static void ics_eoi(ICSState *ics, uint32_t nr)
    548{
    549    int srcno = nr - ics->offset;
    550    ICSIRQState *irq = ics->irqs + srcno;
    551
    552    trace_xics_ics_eoi(nr);
    553
    554    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
    555        irq->status &= ~XICS_STATUS_SENT;
    556    }
    557}
    558
    559static void ics_reset_irq(ICSIRQState *irq)
    560{
    561    irq->priority = 0xff;
    562    irq->saved_priority = 0xff;
    563}
    564
    565static void ics_reset(DeviceState *dev)
    566{
    567    ICSState *ics = ICS(dev);
    568    int i;
    569    uint8_t flags[ics->nr_irqs];
    570
    571    for (i = 0; i < ics->nr_irqs; i++) {
    572        flags[i] = ics->irqs[i].flags;
    573    }
    574
    575    memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);
    576
    577    for (i = 0; i < ics->nr_irqs; i++) {
    578        ics_reset_irq(ics->irqs + i);
    579        ics->irqs[i].flags = flags[i];
    580    }
    581
    582    if (kvm_irqchip_in_kernel()) {
    583        Error *local_err = NULL;
    584
    585        ics_set_kvm_state(ICS(dev), &local_err);
    586        if (local_err) {
    587            error_report_err(local_err);
    588        }
    589    }
    590}
    591
    592static void ics_reset_handler(void *dev)
    593{
    594    ics_reset(dev);
    595}
    596
    597static void ics_realize(DeviceState *dev, Error **errp)
    598{
    599    ICSState *ics = ICS(dev);
    600
    601    assert(ics->xics);
    602
    603    if (!ics->nr_irqs) {
    604        error_setg(errp, "Number of interrupts needs to be greater 0");
    605        return;
    606    }
    607    ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
    608
    609    qemu_register_reset(ics_reset_handler, ics);
    610}
    611
    612static void ics_instance_init(Object *obj)
    613{
    614    ICSState *ics = ICS(obj);
    615
    616    ics->offset = XICS_IRQ_BASE;
    617}
    618
    619static int ics_pre_save(void *opaque)
    620{
    621    ICSState *ics = opaque;
    622
    623    if (kvm_irqchip_in_kernel()) {
    624        ics_get_kvm_state(ics);
    625    }
    626
    627    return 0;
    628}
    629
    630static int ics_post_load(void *opaque, int version_id)
    631{
    632    ICSState *ics = opaque;
    633
    634    if (kvm_irqchip_in_kernel()) {
    635        Error *local_err = NULL;
    636        int ret;
    637
    638        ret = ics_set_kvm_state(ics, &local_err);
    639        if (ret < 0) {
    640            error_report_err(local_err);
    641            return ret;
    642        }
    643    }
    644
    645    return 0;
    646}
    647
    648static const VMStateDescription vmstate_ics_irq = {
    649    .name = "ics/irq",
    650    .version_id = 2,
    651    .minimum_version_id = 1,
    652    .fields = (VMStateField[]) {
    653        VMSTATE_UINT32(server, ICSIRQState),
    654        VMSTATE_UINT8(priority, ICSIRQState),
    655        VMSTATE_UINT8(saved_priority, ICSIRQState),
    656        VMSTATE_UINT8(status, ICSIRQState),
    657        VMSTATE_UINT8(flags, ICSIRQState),
    658        VMSTATE_END_OF_LIST()
    659    },
    660};
    661
    662static const VMStateDescription vmstate_ics = {
    663    .name = "ics",
    664    .version_id = 1,
    665    .minimum_version_id = 1,
    666    .pre_save = ics_pre_save,
    667    .post_load = ics_post_load,
    668    .fields = (VMStateField[]) {
    669        /* Sanity check */
    670        VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL),
    671
    672        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
    673                                             vmstate_ics_irq,
    674                                             ICSIRQState),
    675        VMSTATE_END_OF_LIST()
    676    },
    677};
    678
    679static Property ics_properties[] = {
    680    DEFINE_PROP_UINT32("nr-irqs", ICSState, nr_irqs, 0),
    681    DEFINE_PROP_LINK(ICS_PROP_XICS, ICSState, xics, TYPE_XICS_FABRIC,
    682                     XICSFabric *),
    683    DEFINE_PROP_END_OF_LIST(),
    684};
    685
    686static void ics_class_init(ObjectClass *klass, void *data)
    687{
    688    DeviceClass *dc = DEVICE_CLASS(klass);
    689
    690    dc->realize = ics_realize;
    691    device_class_set_props(dc, ics_properties);
    692    dc->reset = ics_reset;
    693    dc->vmsd = &vmstate_ics;
    694    /*
    695     * Reason: part of XICS interrupt controller, needs to be wired up,
    696     * e.g. by spapr_irq_init().
    697     */
    698    dc->user_creatable = false;
    699}
    700
    701static const TypeInfo ics_info = {
    702    .name = TYPE_ICS,
    703    .parent = TYPE_DEVICE,
    704    .instance_size = sizeof(ICSState),
    705    .instance_init = ics_instance_init,
    706    .class_init = ics_class_init,
    707    .class_size = sizeof(ICSStateClass),
    708};
    709
    710static const TypeInfo xics_fabric_info = {
    711    .name = TYPE_XICS_FABRIC,
    712    .parent = TYPE_INTERFACE,
    713    .class_size = sizeof(XICSFabricClass),
    714};
    715
    716/*
    717 * Exported functions
    718 */
    719ICPState *xics_icp_get(XICSFabric *xi, int server)
    720{
    721    XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(xi);
    722
    723    return xic->icp_get(xi, server);
    724}
    725
    726void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
    727{
    728    assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK));
    729
    730    ics->irqs[srcno].flags |=
    731        lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
    732
    733    if (kvm_irqchip_in_kernel()) {
    734        Error *local_err = NULL;
    735
    736        ics_reset_irq(ics->irqs + srcno);
    737        ics_set_kvm_state_one(ics, srcno, &local_err);
    738        if (local_err) {
    739            error_report_err(local_err);
    740        }
    741    }
    742}
    743
    744static void xics_register_types(void)
    745{
    746    type_register_static(&ics_info);
    747    type_register_static(&icp_info);
    748    type_register_static(&xics_fabric_info);
    749}
    750
    751type_init(xics_register_types)