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