Revision 2173a75f exec.c

b/exec.c
1750 1750
    return 0;
1751 1751
}
1752 1752

  
1753
struct last_map {
1754
    target_phys_addr_t start_addr;
1755
    ram_addr_t size;
1756
    ram_addr_t phys_offset;
1757
};
1758

  
1753 1759
/* The l1_phys_map provides the upper P_L1_BITs of the guest physical
1754 1760
 * address.  Each intermediate table provides the next L2_BITs of guest
1755 1761
 * physical address space.  The number of levels vary based on host and
1756 1762
 * guest configuration, making it efficient to build the final guest
1757 1763
 * physical address by seeding the L1 offset and shifting and adding in
1758 1764
 * each L2 offset as we recurse through them. */
1759
static void phys_page_for_each_1(CPUPhysMemoryClient *client,
1760
                                 int level, void **lp, target_phys_addr_t addr)
1765
static void phys_page_for_each_1(CPUPhysMemoryClient *client, int level,
1766
                                 void **lp, target_phys_addr_t addr,
1767
                                 struct last_map *map)
1761 1768
{
1762 1769
    int i;
1763 1770

  
......
1769 1776
        addr <<= L2_BITS + TARGET_PAGE_BITS;
1770 1777
        for (i = 0; i < L2_SIZE; ++i) {
1771 1778
            if (pd[i].phys_offset != IO_MEM_UNASSIGNED) {
1772
                client->set_memory(client, addr | i << TARGET_PAGE_BITS,
1773
                                   TARGET_PAGE_SIZE, pd[i].phys_offset, false);
1779
                target_phys_addr_t start_addr = addr | i << TARGET_PAGE_BITS;
1780

  
1781
                if (map->size &&
1782
                    start_addr == map->start_addr + map->size &&
1783
                    pd[i].phys_offset == map->phys_offset + map->size) {
1784

  
1785
                    map->size += TARGET_PAGE_SIZE;
1786
                    continue;
1787
                } else if (map->size) {
1788
                    client->set_memory(client, map->start_addr,
1789
                                       map->size, map->phys_offset, false);
1790
                }
1791

  
1792
                map->start_addr = start_addr;
1793
                map->size = TARGET_PAGE_SIZE;
1794
                map->phys_offset = pd[i].phys_offset;
1774 1795
            }
1775 1796
        }
1776 1797
    } else {
1777 1798
        void **pp = *lp;
1778 1799
        for (i = 0; i < L2_SIZE; ++i) {
1779 1800
            phys_page_for_each_1(client, level - 1, pp + i,
1780
                                 (addr << L2_BITS) | i);
1801
                                 (addr << L2_BITS) | i, map);
1781 1802
        }
1782 1803
    }
1783 1804
}
......
1785 1806
static void phys_page_for_each(CPUPhysMemoryClient *client)
1786 1807
{
1787 1808
    int i;
1809
    struct last_map map = { };
1810

  
1788 1811
    for (i = 0; i < P_L1_SIZE; ++i) {
1789 1812
        phys_page_for_each_1(client, P_L1_SHIFT / L2_BITS - 1,
1790
                             l1_phys_map + i, i);
1813
                             l1_phys_map + i, i, &map);
1814
    }
1815
    if (map.size) {
1816
        client->set_memory(client, map.start_addr, map.size, map.phys_offset,
1817
                           false);
1791 1818
    }
1792 1819
}
1793 1820

  

Also available in: Unified diff