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