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