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