Commit 92e873b996adb4cdc8ec9ab7e49d1c88d8749127
1 parent
9fddaa0c
support for non continuous RAM or ROM
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@842 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
46 additions
and
11 deletions
exec.c
... | ... | @@ -64,9 +64,7 @@ uint8_t *phys_ram_base; |
64 | 64 | uint8_t *phys_ram_dirty; |
65 | 65 | |
66 | 66 | typedef struct PageDesc { |
67 | - /* offset in host memory of the page + io_index in the low 12 bits */ | |
68 | - unsigned long phys_offset; | |
69 | - /* list of TBs intersecting this physical page */ | |
67 | + /* list of TBs intersecting this ram page */ | |
70 | 68 | TranslationBlock *first_tb; |
71 | 69 | /* in order to optimize self modifying code, we count the number |
72 | 70 | of lookups we do to a given page to use a bitmap */ |
... | ... | @@ -77,6 +75,11 @@ typedef struct PageDesc { |
77 | 75 | #endif |
78 | 76 | } PageDesc; |
79 | 77 | |
78 | +typedef struct PhysPageDesc { | |
79 | + /* offset in host memory of the page + io_index in the low 12 bits */ | |
80 | + unsigned long phys_offset; | |
81 | +} PhysPageDesc; | |
82 | + | |
80 | 83 | typedef struct VirtPageDesc { |
81 | 84 | /* physical address of code page. It is valid only if 'valid_tag' |
82 | 85 | matches 'virt_valid_tag' */ |
... | ... | @@ -102,7 +105,9 @@ unsigned long host_page_bits; |
102 | 105 | unsigned long host_page_size; |
103 | 106 | unsigned long host_page_mask; |
104 | 107 | |
108 | +/* XXX: for system emulation, it could just be an array */ | |
105 | 109 | static PageDesc *l1_map[L1_SIZE]; |
110 | +static PhysPageDesc *l1_phys_map[L1_SIZE]; | |
106 | 111 | |
107 | 112 | #if !defined(CONFIG_USER_ONLY) |
108 | 113 | static VirtPageDesc *l1_virt_map[L1_SIZE]; |
... | ... | @@ -166,6 +171,31 @@ static inline PageDesc *page_find(unsigned int index) |
166 | 171 | return p + (index & (L2_SIZE - 1)); |
167 | 172 | } |
168 | 173 | |
174 | +static inline PhysPageDesc *phys_page_find_alloc(unsigned int index) | |
175 | +{ | |
176 | + PhysPageDesc **lp, *p; | |
177 | + | |
178 | + lp = &l1_phys_map[index >> L2_BITS]; | |
179 | + p = *lp; | |
180 | + if (!p) { | |
181 | + /* allocate if not found */ | |
182 | + p = qemu_malloc(sizeof(PhysPageDesc) * L2_SIZE); | |
183 | + memset(p, 0, sizeof(PhysPageDesc) * L2_SIZE); | |
184 | + *lp = p; | |
185 | + } | |
186 | + return p + (index & (L2_SIZE - 1)); | |
187 | +} | |
188 | + | |
189 | +static inline PhysPageDesc *phys_page_find(unsigned int index) | |
190 | +{ | |
191 | + PhysPageDesc *p; | |
192 | + | |
193 | + p = l1_phys_map[index >> L2_BITS]; | |
194 | + if (!p) | |
195 | + return 0; | |
196 | + return p + (index & (L2_SIZE - 1)); | |
197 | +} | |
198 | + | |
169 | 199 | #if !defined(CONFIG_USER_ONLY) |
170 | 200 | static void tlb_protect_code(CPUState *env, target_ulong addr); |
171 | 201 | static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr); |
... | ... | @@ -1428,7 +1458,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr, |
1428 | 1458 | target_phys_addr_t paddr, int prot, |
1429 | 1459 | int is_user, int is_softmmu) |
1430 | 1460 | { |
1431 | - PageDesc *p; | |
1461 | + PhysPageDesc *p; | |
1432 | 1462 | unsigned long pd; |
1433 | 1463 | TranslationBlock *first_tb; |
1434 | 1464 | unsigned int index; |
... | ... | @@ -1436,13 +1466,18 @@ int tlb_set_page(CPUState *env, target_ulong vaddr, |
1436 | 1466 | unsigned long addend; |
1437 | 1467 | int ret; |
1438 | 1468 | |
1439 | - p = page_find(paddr >> TARGET_PAGE_BITS); | |
1469 | + p = phys_page_find(paddr >> TARGET_PAGE_BITS); | |
1470 | + first_tb = NULL; | |
1440 | 1471 | if (!p) { |
1441 | 1472 | pd = IO_MEM_UNASSIGNED; |
1442 | - first_tb = NULL; | |
1443 | 1473 | } else { |
1474 | + PageDesc *p1; | |
1444 | 1475 | pd = p->phys_offset; |
1445 | - first_tb = p->first_tb; | |
1476 | + if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) { | |
1477 | + /* NOTE: we also allocate the page at this stage */ | |
1478 | + p1 = page_find_alloc(pd >> TARGET_PAGE_BITS); | |
1479 | + first_tb = p1->first_tb; | |
1480 | + } | |
1446 | 1481 | } |
1447 | 1482 | #if defined(DEBUG_TLB) |
1448 | 1483 | printf("tlb_set_page: vaddr=0x%08x paddr=0x%08x prot=%x u=%d c=%d smmu=%d pd=0x%08x\n", |
... | ... | @@ -1752,11 +1787,11 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr, |
1752 | 1787 | unsigned long phys_offset) |
1753 | 1788 | { |
1754 | 1789 | unsigned long addr, end_addr; |
1755 | - PageDesc *p; | |
1790 | + PhysPageDesc *p; | |
1756 | 1791 | |
1757 | 1792 | end_addr = start_addr + size; |
1758 | 1793 | for(addr = start_addr; addr < end_addr; addr += TARGET_PAGE_SIZE) { |
1759 | - p = page_find_alloc(addr >> TARGET_PAGE_BITS); | |
1794 | + p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS); | |
1760 | 1795 | p->phys_offset = phys_offset; |
1761 | 1796 | if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) |
1762 | 1797 | phys_offset += TARGET_PAGE_SIZE; |
... | ... | @@ -1938,14 +1973,14 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, |
1938 | 1973 | uint32_t val; |
1939 | 1974 | target_phys_addr_t page; |
1940 | 1975 | unsigned long pd; |
1941 | - PageDesc *p; | |
1976 | + PhysPageDesc *p; | |
1942 | 1977 | |
1943 | 1978 | while (len > 0) { |
1944 | 1979 | page = addr & TARGET_PAGE_MASK; |
1945 | 1980 | l = (page + TARGET_PAGE_SIZE) - addr; |
1946 | 1981 | if (l > len) |
1947 | 1982 | l = len; |
1948 | - p = page_find(page >> TARGET_PAGE_BITS); | |
1983 | + p = phys_page_find(page >> TARGET_PAGE_BITS); | |
1949 | 1984 | if (!p) { |
1950 | 1985 | pd = IO_MEM_UNASSIGNED; |
1951 | 1986 | } else { | ... | ... |