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,9 +64,7 @@ uint8_t *phys_ram_base; | ||
64 | uint8_t *phys_ram_dirty; | 64 | uint8_t *phys_ram_dirty; |
65 | 65 | ||
66 | typedef struct PageDesc { | 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 | TranslationBlock *first_tb; | 68 | TranslationBlock *first_tb; |
71 | /* in order to optimize self modifying code, we count the number | 69 | /* in order to optimize self modifying code, we count the number |
72 | of lookups we do to a given page to use a bitmap */ | 70 | of lookups we do to a given page to use a bitmap */ |
@@ -77,6 +75,11 @@ typedef struct PageDesc { | @@ -77,6 +75,11 @@ typedef struct PageDesc { | ||
77 | #endif | 75 | #endif |
78 | } PageDesc; | 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 | typedef struct VirtPageDesc { | 83 | typedef struct VirtPageDesc { |
81 | /* physical address of code page. It is valid only if 'valid_tag' | 84 | /* physical address of code page. It is valid only if 'valid_tag' |
82 | matches 'virt_valid_tag' */ | 85 | matches 'virt_valid_tag' */ |
@@ -102,7 +105,9 @@ unsigned long host_page_bits; | @@ -102,7 +105,9 @@ unsigned long host_page_bits; | ||
102 | unsigned long host_page_size; | 105 | unsigned long host_page_size; |
103 | unsigned long host_page_mask; | 106 | unsigned long host_page_mask; |
104 | 107 | ||
108 | +/* XXX: for system emulation, it could just be an array */ | ||
105 | static PageDesc *l1_map[L1_SIZE]; | 109 | static PageDesc *l1_map[L1_SIZE]; |
110 | +static PhysPageDesc *l1_phys_map[L1_SIZE]; | ||
106 | 111 | ||
107 | #if !defined(CONFIG_USER_ONLY) | 112 | #if !defined(CONFIG_USER_ONLY) |
108 | static VirtPageDesc *l1_virt_map[L1_SIZE]; | 113 | static VirtPageDesc *l1_virt_map[L1_SIZE]; |
@@ -166,6 +171,31 @@ static inline PageDesc *page_find(unsigned int index) | @@ -166,6 +171,31 @@ static inline PageDesc *page_find(unsigned int index) | ||
166 | return p + (index & (L2_SIZE - 1)); | 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 | #if !defined(CONFIG_USER_ONLY) | 199 | #if !defined(CONFIG_USER_ONLY) |
170 | static void tlb_protect_code(CPUState *env, target_ulong addr); | 200 | static void tlb_protect_code(CPUState *env, target_ulong addr); |
171 | static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr); | 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,7 +1458,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr, | ||
1428 | target_phys_addr_t paddr, int prot, | 1458 | target_phys_addr_t paddr, int prot, |
1429 | int is_user, int is_softmmu) | 1459 | int is_user, int is_softmmu) |
1430 | { | 1460 | { |
1431 | - PageDesc *p; | 1461 | + PhysPageDesc *p; |
1432 | unsigned long pd; | 1462 | unsigned long pd; |
1433 | TranslationBlock *first_tb; | 1463 | TranslationBlock *first_tb; |
1434 | unsigned int index; | 1464 | unsigned int index; |
@@ -1436,13 +1466,18 @@ int tlb_set_page(CPUState *env, target_ulong vaddr, | @@ -1436,13 +1466,18 @@ int tlb_set_page(CPUState *env, target_ulong vaddr, | ||
1436 | unsigned long addend; | 1466 | unsigned long addend; |
1437 | int ret; | 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 | if (!p) { | 1471 | if (!p) { |
1441 | pd = IO_MEM_UNASSIGNED; | 1472 | pd = IO_MEM_UNASSIGNED; |
1442 | - first_tb = NULL; | ||
1443 | } else { | 1473 | } else { |
1474 | + PageDesc *p1; | ||
1444 | pd = p->phys_offset; | 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 | #if defined(DEBUG_TLB) | 1482 | #if defined(DEBUG_TLB) |
1448 | printf("tlb_set_page: vaddr=0x%08x paddr=0x%08x prot=%x u=%d c=%d smmu=%d pd=0x%08x\n", | 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,11 +1787,11 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr, | ||
1752 | unsigned long phys_offset) | 1787 | unsigned long phys_offset) |
1753 | { | 1788 | { |
1754 | unsigned long addr, end_addr; | 1789 | unsigned long addr, end_addr; |
1755 | - PageDesc *p; | 1790 | + PhysPageDesc *p; |
1756 | 1791 | ||
1757 | end_addr = start_addr + size; | 1792 | end_addr = start_addr + size; |
1758 | for(addr = start_addr; addr < end_addr; addr += TARGET_PAGE_SIZE) { | 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 | p->phys_offset = phys_offset; | 1795 | p->phys_offset = phys_offset; |
1761 | if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) | 1796 | if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) |
1762 | phys_offset += TARGET_PAGE_SIZE; | 1797 | phys_offset += TARGET_PAGE_SIZE; |
@@ -1938,14 +1973,14 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, | @@ -1938,14 +1973,14 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, | ||
1938 | uint32_t val; | 1973 | uint32_t val; |
1939 | target_phys_addr_t page; | 1974 | target_phys_addr_t page; |
1940 | unsigned long pd; | 1975 | unsigned long pd; |
1941 | - PageDesc *p; | 1976 | + PhysPageDesc *p; |
1942 | 1977 | ||
1943 | while (len > 0) { | 1978 | while (len > 0) { |
1944 | page = addr & TARGET_PAGE_MASK; | 1979 | page = addr & TARGET_PAGE_MASK; |
1945 | l = (page + TARGET_PAGE_SIZE) - addr; | 1980 | l = (page + TARGET_PAGE_SIZE) - addr; |
1946 | if (l > len) | 1981 | if (l > len) |
1947 | l = len; | 1982 | l = len; |
1948 | - p = page_find(page >> TARGET_PAGE_BITS); | 1983 | + p = phys_page_find(page >> TARGET_PAGE_BITS); |
1949 | if (!p) { | 1984 | if (!p) { |
1950 | pd = IO_MEM_UNASSIGNED; | 1985 | pd = IO_MEM_UNASSIGNED; |
1951 | } else { | 1986 | } else { |