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