@samitouri / QOSamiQemu / commits / 12cd2e5ec1

hw/pci-host/astro: Fix LMMIO DIRECT mappings

Fix the existing code which has the mask wrong. Implement the direct mapping via overlapping subregion with priority 3 to make sure the direct mapping gets precedence over the LMMIO region. Signed-off-by: Helge Deller <deller@gmx.de>

Helge Deller committed Mar 29, 2026 at 00:30 UTC 12cd2e5ec1c8f855be890696c16d203724b139a4
1 file changed +25 -14
hw/pci-host/astro.c
+25 -14
@@ -607,9 +607,13 @@ static void adjust_LMMIO_DIRECT_mapping(AstroState *s, unsigned int reg_index)
607 MemoryRegion *lmmio_alias;
608 unsigned int lmmio_index, map_route;
609 hwaddr map_addr;
610 - uint32_t map_size;
610 + uint32_t map_size, map_enabled;
611 struct ElroyState *elroy;
612
613 + /* each LMMIO may access from 1 MB up to 64 MB */
614 + const unsigned int lmmio_mask = ~(1 * MiB - 1);
615 + const unsigned int lmmio_max_size = 64 * MiB;
616 +
617 /* pointer to LMMIO_DIRECT entry */
618 lmmio_index = reg_index / 3;
619 lmmio_alias = &s->lmmio_direct[lmmio_index];
@@ -622,31 +626,38 @@ static void adjust_LMMIO_DIRECT_mapping(AstroState *s, unsigned int reg_index)
626 map_route &= (ELROY_NUM - 1);
627 elroy = s->elroy[map_route];
628
629 + /* make sure the lmmio region is initially turned off */
630 if (lmmio_alias->enabled) {
631 memory_region_set_enabled(lmmio_alias, false);
632 }
633
634 + /* do sanity checks and calculate mmio size */
635 + map_enabled = map_addr & 1;
636 + map_addr &= lmmio_mask;
637 + map_size &= lmmio_mask;
638 + map_size = MIN(map_size, lmmio_max_size);
639 map_addr = F_EXTEND(map_addr);
630 - map_addr &= TARGET_PAGE_MASK;
631 - map_size = (~map_size) + 1;
632 - map_size &= TARGET_PAGE_MASK;
640
634 - /* exit if disabled or zero map size */
635 - if (!(map_addr & 1) || !map_size) {
641 + /* exit if disabled or has zero size. */
642 + if (!map_enabled || !map_size) {
643 return;
644 }
645
639 - if (!memory_region_size(lmmio_alias)) {
646 + if (!lmmio_alias->name) {
647 + char lmmio_name[32];
648 + snprintf(lmmio_name, sizeof(lmmio_name),
649 + "LMMIO-DIRECT-%u", lmmio_index);
650 memory_region_init_alias(lmmio_alias, OBJECT(elroy),
641 - "pci-lmmmio-alias", &elroy->pci_mmio,
651 + lmmio_name, &elroy->pci_mmio,
652 (uint32_t) map_addr, map_size);
643 - memory_region_add_subregion(get_system_memory(), map_addr,
644 - lmmio_alias);
645 - } else {
646 - memory_region_set_alias_offset(lmmio_alias, map_addr);
647 - memory_region_set_size(lmmio_alias, map_size);
648 - memory_region_set_enabled(lmmio_alias, true);
653 + memory_region_add_subregion_overlap(get_system_memory(),
654 + map_addr, lmmio_alias, 3);
655 }
656 +
657 + memory_region_set_address(lmmio_alias, map_addr);
658 + memory_region_set_alias_offset(lmmio_alias, (uint32_t) map_addr);
659 + memory_region_set_size(lmmio_alias, map_size);
660 + memory_region_set_enabled(lmmio_alias, true);
661 }
662
663 static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr,