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