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_init(Object * obj)427 static void elroy_pcihost_init(Object *obj)
428 {
429 ElroyState *s = ELROY_PCI_HOST_BRIDGE(obj);
430 PCIHostState *phb = PCI_HOST_BRIDGE(obj);
431 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
432
433 /* Elroy config access from CPU. */
434 memory_region_init_io(&s->this_mem, OBJECT(s), &elroy_chip_ops,
435 s, "elroy", 0x2000);
436
437 /* Elroy PCI config. */
438 memory_region_init_io(&phb->conf_mem, OBJECT(phb),
439 &elroy_config_addr_ops, DEVICE(s),
440 "pci-conf-idx", 8);
441 memory_region_init_io(&phb->data_mem, OBJECT(phb),
442 &elroy_config_data_ops, DEVICE(s),
443 "pci-conf-data", 8);
444 memory_region_add_subregion(&s->this_mem, 0x40,
445 &phb->conf_mem);
446 memory_region_add_subregion(&s->this_mem, 0x48,
447 &phb->data_mem);
448
449 /* Elroy PCI bus memory. */
450 memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", UINT64_MAX);
451 memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
452 "pci-isa-mmio",
453 ((uint32_t) IOS_DIST_BASE_SIZE) / ROPES_PER_IOC);
454
455 phb->bus = pci_register_root_bus(DEVICE(s), "pci",
456 elroy_set_irq, elroy_pci_map_irq, s,
457 &s->pci_mmio, &s->pci_io,
458 PCI_DEVFN(0, 0), ELROY_IRQS, TYPE_PCI_BUS);
459
460 sysbus_init_mmio(sbd, &s->this_mem);
461
462 qdev_init_gpio_in(DEVICE(obj), elroy_set_irq, ELROY_IRQS);
463 }
464
465 static const VMStateDescription vmstate_elroy = {
466 .name = "Elroy",
467 .version_id = 1,
468 .minimum_version_id = 1,
469 .fields = (const VMStateField[]) {
470 VMSTATE_UINT64(hpa, ElroyState),
471 VMSTATE_UINT32(pci_bus_num, ElroyState),
472 VMSTATE_UINT64(config_address, ElroyState),
473 VMSTATE_UINT64(config_reg_elroy, ElroyState),
474 VMSTATE_UINT64(status_control, ElroyState),
475 VMSTATE_UINT64(arb_mask, ElroyState),
476 VMSTATE_UINT64_ARRAY(mmio_base, ElroyState, (0x0250 - 0x200) / 8),
477 VMSTATE_UINT64(error_config, ElroyState),
478 VMSTATE_UINT32(iosapic_reg_select, ElroyState),
479 VMSTATE_UINT64_ARRAY(iosapic_reg, ElroyState, 0x20),
480 VMSTATE_UINT32(ilr, ElroyState),
481 VMSTATE_END_OF_LIST()
482 }
483 };
484
elroy_pcihost_class_init(ObjectClass * klass,const void * data)485 static void elroy_pcihost_class_init(ObjectClass *klass, const void *data)
486 {
487 DeviceClass *dc = DEVICE_CLASS(klass);
488
489 device_class_set_legacy_reset(dc, elroy_reset);
490 dc->vmsd = &vmstate_elroy;
491 dc->user_creatable = false;
492 }
493
494 static const TypeInfo elroy_pcihost_info = {
495 .name = TYPE_ELROY_PCI_HOST_BRIDGE,
496 .parent = TYPE_PCI_HOST_BRIDGE,
497 .instance_init = elroy_pcihost_init,
498 .instance_size = sizeof(ElroyState),
499 .class_init = elroy_pcihost_class_init,
500 };
501
elroy_register_types(void)502 static void elroy_register_types(void)
503 {
504 type_register_static(&elroy_pcihost_info);
505 }
506
type_init(elroy_register_types)507 type_init(elroy_register_types)
508
509
510 static ElroyState *elroy_init(int num)
511 {
512 DeviceState *dev;
513
514 dev = qdev_new(TYPE_ELROY_PCI_HOST_BRIDGE);
515 dev->id = g_strdup_printf("elroy%d", num);
516 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
517
518 return ELROY_PCI_HOST_BRIDGE(dev);
519 }
520
521 /*
522 * Astro Runway chip.
523 */
524
adjust_LMMIO_DIRECT_mapping(AstroState * s,unsigned int reg_index)525 static void adjust_LMMIO_DIRECT_mapping(AstroState *s, unsigned int reg_index)
526 {
527 MemoryRegion *lmmio_alias;
528 unsigned int lmmio_index, map_route;
529 hwaddr map_addr;
530 uint32_t map_size;
531 struct ElroyState *elroy;
532
533 /* pointer to LMMIO_DIRECT entry */
534 lmmio_index = reg_index / 3;
535 lmmio_alias = &s->lmmio_direct[lmmio_index];
536
537 map_addr = s->ioc_ranges[3 * lmmio_index + 0];
538 map_size = s->ioc_ranges[3 * lmmio_index + 1];
539 map_route = s->ioc_ranges[3 * lmmio_index + 2];
540
541 /* find elroy to which this address is routed */
542 map_route &= (ELROY_NUM - 1);
543 elroy = s->elroy[map_route];
544
545 if (lmmio_alias->enabled) {
546 memory_region_set_enabled(lmmio_alias, false);
547 }
548
549 map_addr = F_EXTEND(map_addr);
550 map_addr &= TARGET_PAGE_MASK;
551 map_size = (~map_size) + 1;
552 map_size &= TARGET_PAGE_MASK;
553
554 /* exit if disabled or zero map size */
555 if (!(map_addr & 1) || !map_size) {
556 return;
557 }
558
559 if (!memory_region_size(lmmio_alias)) {
560 memory_region_init_alias(lmmio_alias, OBJECT(elroy),
561 "pci-lmmmio-alias", &elroy->pci_mmio,
562 (uint32_t) map_addr, map_size);
563 memory_region_add_subregion(get_system_memory(), map_addr,
564 lmmio_alias);
565 } else {
566 memory_region_set_alias_offset(lmmio_alias, map_addr);
567 memory_region_set_size(lmmio_alias, map_size);
568 memory_region_set_enabled(lmmio_alias, true);
569 }
570 }
571
astro_chip_read_with_attrs(void * opaque,hwaddr addr,uint64_t * data,unsigned size,MemTxAttrs attrs)572 static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr,
573 uint64_t *data, unsigned size,
574 MemTxAttrs attrs)
575 {
576 AstroState *s = opaque;
577 MemTxResult ret = MEMTX_OK;
578 uint64_t val = -1;
579 int index;
580
581 switch ((addr >> 3) << 3) {
582 /* R2I registers */
583 case 0x0000: /* ID */
584 val = (0x01 << 3) | 0x01ULL;
585 break;
586 case 0x0008: /* IOC_CTRL */
587 val = s->ioc_ctrl;
588 break;
589 case 0x0010: /* TOC_CLIENT_ID */
590 break;
591 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */
592 val = -1;
593 break;
594 case 0x0078: /* NetBSD reads 0x78 ? */
595 val = -1;
596 break;
597 case 0x0300 ... 0x03d8: /* LMMIO_DIRECT0_BASE... */
598 index = (addr - 0x300) / 8;
599 val = s->ioc_ranges[index];
600 break;
601 case 0x10200:
602 val = 0;
603 break;
604 case 0x10220:
605 case 0x10230: /* HP-UX 11.11 reads it. No idea. */
606 val = -1;
607 break;
608 case 0x22108: /* IOC STATUS_CONTROL */
609 val = s->ioc_status_ctrl;
610 break;
611 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
612 index = (addr - 0x20200) / 8;
613 val = s->ioc_rope_control[index];
614 break;
615 case 0x20040: /* IOC Rope config */
616 val = s->ioc_rope_config;
617 break;
618 case 0x20050: /* IOC Rope debug */
619 val = 0;
620 break;
621 case 0x20108: /* IOC STATUS_CONTROL */
622 val = s->ioc_status_control;
623 break;
624 case 0x20310: /* IOC_PCOM */
625 val = s->tlb_pcom;
626 /* TODO: flush iommu */
627 break;
628 case 0x20400:
629 val = s->ioc_flush_control;
630 break;
631 /* empty placeholders for non-existent elroys */
632 #define EMPTY_PORT(x) case x: case x+8: val = 0; break; \
633 case x+40: case x+48: val = UINT64_MAX; break;
634 EMPTY_PORT(0x30000)
635 EMPTY_PORT(0x32000)
636 EMPTY_PORT(0x34000)
637 EMPTY_PORT(0x36000)
638 EMPTY_PORT(0x38000)
639 EMPTY_PORT(0x3a000)
640 EMPTY_PORT(0x3c000)
641 EMPTY_PORT(0x3e000)
642 #undef EMPTY_PORT
643
644 default:
645 val = 0;
646 ret = MEMTX_DECODE_ERROR;
647 }
648
649 /* for 32-bit accesses mask return value */
650 val = mask_32bit_val(addr, size, val);
651
652 trace_astro_chip_read(addr, size, val);
653 *data = val;
654 return ret;
655 }
656
astro_chip_write_with_attrs(void * opaque,hwaddr addr,uint64_t val,unsigned size,MemTxAttrs attrs)657 static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr,
658 uint64_t val, unsigned size,
659 MemTxAttrs attrs)
660 {
661 MemTxResult ret = MEMTX_OK;
662 AstroState *s = opaque;
663
664 trace_astro_chip_write(addr, size, val);
665
666 switch ((addr >> 3) << 3) {
667 case 0x0000: /* ID */
668 break;
669 case 0x0008: /* IOC_CTRL */
670 val &= 0x0ffffff;
671 put_val_in_int64(&s->ioc_ctrl, addr, size, val);
672 break;
673 case 0x0010: /* TOC_CLIENT_ID */
674 break;
675 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */
676 break;
677 case 0x0300 ... 0x03d8 - 1: /* LMMIO_DIRECT0_BASE... */
678 put_val_in_arrary(s->ioc_ranges, 0x300, addr, size, val);
679 unsigned int index = (addr - 0x300) / 8;
680 /* check if one of the 4 LMMIO_DIRECT regs, each using 3 entries. */
681 if (index < LMMIO_DIRECT_RANGES * 3) {
682 adjust_LMMIO_DIRECT_mapping(s, index);
683 }
684 break;
685 case 0x10200:
686 case 0x10220:
687 case 0x10230: /* HP-UX 11.11 reads it. No idea. */
688 break;
689 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
690 put_val_in_arrary(s->ioc_rope_control, 0x20200, addr, size, val);
691 break;
692 case 0x20040: /* IOC Rope config */
693 case 0x22040:
694 put_val_in_int64(&s->ioc_rope_config, addr, size, val);
695 break;
696 case 0x20300:
697 case 0x22300:
698 put_val_in_int64(&s->tlb_ibase, addr, size, val);
699 break;
700 case 0x20308:
701 case 0x22308:
702 put_val_in_int64(&s->tlb_imask, addr, size, val);
703 break;
704 case 0x20310:
705 case 0x22310:
706 put_val_in_int64(&s->tlb_pcom, addr, size, val);
707 /* TODO: flush iommu */
708 break;
709 case 0x20318:
710 case 0x22318:
711 put_val_in_int64(&s->tlb_tcnfg, addr, size, val);
712 break;
713 case 0x20320:
714 case 0x22320:
715 put_val_in_int64(&s->tlb_pdir_base, addr, size, val);
716 break;
717 case 0x22000: /* func_id */
718 break;
719 case 0x22008: /* func_class */
720 break;
721 case 0x22050: /* rope_debug */
722 break;
723 case 0x22108: /* IOC STATUS_CONTROL */
724 put_val_in_int64(&s->ioc_status_ctrl, addr, size, val);
725 break;
726 /*
727 * empty placeholders for non-existent elroys, e.g.
728 * func_class, pci config & data
729 */
730 #define EMPTY_PORT(x) case x: case x+8: case x+0x40: case x+0x48:
731 EMPTY_PORT(0x30000)
732 EMPTY_PORT(0x32000)
733 EMPTY_PORT(0x34000)
734 EMPTY_PORT(0x36000)
735 EMPTY_PORT(0x38000)
736 EMPTY_PORT(0x3a000)
737 EMPTY_PORT(0x3c000)
738 EMPTY_PORT(0x3e000)
739 break;
740 #undef EMPTY_PORT
741
742 default:
743 ret = MEMTX_DECODE_ERROR;
744 }
745 return ret;
746 }
747
748 static const MemoryRegionOps astro_chip_ops = {
749 .read_with_attrs = astro_chip_read_with_attrs,
750 .write_with_attrs = astro_chip_write_with_attrs,
751 .endianness = DEVICE_LITTLE_ENDIAN,
752 .valid = {
753 .min_access_size = 4,
754 .max_access_size = 8,
755 },
756 .impl = {
757 .min_access_size = 4,
758 .max_access_size = 8,
759 },
760 };
761
762 static const VMStateDescription vmstate_astro = {
763 .name = "Astro",
764 .version_id = 1,
765 .minimum_version_id = 1,
766 .fields = (const VMStateField[]) {
767 VMSTATE_UINT64(ioc_ctrl, AstroState),
768 VMSTATE_UINT64(ioc_status_ctrl, AstroState),
769 VMSTATE_UINT64_ARRAY(ioc_ranges, AstroState, (0x03d8 - 0x300) / 8),
770 VMSTATE_UINT64(ioc_rope_config, AstroState),
771 VMSTATE_UINT64(ioc_status_control, AstroState),
772 VMSTATE_UINT64(ioc_flush_control, AstroState),
773 VMSTATE_UINT64_ARRAY(ioc_rope_control, AstroState, 8),
774 VMSTATE_UINT64(tlb_ibase, AstroState),
775 VMSTATE_UINT64(tlb_imask, AstroState),
776 VMSTATE_UINT64(tlb_pcom, AstroState),
777 VMSTATE_UINT64(tlb_tcnfg, AstroState),
778 VMSTATE_UINT64(tlb_pdir_base, AstroState),
779 VMSTATE_END_OF_LIST()
780 }
781 };
782
astro_reset(DeviceState * dev)783 static void astro_reset(DeviceState *dev)
784 {
785 AstroState *s = ASTRO_CHIP(dev);
786 int i;
787
788 s->ioc_ctrl = 0x29cf;
789 s->ioc_rope_config = 0xc5f;
790 s->ioc_flush_control = 0xb03;
791 s->ioc_status_control = 0;
792 memset(&s->ioc_rope_control, 0, sizeof(s->ioc_rope_control));
793
794 /*
795 * The SBA BASE/MASK registers control CPU -> IO routing.
796 * The LBA BASE/MASK registers control IO -> System routing (in Elroy)
797 */
798 memset(&s->ioc_ranges, 0, sizeof(s->ioc_ranges));
799 s->ioc_ranges[(0x360 - 0x300) / 8] = LMMIO_DIST_BASE_ADDR | 0x01; /* LMMIO_DIST_BASE (SBA) */
800 s->ioc_ranges[(0x368 - 0x300) / 8] = 0xfc000000; /* LMMIO_DIST_MASK */
801 s->ioc_ranges[(0x370 - 0x300) / 8] = 0; /* LMMIO_DIST_ROUTE */
802 s->ioc_ranges[(0x390 - 0x300) / 8] = IOS_DIST_BASE_ADDR | 0x01; /* IOS_DIST_BASE */
803 s->ioc_ranges[(0x398 - 0x300) / 8] = 0xffffff0000; /* IOS_DIST_MASK */
804 s->ioc_ranges[(0x3a0 - 0x300) / 8] = 0x3400000000000000ULL; /* IOS_DIST_ROUTE */
805 s->ioc_ranges[(0x3c0 - 0x300) / 8] = 0xfffee00000; /* IOS_DIRECT_BASE */
806 s->ioc_ranges[(0x3c8 - 0x300) / 8] = 0xffffff0000; /* IOS_DIRECT_MASK */
807 s->ioc_ranges[(0x3d0 - 0x300) / 8] = 0x0; /* IOS_DIRECT_ROUTE */
808
809 s->tlb_ibase = 0;
810 s->tlb_imask = 0;
811 s->tlb_pcom = 0;
812 s->tlb_tcnfg = 0;
813 s->tlb_pdir_base = 0;
814
815 for (i = 0; i < ELROY_NUM; i++) {
816 elroy_reset(DEVICE(s->elroy[i]));
817 }
818 }
819
astro_init(Object * obj)820 static void astro_init(Object *obj)
821 {
822 }
823
astro_realize(DeviceState * obj,Error ** errp)824 static void astro_realize(DeviceState *obj, Error **errp)
825 {
826 AstroState *s = ASTRO_CHIP(obj);
827 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
828 int i;
829
830 memory_region_init_io(&s->this_mem, OBJECT(s), &astro_chip_ops,
831 s, "astro", 0x40000);
832 sysbus_init_mmio(sbd, &s->this_mem);
833
834 /* Host memory as seen from Elroys PCI side, via the IOMMU. */
835 memory_region_init_iommu(&s->iommu, sizeof(s->iommu),
836 TYPE_ASTRO_IOMMU_MEMORY_REGION, OBJECT(s),
837 "iommu-astro", UINT64_MAX);
838 address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu),
839 "bm-pci");
840
841 /* Create Elroys (PCI host bus chips). */
842 for (i = 0; i < ELROY_NUM; i++) {
843 static const int elroy_hpa_offsets[ELROY_NUM] = {
844 0x30000, 0x32000, 0x38000, 0x3c000 };
845 static const char elroy_rope_nr[ELROY_NUM] = {
846 0, 1, 4, 6 }; /* busnum path, e.g. [10:6] */
847 int addr_offset;
848 ElroyState *elroy;
849 hwaddr map_addr;
850 uint64_t map_size;
851 int rope;
852
853 addr_offset = elroy_hpa_offsets[i];
854 rope = elroy_rope_nr[i];
855
856 elroy = elroy_init(i);
857 s->elroy[i] = elroy;
858 elroy->hpa = ASTRO_HPA + addr_offset;
859 elroy->pci_bus_num = i;
860 elroy->astro = s;
861
862 /*
863 * NOTE: we only allow PCI devices on first Elroy for now.
864 * SeaBIOS will not find devices on the other busses.
865 */
866 if (i > 0) {
867 qbus_mark_full(&PCI_HOST_BRIDGE(elroy)->bus->qbus);
868 }
869
870 /* map elroy config addresses into Astro space */
871 memory_region_add_subregion(&s->this_mem, addr_offset,
872 &elroy->this_mem);
873
874 /* LMMIO */
875 elroy->mmio_base[(0x0200 - 0x200) / 8] = 0xf0000001;
876 elroy->mmio_base[(0x0208 - 0x200) / 8] = 0xf8000000;
877 /* GMMIO */
878 elroy->mmio_base[(0x0210 - 0x200) / 8] = 0x000000f800000001;
879 elroy->mmio_base[(0x0218 - 0x200) / 8] = 0x000000ff80000000;
880 /* WLMMIO */
881 elroy->mmio_base[(0x0220 - 0x200) / 8] = 0xf0000001;
882 elroy->mmio_base[(0x0228 - 0x200) / 8] = 0xf0000000;
883 /* WGMMIO */
884 elroy->mmio_base[(0x0230 - 0x200) / 8] = 0x000000f800000001;
885 elroy->mmio_base[(0x0238 - 0x200) / 8] = 0x000000fc00000000;
886 /* IOS_BASE */
887 map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC;
888 elroy->mmio_base[(0x0240 - 0x200) / 8] = rope * map_size | 0x01;
889 elroy->mmio_base[(0x0248 - 0x200) / 8] = 0x0000e000;
890
891 /* map elroys mmio */
892 map_size = LMMIO_DIST_BASE_SIZE / ROPES_PER_IOC;
893 map_addr = F_EXTEND(LMMIO_DIST_BASE_ADDR + rope * map_size);
894 memory_region_init_alias(&elroy->pci_mmio_alias, OBJECT(elroy),
895 "pci-mmio-alias",
896 &elroy->pci_mmio, (uint32_t) map_addr, map_size);
897 memory_region_add_subregion(get_system_memory(), map_addr,
898 &elroy->pci_mmio_alias);
899
900 /* map elroys io */
901 map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC;
902 map_addr = F_EXTEND(IOS_DIST_BASE_ADDR + rope * map_size);
903 memory_region_add_subregion(get_system_memory(), map_addr,
904 &elroy->pci_io);
905
906 /* Host memory as seen from the PCI side, via the IOMMU. */
907 pci_setup_iommu(PCI_HOST_BRIDGE(elroy)->bus, &elroy_pcihost_iommu_ops,
908 elroy);
909 }
910 }
911
astro_class_init(ObjectClass * klass,const void * data)912 static void astro_class_init(ObjectClass *klass, const void *data)
913 {
914 DeviceClass *dc = DEVICE_CLASS(klass);
915
916 device_class_set_legacy_reset(dc, astro_reset);
917 dc->vmsd = &vmstate_astro;
918 dc->realize = astro_realize;
919 /*
920 * astro with elroys are hard part of the newer PA2.0 machines and can not
921 * be created without that hardware
922 */
923 dc->user_creatable = false;
924 }
925
926 static const TypeInfo astro_chip_info = {
927 .name = TYPE_ASTRO_CHIP,
928 .parent = TYPE_SYS_BUS_DEVICE,
929 .instance_init = astro_init,
930 .instance_size = sizeof(AstroState),
931 .class_init = astro_class_init,
932 };
933
astro_iommu_memory_region_class_init(ObjectClass * klass,const void * data)934 static void astro_iommu_memory_region_class_init(ObjectClass *klass,
935 const void *data)
936 {
937 IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
938
939 imrc->translate = astro_translate_iommu;
940 }
941
942 static const TypeInfo astro_iommu_memory_region_info = {
943 .parent = TYPE_IOMMU_MEMORY_REGION,
944 .name = TYPE_ASTRO_IOMMU_MEMORY_REGION,
945 .class_init = astro_iommu_memory_region_class_init,
946 };
947
948
astro_register_types(void)949 static void astro_register_types(void)
950 {
951 type_register_static(&astro_chip_info);
952 type_register_static(&astro_iommu_memory_region_info);
953 }
954
955 type_init(astro_register_types)
956