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 "hw/pci-host/pnv_phb3_regs.h"
13 #include "hw/pci-host/pnv_phb3.h"
14 #include "hw/ppc/pnv.h"
15 #include "hw/pci/msi.h"
17 #include "hw/qdev-properties.h"
18 #include "sysemu/reset.h"
20 static uint64_t phb3_msi_ive_addr(PnvPHB3
*phb
, int srcno
)
22 uint64_t ivtbar
= phb
->regs
[PHB_IVT_BAR
>> 3];
23 uint64_t phbctl
= phb
->regs
[PHB_CONTROL
>> 3];
25 if (!(ivtbar
& PHB_IVT_BAR_ENABLE
)) {
26 qemu_log_mask(LOG_GUEST_ERROR
, "Failed access to disable IVT BAR !");
30 if (srcno
>= (ivtbar
& PHB_IVT_LENGTH_MASK
)) {
31 qemu_log_mask(LOG_GUEST_ERROR
, "MSI out of bounds (%d vs 0x%"PRIx64
")",
32 srcno
, (uint64_t) (ivtbar
& PHB_IVT_LENGTH_MASK
));
36 ivtbar
&= PHB_IVT_BASE_ADDRESS_MASK
;
38 if (phbctl
& PHB_CTRL_IVE_128_BYTES
) {
39 return ivtbar
+ 128 * srcno
;
41 return ivtbar
+ 16 * srcno
;
45 static bool phb3_msi_read_ive(PnvPHB3
*phb
, int srcno
, uint64_t *out_ive
)
47 uint64_t ive_addr
, ive
;
49 ive_addr
= phb3_msi_ive_addr(phb
, srcno
);
54 if (dma_memory_read(&address_space_memory
, ive_addr
,
55 &ive
, sizeof(ive
), MEMTXATTRS_UNSPECIFIED
)) {
56 qemu_log_mask(LOG_GUEST_ERROR
, "Failed to read IVE at 0x%" PRIx64
,
60 *out_ive
= be64_to_cpu(ive
);
65 static void phb3_msi_set_p(Phb3MsiState
*msi
, int srcno
, uint8_t gen
)
68 uint8_t p
= 0x01 | (gen
<< 1);
70 ive_addr
= phb3_msi_ive_addr(msi
->phb
, srcno
);
75 if (dma_memory_write(&address_space_memory
, ive_addr
+ 4,
76 &p
, 1, MEMTXATTRS_UNSPECIFIED
)) {
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,
93 &q
, 1, MEMTXATTRS_UNSPECIFIED
)) {
94 qemu_log_mask(LOG_GUEST_ERROR
,
95 "Failed to write IVE (set Q) at 0x%" PRIx64
, ive_addr
);
99 static void phb3_msi_try_send(Phb3MsiState
*msi
, int srcno
, bool force
)
101 ICSState
*ics
= ICS(msi
);
103 uint64_t server
, prio
, pq
, gen
;
105 if (!phb3_msi_read_ive(msi
->phb
, srcno
, &ive
)) {
109 server
= GETFIELD(IODA2_IVT_SERVER
, ive
);
110 prio
= GETFIELD(IODA2_IVT_PRIORITY
, ive
);
112 pq
= GETFIELD(IODA2_IVT_Q
, ive
) | (GETFIELD(IODA2_IVT_P
, ive
) << 1);
116 gen
= GETFIELD(IODA2_IVT_GEN
, ive
);
119 * The low order 2 bits are the link pointer (Type II interrupts).
120 * Shift back to get a valid IRQ server.
128 phb3_msi_set_q(msi
, srcno
);
130 /* Enabled, set P and send */
131 phb3_msi_set_p(msi
, srcno
, gen
);
132 icp_irq(ics
, server
, srcno
+ ics
->offset
, prio
);
136 /* Already pending, set Q */
137 phb3_msi_set_q(msi
, srcno
);
142 /* Just drop stuff if Q already set */
147 static void phb3_msi_set_irq(void *opaque
, int srcno
, int val
)
149 Phb3MsiState
*msi
= PHB3_MSI(opaque
);
152 phb3_msi_try_send(msi
, srcno
, false);
157 void pnv_phb3_msi_send(Phb3MsiState
*msi
, uint64_t addr
, uint16_t data
,
160 ICSState
*ics
= ICS(msi
);
163 uint32_t src
= ((addr
>> 4) & 0xffff) | (data
& 0x1f);
165 if (src
>= ics
->nr_irqs
) {
166 qemu_log_mask(LOG_GUEST_ERROR
, "MSI %d out of bounds", src
);
170 if (!phb3_msi_read_ive(msi
->phb
, src
, &ive
)) {
173 pe
= GETFIELD(IODA2_IVT_PE
, ive
);
175 qemu_log_mask(LOG_GUEST_ERROR
,
176 "MSI %d send by PE#%d but assigned to PE#%d",
181 qemu_irq_pulse(msi
->qirqs
[src
]);
184 void pnv_phb3_msi_ffi(Phb3MsiState
*msi
, uint64_t val
)
187 pnv_phb3_msi_send(msi
, val
, 0, -1);
190 msi
->phb
->regs
[PHB_FFI_LOCK
>> 3] = 0;
193 static void phb3_msi_reject(ICSState
*ics
, uint32_t nr
)
195 Phb3MsiState
*msi
= PHB3_MSI(ics
);
196 unsigned int srcno
= nr
- ics
->offset
;
197 unsigned int idx
= srcno
>> 6;
198 unsigned int bit
= 1ull << (srcno
& 0x3f);
200 assert(srcno
< PHB3_MAX_MSI
);
202 msi
->rba
[idx
] |= bit
;
203 msi
->rba_sum
|= (1u << idx
);
206 static void phb3_msi_resend(ICSState
*ics
)
208 Phb3MsiState
*msi
= PHB3_MSI(ics
);
211 if (msi
->rba_sum
== 0) {
215 for (i
= 0; i
< 32; i
++) {
216 if ((msi
->rba_sum
& (1u << i
)) == 0) {
219 msi
->rba_sum
&= ~(1u << i
);
220 for (j
= 0; j
< 64; j
++) {
221 if ((msi
->rba
[i
] & (1ull << j
)) == 0) {
224 msi
->rba
[i
] &= ~(1ull << j
);
225 phb3_msi_try_send(msi
, i
* 64 + j
, true);
230 static void phb3_msi_reset_hold(Object
*obj
, ResetType type
)
232 Phb3MsiState
*msi
= PHB3_MSI(obj
);
233 ICSStateClass
*icsc
= ICS_GET_CLASS(obj
);
235 if (icsc
->parent_phases
.hold
) {
236 icsc
->parent_phases
.hold(obj
, type
);
239 memset(msi
->rba
, 0, sizeof(msi
->rba
));
243 void pnv_phb3_msi_update_config(Phb3MsiState
*msi
, uint32_t base
,
246 ICSState
*ics
= ICS(msi
);
248 if (count
> PHB3_MAX_MSI
) {
249 count
= PHB3_MAX_MSI
;
251 ics
->nr_irqs
= count
;
255 static void phb3_msi_realize(DeviceState
*dev
, Error
**errp
)
257 Phb3MsiState
*msi
= PHB3_MSI(dev
);
258 ICSState
*ics
= ICS(msi
);
259 ICSStateClass
*icsc
= ICS_GET_CLASS(ics
);
260 Error
*local_err
= NULL
;
264 icsc
->parent_realize(dev
, &local_err
);
266 error_propagate(errp
, local_err
);
270 msi
->qirqs
= qemu_allocate_irqs(phb3_msi_set_irq
, msi
, ics
->nr_irqs
);
273 static void phb3_msi_instance_init(Object
*obj
)
275 Phb3MsiState
*msi
= PHB3_MSI(obj
);
276 ICSState
*ics
= ICS(obj
);
278 object_property_add_link(obj
, "phb", TYPE_PNV_PHB3
,
279 (Object
**)&msi
->phb
,
280 object_property_allow_set_link
,
281 OBJ_PROP_LINK_STRONG
);
283 /* Will be overridden later */
287 static void phb3_msi_class_init(ObjectClass
*klass
, void *data
)
289 DeviceClass
*dc
= DEVICE_CLASS(klass
);
290 ICSStateClass
*isc
= ICS_CLASS(klass
);
291 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
293 device_class_set_parent_realize(dc
, phb3_msi_realize
,
294 &isc
->parent_realize
);
295 resettable_class_set_parent_phases(rc
, NULL
, phb3_msi_reset_hold
, NULL
,
296 &isc
->parent_phases
);
298 isc
->reject
= phb3_msi_reject
;
299 isc
->resend
= phb3_msi_resend
;
302 static const TypeInfo phb3_msi_info
= {
303 .name
= TYPE_PHB3_MSI
,
305 .instance_size
= sizeof(Phb3MsiState
),
306 .class_init
= phb3_msi_class_init
,
307 .class_size
= sizeof(ICSStateClass
),
308 .instance_init
= phb3_msi_instance_init
,
311 static void pnv_phb3_msi_register_types(void)
313 type_register_static(&phb3_msi_info
);
316 type_init(pnv_phb3_msi_register_types
);
318 void pnv_phb3_msi_pic_print_info(Phb3MsiState
*msi
, GString
*buf
)
320 ICSState
*ics
= ICS(msi
);
323 g_string_append_printf(buf
, "ICS %4x..%4x %p\n",
324 ics
->offset
, ics
->offset
+ ics
->nr_irqs
- 1, ics
);
326 for (i
= 0; i
< ics
->nr_irqs
; i
++) {
329 if (!phb3_msi_read_ive(msi
->phb
, i
, &ive
)) {
333 if (GETFIELD(IODA2_IVT_PRIORITY
, ive
) == 0xff) {
337 g_string_append_printf(buf
, " %4x %c%c server=%04x prio=%02x gen=%d\n",
339 GETFIELD(IODA2_IVT_P
, ive
) ? 'P' : '-',
340 GETFIELD(IODA2_IVT_Q
, ive
) ? 'Q' : '-',
341 (uint32_t) GETFIELD(IODA2_IVT_SERVER
, ive
) >> 2,
342 (uint32_t) GETFIELD(IODA2_IVT_PRIORITY
, ive
),
343 (uint32_t) GETFIELD(IODA2_IVT_GEN
, ive
));