1
2
3
4
5
6
7
8
9#include "qemu/osdep.h"
10#include "qemu/module.h"
11#include "qemu/units.h"
12#include "qapi/error.h"
13#include "hw/pci/pci_host.h"
14#include "cpu.h"
15#include "hw/irq.h"
16#include "alpha_sys.h"
17
18
19#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
20#define TYPE_TYPHOON_IOMMU_MEMORY_REGION "typhoon-iommu-memory-region"
21
22typedef struct TyphoonCchip {
23 MemoryRegion region;
24 uint64_t misc;
25 uint64_t drir;
26 uint64_t dim[4];
27 uint32_t iic[4];
28 AlphaCPU *cpu[4];
29} TyphoonCchip;
30
31typedef struct TyphoonWindow {
32 uint64_t wba;
33 uint64_t wsm;
34 uint64_t tba;
35} TyphoonWindow;
36
37typedef struct TyphoonPchip {
38 MemoryRegion region;
39 MemoryRegion reg_iack;
40 MemoryRegion reg_mem;
41 MemoryRegion reg_io;
42 MemoryRegion reg_conf;
43
44 AddressSpace iommu_as;
45 IOMMUMemoryRegion iommu;
46
47 uint64_t ctl;
48 TyphoonWindow win[4];
49} TyphoonPchip;
50
51OBJECT_DECLARE_SIMPLE_TYPE(TyphoonState, TYPHOON_PCI_HOST_BRIDGE)
52
53struct TyphoonState {
54 PCIHostState parent_obj;
55
56 TyphoonCchip cchip;
57 TyphoonPchip pchip;
58 MemoryRegion dchip_region;
59};
60
61
62static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
63{
64
65 if (cpu != NULL) {
66 CPUState *cs = CPU(cpu);
67 if (req) {
68 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
69 } else {
70 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
71 }
72 }
73}
74
75static MemTxResult cchip_read(void *opaque, hwaddr addr,
76 uint64_t *data, unsigned size,
77 MemTxAttrs attrs)
78{
79 CPUState *cpu = current_cpu;
80 TyphoonState *s = opaque;
81 uint64_t ret = 0;
82
83 switch (addr) {
84 case 0x0000:
85
86
87
88 break;
89
90 case 0x0040:
91
92
93 break;
94
95 case 0x0080:
96
97 ret = s->cchip.misc | (cpu->cpu_index & 3);
98 break;
99
100 case 0x00c0:
101
102 break;
103
104 case 0x0100:
105 case 0x0140:
106 case 0x0180:
107 case 0x01c0:
108
109
110 break;
111
112 case 0x0200:
113
114 ret = s->cchip.dim[0];
115 break;
116 case 0x0240:
117
118 ret = s->cchip.dim[1];
119 break;
120 case 0x0280:
121
122 ret = s->cchip.dim[0] & s->cchip.drir;
123 break;
124 case 0x02c0:
125
126 ret = s->cchip.dim[1] & s->cchip.drir;
127 break;
128 case 0x0300:
129
130 ret = s->cchip.drir;
131 break;
132
133 case 0x0340:
134
135 break;
136
137 case 0x0380:
138
139 ret = s->cchip.iic[0];
140 break;
141 case 0x03c0:
142
143 ret = s->cchip.iic[1];
144 break;
145
146 case 0x0400:
147 case 0x0440:
148 case 0x0480:
149 case 0x04c0:
150
151 break;
152
153 case 0x0580:
154
155
156 break;
157 case 0x05c0:
158
159 break;
160
161 case 0x0600:
162
163 ret = s->cchip.dim[2];
164 break;
165 case 0x0640:
166
167 ret = s->cchip.dim[3];
168 break;
169 case 0x0680:
170
171 ret = s->cchip.dim[2] & s->cchip.drir;
172 break;
173 case 0x06c0:
174
175 ret = s->cchip.dim[3] & s->cchip.drir;
176 break;
177
178 case 0x0700:
179
180 ret = s->cchip.iic[2];
181 break;
182 case 0x0740:
183
184 ret = s->cchip.iic[3];
185 break;
186
187 case 0x0780:
188
189 break;
190
191 case 0x0c00:
192 case 0x0c40:
193 case 0x0c80:
194 case 0x0cc0:
195 break;
196
197 default:
198 return MEMTX_ERROR;
199 }
200
201 *data = ret;
202 return MEMTX_OK;
203}
204
205static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size)
206{
207
208 return 0;
209}
210
211static MemTxResult pchip_read(void *opaque, hwaddr addr, uint64_t *data,
212 unsigned size, MemTxAttrs attrs)
213{
214 TyphoonState *s = opaque;
215 uint64_t ret = 0;
216
217 switch (addr) {
218 case 0x0000:
219
220 ret = s->pchip.win[0].wba;
221 break;
222 case 0x0040:
223
224 ret = s->pchip.win[1].wba;
225 break;
226 case 0x0080:
227
228 ret = s->pchip.win[2].wba;
229 break;
230 case 0x00c0:
231
232 ret = s->pchip.win[3].wba;
233 break;
234
235 case 0x0100:
236
237 ret = s->pchip.win[0].wsm;
238 break;
239 case 0x0140:
240
241 ret = s->pchip.win[1].wsm;
242 break;
243 case 0x0180:
244
245 ret = s->pchip.win[2].wsm;
246 break;
247 case 0x01c0:
248
249 ret = s->pchip.win[3].wsm;
250 break;
251
252 case 0x0200:
253
254 ret = s->pchip.win[0].tba;
255 break;
256 case 0x0240:
257
258 ret = s->pchip.win[1].tba;
259 break;
260 case 0x0280:
261
262 ret = s->pchip.win[2].tba;
263 break;
264 case 0x02c0:
265
266 ret = s->pchip.win[3].tba;
267 break;
268
269 case 0x0300:
270
271 ret = s->pchip.ctl;
272 break;
273 case 0x0340:
274
275 break;
276 case 0x03c0:
277
278 break;
279 case 0x0400:
280
281 break;
282 case 0x0440:
283
284 break;
285 case 0x0480:
286
287 break;
288 case 0x04c0:
289
290 break;
291 case 0x0500:
292 case 0x0540:
293 case 0x0800:
294 break;
295
296 default:
297 return MEMTX_ERROR;
298 }
299
300 *data = ret;
301 return MEMTX_OK;
302}
303
304static MemTxResult cchip_write(void *opaque, hwaddr addr,
305 uint64_t val, unsigned size,
306 MemTxAttrs attrs)
307{
308 TyphoonState *s = opaque;
309 uint64_t oldval, newval;
310
311 switch (addr) {
312 case 0x0000:
313
314
315 break;
316
317 case 0x0040:
318
319
320 break;
321
322 case 0x0080:
323
324 newval = oldval = s->cchip.misc;
325 newval &= ~(val & 0x10000ff0);
326 if (val & 0x100000) {
327 newval &= ~0xff0000ull;
328 } else {
329 newval |= val & 0x00f00000;
330 if ((newval & 0xf0000) == 0) {
331 newval |= val & 0xf0000;
332 }
333 }
334 newval |= (val & 0xf000) >> 4;
335
336 newval &= ~0xf0000000000ull;
337 newval |= val & 0xf0000000000ull;
338 s->cchip.misc = newval;
339
340
341 if ((newval ^ oldval) & 0xff0) {
342 int i;
343 for (i = 0; i < 4; ++i) {
344 AlphaCPU *cpu = s->cchip.cpu[i];
345 if (cpu != NULL) {
346 CPUState *cs = CPU(cpu);
347
348 if (newval & (1 << (i + 8))) {
349 cpu_interrupt(cs, CPU_INTERRUPT_SMP);
350 } else {
351 cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
352 }
353
354
355 if ((newval & (1 << (i + 4))) == 0) {
356 cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
357 }
358 }
359 }
360 }
361 break;
362
363 case 0x00c0:
364
365 break;
366
367 case 0x0100:
368 case 0x0140:
369 case 0x0180:
370 case 0x01c0:
371
372
373 break;
374
375 case 0x0200:
376
377 s->cchip.dim[0] = val;
378 cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
379 break;
380 case 0x0240:
381
382 s->cchip.dim[1] = val;
383 cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
384 break;
385
386 case 0x0280:
387 case 0x02c0:
388 case 0x0300:
389 break;
390
391 case 0x0340:
392
393 break;
394
395 case 0x0380:
396 s->cchip.iic[0] = val & 0xffffff;
397 break;
398 case 0x03c0:
399 s->cchip.iic[1] = val & 0xffffff;
400 break;
401
402 case 0x0400:
403 case 0x0440:
404 case 0x0480:
405 case 0x04c0:
406
407 break;
408
409 case 0x0580:
410
411
412 break;
413 case 0x05c0:
414
415 break;
416
417 case 0x0600:
418
419 s->cchip.dim[2] = val;
420 cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
421 break;
422 case 0x0640:
423
424 s->cchip.dim[3] = val;
425 cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
426 break;
427
428 case 0x0680:
429 case 0x06c0:
430 break;
431
432 case 0x0700:
433 s->cchip.iic[2] = val & 0xffffff;
434 break;
435 case 0x0740:
436 s->cchip.iic[3] = val & 0xffffff;
437 break;
438
439 case 0x0780:
440
441 break;
442
443 case 0x0c00:
444 case 0x0c40:
445 case 0x0c80:
446 case 0x0cc0:
447 break;
448
449 default:
450 return MEMTX_ERROR;
451 }
452
453 return MEMTX_OK;
454}
455
456static void dchip_write(void *opaque, hwaddr addr,
457 uint64_t val, unsigned size)
458{
459
460}
461
462static MemTxResult pchip_write(void *opaque, hwaddr addr,
463 uint64_t val, unsigned size,
464 MemTxAttrs attrs)
465{
466 TyphoonState *s = opaque;
467 uint64_t oldval;
468
469 switch (addr) {
470 case 0x0000:
471
472 s->pchip.win[0].wba = val & 0xfff00003u;
473 break;
474 case 0x0040:
475
476 s->pchip.win[1].wba = val & 0xfff00003u;
477 break;
478 case 0x0080:
479
480 s->pchip.win[2].wba = val & 0xfff00003u;
481 break;
482 case 0x00c0:
483
484 s->pchip.win[3].wba = (val & 0x80fff00001ull) | 2;
485 break;
486
487 case 0x0100:
488
489 s->pchip.win[0].wsm = val & 0xfff00000u;
490 break;
491 case 0x0140:
492
493 s->pchip.win[1].wsm = val & 0xfff00000u;
494 break;
495 case 0x0180:
496
497 s->pchip.win[2].wsm = val & 0xfff00000u;
498 break;
499 case 0x01c0:
500
501 s->pchip.win[3].wsm = val & 0xfff00000u;
502 break;
503
504 case 0x0200:
505
506 s->pchip.win[0].tba = val & 0x7fffffc00ull;
507 break;
508 case 0x0240:
509
510 s->pchip.win[1].tba = val & 0x7fffffc00ull;
511 break;
512 case 0x0280:
513
514 s->pchip.win[2].tba = val & 0x7fffffc00ull;
515 break;
516 case 0x02c0:
517
518 s->pchip.win[3].tba = val & 0x7fffffc00ull;
519 break;
520
521 case 0x0300:
522
523 oldval = s->pchip.ctl;
524 oldval &= ~0x00001cff0fc7ffull;
525 oldval |= val & 0x00001cff0fc7ffull;
526 s->pchip.ctl = oldval;
527 break;
528
529 case 0x0340:
530
531 break;
532 case 0x03c0:
533
534 break;
535 case 0x0400:
536
537 break;
538 case 0x0440:
539
540 break;
541
542 case 0x0480:
543
544 break;
545
546 case 0x04c0:
547
548 break;
549
550 case 0x0500:
551
552 case 0x0540:
553
554 case 0x0800:
555
556 break;
557
558 default:
559 return MEMTX_ERROR;
560 }
561
562 return MEMTX_OK;
563}
564
565static const MemoryRegionOps cchip_ops = {
566 .read_with_attrs = cchip_read,
567 .write_with_attrs = cchip_write,
568 .endianness = DEVICE_LITTLE_ENDIAN,
569 .valid = {
570 .min_access_size = 8,
571 .max_access_size = 8,
572 },
573 .impl = {
574 .min_access_size = 8,
575 .max_access_size = 8,
576 },
577};
578
579static const MemoryRegionOps dchip_ops = {
580 .read = dchip_read,
581 .write = dchip_write,
582 .endianness = DEVICE_LITTLE_ENDIAN,
583 .valid = {
584 .min_access_size = 8,
585 .max_access_size = 8,
586 },
587 .impl = {
588 .min_access_size = 8,
589 .max_access_size = 8,
590 },
591};
592
593static const MemoryRegionOps pchip_ops = {
594 .read_with_attrs = pchip_read,
595 .write_with_attrs = pchip_write,
596 .endianness = DEVICE_LITTLE_ENDIAN,
597 .valid = {
598 .min_access_size = 8,
599 .max_access_size = 8,
600 },
601 .impl = {
602 .min_access_size = 8,
603 .max_access_size = 8,
604 },
605};
606
607
608
609static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret)
610{
611 *ret = (IOMMUTLBEntry) {
612 .target_as = &address_space_memory,
613 .translated_addr = taddr,
614 .addr_mask = mask,
615 .perm = IOMMU_RW,
616 };
617 return true;
618}
619
620
621
622static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret)
623{
624 uint64_t pte = address_space_ldq(&address_space_memory, pte_addr,
625 MEMTXATTRS_UNSPECIFIED, NULL);
626
627
628 if ((pte & 1) == 0) {
629 return false;
630 }
631
632 return make_iommu_tlbe((pte & 0x3ffffe) << 12, 0x1fff, ret);
633}
634
635
636
637static bool window_translate(TyphoonWindow *win, hwaddr addr,
638 IOMMUTLBEntry *ret)
639{
640 uint32_t wba = win->wba;
641 uint64_t wsm = win->wsm;
642 uint64_t tba = win->tba;
643 uint64_t wsm_ext = wsm | 0xfffff;
644
645
646 if ((wba & 1) == 0) {
647 return false;
648 }
649
650
651 if ((addr & ~wsm_ext) != (wba & 0xfff00000u)) {
652 return false;
653 }
654
655 if (wba & 2) {
656
657 hwaddr pte_addr;
658
659
660 pte_addr = tba & ~(wsm >> 10);
661 pte_addr |= (addr & (wsm | 0xfe000)) >> 10;
662 return pte_translate(pte_addr, ret);
663 } else {
664
665 return make_iommu_tlbe(tba & ~wsm_ext, wsm_ext, ret);
666 }
667}
668
669
670
671
672static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
673 hwaddr addr,
674 IOMMUAccessFlags flag,
675 int iommu_idx)
676{
677 TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
678 IOMMUTLBEntry ret;
679 int i;
680
681 if (addr <= 0xffffffffu) {
682
683
684
685 if ((pchip->ctl & 0x20)
686 && addr >= 0x80000
687 && addr <= 0xfffff) {
688 goto failure;
689 }
690
691
692 for (i = 0; i < 3; ++i) {
693 if (window_translate(&pchip->win[i], addr, &ret)) {
694 goto success;
695 }
696 }
697
698
699 if ((pchip->win[3].wba & 0x80000000000ull) == 0
700 && window_translate(&pchip->win[3], addr, &ret)) {
701 goto success;
702 }
703 } else {
704
705
706 if (addr >= 0x10000000000ull && addr < 0x20000000000ull) {
707
708 if (pchip->ctl & 0x40) {
709
710 make_iommu_tlbe(0, 0x007ffffffffull, &ret);
711 goto success;
712 }
713 }
714
715 if (addr >= 0x80000000000ull && addr <= 0xfffffffffffull) {
716
717 if ((pchip->win[3].wba & 0x80000000001ull) == 0x80000000001ull) {
718 uint64_t pte_addr;
719
720 pte_addr = pchip->win[3].tba & 0x7ffc00000ull;
721 pte_addr |= (addr & 0xffffe000u) >> 10;
722 if (pte_translate(pte_addr, &ret)) {
723 goto success;
724 }
725 }
726 }
727 }
728
729 failure:
730 ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE };
731 success:
732 return ret;
733}
734
735static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
736{
737 TyphoonState *s = opaque;
738 return &s->pchip.iommu_as;
739}
740
741static void typhoon_set_irq(void *opaque, int irq, int level)
742{
743 TyphoonState *s = opaque;
744 uint64_t drir;
745 int i;
746
747
748 drir = s->cchip.drir;
749 if (level) {
750 drir |= 1ull << irq;
751 } else {
752 drir &= ~(1ull << irq);
753 }
754 s->cchip.drir = drir;
755
756 for (i = 0; i < 4; ++i) {
757 cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir);
758 }
759}
760
761static void typhoon_set_isa_irq(void *opaque, int irq, int level)
762{
763 typhoon_set_irq(opaque, 55, level);
764}
765
766static void typhoon_set_timer_irq(void *opaque, int irq, int level)
767{
768 TyphoonState *s = opaque;
769 int i;
770
771
772
773
774
775 if (level == 0) {
776 return;
777 }
778
779
780 for (i = 0; i < 4; ++i) {
781 AlphaCPU *cpu = s->cchip.cpu[i];
782 if (cpu != NULL) {
783 uint32_t iic = s->cchip.iic[i];
784
785
786
787
788
789
790
791
792
793
794 iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000);
795 s->cchip.iic[i] = iic;
796
797 if (iic & 0x1000000) {
798
799 s->cchip.misc |= 1 << (i + 4);
800
801 cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
802 }
803 }
804 }
805}
806
807static void typhoon_alarm_timer(void *opaque)
808{
809 TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
810 int cpu = (uintptr_t)opaque & 3;
811
812
813 s->cchip.misc |= 1 << (cpu + 4);
814 cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
815}
816
817PCIBus *typhoon_init(MemoryRegion *ram, qemu_irq *p_isa_irq,
818 qemu_irq *p_rtc_irq, AlphaCPU *cpus[4],
819 pci_map_irq_fn sys_map_irq, uint8_t devfn_min)
820{
821 MemoryRegion *addr_space = get_system_memory();
822 DeviceState *dev;
823 TyphoonState *s;
824 PCIHostState *phb;
825 PCIBus *b;
826 int i;
827
828 dev = qdev_new(TYPE_TYPHOON_PCI_HOST_BRIDGE);
829
830 s = TYPHOON_PCI_HOST_BRIDGE(dev);
831 phb = PCI_HOST_BRIDGE(dev);
832
833 s->cchip.misc = 0x800000000ull;
834 s->pchip.win[3].wba = 2;
835
836
837 for (i = 0; i < 4; i++) {
838 AlphaCPU *cpu = cpus[i];
839 s->cchip.cpu[i] = cpu;
840 if (cpu != NULL) {
841 cpu->alarm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
842 typhoon_alarm_timer,
843 (void *)((uintptr_t)s + i));
844 }
845 }
846
847 *p_isa_irq = qemu_allocate_irq(typhoon_set_isa_irq, s, 0);
848 *p_rtc_irq = qemu_allocate_irq(typhoon_set_timer_irq, s, 0);
849
850
851
852 memory_region_add_subregion(addr_space, 0, ram);
853
854
855
856
857
858
859 memory_region_init_io(&s->pchip.region, OBJECT(s), &pchip_ops, s, "pchip0",
860 256 * MiB);
861 memory_region_add_subregion(addr_space, 0x80180000000ULL,
862 &s->pchip.region);
863
864
865 memory_region_init_io(&s->cchip.region, OBJECT(s), &cchip_ops, s, "cchip0",
866 256 * MiB);
867 memory_region_add_subregion(addr_space, 0x801a0000000ULL,
868 &s->cchip.region);
869
870
871 memory_region_init_io(&s->dchip_region, OBJECT(s), &dchip_ops, s, "dchip0",
872 256 * MiB);
873 memory_region_add_subregion(addr_space, 0x801b0000000ULL,
874 &s->dchip_region);
875
876
877 memory_region_init(&s->pchip.reg_mem, OBJECT(s), "pci0-mem", 4 * GiB);
878 memory_region_add_subregion(addr_space, 0x80000000000ULL,
879 &s->pchip.reg_mem);
880
881
882 memory_region_init_io(&s->pchip.reg_io, OBJECT(s), &alpha_pci_ignore_ops,
883 NULL, "pci0-io", 32 * MiB);
884 memory_region_add_subregion(addr_space, 0x801fc000000ULL,
885 &s->pchip.reg_io);
886
887 b = pci_register_root_bus(dev, "pci",
888 typhoon_set_irq, sys_map_irq, s,
889 &s->pchip.reg_mem, &s->pchip.reg_io,
890 devfn_min, 64, TYPE_PCI_BUS);
891 phb->bus = b;
892 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
893
894
895 memory_region_init_iommu(&s->pchip.iommu, sizeof(s->pchip.iommu),
896 TYPE_TYPHOON_IOMMU_MEMORY_REGION, OBJECT(s),
897 "iommu-typhoon", UINT64_MAX);
898 address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
899 "pchip0-pci");
900 pci_setup_iommu(b, typhoon_pci_dma_iommu, s);
901
902
903 memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops,
904 b, "pci0-iack", 64 * MiB);
905 memory_region_add_subregion(addr_space, 0x801f8000000ULL,
906 &s->pchip.reg_iack);
907
908
909 memory_region_init_io(&s->pchip.reg_conf, OBJECT(s), &alpha_pci_conf1_ops,
910 b, "pci0-conf", 16 * MiB);
911 memory_region_add_subregion(addr_space, 0x801fe000000ULL,
912 &s->pchip.reg_conf);
913
914
915
916
917
918
919
920
921
922
923 return b;
924}
925
926static const TypeInfo typhoon_pcihost_info = {
927 .name = TYPE_TYPHOON_PCI_HOST_BRIDGE,
928 .parent = TYPE_PCI_HOST_BRIDGE,
929 .instance_size = sizeof(TyphoonState),
930};
931
932static void typhoon_iommu_memory_region_class_init(ObjectClass *klass,
933 void *data)
934{
935 IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
936
937 imrc->translate = typhoon_translate_iommu;
938}
939
940static const TypeInfo typhoon_iommu_memory_region_info = {
941 .parent = TYPE_IOMMU_MEMORY_REGION,
942 .name = TYPE_TYPHOON_IOMMU_MEMORY_REGION,
943 .class_init = typhoon_iommu_memory_region_class_init,
944};
945
946static void typhoon_register_types(void)
947{
948 type_register_static(&typhoon_pcihost_info);
949 type_register_static(&typhoon_iommu_memory_region_info);
950}
951
952type_init(typhoon_register_types)
953