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