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