1 /* 2 * HP-PARISC Astro/Pluto/Ike/REO system bus adapter (SBA) 3 * with Elroy PCI bus (LBA) adapter emulation 4 * Found in C3000 and similar machines 5 * 6 * (C) 2023 by Helge Deller <deller@gmx.de> 7 * 8 * This work is licensed under the GNU GPL license version 2 or later. 9 * 10 * Chip documentation is available at: 11 * https://parisc.wiki.kernel.org/index.php/Technical_Documentation 12 * 13 * TODO: 14 * - All user-added devices are currently attached to the first 15 * Elroy (PCI bus) only for now. To fix this additional work in 16 * SeaBIOS and this driver is needed. See "user_creatable" flag below. 17 * - GMMIO (Greater than 4 GB MMIO) register 18 */ 19 20 #define TYPE_ASTRO_IOMMU_MEMORY_REGION "astro-iommu-memory-region" 21 22 #define F_EXTEND(addr) ((addr) | MAKE_64BIT_MASK(32, 32)) 23 24 #include "qemu/osdep.h" 25 #include "qemu/module.h" 26 #include "qemu/units.h" 27 #include "qapi/error.h" 28 #include "hw/irq.h" 29 #include "hw/pci/pci_device.h" 30 #include "hw/pci/pci_bus.h" 31 #include "hw/qdev-properties.h" 32 #include "hw/pci-host/astro.h" 33 #include "hw/hppa/hppa_hardware.h" 34 #include "migration/vmstate.h" 35 #include "target/hppa/cpu.h" 36 #include "trace.h" 37 #include "qom/object.h" 38 #include "exec/target_page.h" 39 40 /* 41 * Helper functions 42 */ 43 44 static uint64_t mask_32bit_val(hwaddr addr, unsigned size, uint64_t val) 45 { 46 if (size == 8) { 47 return val; 48 } 49 if (addr & 4) { 50 val >>= 32; 51 } else { 52 val = (uint32_t) val; 53 } 54 return val; 55 } 56 57 static void put_val_in_int64(uint64_t *p, hwaddr addr, unsigned size, 58 uint64_t val) 59 { 60 if (size == 8) { 61 *p = val; 62 } else if (size == 4) { 63 if (addr & 4) { 64 *p = ((*p << 32) >> 32) | (val << 32); 65 } else { 66 *p = ((*p >> 32) << 32) | (uint32_t) val; 67 } 68 } 69 } 70 71 static void put_val_in_arrary(uint64_t *array, hwaddr start_addr, 72 hwaddr addr, unsigned size, uint64_t val) 73 { 74 int index; 75 76 index = (addr - start_addr) / 8; 77 put_val_in_int64(&array[index], addr, size, val); 78 } 79 80 81 /* 82 * The Elroy PCI host bridge. We have at least 4 of those under Astro. 83 */ 84 85 static MemTxResult elroy_chip_read_with_attrs(void *opaque, hwaddr addr, 86 uint64_t *data, unsigned size, 87 MemTxAttrs attrs) 88 { 89 MemTxResult ret = MEMTX_OK; 90 ElroyState *s = opaque; 91 uint64_t val = -1; 92 int index; 93 94 switch ((addr >> 3) << 3) { 95 case 0x0008: 96 val = 0x6000005; /* func_class */ 97 break; 98 case 0x0058: 99 /* 100 * Scratch register, but firmware initializes it with the 101 * PCI BUS number and Linux/HP-UX uses it then. 102 */ 103 val = s->pci_bus_num; 104 /* Upper byte holds the end of this bus number */ 105 val |= s->pci_bus_num << 8; 106 break; 107 case 0x0080: 108 val = s->arb_mask; /* set ARB mask */ 109 break; 110 case 0x0108: 111 val = s->status_control; 112 break; 113 case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */ 114 index = (addr - 0x200) / 8; 115 val = s->mmio_base[index]; 116 break; 117 case 0x0680: 118 val = s->error_config; 119 break; 120 case 0x0688: 121 val = 0; /* ERROR_STATUS */ 122 break; 123 case 0x0800: /* IOSAPIC_REG_SELECT */ 124 val = s->iosapic_reg_select; 125 break; 126 case 0x0810: /* IOSAPIC_REG_WINDOW */ 127 switch (s->iosapic_reg_select) { 128 case 0x01: /* IOSAPIC_REG_VERSION */ 129 val = (32 << 16) | 1; /* upper 16bit holds max entries */ 130 break; 131 default: 132 if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) { 133 val = s->iosapic_reg[s->iosapic_reg_select]; 134 } else { 135 goto check_hf; 136 } 137 } 138 trace_iosapic_reg_read(s->iosapic_reg_select, size, val); 139 break; 140 default: 141 check_hf: 142 if (s->status_control & HF_ENABLE) { 143 val = 0; 144 ret = MEMTX_DECODE_ERROR; 145 } else { 146 /* return -1ULL if HardFail is disabled */ 147 val = ~0; 148 ret = MEMTX_OK; 149 } 150 } 151 trace_elroy_read(addr, size, val); 152 153 /* for 32-bit accesses mask return value */ 154 val = mask_32bit_val(addr, size, val); 155 156 trace_astro_chip_read(addr, size, val); 157 *data = val; 158 return ret; 159 } 160 161 162 static MemTxResult elroy_chip_write_with_attrs(void *opaque, hwaddr addr, 163 uint64_t val, unsigned size, 164 MemTxAttrs attrs) 165 { 166 ElroyState *s = opaque; 167 int i; 168 169 trace_elroy_write(addr, size, val); 170 171 switch ((addr >> 3) << 3) { 172 case 0x000: /* PCI_ID & PCI_COMMAND_STATUS_REG */ 173 break; 174 case 0x080: 175 put_val_in_int64(&s->arb_mask, addr, size, val); 176 break; 177 case 0x0108: 178 put_val_in_int64(&s->status_control, addr, size, val); 179 break; 180 case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */ 181 put_val_in_arrary(s->mmio_base, 0x200, addr, size, val); 182 break; 183 case 0x300: /* ibase */ 184 case 0x308: /* imask */ 185 break; 186 case 0x0680: 187 put_val_in_int64(&s->error_config, addr, size, val); 188 break; 189 case 0x0800: /* IOSAPIC_REG_SELECT */ 190 s->iosapic_reg_select = val; 191 break; 192 case 0x0810: /* IOSAPIC_REG_WINDOW */ 193 trace_iosapic_reg_write(s->iosapic_reg_select, size, val); 194 if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) { 195 s->iosapic_reg[s->iosapic_reg_select] = val; 196 } else { 197 goto check_hf; 198 } 199 break; 200 case 0x0840: /* IOSAPIC_REG_EOI */ 201 val = le64_to_cpu(val); 202 val &= 63; 203 for (i = 0; i < ELROY_IRQS; i++) { 204 if ((s->iosapic_reg[0x10 + 2 * i] & 63) == val) { 205 s->ilr &= ~(1ull << i); 206 } 207 } 208 break; 209 default: 210 check_hf: 211 if (s->status_control & HF_ENABLE) { 212 return MEMTX_DECODE_ERROR; 213 } 214 } 215 return MEMTX_OK; 216 } 217 218 static const MemoryRegionOps elroy_chip_ops = { 219 .read_with_attrs = elroy_chip_read_with_attrs, 220 .write_with_attrs = elroy_chip_write_with_attrs, 221 .endianness = DEVICE_LITTLE_ENDIAN, 222 .valid = { 223 .min_access_size = 4, 224 .max_access_size = 8, 225 }, 226 .impl = { 227 .min_access_size = 4, 228 .max_access_size = 8, 229 }, 230 }; 231 232 233 /* Unlike pci_config_data_le_ops, no check of high bit set in config_reg. */ 234 235 static uint64_t elroy_config_data_read(void *opaque, hwaddr addr, unsigned len) 236 { 237 uint64_t val; 238 239 PCIHostState *s = opaque; 240 val = pci_data_read(s->bus, s->config_reg | (addr & 3), len); 241 trace_elroy_pci_config_data_read(s->config_reg | (addr & 3), len, val); 242 return val; 243 } 244 245 static void elroy_config_data_write(void *opaque, hwaddr addr, 246 uint64_t val, unsigned len) 247 { 248 PCIHostState *s = opaque; 249 pci_data_write(s->bus, s->config_reg | (addr & 3), val, len); 250 trace_elroy_pci_config_data_write(s->config_reg | (addr & 3), len, val); 251 } 252 253 static const MemoryRegionOps elroy_config_data_ops = { 254 .read = elroy_config_data_read, 255 .write = elroy_config_data_write, 256 .endianness = DEVICE_LITTLE_ENDIAN, 257 }; 258 259 static uint64_t elroy_config_addr_read(void *opaque, hwaddr addr, unsigned len) 260 { 261 ElroyState *s = opaque; 262 return s->config_reg_elroy; 263 } 264 265 static void elroy_config_addr_write(void *opaque, hwaddr addr, 266 uint64_t val, unsigned len) 267 { 268 PCIHostState *s = opaque; 269 ElroyState *es = opaque; 270 es->config_reg_elroy = val; /* keep a copy of original value */ 271 s->config_reg = val; 272 } 273 274 static const MemoryRegionOps elroy_config_addr_ops = { 275 .read = elroy_config_addr_read, 276 .write = elroy_config_addr_write, 277 .valid.min_access_size = 4, 278 .valid.max_access_size = 8, 279 .endianness = DEVICE_LITTLE_ENDIAN, 280 }; 281 282 283 /* Handle PCI-to-system address translation. */ 284 static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu, 285 hwaddr addr, 286 IOMMUAccessFlags flag, 287 int iommu_idx) 288 { 289 AstroState *s = container_of(iommu, AstroState, iommu); 290 hwaddr pdir_ptr, index, ibase; 291 hwaddr addr_mask = 0xfff; /* 4k translation */ 292 uint64_t entry; 293 294 #define IOVP_SHIFT 12 /* equals PAGE_SHIFT */ 295 #define PDIR_INDEX(iovp) ((iovp) >> IOVP_SHIFT) 296 #define SBA_PDIR_VALID_BIT 0x8000000000000000ULL 297 298 addr &= ~addr_mask; 299 300 /* 301 * Default translation: "32-bit PCI Addressing on 40-bit Runway". 302 * For addresses in the 32-bit memory address range ... and then 303 * language which not-coincidentally matches the PSW.W=0 mapping. 304 */ 305 if (addr <= UINT32_MAX) { 306 entry = hppa_abs_to_phys_pa2_w0(addr); 307 } else { 308 entry = addr; 309 } 310 311 /* "range enable" flag cleared? */ 312 if ((s->tlb_ibase & 1) == 0) { 313 goto skip; 314 } 315 316 ibase = s->tlb_ibase & ~1ULL; 317 if ((addr & s->tlb_imask) != ibase) { 318 /* do not translate this one! */ 319 goto skip; 320 } 321 322 index = PDIR_INDEX(addr); 323 pdir_ptr = s->tlb_pdir_base + index * sizeof(entry); 324 entry = ldq_le_phys(&address_space_memory, pdir_ptr); 325 326 if (!(entry & SBA_PDIR_VALID_BIT)) { /* I/O PDIR entry valid ? */ 327 /* failure */ 328 return (IOMMUTLBEntry) { .perm = IOMMU_NONE }; 329 } 330 331 entry &= ~SBA_PDIR_VALID_BIT; 332 entry >>= IOVP_SHIFT; 333 entry <<= 12; 334 335 skip: 336 return (IOMMUTLBEntry) { 337 .target_as = &address_space_memory, 338 .iova = addr, 339 .translated_addr = entry, 340 .addr_mask = addr_mask, 341 .perm = IOMMU_RW, 342 }; 343 } 344 345 static AddressSpace *elroy_pcihost_set_iommu(PCIBus *bus, void *opaque, 346 int devfn) 347 { 348 ElroyState *s = opaque; 349 return &s->astro->iommu_as; 350 } 351 352 static const PCIIOMMUOps elroy_pcihost_iommu_ops = { 353 .get_address_space = elroy_pcihost_set_iommu, 354 }; 355 356 /* 357 * Encoding in IOSAPIC: 358 * base_addr == 0xfffa0000, we want to get 0xa0ff0000. 359 * eid 0x0ff00000 -> 0x00ff0000 360 * id 0x000ff000 -> 0xff000000 361 */ 362 #define SWIZZLE_HPA(a) \ 363 ((((a) & 0x0ff00000) >> 4) | (((a) & 0x000ff000) << 12)) 364 #define UNSWIZZLE_HPA(a) \ 365 (((((a) << 4) & 0x0ff00000) | (((a) >> 12) & 0x000ff000) | 0xf0000000)) 366 367 /* bits in the "low" I/O Sapic IRdT entry */ 368 #define IOSAPIC_IRDT_DISABLE 0x10000 /* if bit is set, mask this irq */ 369 #define IOSAPIC_IRDT_PO_LOW 0x02000 370 #define IOSAPIC_IRDT_LEVEL_TRIG 0x08000 371 #define IOSAPIC_IRDT_MODE_LPRI 0x00100 372 373 #define CPU_IRQ_OFFSET 2 374 375 static void elroy_set_irq(void *opaque, int irq, int level) 376 { 377 ElroyState *s = opaque; 378 uint32_t bit; 379 uint32_t old_ilr = s->ilr; 380 hwaddr cpu_hpa; 381 uint32_t val; 382 383 val = s->iosapic_reg[0x10 + 2 * irq]; 384 cpu_hpa = s->iosapic_reg[0x11 + 2 * irq]; 385 /* low nibble of val has value to write into CPU irq reg */ 386 bit = 1u << (val & (ELROY_IRQS - 1)); 387 cpu_hpa = UNSWIZZLE_HPA(cpu_hpa); 388 389 if (level && (!(val & IOSAPIC_IRDT_DISABLE)) && cpu_hpa) { 390 uint32_t ena = bit & ~old_ilr; 391 s->ilr = old_ilr | bit; 392 if (ena != 0) { 393 stl_be_phys(&address_space_memory, F_EXTEND(cpu_hpa), val & 63); 394 } 395 } else { 396 s->ilr = old_ilr & ~bit; 397 } 398 } 399 400 static int elroy_pci_map_irq(PCIDevice *d, int irq_num) 401 { 402 int slot = PCI_SLOT(d->devfn); 403 404 assert(irq_num >= 0 && irq_num < ELROY_IRQS); 405 return slot & (ELROY_IRQS - 1); 406 } 407 408 static void elroy_reset(DeviceState *dev) 409 { 410 ElroyState *s = ELROY_PCI_HOST_BRIDGE(dev); 411 int irq; 412 413 /* 414 * Make sure to disable interrupts at reboot, otherwise the Linux kernel 415 * serial8250_config_port() in drivers/tty/serial/8250/8250_port.c 416 * will hang during autoconfig(). 417 */ 418 s->ilr = 0; 419 for (irq = 0; irq < ELROY_IRQS; irq++) { 420 s->iosapic_reg[0x10 + 2 * irq] = IOSAPIC_IRDT_PO_LOW | 421 IOSAPIC_IRDT_LEVEL_TRIG | (irq + CPU_IRQ_OFFSET) | 422 IOSAPIC_IRDT_DISABLE; 423 s->iosapic_reg[0x11 + 2 * irq] = SWIZZLE_HPA(CPU_HPA); 424 } 425 } 426 427 static void elroy_pcihost_realize(DeviceState *dev, Error **errp) 428 { 429 ElroyState *s = ELROY_PCI_HOST_BRIDGE(dev); 430 PCIHostState *phb = PCI_HOST_BRIDGE(dev); 431 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 432 Object *obj = OBJECT(s); 433 434 /* Elroy config access from CPU. */ 435 memory_region_init_io(&s->this_mem, obj, &elroy_chip_ops, 436 s, "elroy", 0x2000); 437 438 /* Elroy PCI config. */ 439 memory_region_init_io(&phb->conf_mem, obj, 440 &elroy_config_addr_ops, dev, 441 "pci-conf-idx", 8); 442 memory_region_init_io(&phb->data_mem, obj, 443 &elroy_config_data_ops, dev, 444 "pci-conf-data", 8); 445 memory_region_add_subregion(&s->this_mem, 0x40, 446 &phb->conf_mem); 447 memory_region_add_subregion(&s->this_mem, 0x48, 448 &phb->data_mem); 449 450 /* Elroy PCI bus memory. */ 451 memory_region_init(&s->pci_mmio, obj, "pci-mmio", UINT64_MAX); 452 memory_region_init_io(&s->pci_io, obj, &unassigned_io_ops, obj, 453 "pci-isa-mmio", 454 ((uint32_t) IOS_DIST_BASE_SIZE) / ROPES_PER_IOC); 455 456 phb->bus = pci_register_root_bus(DEVICE(s), "pci", 457 elroy_set_irq, elroy_pci_map_irq, s, 458 &s->pci_mmio, &s->pci_io, 459 PCI_DEVFN(0, 0), ELROY_IRQS, TYPE_PCI_BUS); 460 461 sysbus_init_mmio(sbd, &s->this_mem); 462 463 qdev_init_gpio_in(dev, elroy_set_irq, ELROY_IRQS); 464 } 465 466 static const VMStateDescription vmstate_elroy = { 467 .name = "Elroy", 468 .version_id = 1, 469 .minimum_version_id = 1, 470 .fields = (const VMStateField[]) { 471 VMSTATE_UINT64(hpa, ElroyState), 472 VMSTATE_UINT32(pci_bus_num, ElroyState), 473 VMSTATE_UINT64(config_address, ElroyState), 474 VMSTATE_UINT64(config_reg_elroy, ElroyState), 475 VMSTATE_UINT64(status_control, ElroyState), 476 VMSTATE_UINT64(arb_mask, ElroyState), 477 VMSTATE_UINT64_ARRAY(mmio_base, ElroyState, (0x0250 - 0x200) / 8), 478 VMSTATE_UINT64(error_config, ElroyState), 479 VMSTATE_UINT32(iosapic_reg_select, ElroyState), 480 VMSTATE_UINT64_ARRAY(iosapic_reg, ElroyState, 0x20), 481 VMSTATE_UINT32(ilr, ElroyState), 482 VMSTATE_END_OF_LIST() 483 } 484 }; 485 486 static void elroy_pcihost_class_init(ObjectClass *klass, const void *data) 487 { 488 DeviceClass *dc = DEVICE_CLASS(klass); 489 490 device_class_set_legacy_reset(dc, elroy_reset); 491 dc->realize = elroy_pcihost_realize; 492 dc->vmsd = &vmstate_elroy; 493 dc->user_creatable = false; 494 } 495 496 static const TypeInfo elroy_pcihost_info = { 497 .name = TYPE_ELROY_PCI_HOST_BRIDGE, 498 .parent = TYPE_PCI_HOST_BRIDGE, 499 .instance_size = sizeof(ElroyState), 500 .class_init = elroy_pcihost_class_init, 501 }; 502 503 static void elroy_register_types(void) 504 { 505 type_register_static(&elroy_pcihost_info); 506 } 507 508 type_init(elroy_register_types) 509 510 511 static ElroyState *elroy_init(int num) 512 { 513 DeviceState *dev; 514 515 dev = qdev_new(TYPE_ELROY_PCI_HOST_BRIDGE); 516 dev->id = g_strdup_printf("elroy%d", num); 517 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 518 519 return ELROY_PCI_HOST_BRIDGE(dev); 520 } 521 522 /* 523 * Astro Runway chip. 524 */ 525 526 static void adjust_LMMIO_DIRECT_mapping(AstroState *s, unsigned int reg_index) 527 { 528 MemoryRegion *lmmio_alias; 529 unsigned int lmmio_index, map_route; 530 hwaddr map_addr; 531 uint32_t map_size; 532 struct ElroyState *elroy; 533 534 /* pointer to LMMIO_DIRECT entry */ 535 lmmio_index = reg_index / 3; 536 lmmio_alias = &s->lmmio_direct[lmmio_index]; 537 538 map_addr = s->ioc_ranges[3 * lmmio_index + 0]; 539 map_size = s->ioc_ranges[3 * lmmio_index + 1]; 540 map_route = s->ioc_ranges[3 * lmmio_index + 2]; 541 542 /* find elroy to which this address is routed */ 543 map_route &= (ELROY_NUM - 1); 544 elroy = s->elroy[map_route]; 545 546 if (lmmio_alias->enabled) { 547 memory_region_set_enabled(lmmio_alias, false); 548 } 549 550 map_addr = F_EXTEND(map_addr); 551 map_addr &= TARGET_PAGE_MASK; 552 map_size = (~map_size) + 1; 553 map_size &= TARGET_PAGE_MASK; 554 555 /* exit if disabled or zero map size */ 556 if (!(map_addr & 1) || !map_size) { 557 return; 558 } 559 560 if (!memory_region_size(lmmio_alias)) { 561 memory_region_init_alias(lmmio_alias, OBJECT(elroy), 562 "pci-lmmmio-alias", &elroy->pci_mmio, 563 (uint32_t) map_addr, map_size); 564 memory_region_add_subregion(get_system_memory(), map_addr, 565 lmmio_alias); 566 } else { 567 memory_region_set_alias_offset(lmmio_alias, map_addr); 568 memory_region_set_size(lmmio_alias, map_size); 569 memory_region_set_enabled(lmmio_alias, true); 570 } 571 } 572 573 static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr, 574 uint64_t *data, unsigned size, 575 MemTxAttrs attrs) 576 { 577 AstroState *s = opaque; 578 MemTxResult ret = MEMTX_OK; 579 uint64_t val = -1; 580 int index; 581 582 switch ((addr >> 3) << 3) { 583 /* R2I registers */ 584 case 0x0000: /* ID */ 585 val = (0x01 << 3) | 0x01ULL; 586 break; 587 case 0x0008: /* IOC_CTRL */ 588 val = s->ioc_ctrl; 589 break; 590 case 0x0010: /* TOC_CLIENT_ID */ 591 break; 592 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */ 593 val = -1; 594 break; 595 case 0x0078: /* NetBSD reads 0x78 ? */ 596 val = -1; 597 break; 598 case 0x0300 ... 0x03d8: /* LMMIO_DIRECT0_BASE... */ 599 index = (addr - 0x300) / 8; 600 val = s->ioc_ranges[index]; 601 break; 602 case 0x10200: 603 val = 0; 604 break; 605 case 0x10220: 606 case 0x10230: /* HP-UX 11.11 reads it. No idea. */ 607 val = -1; 608 break; 609 case 0x22108: /* IOC STATUS_CONTROL */ 610 val = s->ioc_status_ctrl; 611 break; 612 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */ 613 index = (addr - 0x20200) / 8; 614 val = s->ioc_rope_control[index]; 615 break; 616 case 0x20040: /* IOC Rope config */ 617 val = s->ioc_rope_config; 618 break; 619 case 0x20050: /* IOC Rope debug */ 620 val = 0; 621 break; 622 case 0x20108: /* IOC STATUS_CONTROL */ 623 val = s->ioc_status_control; 624 break; 625 case 0x20310: /* IOC_PCOM */ 626 val = s->tlb_pcom; 627 /* TODO: flush iommu */ 628 break; 629 case 0x20400: 630 val = s->ioc_flush_control; 631 break; 632 /* empty placeholders for non-existent elroys */ 633 #define EMPTY_PORT(x) case x: case x+8: val = 0; break; \ 634 case x+40: case x+48: val = UINT64_MAX; break; 635 EMPTY_PORT(0x30000) 636 EMPTY_PORT(0x32000) 637 EMPTY_PORT(0x34000) 638 EMPTY_PORT(0x36000) 639 EMPTY_PORT(0x38000) 640 EMPTY_PORT(0x3a000) 641 EMPTY_PORT(0x3c000) 642 EMPTY_PORT(0x3e000) 643 #undef EMPTY_PORT 644 645 default: 646 val = 0; 647 ret = MEMTX_DECODE_ERROR; 648 } 649 650 /* for 32-bit accesses mask return value */ 651 val = mask_32bit_val(addr, size, val); 652 653 trace_astro_chip_read(addr, size, val); 654 *data = val; 655 return ret; 656 } 657 658 static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr, 659 uint64_t val, unsigned size, 660 MemTxAttrs attrs) 661 { 662 MemTxResult ret = MEMTX_OK; 663 AstroState *s = opaque; 664 665 trace_astro_chip_write(addr, size, val); 666 667 switch ((addr >> 3) << 3) { 668 case 0x0000: /* ID */ 669 break; 670 case 0x0008: /* IOC_CTRL */ 671 val &= 0x0ffffff; 672 put_val_in_int64(&s->ioc_ctrl, addr, size, val); 673 break; 674 case 0x0010: /* TOC_CLIENT_ID */ 675 break; 676 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */ 677 break; 678 case 0x0300 ... 0x03d8 - 1: /* LMMIO_DIRECT0_BASE... */ 679 put_val_in_arrary(s->ioc_ranges, 0x300, addr, size, val); 680 unsigned int index = (addr - 0x300) / 8; 681 /* check if one of the 4 LMMIO_DIRECT regs, each using 3 entries. */ 682 if (index < LMMIO_DIRECT_RANGES * 3) { 683 adjust_LMMIO_DIRECT_mapping(s, index); 684 } 685 break; 686 case 0x10200: 687 case 0x10220: 688 case 0x10230: /* HP-UX 11.11 reads it. No idea. */ 689 break; 690 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */ 691 put_val_in_arrary(s->ioc_rope_control, 0x20200, addr, size, val); 692 break; 693 case 0x20040: /* IOC Rope config */ 694 case 0x22040: 695 put_val_in_int64(&s->ioc_rope_config, addr, size, val); 696 break; 697 case 0x20300: 698 case 0x22300: 699 put_val_in_int64(&s->tlb_ibase, addr, size, val); 700 break; 701 case 0x20308: 702 case 0x22308: 703 put_val_in_int64(&s->tlb_imask, addr, size, val); 704 break; 705 case 0x20310: 706 case 0x22310: 707 put_val_in_int64(&s->tlb_pcom, addr, size, val); 708 /* TODO: flush iommu */ 709 break; 710 case 0x20318: 711 case 0x22318: 712 put_val_in_int64(&s->tlb_tcnfg, addr, size, val); 713 break; 714 case 0x20320: 715 case 0x22320: 716 put_val_in_int64(&s->tlb_pdir_base, addr, size, val); 717 break; 718 case 0x22000: /* func_id */ 719 break; 720 case 0x22008: /* func_class */ 721 break; 722 case 0x22050: /* rope_debug */ 723 break; 724 case 0x22108: /* IOC STATUS_CONTROL */ 725 put_val_in_int64(&s->ioc_status_ctrl, addr, size, val); 726 break; 727 /* 728 * empty placeholders for non-existent elroys, e.g. 729 * func_class, pci config & data 730 */ 731 #define EMPTY_PORT(x) case x: case x+8: case x+0x40: case x+0x48: 732 EMPTY_PORT(0x30000) 733 EMPTY_PORT(0x32000) 734 EMPTY_PORT(0x34000) 735 EMPTY_PORT(0x36000) 736 EMPTY_PORT(0x38000) 737 EMPTY_PORT(0x3a000) 738 EMPTY_PORT(0x3c000) 739 EMPTY_PORT(0x3e000) 740 break; 741 #undef EMPTY_PORT 742 743 default: 744 ret = MEMTX_DECODE_ERROR; 745 } 746 return ret; 747 } 748 749 static const MemoryRegionOps astro_chip_ops = { 750 .read_with_attrs = astro_chip_read_with_attrs, 751 .write_with_attrs = astro_chip_write_with_attrs, 752 .endianness = DEVICE_LITTLE_ENDIAN, 753 .valid = { 754 .min_access_size = 4, 755 .max_access_size = 8, 756 }, 757 .impl = { 758 .min_access_size = 4, 759 .max_access_size = 8, 760 }, 761 }; 762 763 static const VMStateDescription vmstate_astro = { 764 .name = "Astro", 765 .version_id = 1, 766 .minimum_version_id = 1, 767 .fields = (const VMStateField[]) { 768 VMSTATE_UINT64(ioc_ctrl, AstroState), 769 VMSTATE_UINT64(ioc_status_ctrl, AstroState), 770 VMSTATE_UINT64_ARRAY(ioc_ranges, AstroState, (0x03d8 - 0x300) / 8), 771 VMSTATE_UINT64(ioc_rope_config, AstroState), 772 VMSTATE_UINT64(ioc_status_control, AstroState), 773 VMSTATE_UINT64(ioc_flush_control, AstroState), 774 VMSTATE_UINT64_ARRAY(ioc_rope_control, AstroState, 8), 775 VMSTATE_UINT64(tlb_ibase, AstroState), 776 VMSTATE_UINT64(tlb_imask, AstroState), 777 VMSTATE_UINT64(tlb_pcom, AstroState), 778 VMSTATE_UINT64(tlb_tcnfg, AstroState), 779 VMSTATE_UINT64(tlb_pdir_base, AstroState), 780 VMSTATE_END_OF_LIST() 781 } 782 }; 783 784 static void astro_reset(DeviceState *dev) 785 { 786 AstroState *s = ASTRO_CHIP(dev); 787 int i; 788 789 s->ioc_ctrl = 0x29cf; 790 s->ioc_rope_config = 0xc5f; 791 s->ioc_flush_control = 0xb03; 792 s->ioc_status_control = 0; 793 memset(&s->ioc_rope_control, 0, sizeof(s->ioc_rope_control)); 794 795 /* 796 * The SBA BASE/MASK registers control CPU -> IO routing. 797 * The LBA BASE/MASK registers control IO -> System routing (in Elroy) 798 */ 799 memset(&s->ioc_ranges, 0, sizeof(s->ioc_ranges)); 800 s->ioc_ranges[(0x360 - 0x300) / 8] = LMMIO_DIST_BASE_ADDR | 0x01; /* LMMIO_DIST_BASE (SBA) */ 801 s->ioc_ranges[(0x368 - 0x300) / 8] = 0xfc000000; /* LMMIO_DIST_MASK */ 802 s->ioc_ranges[(0x370 - 0x300) / 8] = 0; /* LMMIO_DIST_ROUTE */ 803 s->ioc_ranges[(0x390 - 0x300) / 8] = IOS_DIST_BASE_ADDR | 0x01; /* IOS_DIST_BASE */ 804 s->ioc_ranges[(0x398 - 0x300) / 8] = 0xffffff0000; /* IOS_DIST_MASK */ 805 s->ioc_ranges[(0x3a0 - 0x300) / 8] = 0x3400000000000000ULL; /* IOS_DIST_ROUTE */ 806 s->ioc_ranges[(0x3c0 - 0x300) / 8] = 0xfffee00000; /* IOS_DIRECT_BASE */ 807 s->ioc_ranges[(0x3c8 - 0x300) / 8] = 0xffffff0000; /* IOS_DIRECT_MASK */ 808 s->ioc_ranges[(0x3d0 - 0x300) / 8] = 0x0; /* IOS_DIRECT_ROUTE */ 809 810 s->tlb_ibase = 0; 811 s->tlb_imask = 0; 812 s->tlb_pcom = 0; 813 s->tlb_tcnfg = 0; 814 s->tlb_pdir_base = 0; 815 816 for (i = 0; i < ELROY_NUM; i++) { 817 elroy_reset(DEVICE(s->elroy[i])); 818 } 819 } 820 821 static void astro_init(Object *obj) 822 { 823 } 824 825 static void astro_realize(DeviceState *obj, Error **errp) 826 { 827 AstroState *s = ASTRO_CHIP(obj); 828 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 829 int i; 830 831 memory_region_init_io(&s->this_mem, OBJECT(s), &astro_chip_ops, 832 s, "astro", 0x40000); 833 sysbus_init_mmio(sbd, &s->this_mem); 834 835 /* Host memory as seen from Elroys PCI side, via the IOMMU. */ 836 memory_region_init_iommu(&s->iommu, sizeof(s->iommu), 837 TYPE_ASTRO_IOMMU_MEMORY_REGION, OBJECT(s), 838 "iommu-astro", UINT64_MAX); 839 address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), 840 "bm-pci"); 841 842 /* Create Elroys (PCI host bus chips). */ 843 for (i = 0; i < ELROY_NUM; i++) { 844 static const int elroy_hpa_offsets[ELROY_NUM] = { 845 0x30000, 0x32000, 0x38000, 0x3c000 }; 846 static const char elroy_rope_nr[ELROY_NUM] = { 847 0, 1, 4, 6 }; /* busnum path, e.g. [10:6] */ 848 int addr_offset; 849 ElroyState *elroy; 850 hwaddr map_addr; 851 uint64_t map_size; 852 int rope; 853 854 addr_offset = elroy_hpa_offsets[i]; 855 rope = elroy_rope_nr[i]; 856 857 elroy = elroy_init(i); 858 s->elroy[i] = elroy; 859 elroy->hpa = ASTRO_HPA + addr_offset; 860 elroy->pci_bus_num = i; 861 elroy->astro = s; 862 863 /* 864 * NOTE: we only allow PCI devices on first Elroy for now. 865 * SeaBIOS will not find devices on the other busses. 866 */ 867 if (i > 0) { 868 qbus_mark_full(&PCI_HOST_BRIDGE(elroy)->bus->qbus); 869 } 870 871 /* map elroy config addresses into Astro space */ 872 memory_region_add_subregion(&s->this_mem, addr_offset, 873 &elroy->this_mem); 874 875 /* LMMIO */ 876 elroy->mmio_base[(0x0200 - 0x200) / 8] = 0xf0000001; 877 elroy->mmio_base[(0x0208 - 0x200) / 8] = 0xf8000000; 878 /* GMMIO */ 879 elroy->mmio_base[(0x0210 - 0x200) / 8] = 0x000000f800000001; 880 elroy->mmio_base[(0x0218 - 0x200) / 8] = 0x000000ff80000000; 881 /* WLMMIO */ 882 elroy->mmio_base[(0x0220 - 0x200) / 8] = 0xf0000001; 883 elroy->mmio_base[(0x0228 - 0x200) / 8] = 0xf0000000; 884 /* WGMMIO */ 885 elroy->mmio_base[(0x0230 - 0x200) / 8] = 0x000000f800000001; 886 elroy->mmio_base[(0x0238 - 0x200) / 8] = 0x000000fc00000000; 887 /* IOS_BASE */ 888 map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC; 889 elroy->mmio_base[(0x0240 - 0x200) / 8] = rope * map_size | 0x01; 890 elroy->mmio_base[(0x0248 - 0x200) / 8] = 0x0000e000; 891 892 /* map elroys mmio */ 893 map_size = LMMIO_DIST_BASE_SIZE / ROPES_PER_IOC; 894 map_addr = F_EXTEND(LMMIO_DIST_BASE_ADDR + rope * map_size); 895 memory_region_init_alias(&elroy->pci_mmio_alias, OBJECT(elroy), 896 "pci-mmio-alias", 897 &elroy->pci_mmio, (uint32_t) map_addr, map_size); 898 memory_region_add_subregion(get_system_memory(), map_addr, 899 &elroy->pci_mmio_alias); 900 901 /* map elroys io */ 902 map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC; 903 map_addr = F_EXTEND(IOS_DIST_BASE_ADDR + rope * map_size); 904 memory_region_add_subregion(get_system_memory(), map_addr, 905 &elroy->pci_io); 906 907 /* Host memory as seen from the PCI side, via the IOMMU. */ 908 pci_setup_iommu(PCI_HOST_BRIDGE(elroy)->bus, &elroy_pcihost_iommu_ops, 909 elroy); 910 } 911 } 912 913 static void astro_class_init(ObjectClass *klass, const void *data) 914 { 915 DeviceClass *dc = DEVICE_CLASS(klass); 916 917 device_class_set_legacy_reset(dc, astro_reset); 918 dc->vmsd = &vmstate_astro; 919 dc->realize = astro_realize; 920 /* 921 * astro with elroys are hard part of the newer PA2.0 machines and can not 922 * be created without that hardware 923 */ 924 dc->user_creatable = false; 925 } 926 927 static const TypeInfo astro_chip_info = { 928 .name = TYPE_ASTRO_CHIP, 929 .parent = TYPE_SYS_BUS_DEVICE, 930 .instance_init = astro_init, 931 .instance_size = sizeof(AstroState), 932 .class_init = astro_class_init, 933 }; 934 935 static void astro_iommu_memory_region_class_init(ObjectClass *klass, 936 const void *data) 937 { 938 IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); 939 940 imrc->translate = astro_translate_iommu; 941 } 942 943 static const TypeInfo astro_iommu_memory_region_info = { 944 .parent = TYPE_IOMMU_MEMORY_REGION, 945 .name = TYPE_ASTRO_IOMMU_MEMORY_REGION, 946 .class_init = astro_iommu_memory_region_class_init, 947 }; 948 949 950 static void astro_register_types(void) 951 { 952 type_register_static(&astro_chip_info); 953 type_register_static(&astro_iommu_memory_region_info); 954 } 955 956 type_init(astro_register_types) 957