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