Revision 41c1b1c9
b/cpu-exec.c | ||
---|---|---|
125 | 125 |
{ |
126 | 126 |
TranslationBlock *tb, **ptb1; |
127 | 127 |
unsigned int h; |
128 |
target_ulong phys_pc, phys_page1, phys_page2, virt_page2; |
|
128 |
tb_page_addr_t phys_pc, phys_page1, phys_page2; |
|
129 |
target_ulong virt_page2; |
|
129 | 130 |
|
130 | 131 |
tb_invalidated_flag = 0; |
131 | 132 |
|
132 | 133 |
/* find translated block using physical mappings */ |
133 |
phys_pc = get_phys_addr_code(env, pc);
|
|
134 |
phys_pc = get_page_addr_code(env, pc);
|
|
134 | 135 |
phys_page1 = phys_pc & TARGET_PAGE_MASK; |
135 | 136 |
phys_page2 = -1; |
136 | 137 |
h = tb_phys_hash_func(phys_pc); |
... | ... | |
147 | 148 |
if (tb->page_addr[1] != -1) { |
148 | 149 |
virt_page2 = (pc & TARGET_PAGE_MASK) + |
149 | 150 |
TARGET_PAGE_SIZE; |
150 |
phys_page2 = get_phys_addr_code(env, virt_page2);
|
|
151 |
phys_page2 = get_page_addr_code(env, virt_page2);
|
|
151 | 152 |
if (tb->page_addr[1] == phys_page2) |
152 | 153 |
goto found; |
153 | 154 |
} else { |
b/exec-all.h | ||
---|---|---|
25 | 25 |
/* allow to see translation results - the slowdown should be negligible, so we leave it */ |
26 | 26 |
#define DEBUG_DISAS |
27 | 27 |
|
28 |
/* Page tracking code uses ram addresses in system mode, and virtual |
|
29 |
addresses in userspace mode. Define tb_page_addr_t to be an appropriate |
|
30 |
type. */ |
|
31 |
#if defined(CONFIG_USER_ONLY) |
|
32 |
typedef target_ulong tb_page_addr_t; |
|
33 |
#else |
|
34 |
typedef ram_addr_t tb_page_addr_t; |
|
35 |
#endif |
|
36 |
|
|
28 | 37 |
/* is_jmp field values */ |
29 | 38 |
#define DISAS_NEXT 0 /* next instruction can be analyzed */ |
30 | 39 |
#define DISAS_JUMP 1 /* only pc was modified dynamically */ |
... | ... | |
81 | 90 |
void cpu_exec_init(CPUState *env); |
82 | 91 |
void QEMU_NORETURN cpu_loop_exit(void); |
83 | 92 |
int page_unprotect(target_ulong address, unsigned long pc, void *puc); |
84 |
void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
|
|
93 |
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
|
|
85 | 94 |
int is_cpu_write_access); |
86 | 95 |
void tb_invalidate_page_range(target_ulong start, target_ulong end); |
87 | 96 |
void tlb_flush_page(CPUState *env, target_ulong addr); |
... | ... | |
136 | 145 |
/* first and second physical page containing code. The lower bit |
137 | 146 |
of the pointer tells the index in page_next[] */ |
138 | 147 |
struct TranslationBlock *page_next[2]; |
139 |
target_ulong page_addr[2];
|
|
148 |
tb_page_addr_t page_addr[2];
|
|
140 | 149 |
|
141 | 150 |
/* the following data are used to directly call another TB from |
142 | 151 |
the code of this one. */ |
... | ... | |
170 | 179 |
| (tmp & TB_JMP_ADDR_MASK)); |
171 | 180 |
} |
172 | 181 |
|
173 |
static inline unsigned int tb_phys_hash_func(unsigned long pc)
|
|
182 |
static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
|
|
174 | 183 |
{ |
175 | 184 |
return pc & (CODE_GEN_PHYS_HASH_SIZE - 1); |
176 | 185 |
} |
... | ... | |
178 | 187 |
TranslationBlock *tb_alloc(target_ulong pc); |
179 | 188 |
void tb_free(TranslationBlock *tb); |
180 | 189 |
void tb_flush(CPUState *env); |
181 |
void tb_link_phys(TranslationBlock *tb,
|
|
182 |
target_ulong phys_pc, target_ulong phys_page2);
|
|
183 |
void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr);
|
|
190 |
void tb_link_page(TranslationBlock *tb,
|
|
191 |
tb_page_addr_t phys_pc, tb_page_addr_t phys_page2);
|
|
192 |
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
|
|
184 | 193 |
|
185 | 194 |
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; |
186 | 195 |
extern uint8_t *code_gen_ptr; |
... | ... | |
305 | 314 |
#endif |
306 | 315 |
|
307 | 316 |
#if defined(CONFIG_USER_ONLY) |
308 |
static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
|
|
317 |
static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
|
|
309 | 318 |
{ |
310 | 319 |
return addr; |
311 | 320 |
} |
... | ... | |
313 | 322 |
/* NOTE: this function can trigger an exception */ |
314 | 323 |
/* NOTE2: the returned address is not exactly the physical address: it |
315 | 324 |
is the offset relative to phys_ram_base */ |
316 |
static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
|
|
325 |
static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
|
|
317 | 326 |
{ |
318 | 327 |
int mmu_idx, page_index, pd; |
319 | 328 |
void *p; |
b/exec.c | ||
---|---|---|
135 | 135 |
#endif |
136 | 136 |
} PageDesc; |
137 | 137 |
|
138 |
typedef struct PhysPageDesc { |
|
139 |
/* offset in host memory of the page + io_index in the low bits */ |
|
140 |
ram_addr_t phys_offset; |
|
141 |
ram_addr_t region_offset; |
|
142 |
} PhysPageDesc; |
|
143 |
|
|
144 |
/* In system mode we want L1_MAP to be based on physical addresses, |
|
138 |
/* In system mode we want L1_MAP to be based on ram offsets, |
|
145 | 139 |
while in user mode we want it to be based on virtual addresses. */ |
146 | 140 |
#if !defined(CONFIG_USER_ONLY) |
141 |
#if HOST_LONG_BITS < TARGET_PHYS_ADDR_SPACE_BITS |
|
142 |
# define L1_MAP_ADDR_SPACE_BITS HOST_LONG_BITS |
|
143 |
#else |
|
147 | 144 |
# define L1_MAP_ADDR_SPACE_BITS TARGET_PHYS_ADDR_SPACE_BITS |
145 |
#endif |
|
148 | 146 |
#else |
149 | 147 |
# define L1_MAP_ADDR_SPACE_BITS TARGET_VIRT_ADDR_SPACE_BITS |
150 | 148 |
#endif |
... | ... | |
188 | 186 |
static void *l1_map[V_L1_SIZE]; |
189 | 187 |
|
190 | 188 |
#if !defined(CONFIG_USER_ONLY) |
189 |
typedef struct PhysPageDesc { |
|
190 |
/* offset in host memory of the page + io_index in the low bits */ |
|
191 |
ram_addr_t phys_offset; |
|
192 |
ram_addr_t region_offset; |
|
193 |
} PhysPageDesc; |
|
194 |
|
|
191 | 195 |
/* This is a multi-level map on the physical address space. |
192 | 196 |
The bottom level has pointers to PhysPageDesc. */ |
193 | 197 |
static void *l1_phys_map[P_L1_SIZE]; |
... | ... | |
301 | 305 |
#endif |
302 | 306 |
} |
303 | 307 |
|
304 |
static PageDesc *page_find_alloc(target_ulong index, int alloc)
|
|
308 |
static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
|
|
305 | 309 |
{ |
310 |
PageDesc *pd; |
|
311 |
void **lp; |
|
312 |
int i; |
|
313 |
|
|
306 | 314 |
#if defined(CONFIG_USER_ONLY) |
307 | 315 |
/* We can't use qemu_malloc because it may recurse into a locked mutex. |
308 | 316 |
Neither can we record the new pages we reserve while allocating a |
... | ... | |
328 | 336 |
do { P = qemu_mallocz(SIZE); } while (0) |
329 | 337 |
#endif |
330 | 338 |
|
331 |
PageDesc *pd; |
|
332 |
void **lp; |
|
333 |
int i; |
|
334 |
|
|
335 | 339 |
/* Level 1. Always allocated. */ |
336 | 340 |
lp = l1_map + ((index >> V_L1_SHIFT) & (V_L1_SIZE - 1)); |
337 | 341 |
|
... | ... | |
374 | 378 |
return pd + (index & (L2_SIZE - 1)); |
375 | 379 |
} |
376 | 380 |
|
377 |
static inline PageDesc *page_find(target_ulong index)
|
|
381 |
static inline PageDesc *page_find(tb_page_addr_t index)
|
|
378 | 382 |
{ |
379 | 383 |
return page_find_alloc(index, 0); |
380 | 384 |
} |
... | ... | |
791 | 795 |
tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n])); |
792 | 796 |
} |
793 | 797 |
|
794 |
void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
|
|
798 |
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
|
|
795 | 799 |
{ |
796 | 800 |
CPUState *env; |
797 | 801 |
PageDesc *p; |
798 | 802 |
unsigned int h, n1; |
799 |
target_phys_addr_t phys_pc;
|
|
803 |
tb_page_addr_t phys_pc;
|
|
800 | 804 |
TranslationBlock *tb1, *tb2; |
801 | 805 |
|
802 | 806 |
/* remove the TB from the hash list */ |
... | ... | |
908 | 912 |
{ |
909 | 913 |
TranslationBlock *tb; |
910 | 914 |
uint8_t *tc_ptr; |
911 |
target_ulong phys_pc, phys_page2, virt_page2; |
|
915 |
tb_page_addr_t phys_pc, phys_page2; |
|
916 |
target_ulong virt_page2; |
|
912 | 917 |
int code_gen_size; |
913 | 918 |
|
914 |
phys_pc = get_phys_addr_code(env, pc);
|
|
919 |
phys_pc = get_page_addr_code(env, pc);
|
|
915 | 920 |
tb = tb_alloc(pc); |
916 | 921 |
if (!tb) { |
917 | 922 |
/* flush must be done */ |
... | ... | |
933 | 938 |
virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; |
934 | 939 |
phys_page2 = -1; |
935 | 940 |
if ((pc & TARGET_PAGE_MASK) != virt_page2) { |
936 |
phys_page2 = get_phys_addr_code(env, virt_page2);
|
|
941 |
phys_page2 = get_page_addr_code(env, virt_page2);
|
|
937 | 942 |
} |
938 |
tb_link_phys(tb, phys_pc, phys_page2);
|
|
943 |
tb_link_page(tb, phys_pc, phys_page2);
|
|
939 | 944 |
return tb; |
940 | 945 |
} |
941 | 946 |
|
... | ... | |
944 | 949 |
the same physical page. 'is_cpu_write_access' should be true if called |
945 | 950 |
from a real cpu write access: the virtual CPU will exit the current |
946 | 951 |
TB if code is modified inside this TB. */ |
947 |
void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
|
|
952 |
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
|
|
948 | 953 |
int is_cpu_write_access) |
949 | 954 |
{ |
950 | 955 |
TranslationBlock *tb, *tb_next, *saved_tb; |
951 | 956 |
CPUState *env = cpu_single_env; |
952 |
target_ulong tb_start, tb_end;
|
|
957 |
tb_page_addr_t tb_start, tb_end;
|
|
953 | 958 |
PageDesc *p; |
954 | 959 |
int n; |
955 | 960 |
#ifdef TARGET_HAS_PRECISE_SMC |
... | ... | |
1051 | 1056 |
} |
1052 | 1057 |
|
1053 | 1058 |
/* len must be <= 8 and start must be a multiple of len */ |
1054 |
static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
|
|
1059 |
static inline void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len)
|
|
1055 | 1060 |
{ |
1056 | 1061 |
PageDesc *p; |
1057 | 1062 |
int offset, b; |
... | ... | |
1078 | 1083 |
} |
1079 | 1084 |
|
1080 | 1085 |
#if !defined(CONFIG_SOFTMMU) |
1081 |
static void tb_invalidate_phys_page(target_phys_addr_t addr,
|
|
1086 |
static void tb_invalidate_phys_page(tb_page_addr_t addr,
|
|
1082 | 1087 |
unsigned long pc, void *puc) |
1083 | 1088 |
{ |
1084 | 1089 |
TranslationBlock *tb; |
... | ... | |
1140 | 1145 |
|
1141 | 1146 |
/* add the tb in the target page and protect it if necessary */ |
1142 | 1147 |
static inline void tb_alloc_page(TranslationBlock *tb, |
1143 |
unsigned int n, target_ulong page_addr)
|
|
1148 |
unsigned int n, tb_page_addr_t page_addr)
|
|
1144 | 1149 |
{ |
1145 | 1150 |
PageDesc *p; |
1146 | 1151 |
TranslationBlock *last_first_tb; |
... | ... | |
1221 | 1226 |
|
1222 | 1227 |
/* add a new TB and link it to the physical page tables. phys_page2 is |
1223 | 1228 |
(-1) to indicate that only one page contains the TB. */ |
1224 |
void tb_link_phys(TranslationBlock *tb,
|
|
1225 |
target_ulong phys_pc, target_ulong phys_page2)
|
|
1229 |
void tb_link_page(TranslationBlock *tb,
|
|
1230 |
tb_page_addr_t phys_pc, tb_page_addr_t phys_page2)
|
|
1226 | 1231 |
{ |
1227 | 1232 |
unsigned int h; |
1228 | 1233 |
TranslationBlock **ptb; |
Also available in: Unified diff