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