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