74 |
uint8_t *phys_ram_base; |
uint8_t *phys_ram_base; |
75 |
uint8_t *phys_ram_dirty; |
uint8_t *phys_ram_dirty; |
76 |
|
|
77 |
|
CPUState *first_cpu; |
78 |
|
/* current CPU in the current thread. It is only valid inside |
79 |
|
cpu_exec() */ |
80 |
|
CPUState *cpu_single_env; |
81 |
|
|
82 |
typedef struct PageDesc { |
typedef struct PageDesc { |
83 |
/* list of TBs intersecting this ram page */ |
/* list of TBs intersecting this ram page */ |
84 |
TranslationBlock *first_tb; |
TranslationBlock *first_tb; |
238 |
} |
} |
239 |
|
|
240 |
#if !defined(CONFIG_USER_ONLY) |
#if !defined(CONFIG_USER_ONLY) |
241 |
static void tlb_protect_code(CPUState *env, ram_addr_t ram_addr, |
static void tlb_protect_code(ram_addr_t ram_addr); |
|
target_ulong vaddr); |
|
242 |
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, |
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, |
243 |
target_ulong vaddr); |
target_ulong vaddr); |
244 |
#endif |
#endif |
245 |
|
|
246 |
void cpu_exec_init(void) |
void cpu_exec_init(CPUState *env) |
247 |
{ |
{ |
248 |
|
CPUState **penv; |
249 |
|
int cpu_index; |
250 |
|
|
251 |
if (!code_gen_ptr) { |
if (!code_gen_ptr) { |
252 |
code_gen_ptr = code_gen_buffer; |
code_gen_ptr = code_gen_buffer; |
253 |
page_init(); |
page_init(); |
254 |
io_mem_init(); |
io_mem_init(); |
255 |
} |
} |
256 |
|
env->next_cpu = NULL; |
257 |
|
penv = &first_cpu; |
258 |
|
cpu_index = 0; |
259 |
|
while (*penv != NULL) { |
260 |
|
penv = (CPUState **)&(*penv)->next_cpu; |
261 |
|
cpu_index++; |
262 |
|
} |
263 |
|
env->cpu_index = cpu_index; |
264 |
|
*penv = env; |
265 |
} |
} |
266 |
|
|
267 |
static inline void invalidate_page_bitmap(PageDesc *p) |
static inline void invalidate_page_bitmap(PageDesc *p) |
293 |
|
|
294 |
/* flush all the translation blocks */ |
/* flush all the translation blocks */ |
295 |
/* XXX: tb_flush is currently not thread safe */ |
/* XXX: tb_flush is currently not thread safe */ |
296 |
void tb_flush(CPUState *env) |
void tb_flush(CPUState *env1) |
297 |
{ |
{ |
298 |
|
CPUState *env; |
299 |
#if defined(DEBUG_FLUSH) |
#if defined(DEBUG_FLUSH) |
300 |
printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", |
printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", |
301 |
code_gen_ptr - code_gen_buffer, |
code_gen_ptr - code_gen_buffer, |
303 |
nb_tbs > 0 ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0); |
nb_tbs > 0 ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0); |
304 |
#endif |
#endif |
305 |
nb_tbs = 0; |
nb_tbs = 0; |
306 |
memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *)); |
|
307 |
|
for(env = first_cpu; env != NULL; env = env->next_cpu) { |
308 |
|
memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *)); |
309 |
|
} |
310 |
|
|
311 |
memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *)); |
memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *)); |
312 |
page_flush_tb(); |
page_flush_tb(); |
444 |
|
|
445 |
static inline void tb_phys_invalidate(TranslationBlock *tb, unsigned int page_addr) |
static inline void tb_phys_invalidate(TranslationBlock *tb, unsigned int page_addr) |
446 |
{ |
{ |
447 |
|
CPUState *env; |
448 |
PageDesc *p; |
PageDesc *p; |
449 |
unsigned int h, n1; |
unsigned int h, n1; |
450 |
target_ulong phys_pc; |
target_ulong phys_pc; |
472 |
|
|
473 |
/* remove the TB from the hash list */ |
/* remove the TB from the hash list */ |
474 |
h = tb_jmp_cache_hash_func(tb->pc); |
h = tb_jmp_cache_hash_func(tb->pc); |
475 |
cpu_single_env->tb_jmp_cache[h] = NULL; |
for(env = first_cpu; env != NULL; env = env->next_cpu) { |
476 |
|
if (env->tb_jmp_cache[h] == tb) |
477 |
|
env->tb_jmp_cache[h] = NULL; |
478 |
|
} |
479 |
|
|
480 |
/* suppress this TB from the two jump lists */ |
/* suppress this TB from the two jump lists */ |
481 |
tb_jmp_remove(tb, 0); |
tb_jmp_remove(tb, 0); |
842 |
protected. So we handle the case where only the first TB is |
protected. So we handle the case where only the first TB is |
843 |
allocated in a physical page */ |
allocated in a physical page */ |
844 |
if (!last_first_tb) { |
if (!last_first_tb) { |
845 |
target_ulong virt_addr; |
tlb_protect_code(page_addr); |
|
|
|
|
virt_addr = (tb->pc & TARGET_PAGE_MASK) + (n << TARGET_PAGE_BITS); |
|
|
tlb_protect_code(cpu_single_env, page_addr, virt_addr); |
|
846 |
} |
} |
847 |
#endif |
#endif |
848 |
|
|
1267 |
#endif |
#endif |
1268 |
} |
} |
1269 |
|
|
|
static inline void tlb_protect_code1(CPUTLBEntry *tlb_entry, target_ulong addr) |
|
|
{ |
|
|
if (addr == (tlb_entry->address & |
|
|
(TARGET_PAGE_MASK | TLB_INVALID_MASK)) && |
|
|
(tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { |
|
|
tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY; |
|
|
} |
|
|
} |
|
|
|
|
1270 |
/* update the TLBs so that writes to code in the virtual page 'addr' |
/* update the TLBs so that writes to code in the virtual page 'addr' |
1271 |
can be detected */ |
can be detected */ |
1272 |
static void tlb_protect_code(CPUState *env, ram_addr_t ram_addr, |
static void tlb_protect_code(ram_addr_t ram_addr) |
|
target_ulong vaddr) |
|
1273 |
{ |
{ |
1274 |
int i; |
cpu_physical_memory_reset_dirty(ram_addr, |
1275 |
|
ram_addr + TARGET_PAGE_SIZE, |
1276 |
vaddr &= TARGET_PAGE_MASK; |
CODE_DIRTY_FLAG); |
|
i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
|
|
tlb_protect_code1(&env->tlb_write[0][i], vaddr); |
|
|
tlb_protect_code1(&env->tlb_write[1][i], vaddr); |
|
|
|
|
|
#ifdef USE_KQEMU |
|
|
if (env->kqemu_enabled) { |
|
|
kqemu_set_notdirty(env, ram_addr); |
|
|
} |
|
|
#endif |
|
|
phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] &= ~CODE_DIRTY_FLAG; |
|
|
|
|
|
#if !defined(CONFIG_SOFTMMU) |
|
|
/* NOTE: as we generated the code for this page, it is already at |
|
|
least readable */ |
|
|
if (vaddr < MMAP_AREA_END) |
|
|
mprotect((void *)vaddr, TARGET_PAGE_SIZE, PROT_READ); |
|
|
#endif |
|
1277 |
} |
} |
1278 |
|
|
1279 |
/* update the TLB so that writes in physical page 'phys_addr' are no longer |
/* update the TLB so that writes in physical page 'phys_addr' are no longer |
1311 |
if (length == 0) |
if (length == 0) |
1312 |
return; |
return; |
1313 |
len = length >> TARGET_PAGE_BITS; |
len = length >> TARGET_PAGE_BITS; |
|
env = cpu_single_env; |
|
1314 |
#ifdef USE_KQEMU |
#ifdef USE_KQEMU |
1315 |
|
/* XXX: should not depend on cpu context */ |
1316 |
|
env = first_cpu; |
1317 |
if (env->kqemu_enabled) { |
if (env->kqemu_enabled) { |
1318 |
ram_addr_t addr; |
ram_addr_t addr; |
1319 |
addr = start; |
addr = start; |
1331 |
/* we modify the TLB cache so that the dirty bit will be set again |
/* we modify the TLB cache so that the dirty bit will be set again |
1332 |
when accessing the range */ |
when accessing the range */ |
1333 |
start1 = start + (unsigned long)phys_ram_base; |
start1 = start + (unsigned long)phys_ram_base; |
1334 |
for(i = 0; i < CPU_TLB_SIZE; i++) |
for(env = first_cpu; env != NULL; env = env->next_cpu) { |
1335 |
tlb_reset_dirty_range(&env->tlb_write[0][i], start1, length); |
for(i = 0; i < CPU_TLB_SIZE; i++) |
1336 |
for(i = 0; i < CPU_TLB_SIZE; i++) |
tlb_reset_dirty_range(&env->tlb_write[0][i], start1, length); |
1337 |
tlb_reset_dirty_range(&env->tlb_write[1][i], start1, length); |
for(i = 0; i < CPU_TLB_SIZE; i++) |
1338 |
|
tlb_reset_dirty_range(&env->tlb_write[1][i], start1, length); |
1339 |
|
} |
1340 |
|
|
1341 |
#if !defined(CONFIG_SOFTMMU) |
#if !defined(CONFIG_SOFTMMU) |
1342 |
/* XXX: this is expensive */ |
/* XXX: this is expensive */ |
1404 |
|
|
1405 |
/* update the TLB corresponding to virtual page vaddr and phys addr |
/* update the TLB corresponding to virtual page vaddr and phys addr |
1406 |
addr so that it is no longer dirty */ |
addr so that it is no longer dirty */ |
1407 |
static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr) |
static inline void tlb_set_dirty(CPUState *env, |
1408 |
|
unsigned long addr, target_ulong vaddr) |
1409 |
{ |
{ |
|
CPUState *env = cpu_single_env; |
|
1410 |
int i; |
int i; |
1411 |
|
|
1412 |
addr &= TARGET_PAGE_MASK; |
addr &= TARGET_PAGE_MASK; |
1720 |
} |
} |
1721 |
} |
} |
1722 |
|
|
1723 |
static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr) |
static inline void tlb_set_dirty(CPUState *env, |
1724 |
|
unsigned long addr, target_ulong vaddr) |
1725 |
{ |
{ |
1726 |
} |
} |
1727 |
#endif /* defined(CONFIG_USER_ONLY) */ |
#endif /* defined(CONFIG_USER_ONLY) */ |
1785 |
/* we remove the notdirty callback only if the code has been |
/* we remove the notdirty callback only if the code has been |
1786 |
flushed */ |
flushed */ |
1787 |
if (dirty_flags == 0xff) |
if (dirty_flags == 0xff) |
1788 |
tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr); |
tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr); |
1789 |
} |
} |
1790 |
|
|
1791 |
static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) |
static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) |
1806 |
/* we remove the notdirty callback only if the code has been |
/* we remove the notdirty callback only if the code has been |
1807 |
flushed */ |
flushed */ |
1808 |
if (dirty_flags == 0xff) |
if (dirty_flags == 0xff) |
1809 |
tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr); |
tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr); |
1810 |
} |
} |
1811 |
|
|
1812 |
static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
1827 |
/* we remove the notdirty callback only if the code has been |
/* we remove the notdirty callback only if the code has been |
1828 |
flushed */ |
flushed */ |
1829 |
if (dirty_flags == 0xff) |
if (dirty_flags == 0xff) |
1830 |
tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr); |
tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr); |
1831 |
} |
} |
1832 |
|
|
1833 |
static CPUReadMemoryFunc *error_mem_read[3] = { |
static CPUReadMemoryFunc *error_mem_read[3] = { |
1951 |
if (is_write) { |
if (is_write) { |
1952 |
if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { |
if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { |
1953 |
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); |
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); |
1954 |
|
/* XXX: could force cpu_single_env to NULL to avoid |
1955 |
|
potential bugs */ |
1956 |
if (l >= 4 && ((addr & 3) == 0)) { |
if (l >= 4 && ((addr & 3) == 0)) { |
1957 |
/* 32 bit write access */ |
/* 32 bit write access */ |
1958 |
val = ldl_p(buf); |
val = ldl_p(buf); |