1 /* 2 * QEMU PowerPC PowerNV (POWER8) PHB3 model 3 * 4 * Copyright (c) 2014-2020, IBM Corporation. 5 * 6 * This code is licensed under the GPL version 2 or later. See the 7 * COPYING file in the top-level directory. 8 */ 9 #include "qemu/osdep.h" 10 #include "qemu/log.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" 18 #include "hw/irq.h" 19 #include "hw/qdev-properties.h" 20 #include "sysemu/reset.h" 21 22 static uint64_t phb3_msi_ive_addr(PnvPHB3 *phb, int srcno) 23 { 24 uint64_t ivtbar = phb->regs[PHB_IVT_BAR >> 3]; 25 uint64_t phbctl = phb->regs[PHB_CONTROL >> 3]; 26 27 if (!(ivtbar & PHB_IVT_BAR_ENABLE)) { 28 qemu_log_mask(LOG_GUEST_ERROR, "Failed access to disable IVT BAR !"); 29 return 0; 30 } 31 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)); 35 return 0; 36 } 37 38 ivtbar &= PHB_IVT_BASE_ADDRESS_MASK; 39 40 if (phbctl & PHB_CTRL_IVE_128_BYTES) { 41 return ivtbar + 128 * srcno; 42 } else { 43 return ivtbar + 16 * srcno; 44 } 45 } 46 47 static bool phb3_msi_read_ive(PnvPHB3 *phb, int srcno, uint64_t *out_ive) 48 { 49 uint64_t ive_addr, ive; 50 51 ive_addr = phb3_msi_ive_addr(phb, srcno); 52 if (!ive_addr) { 53 return false; 54 } 55 56 if (dma_memory_read(&address_space_memory, ive_addr, 57 &ive, sizeof(ive), MEMTXATTRS_UNSPECIFIED)) { 58 qemu_log_mask(LOG_GUEST_ERROR, "Failed to read IVE at 0x%" PRIx64, 59 ive_addr); 60 return false; 61 } 62 *out_ive = be64_to_cpu(ive); 63 64 return true; 65 } 66 67 static void phb3_msi_set_p(Phb3MsiState *msi, int srcno, uint8_t gen) 68 { 69 uint64_t ive_addr; 70 uint8_t p = 0x01 | (gen << 1); 71 72 ive_addr = phb3_msi_ive_addr(msi->phb, srcno); 73 if (!ive_addr) { 74 return; 75 } 76 77 if (dma_memory_write(&address_space_memory, ive_addr + 4, 78 &p, 1, MEMTXATTRS_UNSPECIFIED)) { 79 qemu_log_mask(LOG_GUEST_ERROR, 80 "Failed to write IVE (set P) at 0x%" PRIx64, ive_addr); 81 } 82 } 83 84 static void phb3_msi_set_q(Phb3MsiState *msi, int srcno) 85 { 86 uint64_t ive_addr; 87 uint8_t q = 0x01; 88 89 ive_addr = phb3_msi_ive_addr(msi->phb, srcno); 90 if (!ive_addr) { 91 return; 92 } 93 94 if (dma_memory_write(&address_space_memory, ive_addr + 5, 95 &q, 1, MEMTXATTRS_UNSPECIFIED)) { 96 qemu_log_mask(LOG_GUEST_ERROR, 97 "Failed to write IVE (set Q) at 0x%" PRIx64, ive_addr); 98 } 99 } 100 101 static void phb3_msi_try_send(Phb3MsiState *msi, int srcno, bool force) 102 { 103 ICSState *ics = ICS(msi); 104 uint64_t ive; 105 uint64_t server, prio, pq, gen; 106 107 if (!phb3_msi_read_ive(msi->phb, srcno, &ive)) { 108 return; 109 } 110 111 server = GETFIELD(IODA2_IVT_SERVER, ive); 112 prio = GETFIELD(IODA2_IVT_PRIORITY, ive); 113 if (!force) { 114 pq = GETFIELD(IODA2_IVT_Q, ive) | (GETFIELD(IODA2_IVT_P, ive) << 1); 115 } else { 116 pq = 0; 117 } 118 gen = GETFIELD(IODA2_IVT_GEN, ive); 119 120 /* 121 * The low order 2 bits are the link pointer (Type II interrupts). 122 * Shift back to get a valid IRQ server. 123 */ 124 server >>= 2; 125 126 switch (pq) { 127 case 0: /* 00 */ 128 if (prio == 0xff) { 129 /* Masked, set Q */ 130 phb3_msi_set_q(msi, srcno); 131 } else { 132 /* Enabled, set P and send */ 133 phb3_msi_set_p(msi, srcno, gen); 134 icp_irq(ics, server, srcno + ics->offset, prio); 135 } 136 break; 137 case 2: /* 10 */ 138 /* Already pending, set Q */ 139 phb3_msi_set_q(msi, srcno); 140 break; 141 case 1: /* 01 */ 142 case 3: /* 11 */ 143 default: 144 /* Just drop stuff if Q already set */ 145 break; 146 } 147 } 148 149 static void phb3_msi_set_irq(void *opaque, int srcno, int val) 150 { 151 Phb3MsiState *msi = PHB3_MSI(opaque); 152 153 if (val) { 154 phb3_msi_try_send(msi, srcno, false); 155 } 156 } 157 158 159 void pnv_phb3_msi_send(Phb3MsiState *msi, uint64_t addr, uint16_t data, 160 int32_t dev_pe) 161 { 162 ICSState *ics = ICS(msi); 163 uint64_t ive; 164 uint16_t pe; 165 uint32_t src = ((addr >> 4) & 0xffff) | (data & 0x1f); 166 167 if (src >= ics->nr_irqs) { 168 qemu_log_mask(LOG_GUEST_ERROR, "MSI %d out of bounds", src); 169 return; 170 } 171 if (dev_pe >= 0) { 172 if (!phb3_msi_read_ive(msi->phb, src, &ive)) { 173 return; 174 } 175 pe = GETFIELD(IODA2_IVT_PE, ive); 176 if (pe != dev_pe) { 177 qemu_log_mask(LOG_GUEST_ERROR, 178 "MSI %d send by PE#%d but assigned to PE#%d", 179 src, dev_pe, pe); 180 return; 181 } 182 } 183 qemu_irq_pulse(msi->qirqs[src]); 184 } 185 186 void pnv_phb3_msi_ffi(Phb3MsiState *msi, uint64_t val) 187 { 188 /* Emit interrupt */ 189 pnv_phb3_msi_send(msi, val, 0, -1); 190 191 /* Clear FFI lock */ 192 msi->phb->regs[PHB_FFI_LOCK >> 3] = 0; 193 } 194 195 static void phb3_msi_reject(ICSState *ics, uint32_t nr) 196 { 197 Phb3MsiState *msi = PHB3_MSI(ics); 198 unsigned int srcno = nr - ics->offset; 199 unsigned int idx = srcno >> 6; 200 unsigned int bit = 1ull << (srcno & 0x3f); 201 202 assert(srcno < PHB3_MAX_MSI); 203 204 msi->rba[idx] |= bit; 205 msi->rba_sum |= (1u << idx); 206 } 207 208 static void phb3_msi_resend(ICSState *ics) 209 { 210 Phb3MsiState *msi = PHB3_MSI(ics); 211 unsigned int i, j; 212 213 if (msi->rba_sum == 0) { 214 return; 215 } 216 217 for (i = 0; i < 32; i++) { 218 if ((msi->rba_sum & (1u << i)) == 0) { 219 continue; 220 } 221 msi->rba_sum &= ~(1u << i); 222 for (j = 0; j < 64; j++) { 223 if ((msi->rba[i] & (1ull << j)) == 0) { 224 continue; 225 } 226 msi->rba[i] &= ~(1ull << j); 227 phb3_msi_try_send(msi, i * 64 + j, true); 228 } 229 } 230 } 231 232 static void phb3_msi_reset(DeviceState *dev) 233 { 234 Phb3MsiState *msi = PHB3_MSI(dev); 235 ICSStateClass *icsc = ICS_GET_CLASS(dev); 236 237 icsc->parent_reset(dev); 238 239 memset(msi->rba, 0, sizeof(msi->rba)); 240 msi->rba_sum = 0; 241 } 242 243 static void phb3_msi_reset_handler(void *dev) 244 { 245 phb3_msi_reset(dev); 246 } 247 248 void pnv_phb3_msi_update_config(Phb3MsiState *msi, uint32_t base, 249 uint32_t count) 250 { 251 ICSState *ics = ICS(msi); 252 253 if (count > PHB3_MAX_MSI) { 254 count = PHB3_MAX_MSI; 255 } 256 ics->nr_irqs = count; 257 ics->offset = base; 258 } 259 260 static void phb3_msi_realize(DeviceState *dev, Error **errp) 261 { 262 Phb3MsiState *msi = PHB3_MSI(dev); 263 ICSState *ics = ICS(msi); 264 ICSStateClass *icsc = ICS_GET_CLASS(ics); 265 Error *local_err = NULL; 266 267 assert(msi->phb); 268 269 icsc->parent_realize(dev, &local_err); 270 if (local_err) { 271 error_propagate(errp, local_err); 272 return; 273 } 274 275 msi->qirqs = qemu_allocate_irqs(phb3_msi_set_irq, msi, ics->nr_irqs); 276 277 qemu_register_reset(phb3_msi_reset_handler, dev); 278 } 279 280 static void phb3_msi_instance_init(Object *obj) 281 { 282 Phb3MsiState *msi = PHB3_MSI(obj); 283 ICSState *ics = ICS(obj); 284 285 object_property_add_link(obj, "phb", TYPE_PNV_PHB3, 286 (Object **)&msi->phb, 287 object_property_allow_set_link, 288 OBJ_PROP_LINK_STRONG); 289 290 /* Will be overriden later */ 291 ics->offset = 0; 292 } 293 294 static void phb3_msi_class_init(ObjectClass *klass, void *data) 295 { 296 DeviceClass *dc = DEVICE_CLASS(klass); 297 ICSStateClass *isc = ICS_CLASS(klass); 298 299 device_class_set_parent_realize(dc, phb3_msi_realize, 300 &isc->parent_realize); 301 device_class_set_parent_reset(dc, phb3_msi_reset, 302 &isc->parent_reset); 303 304 isc->reject = phb3_msi_reject; 305 isc->resend = phb3_msi_resend; 306 } 307 308 static const TypeInfo phb3_msi_info = { 309 .name = TYPE_PHB3_MSI, 310 .parent = TYPE_ICS, 311 .instance_size = sizeof(Phb3MsiState), 312 .class_init = phb3_msi_class_init, 313 .class_size = sizeof(ICSStateClass), 314 .instance_init = phb3_msi_instance_init, 315 }; 316 317 static void pnv_phb3_msi_register_types(void) 318 { 319 type_register_static(&phb3_msi_info); 320 } 321 322 type_init(pnv_phb3_msi_register_types); 323 324 void pnv_phb3_msi_pic_print_info(Phb3MsiState *msi, Monitor *mon) 325 { 326 ICSState *ics = ICS(msi); 327 int i; 328 329 monitor_printf(mon, "ICS %4x..%4x %p\n", 330 ics->offset, ics->offset + ics->nr_irqs - 1, ics); 331 332 for (i = 0; i < ics->nr_irqs; i++) { 333 uint64_t ive; 334 335 if (!phb3_msi_read_ive(msi->phb, i, &ive)) { 336 return; 337 } 338 339 if (GETFIELD(IODA2_IVT_PRIORITY, ive) == 0xff) { 340 continue; 341 } 342 343 monitor_printf(mon, " %4x %c%c server=%04x prio=%02x gen=%d\n", 344 ics->offset + i, 345 GETFIELD(IODA2_IVT_P, ive) ? 'P' : '-', 346 GETFIELD(IODA2_IVT_Q, ive) ? 'Q' : '-', 347 (uint32_t) GETFIELD(IODA2_IVT_SERVER, ive) >> 2, 348 (uint32_t) GETFIELD(IODA2_IVT_PRIORITY, ive), 349 (uint32_t) GETFIELD(IODA2_IVT_GEN, ive)); 350 } 351 } 352