Commit 92e873b996adb4cdc8ec9ab7e49d1c88d8749127

Authored by bellard
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
... ... @@ -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 {
... ...