|
|
1.1 root 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.h"
29: #include "hw/spapr.h"
30: #include "hw/xics.h"
31:
32: /*
33: * ICP: Presentation layer
34: */
35:
36: struct icp_server_state {
37: uint32_t xirr;
38: uint8_t pending_priority;
39: uint8_t mfrr;
40: qemu_irq output;
41: };
42:
43: #define XISR_MASK 0x00ffffff
44: #define CPPR_MASK 0xff000000
45:
46: #define XISR(ss) (((ss)->xirr) & XISR_MASK)
47: #define CPPR(ss) (((ss)->xirr) >> 24)
48:
49: struct ics_state;
50:
51: struct icp_state {
52: long nr_servers;
53: struct icp_server_state *ss;
54: struct ics_state *ics;
55: };
56:
57: static void ics_reject(struct ics_state *ics, int nr);
58: static void ics_resend(struct ics_state *ics);
59: static void ics_eoi(struct ics_state *ics, int nr);
60:
61: static void icp_check_ipi(struct icp_state *icp, int server)
62: {
63: struct icp_server_state *ss = icp->ss + server;
64:
65: if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
66: return;
67: }
68:
69: if (XISR(ss)) {
70: ics_reject(icp->ics, XISR(ss));
71: }
72:
73: ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
74: ss->pending_priority = ss->mfrr;
75: qemu_irq_raise(ss->output);
76: }
77:
78: static void icp_resend(struct icp_state *icp, int server)
79: {
80: struct icp_server_state *ss = icp->ss + server;
81:
82: if (ss->mfrr < CPPR(ss)) {
83: icp_check_ipi(icp, server);
84: }
85: ics_resend(icp->ics);
86: }
87:
88: static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr)
89: {
90: struct icp_server_state *ss = icp->ss + server;
91: uint8_t old_cppr;
92: uint32_t old_xisr;
93:
94: old_cppr = CPPR(ss);
95: ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
96:
97: if (cppr < old_cppr) {
98: if (XISR(ss) && (cppr <= ss->pending_priority)) {
99: old_xisr = XISR(ss);
100: ss->xirr &= ~XISR_MASK; /* Clear XISR */
101: qemu_irq_lower(ss->output);
102: ics_reject(icp->ics, old_xisr);
103: }
104: } else {
105: if (!XISR(ss)) {
106: icp_resend(icp, server);
107: }
108: }
109: }
110:
111: static void icp_set_mfrr(struct icp_state *icp, int nr, uint8_t mfrr)
112: {
113: struct icp_server_state *ss = icp->ss + nr;
114:
115: ss->mfrr = mfrr;
116: if (mfrr < CPPR(ss)) {
117: icp_check_ipi(icp, nr);
118: }
119: }
120:
121: static uint32_t icp_accept(struct icp_server_state *ss)
122: {
123: uint32_t xirr;
124:
125: qemu_irq_lower(ss->output);
126: xirr = ss->xirr;
127: ss->xirr = ss->pending_priority << 24;
128: return xirr;
129: }
130:
131: static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
132: {
133: struct icp_server_state *ss = icp->ss + server;
134:
135: /* Send EOI -> ICS */
136: ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
1.1.1.3 ! root 137: ics_eoi(icp->ics, xirr & XISR_MASK);
1.1 root 138: if (!XISR(ss)) {
139: icp_resend(icp, server);
140: }
141: }
142:
143: static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
144: {
145: struct icp_server_state *ss = icp->ss + server;
146:
147: if ((priority >= CPPR(ss))
148: || (XISR(ss) && (ss->pending_priority <= priority))) {
149: ics_reject(icp->ics, nr);
150: } else {
151: if (XISR(ss)) {
152: ics_reject(icp->ics, XISR(ss));
153: }
154: ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
155: ss->pending_priority = priority;
156: qemu_irq_raise(ss->output);
157: }
158: }
159:
160: /*
161: * ICS: Source layer
162: */
163:
164: struct ics_irq_state {
165: int server;
166: uint8_t priority;
167: uint8_t saved_priority;
1.1.1.3 ! root 168: enum xics_irq_type type;
! 169: int asserted:1;
! 170: int sent:1;
1.1 root 171: int rejected:1;
172: int masked_pending:1;
173: };
174:
175: struct ics_state {
176: int nr_irqs;
177: int offset;
178: qemu_irq *qirqs;
179: struct ics_irq_state *irqs;
180: struct icp_state *icp;
181: };
182:
183: static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
184: {
185: return (nr >= ics->offset)
186: && (nr < (ics->offset + ics->nr_irqs));
187: }
188:
1.1.1.3 ! root 189: static void resend_msi(struct ics_state *ics, int srcno)
! 190: {
! 191: struct ics_irq_state *irq = ics->irqs + srcno;
! 192:
! 193: /* FIXME: filter by server#? */
! 194: if (irq->rejected) {
! 195: irq->rejected = 0;
! 196: if (irq->priority != 0xff) {
! 197: icp_irq(ics->icp, irq->server, srcno + ics->offset,
! 198: irq->priority);
! 199: }
! 200: }
! 201: }
! 202:
! 203: static void resend_lsi(struct ics_state *ics, int srcno)
! 204: {
! 205: struct ics_irq_state *irq = ics->irqs + srcno;
! 206:
! 207: if ((irq->priority != 0xff) && irq->asserted && !irq->sent) {
! 208: irq->sent = 1;
! 209: icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
! 210: }
! 211: }
! 212:
! 213: static void set_irq_msi(struct ics_state *ics, int srcno, int val)
1.1 root 214: {
1.1.1.2 root 215: struct ics_irq_state *irq = ics->irqs + srcno;
1.1 root 216:
217: if (val) {
218: if (irq->priority == 0xff) {
219: irq->masked_pending = 1;
220: /* masked pending */ ;
221: } else {
1.1.1.2 root 222: icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
1.1 root 223: }
224: }
225: }
226:
1.1.1.3 ! root 227: static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
1.1 root 228: {
1.1.1.3 ! root 229: struct ics_irq_state *irq = ics->irqs + srcno;
1.1 root 230:
1.1.1.3 ! root 231: irq->asserted = val;
! 232: resend_lsi(ics, srcno);
1.1 root 233: }
234:
1.1.1.3 ! root 235: static void ics_set_irq(void *opaque, int srcno, int val)
1.1 root 236: {
1.1.1.3 ! root 237: struct ics_state *ics = (struct ics_state *)opaque;
! 238: struct ics_irq_state *irq = ics->irqs + srcno;
1.1 root 239:
1.1.1.3 ! root 240: if (irq->type == XICS_LSI) {
! 241: set_irq_lsi(ics, srcno, val);
! 242: } else {
! 243: set_irq_msi(ics, srcno, val);
! 244: }
! 245: }
1.1 root 246:
1.1.1.3 ! root 247: static void write_xive_msi(struct ics_state *ics, int srcno)
! 248: {
! 249: struct ics_irq_state *irq = ics->irqs + srcno;
! 250:
! 251: if (!irq->masked_pending || (irq->priority == 0xff)) {
! 252: return;
1.1 root 253: }
1.1.1.3 ! root 254:
! 255: irq->masked_pending = 0;
! 256: icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
1.1 root 257: }
258:
1.1.1.3 ! root 259: static void write_xive_lsi(struct ics_state *ics, int srcno)
1.1 root 260: {
1.1.1.3 ! root 261: resend_lsi(ics, srcno);
! 262: }
! 263:
! 264: static void ics_write_xive(struct ics_state *ics, int nr, int server,
! 265: uint8_t priority)
! 266: {
! 267: int srcno = nr - ics->offset;
! 268: struct ics_irq_state *irq = ics->irqs + srcno;
1.1 root 269:
270: irq->server = server;
271: irq->priority = priority;
272:
1.1.1.3 ! root 273: if (irq->type == XICS_LSI) {
! 274: write_xive_lsi(ics, srcno);
! 275: } else {
! 276: write_xive_msi(ics, srcno);
1.1 root 277: }
278: }
279:
280: static void ics_reject(struct ics_state *ics, int nr)
281: {
1.1.1.3 ! root 282: struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
! 283:
! 284: irq->rejected = 1; /* Irrelevant but harmless for LSI */
! 285: irq->sent = 0; /* Irrelevant but harmless for MSI */
1.1 root 286: }
287:
288: static void ics_resend(struct ics_state *ics)
289: {
1.1.1.3 ! root 290: int i;
! 291:
! 292: for (i = 0; i < ics->nr_irqs; i++) {
! 293: struct ics_irq_state *irq = ics->irqs + i;
! 294:
! 295: /* FIXME: filter by server#? */
! 296: if (irq->type == XICS_LSI) {
! 297: resend_lsi(ics, i);
! 298: } else {
! 299: resend_msi(ics, i);
! 300: }
! 301: }
1.1 root 302: }
303:
304: static void ics_eoi(struct ics_state *ics, int nr)
305: {
1.1.1.3 ! root 306: int srcno = nr - ics->offset;
! 307: struct ics_irq_state *irq = ics->irqs + srcno;
! 308:
! 309: if (irq->type == XICS_LSI) {
! 310: irq->sent = 0;
! 311: }
1.1 root 312: }
313:
314: /*
315: * Exported functions
316: */
317:
1.1.1.3 ! root 318: qemu_irq xics_assign_irq(struct icp_state *icp, int irq,
! 319: enum xics_irq_type type)
1.1 root 320: {
321: if ((irq < icp->ics->offset)
322: || (irq >= (icp->ics->offset + icp->ics->nr_irqs))) {
323: return NULL;
324: }
325:
1.1.1.3 ! root 326: assert((type == XICS_MSI) || (type == XICS_LSI));
! 327:
! 328: icp->ics->irqs[irq - icp->ics->offset].type = type;
1.1 root 329: return icp->ics->qirqs[irq - icp->ics->offset];
330: }
331:
1.1.1.3 ! root 332: static target_ulong h_cppr(CPUPPCState *env, sPAPREnvironment *spapr,
1.1 root 333: target_ulong opcode, target_ulong *args)
334: {
335: target_ulong cppr = args[0];
336:
337: icp_set_cppr(spapr->icp, env->cpu_index, cppr);
338: return H_SUCCESS;
339: }
340:
1.1.1.3 ! root 341: static target_ulong h_ipi(CPUPPCState *env, sPAPREnvironment *spapr,
1.1 root 342: target_ulong opcode, target_ulong *args)
343: {
344: target_ulong server = args[0];
345: target_ulong mfrr = args[1];
346:
347: if (server >= spapr->icp->nr_servers) {
348: return H_PARAMETER;
349: }
350:
351: icp_set_mfrr(spapr->icp, server, mfrr);
352: return H_SUCCESS;
353:
354: }
355:
1.1.1.3 ! root 356: static target_ulong h_xirr(CPUPPCState *env, sPAPREnvironment *spapr,
1.1 root 357: target_ulong opcode, target_ulong *args)
358: {
359: uint32_t xirr = icp_accept(spapr->icp->ss + env->cpu_index);
360:
361: args[0] = xirr;
362: return H_SUCCESS;
363: }
364:
1.1.1.3 ! root 365: static target_ulong h_eoi(CPUPPCState *env, sPAPREnvironment *spapr,
1.1 root 366: target_ulong opcode, target_ulong *args)
367: {
368: target_ulong xirr = args[0];
369:
370: icp_eoi(spapr->icp, env->cpu_index, xirr);
371: return H_SUCCESS;
372: }
373:
374: static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
375: uint32_t nargs, target_ulong args,
376: uint32_t nret, target_ulong rets)
377: {
378: struct ics_state *ics = spapr->icp->ics;
379: uint32_t nr, server, priority;
380:
381: if ((nargs != 3) || (nret != 1)) {
382: rtas_st(rets, 0, -3);
383: return;
384: }
385:
386: nr = rtas_ld(args, 0);
387: server = rtas_ld(args, 1);
388: priority = rtas_ld(args, 2);
389:
390: if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
391: || (priority > 0xff)) {
392: rtas_st(rets, 0, -3);
393: return;
394: }
395:
1.1.1.3 ! root 396: ics_write_xive(ics, nr, server, priority);
1.1 root 397:
398: rtas_st(rets, 0, 0); /* Success */
399: }
400:
401: static void rtas_get_xive(sPAPREnvironment *spapr, uint32_t token,
402: uint32_t nargs, target_ulong args,
403: uint32_t nret, target_ulong rets)
404: {
405: struct ics_state *ics = spapr->icp->ics;
406: uint32_t nr;
407:
408: if ((nargs != 1) || (nret != 3)) {
409: rtas_st(rets, 0, -3);
410: return;
411: }
412:
413: nr = rtas_ld(args, 0);
414:
415: if (!ics_valid_irq(ics, nr)) {
416: rtas_st(rets, 0, -3);
417: return;
418: }
419:
420: rtas_st(rets, 0, 0); /* Success */
421: rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
422: rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
423: }
424:
425: static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token,
426: uint32_t nargs, target_ulong args,
427: uint32_t nret, target_ulong rets)
428: {
429: struct ics_state *ics = spapr->icp->ics;
430: uint32_t nr;
431:
432: if ((nargs != 1) || (nret != 1)) {
433: rtas_st(rets, 0, -3);
434: return;
435: }
436:
437: nr = rtas_ld(args, 0);
438:
439: if (!ics_valid_irq(ics, nr)) {
440: rtas_st(rets, 0, -3);
441: return;
442: }
443:
444: /* This is a NOP for now, since the described PAPR semantics don't
445: * seem to gel with what Linux does */
446: #if 0
447: struct ics_irq_state *irq = xics->irqs + (nr - xics->offset);
448:
449: irq->saved_priority = irq->priority;
1.1.1.2 root 450: ics_write_xive_msi(xics, nr, irq->server, 0xff);
1.1 root 451: #endif
452:
453: rtas_st(rets, 0, 0); /* Success */
454: }
455:
456: static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token,
457: uint32_t nargs, target_ulong args,
458: uint32_t nret, target_ulong rets)
459: {
460: struct ics_state *ics = spapr->icp->ics;
461: uint32_t nr;
462:
463: if ((nargs != 1) || (nret != 1)) {
464: rtas_st(rets, 0, -3);
465: return;
466: }
467:
468: nr = rtas_ld(args, 0);
469:
470: if (!ics_valid_irq(ics, nr)) {
471: rtas_st(rets, 0, -3);
472: return;
473: }
474:
475: /* This is a NOP for now, since the described PAPR semantics don't
476: * seem to gel with what Linux does */
477: #if 0
478: struct ics_irq_state *irq = xics->irqs + (nr - xics->offset);
479:
1.1.1.2 root 480: ics_write_xive_msi(xics, nr, irq->server, irq->saved_priority);
1.1 root 481: #endif
482:
483: rtas_st(rets, 0, 0); /* Success */
484: }
485:
486: struct icp_state *xics_system_init(int nr_irqs)
487: {
1.1.1.3 ! root 488: CPUPPCState *env;
1.1 root 489: int max_server_num;
490: int i;
491: struct icp_state *icp;
492: struct ics_state *ics;
493:
494: max_server_num = -1;
495: for (env = first_cpu; env != NULL; env = env->next_cpu) {
496: if (env->cpu_index > max_server_num) {
497: max_server_num = env->cpu_index;
498: }
499: }
500:
1.1.1.2 root 501: icp = g_malloc0(sizeof(*icp));
1.1 root 502: icp->nr_servers = max_server_num + 1;
1.1.1.2 root 503: icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
1.1 root 504:
505: for (i = 0; i < icp->nr_servers; i++) {
506: icp->ss[i].mfrr = 0xff;
507: }
508:
509: for (env = first_cpu; env != NULL; env = env->next_cpu) {
510: struct icp_server_state *ss = &icp->ss[env->cpu_index];
511:
512: switch (PPC_INPUT(env)) {
513: case PPC_FLAGS_INPUT_POWER7:
514: ss->output = env->irq_inputs[POWER7_INPUT_INT];
515: break;
516:
517: case PPC_FLAGS_INPUT_970:
518: ss->output = env->irq_inputs[PPC970_INPUT_INT];
519: break;
520:
521: default:
522: hw_error("XICS interrupt model does not support this CPU bus "
523: "model\n");
524: exit(1);
525: }
526: }
527:
1.1.1.2 root 528: ics = g_malloc0(sizeof(*ics));
1.1 root 529: ics->nr_irqs = nr_irqs;
530: ics->offset = 16;
1.1.1.2 root 531: ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state));
1.1 root 532:
533: icp->ics = ics;
534: ics->icp = icp;
535:
536: for (i = 0; i < nr_irqs; i++) {
537: ics->irqs[i].priority = 0xff;
538: ics->irqs[i].saved_priority = 0xff;
539: }
540:
1.1.1.3 ! root 541: ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
1.1 root 542:
543: spapr_register_hypercall(H_CPPR, h_cppr);
544: spapr_register_hypercall(H_IPI, h_ipi);
545: spapr_register_hypercall(H_XIRR, h_xirr);
546: spapr_register_hypercall(H_EOI, h_eoi);
547:
548: spapr_rtas_register("ibm,set-xive", rtas_set_xive);
549: spapr_rtas_register("ibm,get-xive", rtas_get_xive);
550: spapr_rtas_register("ibm,int-off", rtas_int_off);
551: spapr_rtas_register("ibm,int-on", rtas_int_on);
552:
553: return icp;
554: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.