@samitouri / QOSamiQemu / commits / a45862947e

hw/pci-host/astro: Add GMMIO mapping

Implement the GMMIO mapping. Signed-off-by: Helge Deller <deller@gmx.de>

Helge Deller committed Mar 29, 2026 at 00:34 UTC a45862947e417a6006be14dee9148a58e3689a76
1 file changed +70 -1
hw/pci-host/astro.c
+70 -1
@@ -14,7 +14,6 @@
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
17 */
18
19 #define TYPE_ASTRO_IOMMU_MEMORY_REGION "astro-iommu-memory-region"
@@ -660,6 +659,73 @@ static void adjust_LMMIO_DIRECT_mapping(AstroState *s, unsigned int reg_index)
659 memory_region_set_enabled(lmmio_alias, true);
660 }
661
662 +static void adjust_GMMIO_mapping(AstroState *s)
663 +{
664 + MemoryRegion *gmmio;
665 + uint64_t map_addr, map_size, align_mask;
666 + uint32_t map_route, map_enabled, i;
667 +
668 + gmmio = &s->gmmio;
669 + map_addr = s->ioc_ranges[(0x378 - 0x300) / 8]; /* GMMIO_DIST_BASE */
670 + map_enabled = map_addr & 1;
671 + map_addr &= MAKE_64BIT_MASK(32, 8);
672 + s->ioc_ranges[(0x378 - 0x300) / 8] = map_addr | map_enabled;
673 +
674 + map_route = s->ioc_ranges[(0x388 - 0x300) / 8] >> 58; /* GMMIO_DIST_ROUTE */
675 + map_route = MIN(MAX(map_route, 29), 33); /* between 4-16 GB total */
676 + map_size = 1ULL << map_route; /* size of each mapping */
677 + align_mask = ~(map_size - 1);
678 +
679 + /* make sure the lmmio region is initially turned off */
680 + if (gmmio->enabled) {
681 + memory_region_set_enabled(gmmio, false);
682 + }
683 +
684 + /* do sanity checks and calculate mmio size */
685 + map_addr &= align_mask;
686 +
687 + /* exit if disabled */
688 + if (!map_enabled) {
689 + return;
690 + }
691 +
692 + if (!gmmio->name) {
693 + memory_region_init_io(gmmio, OBJECT(s), &unassigned_io_ops, s,
694 + "GMMIO", ROPES_PER_IOC * map_size);
695 + memory_region_add_subregion_overlap(get_system_memory(),
696 + map_addr, gmmio, 1);
697 + }
698 +
699 + memory_region_set_address(gmmio, map_addr);
700 + memory_region_set_size(gmmio, ROPES_PER_IOC * map_size);
701 + memory_region_set_enabled(gmmio, true);
702 +
703 + for (i = 0; i < ELROY_NUM; i++) {
704 + MemoryRegion *alias;
705 + ElroyState *elroy;
706 + int rope;
707 +
708 + elroy = s->elroy[i];
709 + alias = &elroy->gmmio_alias;
710 + rope = elroy_rope_nr[i];
711 + if (alias->enabled) {
712 + memory_region_set_enabled(alias, false);
713 + }
714 +
715 + if (!alias->name) {
716 + memory_region_init_alias(alias, OBJECT(elroy),
717 + "gmmio-alias", &elroy->pci_mmio, 0, map_size);
718 + memory_region_add_subregion_overlap(gmmio, rope * map_size,
719 + alias, 2);
720 + }
721 +
722 + memory_region_set_address(alias, rope * map_size);
723 + memory_region_set_alias_offset(alias, map_addr + rope * map_size);
724 + memory_region_set_size(alias, map_size);
725 + memory_region_set_enabled(alias, true);
726 + }
727 +}
728 +
729 static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr,
730 uint64_t *data, unsigned size,
731 MemTxAttrs attrs)
@@ -775,6 +841,9 @@ static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr,
841 if (addr >= 0x360 && addr <= 0x370 + 7) {
842 adjust_LMMIO_mapping(s);
843 }
844 + if (addr >= 0x378 && addr <= 0x388 + 7) {
845 + adjust_GMMIO_mapping(s);
846 + }
847 break;
848 case 0x10200:
849 case 0x10220: