2 * QEMU PowerPC PowerNV (POWER8) PHB3 model
4 * Copyright (c) 2014-2020, IBM Corporation.
6 * This code is licensed under the GPL version 2 or later. See the
7 * COPYING file in the top-level directory.
9 #include "qemu/osdep.h"
11 #include "qapi/error.h"
12 #include "qemu-common.h"
13 #include "hw/pci-host/pnv_phb3_regs.h"
14 #include "hw/pci-host/pnv_phb3.h"
15 #include "hw/ppc/pnv.h"
16 #include "hw/pci/msi.h"
17 #include "monitor/monitor.h"
19 #include "hw/qdev-properties.h"
20 #include "sysemu/reset.h"
22 static uint64_t phb3_msi_ive_addr(PnvPHB3
*phb
, int srcno
)
24 uint64_t ivtbar
= phb
->regs
[PHB_IVT_BAR
>> 3];
25 uint64_t phbctl
= phb
->regs
[PHB_CONTROL
>> 3];
27 if (!(ivtbar
& PHB_IVT_BAR_ENABLE
)) {
28 qemu_log_mask(LOG_GUEST_ERROR
, "Failed access to disable IVT BAR !");
32 if (srcno
>= (ivtbar
& PHB_IVT_LENGTH_MASK
)) {
33 qemu_log_mask(LOG_GUEST_ERROR
, "MSI out of bounds (%d vs 0x%"PRIx64
")",
34 srcno
, (uint64_t) (ivtbar
& PHB_IVT_LENGTH_MASK
));
38 ivtbar
&= PHB_IVT_BASE_ADDRESS_MASK
;
40 if (phbctl
& PHB_CTRL_IVE_128_BYTES
) {
41 return ivtbar
+ 128 * srcno
;
43 return ivtbar
+ 16 * srcno
;
47 static bool phb3_msi_read_ive(PnvPHB3
*phb
, int srcno
, uint64_t *out_ive
)
49 uint64_t ive_addr
, ive
;
51 ive_addr
= phb3_msi_ive_addr(phb
, srcno
);
56 if (dma_memory_read(&address_space_memory
, ive_addr
, &ive
, sizeof(ive
))) {
57 qemu_log_mask(LOG_GUEST_ERROR
, "Failed to read IVE at 0x%" PRIx64
,
61 *out_ive
= be64_to_cpu(ive
);
66 static void phb3_msi_set_p(Phb3MsiState
*msi
, int srcno
, uint8_t gen
)
69 uint8_t p
= 0x01 | (gen
<< 1);
71 ive_addr
= phb3_msi_ive_addr(msi
->phb
, srcno
);
76 if (dma_memory_write(&address_space_memory
, ive_addr
+ 4, &p
, 1)) {
77 qemu_log_mask(LOG_GUEST_ERROR
,
78 "Failed to write IVE (set P) at 0x%" PRIx64
, ive_addr
);
82 static void phb3_msi_set_q(Phb3MsiState
*msi
, int srcno
)
87 ive_addr
= phb3_msi_ive_addr(msi
->phb
, srcno
);
92 if (dma_memory_write(&address_space_memory
, ive_addr
+ 5, &q
, 1)) {
93 qemu_log_mask(LOG_GUEST_ERROR
,
94 "Failed to write IVE (set Q) at 0x%" PRIx64
, ive_addr
);
98 static void phb3_msi_try_send(Phb3MsiState
*msi
, int srcno
, bool force
)
100 ICSState
*ics
= ICS(msi
);
102 uint64_t server
, prio
, pq
, gen
;
104 if (!phb3_msi_read_ive(msi
->phb
, srcno
, &ive
)) {
108 server
= GETFIELD(IODA2_IVT_SERVER
, ive
);
109 prio
= GETFIELD(IODA2_IVT_PRIORITY
, ive
);
111 pq
= GETFIELD(IODA2_IVT_Q
, ive
) | (GETFIELD(IODA2_IVT_P
, ive
) << 1);
115 gen
= GETFIELD(IODA2_IVT_GEN
, ive
);
118 * The low order 2 bits are the link pointer (Type II interrupts).
119 * Shift back to get a valid IRQ server.
127 phb3_msi_set_q(msi
, srcno
);
129 /* Enabled, set P and send */
130 phb3_msi_set_p(msi
, srcno
, gen
);
131 icp_irq(ics
, server
, srcno
+ ics
->offset
, prio
);
135 /* Already pending, set Q */
136 phb3_msi_set_q(msi
, srcno
);
141 /* Just drop stuff if Q already set */
146 static void phb3_msi_set_irq(void *opaque
, int srcno
, int val
)
148 Phb3MsiState
*msi
= PHB3_MSI(opaque
);
151 phb3_msi_try_send(msi
, srcno
, false);
156 void pnv_phb3_msi_send(Phb3MsiState
*msi
, uint64_t addr
, uint16_t data
,
159 ICSState
*ics
= ICS(msi
);
162 uint32_t src
= ((addr
>> 4) & 0xffff) | (data
& 0x1f);
164 if (src
>= ics
->nr_irqs
) {
165 qemu_log_mask(LOG_GUEST_ERROR
, "MSI %d out of bounds", src
);
169 if (!phb3_msi_read_ive(msi
->phb
, src
, &ive
)) {
172 pe
= GETFIELD(IODA2_IVT_PE
, ive
);
174 qemu_log_mask(LOG_GUEST_ERROR
,
175 "MSI %d send by PE#%d but assigned to PE#%d",
180 qemu_irq_pulse(msi
->qirqs
[src
]);
183 void pnv_phb3_msi_ffi(Phb3MsiState
*msi
, uint64_t val
)
186 pnv_phb3_msi_send(msi
, val
, 0, -1);
189 msi
->phb
->regs
[PHB_FFI_LOCK
>> 3] = 0;
192 static void phb3_msi_reject(ICSState
*ics
, uint32_t nr
)
194 Phb3MsiState
*msi
= PHB3_MSI(ics
);
195 unsigned int srcno
= nr
- ics
->offset
;
196 unsigned int idx
= srcno
>> 6;
197 unsigned int bit
= 1ull << (srcno
& 0x3f);
199 assert(srcno
< PHB3_MAX_MSI
);
201 msi
->rba
[idx
] |= bit
;
202 msi
->rba_sum
|= (1u << idx
);
205 static void phb3_msi_resend(ICSState
*ics
)
207 Phb3MsiState
*msi
= PHB3_MSI(ics
);
210 if (msi
->rba_sum
== 0) {
214 for (i
= 0; i
< 32; i
++) {
215 if ((msi
->rba_sum
& (1u << i
)) == 0) {
218 msi
->rba_sum
&= ~(1u << i
);
219 for (j
= 0; j
< 64; j
++) {
220 if ((msi
->rba
[i
] & (1ull << j
)) == 0) {
223 msi
->rba
[i
] &= ~(1ull << j
);
224 phb3_msi_try_send(msi
, i
* 64 + j
, true);
229 static void phb3_msi_reset(DeviceState
*dev
)
231 Phb3MsiState
*msi
= PHB3_MSI(dev
);
232 ICSStateClass
*icsc
= ICS_GET_CLASS(dev
);
234 icsc
->parent_reset(dev
);
236 memset(msi
->rba
, 0, sizeof(msi
->rba
));
240 static void phb3_msi_reset_handler(void *dev
)
245 void pnv_phb3_msi_update_config(Phb3MsiState
*msi
, uint32_t base
,
248 ICSState
*ics
= ICS(msi
);
250 if (count
> PHB3_MAX_MSI
) {
251 count
= PHB3_MAX_MSI
;
253 ics
->nr_irqs
= count
;
257 static void phb3_msi_realize(DeviceState
*dev
, Error
**errp
)
259 Phb3MsiState
*msi
= PHB3_MSI(dev
);
260 ICSState
*ics
= ICS(msi
);
261 ICSStateClass
*icsc
= ICS_GET_CLASS(ics
);
262 Error
*local_err
= NULL
;
266 icsc
->parent_realize(dev
, &local_err
);
268 error_propagate(errp
, local_err
);
272 msi
->qirqs
= qemu_allocate_irqs(phb3_msi_set_irq
, msi
, ics
->nr_irqs
);
274 qemu_register_reset(phb3_msi_reset_handler
, dev
);
277 static void phb3_msi_instance_init(Object
*obj
)
279 Phb3MsiState
*msi
= PHB3_MSI(obj
);
280 ICSState
*ics
= ICS(obj
);
282 object_property_add_link(obj
, "phb", TYPE_PNV_PHB3
,
283 (Object
**)&msi
->phb
,
284 object_property_allow_set_link
,
285 OBJ_PROP_LINK_STRONG
);
287 /* Will be overriden later */
291 static void phb3_msi_class_init(ObjectClass
*klass
, void *data
)
293 DeviceClass
*dc
= DEVICE_CLASS(klass
);
294 ICSStateClass
*isc
= ICS_CLASS(klass
);
296 device_class_set_parent_realize(dc
, phb3_msi_realize
,
297 &isc
->parent_realize
);
298 device_class_set_parent_reset(dc
, phb3_msi_reset
,
301 isc
->reject
= phb3_msi_reject
;
302 isc
->resend
= phb3_msi_resend
;
305 static const TypeInfo phb3_msi_info
= {
306 .name
= TYPE_PHB3_MSI
,
308 .instance_size
= sizeof(Phb3MsiState
),
309 .class_init
= phb3_msi_class_init
,
310 .class_size
= sizeof(ICSStateClass
),
311 .instance_init
= phb3_msi_instance_init
,
314 static void pnv_phb3_msi_register_types(void)
316 type_register_static(&phb3_msi_info
);
319 type_init(pnv_phb3_msi_register_types
);
321 void pnv_phb3_msi_pic_print_info(Phb3MsiState
*msi
, Monitor
*mon
)
323 ICSState
*ics
= ICS(msi
);
326 monitor_printf(mon
, "ICS %4x..%4x %p\n",
327 ics
->offset
, ics
->offset
+ ics
->nr_irqs
- 1, ics
);
329 for (i
= 0; i
< ics
->nr_irqs
; i
++) {
332 if (!phb3_msi_read_ive(msi
->phb
, i
, &ive
)) {
336 if (GETFIELD(IODA2_IVT_PRIORITY
, ive
) == 0xff) {
340 monitor_printf(mon
, " %4x %c%c server=%04x prio=%02x gen=%d\n",
342 GETFIELD(IODA2_IVT_P
, ive
) ? 'P' : '-',
343 GETFIELD(IODA2_IVT_Q
, ive
) ? 'Q' : '-',
344 (uint32_t) GETFIELD(IODA2_IVT_SERVER
, ive
) >> 2,
345 (uint32_t) GETFIELD(IODA2_IVT_PRIORITY
, ive
),
346 (uint32_t) GETFIELD(IODA2_IVT_GEN
, ive
));