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 { |