qemu/hw/intc/xics.c
<<
>>
Prefs
   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 "hw/hw.h"
  29#include "trace.h"
  30#include "qemu/timer.h"
  31#include "hw/ppc/spapr.h"
  32#include "hw/ppc/xics.h"
  33#include "qemu/error-report.h"
  34#include "qapi/visitor.h"
  35
  36void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
  37{
  38    CPUState *cs = CPU(cpu);
  39    CPUPPCState *env = &cpu->env;
  40    ICPState *ss = &icp->ss[cs->cpu_index];
  41    XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
  42
  43    assert(cs->cpu_index < icp->nr_servers);
  44
  45    if (info->cpu_setup) {
  46        info->cpu_setup(icp, cpu);
  47    }
  48
  49    switch (PPC_INPUT(env)) {
  50    case PPC_FLAGS_INPUT_POWER7:
  51        ss->output = env->irq_inputs[POWER7_INPUT_INT];
  52        break;
  53
  54    case PPC_FLAGS_INPUT_970:
  55        ss->output = env->irq_inputs[PPC970_INPUT_INT];
  56        break;
  57
  58    default:
  59        error_report("XICS interrupt controller does not support this CPU "
  60                     "bus model");
  61        abort();
  62    }
  63}
  64
  65/*
  66 * XICS Common class - parent for emulated XICS and KVM-XICS
  67 */
  68static void xics_common_reset(DeviceState *d)
  69{
  70    XICSState *icp = XICS_COMMON(d);
  71    int i;
  72
  73    for (i = 0; i < icp->nr_servers; i++) {
  74        device_reset(DEVICE(&icp->ss[i]));
  75    }
  76
  77    device_reset(DEVICE(icp->ics));
  78}
  79
  80static void xics_prop_get_nr_irqs(Object *obj, Visitor *v,
  81                                  void *opaque, const char *name, Error **errp)
  82{
  83    XICSState *icp = XICS_COMMON(obj);
  84    int64_t value = icp->nr_irqs;
  85
  86    visit_type_int(v, &value, name, errp);
  87}
  88
  89static void xics_prop_set_nr_irqs(Object *obj, Visitor *v,
  90                                  void *opaque, const char *name, Error **errp)
  91{
  92    XICSState *icp = XICS_COMMON(obj);
  93    XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
  94    Error *error = NULL;
  95    int64_t value;
  96
  97    visit_type_int(v, &value, name, &error);
  98    if (error) {
  99        error_propagate(errp, error);
 100        return;
 101    }
 102    if (icp->nr_irqs) {
 103        error_setg(errp, "Number of interrupts is already set to %u",
 104                   icp->nr_irqs);
 105        return;
 106    }
 107
 108    assert(info->set_nr_irqs);
 109    assert(icp->ics);
 110    info->set_nr_irqs(icp, value, errp);
 111}
 112
 113static void xics_prop_get_nr_servers(Object *obj, Visitor *v,
 114                                     void *opaque, const char *name,
 115                                     Error **errp)
 116{
 117    XICSState *icp = XICS_COMMON(obj);
 118    int64_t value = icp->nr_servers;
 119
 120    visit_type_int(v, &value, name, errp);
 121}
 122
 123static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
 124                                     void *opaque, const char *name,
 125                                     Error **errp)
 126{
 127    XICSState *icp = XICS_COMMON(obj);
 128    XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
 129    Error *error = NULL;
 130    int64_t value;
 131
 132    visit_type_int(v, &value, name, &error);
 133    if (error) {
 134        error_propagate(errp, error);
 135        return;
 136    }
 137    if (icp->nr_servers) {
 138        error_setg(errp, "Number of servers is already set to %u",
 139                   icp->nr_servers);
 140        return;
 141    }
 142
 143    assert(info->set_nr_servers);
 144    info->set_nr_servers(icp, value, errp);
 145}
 146
 147static void xics_common_initfn(Object *obj)
 148{
 149    object_property_add(obj, "nr_irqs", "int",
 150                        xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
 151                        NULL, NULL, NULL);
 152    object_property_add(obj, "nr_servers", "int",
 153                        xics_prop_get_nr_servers, xics_prop_set_nr_servers,
 154                        NULL, NULL, NULL);
 155}
 156
 157static void xics_common_class_init(ObjectClass *oc, void *data)
 158{
 159    DeviceClass *dc = DEVICE_CLASS(oc);
 160
 161    dc->reset = xics_common_reset;
 162}
 163
 164static const TypeInfo xics_common_info = {
 165    .name          = TYPE_XICS_COMMON,
 166    .parent        = TYPE_SYS_BUS_DEVICE,
 167    .instance_size = sizeof(XICSState),
 168    .class_size    = sizeof(XICSStateClass),
 169    .instance_init = xics_common_initfn,
 170    .class_init    = xics_common_class_init,
 171};
 172
 173/*
 174 * ICP: Presentation layer
 175 */
 176
 177#define XISR_MASK  0x00ffffff
 178#define CPPR_MASK  0xff000000
 179
 180#define XISR(ss)   (((ss)->xirr) & XISR_MASK)
 181#define CPPR(ss)   (((ss)->xirr) >> 24)
 182
 183static void ics_reject(ICSState *ics, int nr);
 184static void ics_resend(ICSState *ics);
 185static void ics_eoi(ICSState *ics, int nr);
 186
 187static void icp_check_ipi(XICSState *icp, int server)
 188{
 189    ICPState *ss = icp->ss + server;
 190
 191    if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
 192        return;
 193    }
 194
 195    trace_xics_icp_check_ipi(server, ss->mfrr);
 196
 197    if (XISR(ss)) {
 198        ics_reject(icp->ics, XISR(ss));
 199    }
 200
 201    ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
 202    ss->pending_priority = ss->mfrr;
 203    qemu_irq_raise(ss->output);
 204}
 205
 206static void icp_resend(XICSState *icp, int server)
 207{
 208    ICPState *ss = icp->ss + server;
 209
 210    if (ss->mfrr < CPPR(ss)) {
 211        icp_check_ipi(icp, server);
 212    }
 213    ics_resend(icp->ics);
 214}
 215
 216static void icp_set_cppr(XICSState *icp, int server, uint8_t cppr)
 217{
 218    ICPState *ss = icp->ss + server;
 219    uint8_t old_cppr;
 220    uint32_t old_xisr;
 221
 222    old_cppr = CPPR(ss);
 223    ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
 224
 225    if (cppr < old_cppr) {
 226        if (XISR(ss) && (cppr <= ss->pending_priority)) {
 227            old_xisr = XISR(ss);
 228            ss->xirr &= ~XISR_MASK; /* Clear XISR */
 229            ss->pending_priority = 0xff;
 230            qemu_irq_lower(ss->output);
 231            ics_reject(icp->ics, old_xisr);
 232        }
 233    } else {
 234        if (!XISR(ss)) {
 235            icp_resend(icp, server);
 236        }
 237    }
 238}
 239
 240static void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr)
 241{
 242    ICPState *ss = icp->ss + server;
 243
 244    ss->mfrr = mfrr;
 245    if (mfrr < CPPR(ss)) {
 246        icp_check_ipi(icp, server);
 247    }
 248}
 249
 250static uint32_t icp_accept(ICPState *ss)
 251{
 252    uint32_t xirr = ss->xirr;
 253
 254    qemu_irq_lower(ss->output);
 255    ss->xirr = ss->pending_priority << 24;
 256    ss->pending_priority = 0xff;
 257
 258    trace_xics_icp_accept(xirr, ss->xirr);
 259
 260    return xirr;
 261}
 262
 263static void icp_eoi(XICSState *icp, int server, uint32_t xirr)
 264{
 265    ICPState *ss = icp->ss + server;
 266
 267    /* Send EOI -> ICS */
 268    ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
 269    trace_xics_icp_eoi(server, xirr, ss->xirr);
 270    ics_eoi(icp->ics, xirr & XISR_MASK);
 271    if (!XISR(ss)) {
 272        icp_resend(icp, server);
 273    }
 274}
 275
 276static void icp_irq(XICSState *icp, int server, int nr, uint8_t priority)
 277{
 278    ICPState *ss = icp->ss + server;
 279
 280    trace_xics_icp_irq(server, nr, priority);
 281
 282    if ((priority >= CPPR(ss))
 283        || (XISR(ss) && (ss->pending_priority <= priority))) {
 284        ics_reject(icp->ics, nr);
 285    } else {
 286        if (XISR(ss)) {
 287            ics_reject(icp->ics, XISR(ss));
 288        }
 289        ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
 290        ss->pending_priority = priority;
 291        trace_xics_icp_raise(ss->xirr, ss->pending_priority);
 292        qemu_irq_raise(ss->output);
 293    }
 294}
 295
 296static void icp_dispatch_pre_save(void *opaque)
 297{
 298    ICPState *ss = opaque;
 299    ICPStateClass *info = ICP_GET_CLASS(ss);
 300
 301    if (info->pre_save) {
 302        info->pre_save(ss);
 303    }
 304}
 305
 306static int icp_dispatch_post_load(void *opaque, int version_id)
 307{
 308    ICPState *ss = opaque;
 309    ICPStateClass *info = ICP_GET_CLASS(ss);
 310
 311    if (info->post_load) {
 312        return info->post_load(ss, version_id);
 313    }
 314
 315    return 0;
 316}
 317
 318static const VMStateDescription vmstate_icp_server = {
 319    .name = "icp/server",
 320    .version_id = 1,
 321    .minimum_version_id = 1,
 322    .minimum_version_id_old = 1,
 323    .pre_save = icp_dispatch_pre_save,
 324    .post_load = icp_dispatch_post_load,
 325    .fields      = (VMStateField []) {
 326        /* Sanity check */
 327        VMSTATE_UINT32(xirr, ICPState),
 328        VMSTATE_UINT8(pending_priority, ICPState),
 329        VMSTATE_UINT8(mfrr, ICPState),
 330        VMSTATE_END_OF_LIST()
 331    },
 332};
 333
 334static void icp_reset(DeviceState *dev)
 335{
 336    ICPState *icp = ICP(dev);
 337
 338    icp->xirr = 0;
 339    icp->pending_priority = 0xff;
 340    icp->mfrr = 0xff;
 341
 342    /* Make all outputs are deasserted */
 343    qemu_set_irq(icp->output, 0);
 344}
 345
 346static void icp_class_init(ObjectClass *klass, void *data)
 347{
 348    DeviceClass *dc = DEVICE_CLASS(klass);
 349
 350    dc->reset = icp_reset;
 351    dc->vmsd = &vmstate_icp_server;
 352}
 353
 354static const TypeInfo icp_info = {
 355    .name = TYPE_ICP,
 356    .parent = TYPE_DEVICE,
 357    .instance_size = sizeof(ICPState),
 358    .class_init = icp_class_init,
 359    .class_size = sizeof(ICPStateClass),
 360};
 361
 362/*
 363 * ICS: Source layer
 364 */
 365static int ics_valid_irq(ICSState *ics, uint32_t nr)
 366{
 367    return (nr >= ics->offset)
 368        && (nr < (ics->offset + ics->nr_irqs));
 369}
 370
 371static void resend_msi(ICSState *ics, int srcno)
 372{
 373    ICSIRQState *irq = ics->irqs + srcno;
 374
 375    /* FIXME: filter by server#? */
 376    if (irq->status & XICS_STATUS_REJECTED) {
 377        irq->status &= ~XICS_STATUS_REJECTED;
 378        if (irq->priority != 0xff) {
 379            icp_irq(ics->icp, irq->server, srcno + ics->offset,
 380                    irq->priority);
 381        }
 382    }
 383}
 384
 385static void resend_lsi(ICSState *ics, int srcno)
 386{
 387    ICSIRQState *irq = ics->irqs + srcno;
 388
 389    if ((irq->priority != 0xff)
 390        && (irq->status & XICS_STATUS_ASSERTED)
 391        && !(irq->status & XICS_STATUS_SENT)) {
 392        irq->status |= XICS_STATUS_SENT;
 393        icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
 394    }
 395}
 396
 397static void set_irq_msi(ICSState *ics, int srcno, int val)
 398{
 399    ICSIRQState *irq = ics->irqs + srcno;
 400
 401    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
 402
 403    if (val) {
 404        if (irq->priority == 0xff) {
 405            irq->status |= XICS_STATUS_MASKED_PENDING;
 406            trace_xics_masked_pending();
 407        } else  {
 408            icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
 409        }
 410    }
 411}
 412
 413static void set_irq_lsi(ICSState *ics, int srcno, int val)
 414{
 415    ICSIRQState *irq = ics->irqs + srcno;
 416
 417    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
 418    if (val) {
 419        irq->status |= XICS_STATUS_ASSERTED;
 420    } else {
 421        irq->status &= ~XICS_STATUS_ASSERTED;
 422    }
 423    resend_lsi(ics, srcno);
 424}
 425
 426static void ics_set_irq(void *opaque, int srcno, int val)
 427{
 428    ICSState *ics = (ICSState *)opaque;
 429
 430    if (ics->islsi[srcno]) {
 431        set_irq_lsi(ics, srcno, val);
 432    } else {
 433        set_irq_msi(ics, srcno, val);
 434    }
 435}
 436
 437static void write_xive_msi(ICSState *ics, int srcno)
 438{
 439    ICSIRQState *irq = ics->irqs + srcno;
 440
 441    if (!(irq->status & XICS_STATUS_MASKED_PENDING)
 442        || (irq->priority == 0xff)) {
 443        return;
 444    }
 445
 446    irq->status &= ~XICS_STATUS_MASKED_PENDING;
 447    icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
 448}
 449
 450static void write_xive_lsi(ICSState *ics, int srcno)
 451{
 452    resend_lsi(ics, srcno);
 453}
 454
 455static void ics_write_xive(ICSState *ics, int nr, int server,
 456                           uint8_t priority, uint8_t saved_priority)
 457{
 458    int srcno = nr - ics->offset;
 459    ICSIRQState *irq = ics->irqs + srcno;
 460
 461    irq->server = server;
 462    irq->priority = priority;
 463    irq->saved_priority = saved_priority;
 464
 465    trace_xics_ics_write_xive(nr, srcno, server, priority);
 466
 467    if (ics->islsi[srcno]) {
 468        write_xive_lsi(ics, srcno);
 469    } else {
 470        write_xive_msi(ics, srcno);
 471    }
 472}
 473
 474static void ics_reject(ICSState *ics, int nr)
 475{
 476    ICSIRQState *irq = ics->irqs + nr - ics->offset;
 477
 478    trace_xics_ics_reject(nr, nr - ics->offset);
 479    irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
 480    irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
 481}
 482
 483static void ics_resend(ICSState *ics)
 484{
 485    int i;
 486
 487    for (i = 0; i < ics->nr_irqs; i++) {
 488        /* FIXME: filter by server#? */
 489        if (ics->islsi[i]) {
 490            resend_lsi(ics, i);
 491        } else {
 492            resend_msi(ics, i);
 493        }
 494    }
 495}
 496
 497static void ics_eoi(ICSState *ics, int nr)
 498{
 499    int srcno = nr - ics->offset;
 500    ICSIRQState *irq = ics->irqs + srcno;
 501
 502    trace_xics_ics_eoi(nr);
 503
 504    if (ics->islsi[srcno]) {
 505        irq->status &= ~XICS_STATUS_SENT;
 506    }
 507}
 508
 509static void ics_reset(DeviceState *dev)
 510{
 511    ICSState *ics = ICS(dev);
 512    int i;
 513
 514    memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);
 515    for (i = 0; i < ics->nr_irqs; i++) {
 516        ics->irqs[i].priority = 0xff;
 517        ics->irqs[i].saved_priority = 0xff;
 518    }
 519}
 520
 521static int ics_post_load(ICSState *ics, int version_id)
 522{
 523    int i;
 524
 525    for (i = 0; i < ics->icp->nr_servers; i++) {
 526        icp_resend(ics->icp, i);
 527    }
 528
 529    return 0;
 530}
 531
 532static void ics_dispatch_pre_save(void *opaque)
 533{
 534    ICSState *ics = opaque;
 535    ICSStateClass *info = ICS_GET_CLASS(ics);
 536
 537    if (info->pre_save) {
 538        info->pre_save(ics);
 539    }
 540}
 541
 542static int ics_dispatch_post_load(void *opaque, int version_id)
 543{
 544    ICSState *ics = opaque;
 545    ICSStateClass *info = ICS_GET_CLASS(ics);
 546
 547    if (info->post_load) {
 548        return info->post_load(ics, version_id);
 549    }
 550
 551    return 0;
 552}
 553
 554static const VMStateDescription vmstate_ics_irq = {
 555    .name = "ics/irq",
 556    .version_id = 1,
 557    .minimum_version_id = 1,
 558    .minimum_version_id_old = 1,
 559    .fields      = (VMStateField []) {
 560        VMSTATE_UINT32(server, ICSIRQState),
 561        VMSTATE_UINT8(priority, ICSIRQState),
 562        VMSTATE_UINT8(saved_priority, ICSIRQState),
 563        VMSTATE_UINT8(status, ICSIRQState),
 564        VMSTATE_END_OF_LIST()
 565    },
 566};
 567
 568static const VMStateDescription vmstate_ics = {
 569    .name = "ics",
 570    .version_id = 1,
 571    .minimum_version_id = 1,
 572    .minimum_version_id_old = 1,
 573    .pre_save = ics_dispatch_pre_save,
 574    .post_load = ics_dispatch_post_load,
 575    .fields      = (VMStateField []) {
 576        /* Sanity check */
 577        VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
 578
 579        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
 580                                             vmstate_ics_irq, ICSIRQState),
 581        VMSTATE_END_OF_LIST()
 582    },
 583};
 584
 585static void ics_initfn(Object *obj)
 586{
 587    ICSState *ics = ICS(obj);
 588
 589    ics->offset = XICS_IRQ_BASE;
 590}
 591
 592static void ics_realize(DeviceState *dev, Error **errp)
 593{
 594    ICSState *ics = ICS(dev);
 595
 596    if (!ics->nr_irqs) {
 597        error_setg(errp, "Number of interrupts needs to be greater 0");
 598        return;
 599    }
 600    ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
 601    ics->islsi = g_malloc0(ics->nr_irqs * sizeof(bool));
 602    ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
 603}
 604
 605static void ics_class_init(ObjectClass *klass, void *data)
 606{
 607    DeviceClass *dc = DEVICE_CLASS(klass);
 608    ICSStateClass *isc = ICS_CLASS(klass);
 609
 610    dc->realize = ics_realize;
 611    dc->vmsd = &vmstate_ics;
 612    dc->reset = ics_reset;
 613    isc->post_load = ics_post_load;
 614}
 615
 616static const TypeInfo ics_info = {
 617    .name = TYPE_ICS,
 618    .parent = TYPE_DEVICE,
 619    .instance_size = sizeof(ICSState),
 620    .class_init = ics_class_init,
 621    .class_size = sizeof(ICSStateClass),
 622    .instance_init = ics_initfn,
 623};
 624
 625/*
 626 * Exported functions
 627 */
 628
 629qemu_irq xics_get_qirq(XICSState *icp, int irq)
 630{
 631    if (!ics_valid_irq(icp->ics, irq)) {
 632        return NULL;
 633    }
 634
 635    return icp->ics->qirqs[irq - icp->ics->offset];
 636}
 637
 638void xics_set_irq_type(XICSState *icp, int irq, bool lsi)
 639{
 640    assert(ics_valid_irq(icp->ics, irq));
 641
 642    icp->ics->islsi[irq - icp->ics->offset] = lsi;
 643}
 644
 645/*
 646 * Guest interfaces
 647 */
 648
 649static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 650                           target_ulong opcode, target_ulong *args)
 651{
 652    CPUState *cs = CPU(cpu);
 653    target_ulong cppr = args[0];
 654
 655    icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
 656    return H_SUCCESS;
 657}
 658
 659static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 660                          target_ulong opcode, target_ulong *args)
 661{
 662    target_ulong server = args[0];
 663    target_ulong mfrr = args[1];
 664
 665    if (server >= spapr->icp->nr_servers) {
 666        return H_PARAMETER;
 667    }
 668
 669    icp_set_mfrr(spapr->icp, server, mfrr);
 670    return H_SUCCESS;
 671}
 672
 673static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 674                           target_ulong opcode, target_ulong *args)
 675{
 676    CPUState *cs = CPU(cpu);
 677    uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
 678
 679    args[0] = xirr;
 680    return H_SUCCESS;
 681}
 682
 683static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 684                             target_ulong opcode, target_ulong *args)
 685{
 686    CPUState *cs = CPU(cpu);
 687    ICPState *ss = &spapr->icp->ss[cs->cpu_index];
 688    uint32_t xirr = icp_accept(ss);
 689
 690    args[0] = xirr;
 691    args[1] = cpu_get_real_ticks();
 692    return H_SUCCESS;
 693}
 694
 695static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 696                          target_ulong opcode, target_ulong *args)
 697{
 698    CPUState *cs = CPU(cpu);
 699    target_ulong xirr = args[0];
 700
 701    icp_eoi(spapr->icp, cs->cpu_index, xirr);
 702    return H_SUCCESS;
 703}
 704
 705static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 706                            target_ulong opcode, target_ulong *args)
 707{
 708    CPUState *cs = CPU(cpu);
 709    ICPState *ss = &spapr->icp->ss[cs->cpu_index];
 710
 711    args[0] = ss->xirr;
 712    args[1] = ss->mfrr;
 713
 714    return H_SUCCESS;
 715}
 716
 717static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 718                          uint32_t token,
 719                          uint32_t nargs, target_ulong args,
 720                          uint32_t nret, target_ulong rets)
 721{
 722    ICSState *ics = spapr->icp->ics;
 723    uint32_t nr, server, priority;
 724
 725    if ((nargs != 3) || (nret != 1)) {
 726        rtas_st(rets, 0, -3);
 727        return;
 728    }
 729
 730    nr = rtas_ld(args, 0);
 731    server = rtas_ld(args, 1);
 732    priority = rtas_ld(args, 2);
 733
 734    if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
 735        || (priority > 0xff)) {
 736        rtas_st(rets, 0, -3);
 737        return;
 738    }
 739
 740    ics_write_xive(ics, nr, server, priority, priority);
 741
 742    rtas_st(rets, 0, 0); /* Success */
 743}
 744
 745static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 746                          uint32_t token,
 747                          uint32_t nargs, target_ulong args,
 748                          uint32_t nret, target_ulong rets)
 749{
 750    ICSState *ics = spapr->icp->ics;
 751    uint32_t nr;
 752
 753    if ((nargs != 1) || (nret != 3)) {
 754        rtas_st(rets, 0, -3);
 755        return;
 756    }
 757
 758    nr = rtas_ld(args, 0);
 759
 760    if (!ics_valid_irq(ics, nr)) {
 761        rtas_st(rets, 0, -3);
 762        return;
 763    }
 764
 765    rtas_st(rets, 0, 0); /* Success */
 766    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
 767    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
 768}
 769
 770static void rtas_int_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 771                         uint32_t token,
 772                         uint32_t nargs, target_ulong args,
 773                         uint32_t nret, target_ulong rets)
 774{
 775    ICSState *ics = spapr->icp->ics;
 776    uint32_t nr;
 777
 778    if ((nargs != 1) || (nret != 1)) {
 779        rtas_st(rets, 0, -3);
 780        return;
 781    }
 782
 783    nr = rtas_ld(args, 0);
 784
 785    if (!ics_valid_irq(ics, nr)) {
 786        rtas_st(rets, 0, -3);
 787        return;
 788    }
 789
 790    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
 791                   ics->irqs[nr - ics->offset].priority);
 792
 793    rtas_st(rets, 0, 0); /* Success */
 794}
 795
 796static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 797                        uint32_t token,
 798                        uint32_t nargs, target_ulong args,
 799                        uint32_t nret, target_ulong rets)
 800{
 801    ICSState *ics = spapr->icp->ics;
 802    uint32_t nr;
 803
 804    if ((nargs != 1) || (nret != 1)) {
 805        rtas_st(rets, 0, -3);
 806        return;
 807    }
 808
 809    nr = rtas_ld(args, 0);
 810
 811    if (!ics_valid_irq(ics, nr)) {
 812        rtas_st(rets, 0, -3);
 813        return;
 814    }
 815
 816    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
 817                   ics->irqs[nr - ics->offset].saved_priority,
 818                   ics->irqs[nr - ics->offset].saved_priority);
 819
 820    rtas_st(rets, 0, 0); /* Success */
 821}
 822
 823/*
 824 * XICS
 825 */
 826
 827static void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp)
 828{
 829    icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
 830}
 831
 832static void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers,
 833                                Error **errp)
 834{
 835    int i;
 836
 837    icp->nr_servers = nr_servers;
 838
 839    icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
 840    for (i = 0; i < icp->nr_servers; i++) {
 841        char buffer[32];
 842        object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_ICP);
 843        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
 844        object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
 845                                  errp);
 846    }
 847}
 848
 849static void xics_realize(DeviceState *dev, Error **errp)
 850{
 851    XICSState *icp = XICS(dev);
 852    Error *error = NULL;
 853    int i;
 854
 855    if (!icp->nr_servers) {
 856        error_setg(errp, "Number of servers needs to be greater 0");
 857        return;
 858    }
 859
 860    /* Registration of global state belongs into realize */
 861    spapr_rtas_register("ibm,set-xive", rtas_set_xive);
 862    spapr_rtas_register("ibm,get-xive", rtas_get_xive);
 863    spapr_rtas_register("ibm,int-off", rtas_int_off);
 864    spapr_rtas_register("ibm,int-on", rtas_int_on);
 865
 866    spapr_register_hypercall(H_CPPR, h_cppr);
 867    spapr_register_hypercall(H_IPI, h_ipi);
 868    spapr_register_hypercall(H_XIRR, h_xirr);
 869    spapr_register_hypercall(H_XIRR_X, h_xirr_x);
 870    spapr_register_hypercall(H_EOI, h_eoi);
 871    spapr_register_hypercall(H_IPOLL, h_ipoll);
 872
 873    object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
 874    if (error) {
 875        error_propagate(errp, error);
 876        return;
 877    }
 878
 879    for (i = 0; i < icp->nr_servers; i++) {
 880        object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized", &error);
 881        if (error) {
 882            error_propagate(errp, error);
 883            return;
 884        }
 885    }
 886}
 887
 888static void xics_initfn(Object *obj)
 889{
 890    XICSState *xics = XICS(obj);
 891
 892    xics->ics = ICS(object_new(TYPE_ICS));
 893    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
 894    xics->ics->icp = xics;
 895}
 896
 897static void xics_class_init(ObjectClass *oc, void *data)
 898{
 899    DeviceClass *dc = DEVICE_CLASS(oc);
 900    XICSStateClass *xsc = XICS_CLASS(oc);
 901
 902    dc->realize = xics_realize;
 903    xsc->set_nr_irqs = xics_set_nr_irqs;
 904    xsc->set_nr_servers = xics_set_nr_servers;
 905}
 906
 907static const TypeInfo xics_info = {
 908    .name          = TYPE_XICS,
 909    .parent        = TYPE_XICS_COMMON,
 910    .instance_size = sizeof(XICSState),
 911    .class_size = sizeof(XICSStateClass),
 912    .class_init    = xics_class_init,
 913    .instance_init = xics_initfn,
 914};
 915
 916static void xics_register_types(void)
 917{
 918    type_register_static(&xics_common_info);
 919    type_register_static(&xics_info);
 920    type_register_static(&ics_info);
 921    type_register_static(&icp_info);
 922}
 923
 924type_init(xics_register_types)
 925