xref: /openbmc/qemu/hw/pci-host/astro.c (revision 235fe6d0)
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 /*
349  * Encoding in IOSAPIC:
350  * base_addr == 0xfffa0000, we want to get 0xa0ff0000.
351  * eid  0x0ff00000 -> 0x00ff0000
352  * id   0x000ff000 -> 0xff000000
353  */
354 #define SWIZZLE_HPA(a) \
355         ((((a) & 0x0ff00000) >> 4) | (((a) & 0x000ff000) << 12))
356 #define UNSWIZZLE_HPA(a) \
357         (((((a) << 4) & 0x0ff00000) | (((a) >> 12) & 0x000ff000) | 0xf0000000))
358 
359 /* bits in the "low" I/O Sapic IRdT entry */
360 #define IOSAPIC_IRDT_DISABLE      0x10000 /* if bit is set, mask this irq */
361 #define IOSAPIC_IRDT_PO_LOW       0x02000
362 #define IOSAPIC_IRDT_LEVEL_TRIG   0x08000
363 #define IOSAPIC_IRDT_MODE_LPRI    0x00100
364 
365 #define CPU_IRQ_OFFSET            2
366 
367 static void elroy_set_irq(void *opaque, int irq, int level)
368 {
369     ElroyState *s = opaque;
370     uint32_t bit;
371     uint32_t old_ilr = s->ilr;
372     hwaddr cpu_hpa;
373     uint32_t val;
374 
375     val     = s->iosapic_reg[0x10 + 2 * irq];
376     cpu_hpa = s->iosapic_reg[0x11 + 2 * irq];
377     /* low nibble of val has value to write into CPU irq reg */
378     bit     = 1u << (val & (ELROY_IRQS - 1));
379     cpu_hpa = UNSWIZZLE_HPA(cpu_hpa);
380 
381     if (level && (!(val & IOSAPIC_IRDT_DISABLE)) && cpu_hpa) {
382         uint32_t ena = bit & ~old_ilr;
383         s->ilr = old_ilr | bit;
384         if (ena != 0) {
385             stl_be_phys(&address_space_memory, cpu_hpa, val & 63);
386         }
387     } else {
388         s->ilr = old_ilr & ~bit;
389     }
390 }
391 
392 static int elroy_pci_map_irq(PCIDevice *d, int irq_num)
393 {
394     int slot = PCI_SLOT(d->devfn);
395 
396     assert(irq_num >= 0 && irq_num < ELROY_IRQS);
397     return slot & (ELROY_IRQS - 1);
398 }
399 
400 static void elroy_reset(DeviceState *dev)
401 {
402     ElroyState *s = ELROY_PCI_HOST_BRIDGE(dev);
403     int irq;
404 
405     /*
406      * Make sure to disable interrupts at reboot, otherwise the Linux kernel
407      * serial8250_config_port() in drivers/tty/serial/8250/8250_port.c
408      * will hang during autoconfig().
409      */
410     s->ilr = 0;
411     for (irq = 0; irq < ELROY_IRQS; irq++) {
412         s->iosapic_reg[0x10 + 2 * irq] = IOSAPIC_IRDT_PO_LOW |
413                 IOSAPIC_IRDT_LEVEL_TRIG | (irq + CPU_IRQ_OFFSET) |
414                 IOSAPIC_IRDT_DISABLE;
415         s->iosapic_reg[0x11 + 2 * irq] = SWIZZLE_HPA(CPU_HPA);
416     }
417 }
418 
419 static void elroy_pcihost_init(Object *obj)
420 {
421     ElroyState *s = ELROY_PCI_HOST_BRIDGE(obj);
422     PCIHostState *phb = PCI_HOST_BRIDGE(obj);
423     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
424 
425     /* Elroy config access from CPU.  */
426     memory_region_init_io(&s->this_mem, OBJECT(s), &elroy_chip_ops,
427                           s, "elroy", 0x2000);
428 
429     /* Elroy PCI config. */
430     memory_region_init_io(&phb->conf_mem, OBJECT(phb),
431                           &elroy_config_addr_ops, DEVICE(s),
432                           "pci-conf-idx", 8);
433     memory_region_init_io(&phb->data_mem, OBJECT(phb),
434                           &elroy_config_data_ops, DEVICE(s),
435                           "pci-conf-data", 8);
436     memory_region_add_subregion(&s->this_mem, 0x40,
437                                 &phb->conf_mem);
438     memory_region_add_subregion(&s->this_mem, 0x48,
439                                 &phb->data_mem);
440 
441     /* Elroy PCI bus memory.  */
442     memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", UINT64_MAX);
443     memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
444                             "pci-isa-mmio",
445                             ((uint32_t) IOS_DIST_BASE_SIZE) / ROPES_PER_IOC);
446 
447     phb->bus = pci_register_root_bus(DEVICE(s), "pci",
448                                      elroy_set_irq, elroy_pci_map_irq, s,
449                                      &s->pci_mmio, &s->pci_io,
450                                      PCI_DEVFN(0, 0), ELROY_IRQS, TYPE_PCI_BUS);
451 
452     sysbus_init_mmio(sbd, &s->this_mem);
453 
454     qdev_init_gpio_in(DEVICE(obj), elroy_set_irq, ELROY_IRQS);
455 }
456 
457 static Property elroy_pcihost_properties[] = {
458     DEFINE_PROP_END_OF_LIST(),
459 };
460 
461 static const VMStateDescription vmstate_elroy = {
462     .name = "Elroy",
463     .version_id = 1,
464     .minimum_version_id = 1,
465     .fields = (VMStateField[]) {
466         VMSTATE_UINT64(hpa, ElroyState),
467         VMSTATE_UINT32(pci_bus_num, ElroyState),
468         VMSTATE_UINT64(config_address, ElroyState),
469         VMSTATE_UINT64(config_reg_elroy, ElroyState),
470         VMSTATE_UINT64(status_control, ElroyState),
471         VMSTATE_UINT64(arb_mask, ElroyState),
472         VMSTATE_UINT64_ARRAY(mmio_base, ElroyState, (0x0250 - 0x200) / 8),
473         VMSTATE_UINT64(error_config, ElroyState),
474         VMSTATE_UINT32(iosapic_reg_select, ElroyState),
475         VMSTATE_UINT64_ARRAY(iosapic_reg, ElroyState, 0x20),
476         VMSTATE_UINT32(ilr, ElroyState),
477         VMSTATE_END_OF_LIST()
478     }
479 };
480 
481 static void elroy_pcihost_class_init(ObjectClass *klass, void *data)
482 {
483     DeviceClass *dc = DEVICE_CLASS(klass);
484 
485     dc->reset = elroy_reset;
486     device_class_set_props(dc, elroy_pcihost_properties);
487     dc->vmsd = &vmstate_elroy;
488     dc->user_creatable = false;
489 }
490 
491 static const TypeInfo elroy_pcihost_info = {
492     .name          = TYPE_ELROY_PCI_HOST_BRIDGE,
493     .parent        = TYPE_PCI_HOST_BRIDGE,
494     .instance_init = elroy_pcihost_init,
495     .instance_size = sizeof(ElroyState),
496     .class_init    = elroy_pcihost_class_init,
497 };
498 
499 static void elroy_register_types(void)
500 {
501     type_register_static(&elroy_pcihost_info);
502 }
503 
504 type_init(elroy_register_types)
505 
506 
507 static ElroyState *elroy_init(int num)
508 {
509     DeviceState *dev;
510 
511     dev = qdev_new(TYPE_ELROY_PCI_HOST_BRIDGE);
512     dev->id = g_strdup_printf("elroy%d", num);
513     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
514 
515     return ELROY_PCI_HOST_BRIDGE(dev);
516 }
517 
518 /*
519  * Astro Runway chip.
520  */
521 
522 static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr,
523                                              uint64_t *data, unsigned size,
524                                              MemTxAttrs attrs)
525 {
526     AstroState *s = opaque;
527     MemTxResult ret = MEMTX_OK;
528     uint64_t val = -1;
529     int index;
530 
531     switch ((addr >> 3) << 3) {
532     /* R2I registers */
533     case 0x0000:        /* ID */
534         val = (0x01 << 3) | 0x01ULL;
535         break;
536     case 0x0008:        /* IOC_CTRL */
537         val = s->ioc_ctrl;
538         break;
539     case 0x0010:        /* TOC_CLIENT_ID */
540         break;
541     case 0x0030:        /* HP-UX 10.20 and 11.11 reads it. No idea. */
542         val = -1;
543         break;
544     case 0x0300 ... 0x03d8:     /* LMMIO_DIRECT0_BASE... */
545         index = (addr - 0x300) / 8;
546         val = s->ioc_ranges[index];
547         break;
548     case 0x10200:
549         val = 0;
550         break;
551     case 0x10220:
552     case 0x10230:        /* HP-UX 11.11 reads it. No idea. */
553         val = -1;
554         break;
555     case 0x22108:        /* IOC STATUS_CONTROL */
556         val = s->ioc_status_ctrl;
557         break;
558     case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
559         index = (addr - 0x20200) / 8;
560         val = s->ioc_rope_control[index];
561         break;
562     case 0x20040:        /* IOC Rope config */
563         val = s->ioc_rope_config;
564         break;
565     case 0x20050:        /* IOC Rope debug */
566         val = 0;
567         break;
568     case 0x20108:        /* IOC STATUS_CONTROL */
569         val = s->ioc_status_control;
570         break;
571     case 0x20310:        /* IOC_PCOM */
572         val = s->tlb_pcom;
573         /* TODO: flush iommu */
574         break;
575     case 0x20400:
576         val = s->ioc_flush_control;
577         break;
578     /* empty placeholders for non-existent elroys */
579 #define EMPTY_PORT(x) case x:    case x+8:   val = 0;          break; \
580                       case x+40: case x+48:  val = UINT64_MAX; break;
581         EMPTY_PORT(0x30000)
582         EMPTY_PORT(0x32000)
583         EMPTY_PORT(0x34000)
584         EMPTY_PORT(0x36000)
585         EMPTY_PORT(0x38000)
586         EMPTY_PORT(0x3a000)
587         EMPTY_PORT(0x3c000)
588         EMPTY_PORT(0x3e000)
589 #undef EMPTY_PORT
590 
591     default:
592         trace_astro_chip_read(addr, size, val);
593         g_assert_not_reached();
594     }
595 
596     /* for 32-bit accesses mask return value */
597     val = mask_32bit_val(addr, size, val);
598 
599     trace_astro_chip_read(addr, size, val);
600     *data = val;
601     return ret;
602 }
603 
604 static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr,
605                                               uint64_t val, unsigned size,
606                                               MemTxAttrs attrs)
607 {
608     AstroState *s = opaque;
609 
610     trace_astro_chip_write(addr, size, val);
611 
612     switch ((addr >> 3) << 3) {
613     case 0x0000:        /* ID */
614         break;
615     case 0x0008:        /* IOC_CTRL */
616         val &= 0x0ffffff;
617         put_val_in_int64(&s->ioc_ctrl, addr, size, val);
618         break;
619     case 0x0010:        /* TOC_CLIENT_ID */
620         break;
621     case 0x0030:        /* HP-UX 10.20 and 11.11 reads it. No idea. */
622         break;
623     case 0x0300 ... 0x03d8 - 1: /* LMMIO_DIRECT0_BASE... */
624         put_val_in_arrary(s->ioc_ranges, 0x300, addr, size, val);
625         break;
626     case 0x10200:
627     case 0x10220:
628     case 0x10230:        /* HP-UX 11.11 reads it. No idea. */
629         break;
630     case 0x22108:        /* IOC STATUS_CONTROL */
631         put_val_in_int64(&s->ioc_status_ctrl, addr, size, val);
632         break;
633     case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
634         put_val_in_arrary(s->ioc_rope_control, 0x20200, addr, size, val);
635         break;
636     case 0x20040:        /* IOC Rope config */
637         put_val_in_int64(&s->ioc_rope_config, addr, size, val);
638         break;
639     case 0x20300:
640         put_val_in_int64(&s->tlb_ibase, addr, size, val);
641         break;
642     case 0x20308:
643         put_val_in_int64(&s->tlb_imask, addr, size, val);
644         break;
645     case 0x20310:
646         put_val_in_int64(&s->tlb_pcom, addr, size, val);
647         /* TODO: flush iommu */
648         break;
649     case 0x20318:
650         put_val_in_int64(&s->tlb_tcnfg, addr, size, val);
651         break;
652     case 0x20320:
653         put_val_in_int64(&s->tlb_pdir_base, addr, size, val);
654         break;
655     /*
656      * empty placeholders for non-existent elroys, e.g.
657      * func_class, pci config & data
658      */
659 #define EMPTY_PORT(x) case x: case x+8: case x+0x40: case x+0x48:
660         EMPTY_PORT(0x30000)
661         EMPTY_PORT(0x32000)
662         EMPTY_PORT(0x34000)
663         EMPTY_PORT(0x36000)
664         EMPTY_PORT(0x38000)
665         EMPTY_PORT(0x3a000)
666         EMPTY_PORT(0x3c000)
667         EMPTY_PORT(0x3e000)
668         break;
669 #undef EMPTY_PORT
670 
671     default:
672         /* Controlled by astro_chip_mem_valid above.  */
673         trace_astro_chip_write(addr, size, val);
674         g_assert_not_reached();
675     }
676     return MEMTX_OK;
677 }
678 
679 static const MemoryRegionOps astro_chip_ops = {
680     .read_with_attrs = astro_chip_read_with_attrs,
681     .write_with_attrs = astro_chip_write_with_attrs,
682     .endianness = DEVICE_LITTLE_ENDIAN,
683     .valid = {
684         .min_access_size = 4,
685         .max_access_size = 8,
686     },
687     .impl = {
688         .min_access_size = 4,
689         .max_access_size = 8,
690     },
691 };
692 
693 static const VMStateDescription vmstate_astro = {
694     .name = "Astro",
695     .version_id = 1,
696     .minimum_version_id = 1,
697     .fields = (VMStateField[]) {
698         VMSTATE_UINT64(ioc_ctrl, AstroState),
699         VMSTATE_UINT64(ioc_status_ctrl, AstroState),
700         VMSTATE_UINT64_ARRAY(ioc_ranges, AstroState, (0x03d8 - 0x300) / 8),
701         VMSTATE_UINT64(ioc_rope_config, AstroState),
702         VMSTATE_UINT64(ioc_status_control, AstroState),
703         VMSTATE_UINT64(ioc_flush_control, AstroState),
704         VMSTATE_UINT64_ARRAY(ioc_rope_control, AstroState, 8),
705         VMSTATE_UINT64(tlb_ibase, AstroState),
706         VMSTATE_UINT64(tlb_imask, AstroState),
707         VMSTATE_UINT64(tlb_pcom, AstroState),
708         VMSTATE_UINT64(tlb_tcnfg, AstroState),
709         VMSTATE_UINT64(tlb_pdir_base, AstroState),
710         VMSTATE_END_OF_LIST()
711     }
712 };
713 
714 static void astro_reset(DeviceState *dev)
715 {
716     AstroState *s = ASTRO_CHIP(dev);
717     int i;
718 
719     s->ioc_ctrl = 0x29cf;
720     s->ioc_rope_config = 0xc5f;
721     s->ioc_flush_control = 0xb03;
722     s->ioc_status_control = 0;
723     memset(&s->ioc_rope_control, 0, sizeof(s->ioc_rope_control));
724 
725     /*
726      * The SBA BASE/MASK registers control CPU -> IO routing.
727      * The LBA BASE/MASK registers control IO -> System routing (in Elroy)
728      */
729     memset(&s->ioc_ranges, 0, sizeof(s->ioc_ranges));
730     s->ioc_ranges[(0x360 - 0x300) / 8] = LMMIO_DIST_BASE_ADDR | 0x01; /* LMMIO_DIST_BASE (SBA) */
731     s->ioc_ranges[(0x368 - 0x300) / 8] = 0xfc000000;          /* LMMIO_DIST_MASK */
732     s->ioc_ranges[(0x370 - 0x300) / 8] = 0;                   /* LMMIO_DIST_ROUTE */
733     s->ioc_ranges[(0x390 - 0x300) / 8] = IOS_DIST_BASE_ADDR | 0x01; /* IOS_DIST_BASE */
734     s->ioc_ranges[(0x398 - 0x300) / 8] = 0xffffff0000;        /* IOS_DIST_MASK    */
735     s->ioc_ranges[(0x3a0 - 0x300) / 8] = 0x3400000000000000ULL; /* IOS_DIST_ROUTE */
736     s->ioc_ranges[(0x3c0 - 0x300) / 8] = 0xfffee00000;        /* IOS_DIRECT_BASE  */
737     s->ioc_ranges[(0x3c8 - 0x300) / 8] = 0xffffff0000;        /* IOS_DIRECT_MASK  */
738     s->ioc_ranges[(0x3d0 - 0x300) / 8] = 0x0;                 /* IOS_DIRECT_ROUTE */
739 
740     s->tlb_ibase = 0;
741     s->tlb_imask = 0;
742     s->tlb_pcom = 0;
743     s->tlb_tcnfg = 0;
744     s->tlb_pdir_base = 0;
745 
746     for (i = 0; i < ELROY_NUM; i++) {
747         elroy_reset(DEVICE(s->elroy[i]));
748     }
749 }
750 
751 static void astro_init(Object *obj)
752 {
753 }
754 
755 static void astro_realize(DeviceState *obj, Error **errp)
756 {
757     AstroState *s = ASTRO_CHIP(obj);
758     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
759     int i;
760 
761     memory_region_init_io(&s->this_mem, OBJECT(s), &astro_chip_ops,
762                           s, "astro", 0x40000);
763     sysbus_init_mmio(sbd, &s->this_mem);
764 
765     /* Host memory as seen from Elroys PCI side, via the IOMMU.  */
766     memory_region_init_iommu(&s->iommu, sizeof(s->iommu),
767                              TYPE_ASTRO_IOMMU_MEMORY_REGION, OBJECT(s),
768                              "iommu-astro", UINT64_MAX);
769     address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu),
770                        "bm-pci");
771 
772     /* Create Elroys (PCI host bus chips).  */
773     for (i = 0; i < ELROY_NUM; i++) {
774         static const int elroy_hpa_offsets[ELROY_NUM] = {
775                     0x30000, 0x32000, 0x38000, 0x3c000 };
776         static const char elroy_rope_nr[ELROY_NUM] = {
777                     0, 1, 4, 6 }; /* busnum path, e.g. [10:6] */
778         int addr_offset;
779         ElroyState *elroy;
780         hwaddr map_addr;
781         uint64_t map_size;
782         int rope;
783 
784         addr_offset = elroy_hpa_offsets[i];
785         rope = elroy_rope_nr[i];
786 
787         elroy = elroy_init(i);
788         s->elroy[i] = elroy;
789         elroy->hpa = ASTRO_HPA + addr_offset;
790         elroy->pci_bus_num = i;
791         elroy->astro = s;
792 
793         /*
794          * NOTE: we only allow PCI devices on first Elroy for now.
795          * SeaBIOS will not find devices on the other busses.
796          */
797         if (i > 0) {
798             qbus_mark_full(&PCI_HOST_BRIDGE(elroy)->bus->qbus);
799         }
800 
801         /* map elroy config addresses into Astro space */
802         memory_region_add_subregion(&s->this_mem, addr_offset,
803                                     &elroy->this_mem);
804 
805         /* LMMIO */
806         elroy->mmio_base[(0x0200 - 0x200) / 8] = 0xf0000001;
807         elroy->mmio_base[(0x0208 - 0x200) / 8] = 0xf8000000;
808         /* GMMIO */
809         elroy->mmio_base[(0x0210 - 0x200) / 8] = 0x000000f800000001;
810         elroy->mmio_base[(0x0218 - 0x200) / 8] = 0x000000ff80000000;
811         /* WLMMIO */
812         elroy->mmio_base[(0x0220 - 0x200) / 8] = 0xf0000001;
813         elroy->mmio_base[(0x0228 - 0x200) / 8] = 0xf0000000;
814         /* WGMMIO */
815         elroy->mmio_base[(0x0230 - 0x200) / 8] = 0x000000f800000001;
816         elroy->mmio_base[(0x0238 - 0x200) / 8] = 0x000000fc00000000;
817         /* IOS_BASE */
818         map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC;
819         elroy->mmio_base[(0x0240 - 0x200) / 8] = rope * map_size | 0x01;
820         elroy->mmio_base[(0x0248 - 0x200) / 8] = 0x0000e000;
821 
822         /* map elroys mmio */
823         map_size = LMMIO_DIST_BASE_SIZE / ROPES_PER_IOC;
824         map_addr = (uint32_t) (LMMIO_DIST_BASE_ADDR + rope * map_size);
825         memory_region_init_alias(&elroy->pci_mmio_alias, OBJECT(elroy),
826                                  "pci-mmio-alias",
827                                  &elroy->pci_mmio, map_addr, map_size);
828         memory_region_add_subregion(get_system_memory(), map_addr,
829                                  &elroy->pci_mmio_alias);
830 
831         map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC;
832         map_addr = (uint32_t) (IOS_DIST_BASE_ADDR + rope * map_size);
833         memory_region_add_subregion(get_system_memory(), map_addr,
834                                  &elroy->pci_io);
835 
836         /* Host memory as seen from the PCI side, via the IOMMU.  */
837         pci_setup_iommu(PCI_HOST_BRIDGE(elroy)->bus, elroy_pcihost_set_iommu,
838                                  elroy);
839     }
840 }
841 
842 static void astro_class_init(ObjectClass *klass, void *data)
843 {
844     DeviceClass *dc = DEVICE_CLASS(klass);
845 
846     dc->reset = astro_reset;
847     dc->vmsd = &vmstate_astro;
848     dc->realize = astro_realize;
849     /*
850      * astro with elroys are hard part of the newer PA2.0 machines and can not
851      * be created without that hardware
852      */
853     dc->user_creatable = false;
854 }
855 
856 static const TypeInfo astro_chip_info = {
857     .name          = TYPE_ASTRO_CHIP,
858     .parent        = TYPE_SYS_BUS_DEVICE,
859     .instance_init = astro_init,
860     .instance_size = sizeof(AstroState),
861     .class_init    = astro_class_init,
862 };
863 
864 static void astro_iommu_memory_region_class_init(ObjectClass *klass,
865                                                    void *data)
866 {
867     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
868 
869     imrc->translate = astro_translate_iommu;
870 }
871 
872 static const TypeInfo astro_iommu_memory_region_info = {
873     .parent = TYPE_IOMMU_MEMORY_REGION,
874     .name = TYPE_ASTRO_IOMMU_MEMORY_REGION,
875     .class_init = astro_iommu_memory_region_class_init,
876 };
877 
878 
879 static void astro_register_types(void)
880 {
881     type_register_static(&astro_chip_info);
882     type_register_static(&astro_iommu_memory_region_info);
883 }
884 
885 type_init(astro_register_types)
886