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"
16 #include "monitor/monitor.h"
18 #include "hw/qdev-properties.h"
19 #include "sysemu/reset.h"
21 static uint64_t phb3_msi_ive_addr(PnvPHB3
*phb
, int srcno
)
23 uint64_t ivtbar
= phb
->regs
[PHB_IVT_BAR
>> 3];
24 uint64_t phbctl
= phb
->regs
[PHB_CONTROL
>> 3];
26 if (!(ivtbar
& PHB_IVT_BAR_ENABLE
)) {
27 qemu_log_mask(LOG_GUEST_ERROR
, "Failed access to disable IVT BAR !");
31 if (srcno
>= (ivtbar
& PHB_IVT_LENGTH_MASK
)) {
32 qemu_log_mask(LOG_GUEST_ERROR
, "MSI out of bounds (%d vs 0x%"PRIx64
")",
33 srcno
, (uint64_t) (ivtbar
& PHB_IVT_LENGTH_MASK
));
37 ivtbar
&= PHB_IVT_BASE_ADDRESS_MASK
;
39 if (phbctl
& PHB_CTRL_IVE_128_BYTES
) {
40 return ivtbar
+ 128 * srcno
;
42 return ivtbar
+ 16 * srcno
;
46 static bool phb3_msi_read_ive(PnvPHB3
*phb
, int srcno
, uint64_t *out_ive
)
48 uint64_t ive_addr
, ive
;
50 ive_addr
= phb3_msi_ive_addr(phb
, srcno
);
55 if (dma_memory_read(&address_space_memory
, ive_addr
,
56 &ive
, sizeof(ive
), MEMTXATTRS_UNSPECIFIED
)) {
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,
77 &p
, 1, MEMTXATTRS_UNSPECIFIED
)) {
78 qemu_log_mask(LOG_GUEST_ERROR
,
79 "Failed to write IVE (set P) at 0x%" PRIx64
, ive_addr
);
83 static void phb3_msi_set_q(Phb3MsiState
*msi
, int srcno
)
88 ive_addr
= phb3_msi_ive_addr(msi
->phb
, srcno
);
93 if (dma_memory_write(&address_space_memory
, ive_addr
+ 5,
94 &q
, 1, MEMTXATTRS_UNSPECIFIED
)) {
95 qemu_log_mask(LOG_GUEST_ERROR
,
96 "Failed to write IVE (set Q) at 0x%" PRIx64
, ive_addr
);
100 static void phb3_msi_try_send(Phb3MsiState
*msi
, int srcno
, bool force
)
102 ICSState
*ics
= ICS(msi
);
104 uint64_t server
, prio
, pq
, gen
;
106 if (!phb3_msi_read_ive(msi
->phb
, srcno
, &ive
)) {
110 server
= GETFIELD(IODA2_IVT_SERVER
, ive
);
111 prio
= GETFIELD(IODA2_IVT_PRIORITY
, ive
);
113 pq
= GETFIELD(IODA2_IVT_Q
, ive
) | (GETFIELD(IODA2_IVT_P
, ive
) << 1);
117 gen
= GETFIELD(IODA2_IVT_GEN
, ive
);
120 * The low order 2 bits are the link pointer (Type II interrupts).
121 * Shift back to get a valid IRQ server.
129 phb3_msi_set_q(msi
, srcno
);
131 /* Enabled, set P and send */
132 phb3_msi_set_p(msi
, srcno
, gen
);
133 icp_irq(ics
, server
, srcno
+ ics
->offset
, prio
);
137 /* Already pending, set Q */
138 phb3_msi_set_q(msi
, srcno
);
143 /* Just drop stuff if Q already set */
148 static void phb3_msi_set_irq(void *opaque
, int srcno
, int val
)
150 Phb3MsiState
*msi
= PHB3_MSI(opaque
);
153 phb3_msi_try_send(msi
, srcno
, false);
158 void pnv_phb3_msi_send(Phb3MsiState
*msi
, uint64_t addr
, uint16_t data
,
161 ICSState
*ics
= ICS(msi
);
164 uint32_t src
= ((addr
>> 4) & 0xffff) | (data
& 0x1f);
166 if (src
>= ics
->nr_irqs
) {
167 qemu_log_mask(LOG_GUEST_ERROR
, "MSI %d out of bounds", src
);
171 if (!phb3_msi_read_ive(msi
->phb
, src
, &ive
)) {
174 pe
= GETFIELD(IODA2_IVT_PE
, ive
);
176 qemu_log_mask(LOG_GUEST_ERROR
,
177 "MSI %d send by PE#%d but assigned to PE#%d",
182 qemu_irq_pulse(msi
->qirqs
[src
]);
185 void pnv_phb3_msi_ffi(Phb3MsiState
*msi
, uint64_t val
)
188 pnv_phb3_msi_send(msi
, val
, 0, -1);
191 msi
->phb
->regs
[PHB_FFI_LOCK
>> 3] = 0;
194 static void phb3_msi_reject(ICSState
*ics
, uint32_t nr
)
196 Phb3MsiState
*msi
= PHB3_MSI(ics
);
197 unsigned int srcno
= nr
- ics
->offset
;
198 unsigned int idx
= srcno
>> 6;
199 unsigned int bit
= 1ull << (srcno
& 0x3f);
201 assert(srcno
< PHB3_MAX_MSI
);
203 msi
->rba
[idx
] |= bit
;
204 msi
->rba_sum
|= (1u << idx
);
207 static void phb3_msi_resend(ICSState
*ics
)
209 Phb3MsiState
*msi
= PHB3_MSI(ics
);
212 if (msi
->rba_sum
== 0) {
216 for (i
= 0; i
< 32; i
++) {
217 if ((msi
->rba_sum
& (1u << i
)) == 0) {
220 msi
->rba_sum
&= ~(1u << i
);
221 for (j
= 0; j
< 64; j
++) {
222 if ((msi
->rba
[i
] & (1ull << j
)) == 0) {
225 msi
->rba
[i
] &= ~(1ull << j
);
226 phb3_msi_try_send(msi
, i
* 64 + j
, true);
231 static void phb3_msi_reset(DeviceState
*dev
)
233 Phb3MsiState
*msi
= PHB3_MSI(dev
);
234 ICSStateClass
*icsc
= ICS_GET_CLASS(dev
);
236 icsc
->parent_reset(dev
);
238 memset(msi
->rba
, 0, sizeof(msi
->rba
));
242 static void phb3_msi_reset_handler(void *dev
)
247 void pnv_phb3_msi_update_config(Phb3MsiState
*msi
, uint32_t base
,
250 ICSState
*ics
= ICS(msi
);
252 if (count
> PHB3_MAX_MSI
) {
253 count
= PHB3_MAX_MSI
;
255 ics
->nr_irqs
= count
;
259 static void phb3_msi_realize(DeviceState
*dev
, Error
**errp
)
261 Phb3MsiState
*msi
= PHB3_MSI(dev
);
262 ICSState
*ics
= ICS(msi
);
263 ICSStateClass
*icsc
= ICS_GET_CLASS(ics
);
264 Error
*local_err
= NULL
;
268 icsc
->parent_realize(dev
, &local_err
);
270 error_propagate(errp
, local_err
);
274 msi
->qirqs
= qemu_allocate_irqs(phb3_msi_set_irq
, msi
, ics
->nr_irqs
);
276 qemu_register_reset(phb3_msi_reset_handler
, dev
);
279 static void phb3_msi_instance_init(Object
*obj
)
281 Phb3MsiState
*msi
= PHB3_MSI(obj
);
282 ICSState
*ics
= ICS(obj
);
284 object_property_add_link(obj
, "phb", TYPE_PNV_PHB3
,
285 (Object
**)&msi
->phb
,
286 object_property_allow_set_link
,
287 OBJ_PROP_LINK_STRONG
);
289 /* Will be overriden later */
293 static void phb3_msi_class_init(ObjectClass
*klass
, void *data
)
295 DeviceClass
*dc
= DEVICE_CLASS(klass
);
296 ICSStateClass
*isc
= ICS_CLASS(klass
);
298 device_class_set_parent_realize(dc
, phb3_msi_realize
,
299 &isc
->parent_realize
);
300 device_class_set_parent_reset(dc
, phb3_msi_reset
,
303 isc
->reject
= phb3_msi_reject
;
304 isc
->resend
= phb3_msi_resend
;
307 static const TypeInfo phb3_msi_info
= {
308 .name
= TYPE_PHB3_MSI
,
310 .instance_size
= sizeof(Phb3MsiState
),
311 .class_init
= phb3_msi_class_init
,
312 .class_size
= sizeof(ICSStateClass
),
313 .instance_init
= phb3_msi_instance_init
,
316 static void pnv_phb3_msi_register_types(void)
318 type_register_static(&phb3_msi_info
);
321 type_init(pnv_phb3_msi_register_types
);
323 void pnv_phb3_msi_pic_print_info(Phb3MsiState
*msi
, Monitor
*mon
)
325 ICSState
*ics
= ICS(msi
);
328 monitor_printf(mon
, "ICS %4x..%4x %p\n",
329 ics
->offset
, ics
->offset
+ ics
->nr_irqs
- 1, ics
);
331 for (i
= 0; i
< ics
->nr_irqs
; i
++) {
334 if (!phb3_msi_read_ive(msi
->phb
, i
, &ive
)) {
338 if (GETFIELD(IODA2_IVT_PRIORITY
, ive
) == 0xff) {
342 monitor_printf(mon
, " %4x %c%c server=%04x prio=%02x gen=%d\n",
344 GETFIELD(IODA2_IVT_P
, ive
) ? 'P' : '-',
345 GETFIELD(IODA2_IVT_Q
, ive
) ? 'Q' : '-',
346 (uint32_t) GETFIELD(IODA2_IVT_SERVER
, ive
) >> 2,
347 (uint32_t) GETFIELD(IODA2_IVT_PRIORITY
, ive
),
348 (uint32_t) GETFIELD(IODA2_IVT_GEN
, ive
));