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