1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include "config.h"
21: #ifdef _WIN32
22: #define WIN32_LEAN_AND_MEAN
23: #include <windows.h>
24: #else
25: #include <sys/types.h>
26: #include <sys/mman.h>
27: #endif
28: #include <stdlib.h>
29: #include <stdio.h>
30: #include <stdarg.h>
31: #include <string.h>
32: #include <errno.h>
33: #include <unistd.h>
34: #include <inttypes.h>
35:
36: #include "cpu.h"
37: #include "exec-all.h"
38: #if defined(CONFIG_USER_ONLY)
39: #include <qemu.h>
40: #endif
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54: #if !defined(CONFIG_USER_ONLY)
55:
56: #undef DEBUG_TB_CHECK
57: #endif
58:
59:
60: #define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - code_gen_max_block_size())
61:
62: #define SMC_BITMAP_USE_THRESHOLD 10
63:
64: #define MMAP_AREA_START 0x00000000
65: #define MMAP_AREA_END 0xa8000000
66:
67: #if defined(TARGET_SPARC64)
68: #define TARGET_PHYS_ADDR_SPACE_BITS 41
69: #elif defined(TARGET_SPARC)
70: #define TARGET_PHYS_ADDR_SPACE_BITS 36
71: #elif defined(TARGET_ALPHA)
72: #define TARGET_PHYS_ADDR_SPACE_BITS 42
73: #define TARGET_VIRT_ADDR_SPACE_BITS 42
74: #elif defined(TARGET_PPC64)
75: #define TARGET_PHYS_ADDR_SPACE_BITS 42
76: #else
77:
78: #define TARGET_PHYS_ADDR_SPACE_BITS 32
79: #endif
80:
81: TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
82: TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
83: int nb_tbs;
84:
85: spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
86:
87: uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE] __attribute__((aligned (32)));
88: uint8_t *code_gen_ptr;
89:
90: int phys_ram_size;
91: int phys_ram_fd;
92: uint8_t *phys_ram_base;
93: uint8_t *phys_ram_dirty;
94: static ram_addr_t phys_ram_alloc_offset = 0;
95:
96: CPUState *first_cpu;
97:
98:
99: CPUState *cpu_single_env;
100:
101: typedef struct PageDesc {
102:
103: TranslationBlock *first_tb;
104:
105:
106: unsigned int code_write_count;
107: uint8_t *code_bitmap;
108: #if defined(CONFIG_USER_ONLY)
109: unsigned long flags;
110: #endif
111: } PageDesc;
112:
113: typedef struct PhysPageDesc {
114:
115: uint32_t phys_offset;
116: } PhysPageDesc;
117:
118: #define L2_BITS 10
119: #if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
120:
121:
122:
123:
124: #define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
125: #else
126: #define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
127: #endif
128:
129: #define L1_SIZE (1 << L1_BITS)
130: #define L2_SIZE (1 << L2_BITS)
131:
132: static void io_mem_init(void);
133:
134: unsigned long qemu_real_host_page_size;
135: unsigned long qemu_host_page_bits;
136: unsigned long qemu_host_page_size;
137: unsigned long qemu_host_page_mask;
138:
139:
140: static PageDesc *l1_map[L1_SIZE];
141: PhysPageDesc **l1_phys_map;
142:
143:
144: CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
145: CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
146: void *io_mem_opaque[IO_MEM_NB_ENTRIES];
147: static int io_mem_nb;
148: #if defined(CONFIG_SOFTMMU)
149: static int io_mem_watch;
150: #endif
151:
152:
153: char *logfilename = "/tmp/qemu.log";
154: FILE *logfile;
155: int loglevel;
156: static int log_append = 0;
157:
158:
159: static int tlb_flush_count;
160: static int tb_flush_count;
161: static int tb_phys_invalidate_count;
162:
163: #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
164: typedef struct subpage_t {
165: target_phys_addr_t base;
166: CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
167: CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
168: void *opaque[TARGET_PAGE_SIZE][2][4];
169: } subpage_t;
170:
171: static void page_init(void)
172: {
173:
174:
175: #ifdef _WIN32
176: {
177: SYSTEM_INFO system_info;
178: DWORD old_protect;
179:
180: GetSystemInfo(&system_info);
181: qemu_real_host_page_size = system_info.dwPageSize;
182:
183: VirtualProtect(code_gen_buffer, sizeof(code_gen_buffer),
184: PAGE_EXECUTE_READWRITE, &old_protect);
185: }
186: #else
187: qemu_real_host_page_size = getpagesize();
188: {
189: unsigned long start, end;
190:
191: start = (unsigned long)code_gen_buffer;
192: start &= ~(qemu_real_host_page_size - 1);
193:
194: end = (unsigned long)code_gen_buffer + sizeof(code_gen_buffer);
195: end += qemu_real_host_page_size - 1;
196: end &= ~(qemu_real_host_page_size - 1);
197:
198: mprotect((void *)start, end - start,
199: PROT_READ | PROT_WRITE | PROT_EXEC);
200: }
201: #endif
202:
203: if (qemu_host_page_size == 0)
204: qemu_host_page_size = qemu_real_host_page_size;
205: if (qemu_host_page_size < TARGET_PAGE_SIZE)
206: qemu_host_page_size = TARGET_PAGE_SIZE;
207: qemu_host_page_bits = 0;
208: while ((1 << qemu_host_page_bits) < qemu_host_page_size)
209: qemu_host_page_bits++;
210: qemu_host_page_mask = ~(qemu_host_page_size - 1);
211: l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
212: memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
213:
214: #if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
215: {
216: long long startaddr, endaddr;
217: FILE *f;
218: int n;
219:
220: f = fopen("/proc/self/maps", "r");
221: if (f) {
222: do {
223: n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
224: if (n == 2) {
225: page_set_flags(TARGET_PAGE_ALIGN(startaddr),
226: TARGET_PAGE_ALIGN(endaddr),
227: PAGE_RESERVED);
228: }
229: } while (!feof(f));
230: fclose(f);
231: }
232: }
233: #endif
234: }
235:
236: static inline PageDesc *page_find_alloc(unsigned int index)
237: {
238: PageDesc **lp, *p;
239:
240: lp = &l1_map[index >> L2_BITS];
241: p = *lp;
242: if (!p) {
243:
244: p = qemu_malloc(sizeof(PageDesc) * L2_SIZE);
245: memset(p, 0, sizeof(PageDesc) * L2_SIZE);
246: *lp = p;
247: }
248: return p + (index & (L2_SIZE - 1));
249: }
250:
251: static inline PageDesc *page_find(unsigned int index)
252: {
253: PageDesc *p;
254:
255: p = l1_map[index >> L2_BITS];
256: if (!p)
257: return 0;
258: return p + (index & (L2_SIZE - 1));
259: }
260:
261: static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
262: {
263: void **lp, **p;
264: PhysPageDesc *pd;
265:
266: p = (void **)l1_phys_map;
267: #if TARGET_PHYS_ADDR_SPACE_BITS > 32
268:
269: #if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
270: #error unsupported TARGET_PHYS_ADDR_SPACE_BITS
271: #endif
272: lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
273: p = *lp;
274: if (!p) {
275:
276: if (!alloc)
277: return NULL;
278: p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
279: memset(p, 0, sizeof(void *) * L1_SIZE);
280: *lp = p;
281: }
282: #endif
283: lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
284: pd = *lp;
285: if (!pd) {
286: int i;
287:
288: if (!alloc)
289: return NULL;
290: pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
291: *lp = pd;
292: for (i = 0; i < L2_SIZE; i++)
293: pd[i].phys_offset = IO_MEM_UNASSIGNED;
294: }
295: return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
296: }
297:
298: static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
299: {
300: return phys_page_find_alloc(index, 0);
301: }
302:
303: #if !defined(CONFIG_USER_ONLY)
304: static void tlb_protect_code(ram_addr_t ram_addr);
305: static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
306: target_ulong vaddr);
307: #endif
308:
309: void cpu_exec_init(CPUState *env)
310: {
311: CPUState **penv;
312: int cpu_index;
313:
314: if (!code_gen_ptr) {
315: code_gen_ptr = code_gen_buffer;
316: page_init();
317: io_mem_init();
318: }
319: env->next_cpu = NULL;
320: penv = &first_cpu;
321: cpu_index = 0;
322: while (*penv != NULL) {
323: penv = (CPUState **)&(*penv)->next_cpu;
324: cpu_index++;
325: }
326: env->cpu_index = cpu_index;
327: env->nb_watchpoints = 0;
328: *penv = env;
329: }
330:
331: static inline void invalidate_page_bitmap(PageDesc *p)
332: {
333: if (p->code_bitmap) {
334: qemu_free(p->code_bitmap);
335: p->code_bitmap = NULL;
336: }
337: p->code_write_count = 0;
338: }
339:
340:
341: static void page_flush_tb(void)
342: {
343: int i, j;
344: PageDesc *p;
345:
346: for(i = 0; i < L1_SIZE; i++) {
347: p = l1_map[i];
348: if (p) {
349: for(j = 0; j < L2_SIZE; j++) {
350: p->first_tb = NULL;
351: invalidate_page_bitmap(p);
352: p++;
353: }
354: }
355: }
356: }
357:
358:
359:
360: void tb_flush(CPUState *env1)
361: {
362: CPUState *env;
363: #if defined(DEBUG_FLUSH)
364: printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
365: (unsigned long)(code_gen_ptr - code_gen_buffer),
366: nb_tbs, nb_tbs > 0 ?
367: ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
368: #endif
369: nb_tbs = 0;
370:
371: for(env = first_cpu; env != NULL; env = env->next_cpu) {
372: memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
373: }
374:
375: memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
376: page_flush_tb();
377:
378: code_gen_ptr = code_gen_buffer;
379:
380:
381: tb_flush_count++;
382: }
383:
384: #ifdef DEBUG_TB_CHECK
385:
386: static void tb_invalidate_check(target_ulong address)
387: {
388: TranslationBlock *tb;
389: int i;
390: address &= TARGET_PAGE_MASK;
391: for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
392: for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
393: if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
394: address >= tb->pc + tb->size)) {
395: printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
396: address, (long)tb->pc, tb->size);
397: }
398: }
399: }
400: }
401:
402:
403: static void tb_page_check(void)
404: {
405: TranslationBlock *tb;
406: int i, flags1, flags2;
407:
408: for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
409: for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
410: flags1 = page_get_flags(tb->pc);
411: flags2 = page_get_flags(tb->pc + tb->size - 1);
412: if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
413: printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
414: (long)tb->pc, tb->size, flags1, flags2);
415: }
416: }
417: }
418: }
419:
420: void tb_jmp_check(TranslationBlock *tb)
421: {
422: TranslationBlock *tb1;
423: unsigned int n1;
424:
425:
426: tb1 = tb->jmp_first;
427: for(;;) {
428: n1 = (long)tb1 & 3;
429: tb1 = (TranslationBlock *)((long)tb1 & ~3);
430: if (n1 == 2)
431: break;
432: tb1 = tb1->jmp_next[n1];
433: }
434:
435: if (tb1 != tb) {
436: printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
437: }
438: }
439:
440: #endif
441:
442:
443: static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
444: int next_offset)
445: {
446: TranslationBlock *tb1;
447: for(;;) {
448: tb1 = *ptb;
449: if (tb1 == tb) {
450: *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
451: break;
452: }
453: ptb = (TranslationBlock **)((char *)tb1 + next_offset);
454: }
455: }
456:
457: static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
458: {
459: TranslationBlock *tb1;
460: unsigned int n1;
461:
462: for(;;) {
463: tb1 = *ptb;
464: n1 = (long)tb1 & 3;
465: tb1 = (TranslationBlock *)((long)tb1 & ~3);
466: if (tb1 == tb) {
467: *ptb = tb1->page_next[n1];
468: break;
469: }
470: ptb = &tb1->page_next[n1];
471: }
472: }
473:
474: static inline void tb_jmp_remove(TranslationBlock *tb, int n)
475: {
476: TranslationBlock *tb1, **ptb;
477: unsigned int n1;
478:
479: ptb = &tb->jmp_next[n];
480: tb1 = *ptb;
481: if (tb1) {
482:
483: for(;;) {
484: tb1 = *ptb;
485: n1 = (long)tb1 & 3;
486: tb1 = (TranslationBlock *)((long)tb1 & ~3);
487: if (n1 == n && tb1 == tb)
488: break;
489: if (n1 == 2) {
490: ptb = &tb1->jmp_first;
491: } else {
492: ptb = &tb1->jmp_next[n1];
493: }
494: }
495:
496: *ptb = tb->jmp_next[n];
497:
498: tb->jmp_next[n] = NULL;
499: }
500: }
501:
502:
503:
504: static inline void tb_reset_jump(TranslationBlock *tb, int n)
505: {
506: tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
507: }
508:
509: static inline void tb_phys_invalidate(TranslationBlock *tb, unsigned int page_addr)
510: {
511: CPUState *env;
512: PageDesc *p;
513: unsigned int h, n1;
514: target_ulong phys_pc;
515: TranslationBlock *tb1, *tb2;
516:
517:
518: phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
519: h = tb_phys_hash_func(phys_pc);
520: tb_remove(&tb_phys_hash[h], tb,
521: offsetof(TranslationBlock, phys_hash_next));
522:
523:
524: if (tb->page_addr[0] != page_addr) {
525: p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
526: tb_page_remove(&p->first_tb, tb);
527: invalidate_page_bitmap(p);
528: }
529: if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
530: p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
531: tb_page_remove(&p->first_tb, tb);
532: invalidate_page_bitmap(p);
533: }
534:
535: tb_invalidated_flag = 1;
536:
537:
538: h = tb_jmp_cache_hash_func(tb->pc);
539: for(env = first_cpu; env != NULL; env = env->next_cpu) {
540: if (env->tb_jmp_cache[h] == tb)
541: env->tb_jmp_cache[h] = NULL;
542: }
543:
544:
545: tb_jmp_remove(tb, 0);
546: tb_jmp_remove(tb, 1);
547:
548:
549: tb1 = tb->jmp_first;
550: for(;;) {
551: n1 = (long)tb1 & 3;
552: if (n1 == 2)
553: break;
554: tb1 = (TranslationBlock *)((long)tb1 & ~3);
555: tb2 = tb1->jmp_next[n1];
556: tb_reset_jump(tb1, n1);
557: tb1->jmp_next[n1] = NULL;
558: tb1 = tb2;
559: }
560: tb->jmp_first = (TranslationBlock *)((long)tb | 2);
561:
562: tb_phys_invalidate_count++;
563: }
564:
565: static inline void set_bits(uint8_t *tab, int start, int len)
566: {
567: int end, mask, end1;
568:
569: end = start + len;
570: tab += start >> 3;
571: mask = 0xff << (start & 7);
572: if ((start & ~7) == (end & ~7)) {
573: if (start < end) {
574: mask &= ~(0xff << (end & 7));
575: *tab |= mask;
576: }
577: } else {
578: *tab++ |= mask;
579: start = (start + 8) & ~7;
580: end1 = end & ~7;
581: while (start < end1) {
582: *tab++ = 0xff;
583: start += 8;
584: }
585: if (start < end) {
586: mask = ~(0xff << (end & 7));
587: *tab |= mask;
588: }
589: }
590: }
591:
592: static void build_page_bitmap(PageDesc *p)
593: {
594: int n, tb_start, tb_end;
595: TranslationBlock *tb;
596: