Commit 66e85a21c7f65540ac1976ed29ed9973089fe1f1
1 parent
90a9fdae
MMU support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@262 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
86 additions
and
8 deletions
cpu-i386.h
| ... | ... | @@ -50,7 +50,8 @@ |
| 50 | 50 | |
| 51 | 51 | /* segment descriptor fields */ |
| 52 | 52 | #define DESC_G_MASK (1 << 23) |
| 53 | -#define DESC_B_MASK (1 << 22) | |
| 53 | +#define DESC_B_SHIFT 22 | |
| 54 | +#define DESC_B_MASK (1 << DESC_B_SHIFT) | |
| 54 | 55 | #define DESC_AVL_MASK (1 << 20) |
| 55 | 56 | #define DESC_P_MASK (1 << 15) |
| 56 | 57 | #define DESC_DPL_SHIFT 13 |
| ... | ... | @@ -95,6 +96,34 @@ |
| 95 | 96 | #define CR4_PVI_MASK (1 << 1) |
| 96 | 97 | #define CR4_TSD_MASK (1 << 2) |
| 97 | 98 | #define CR4_DE_MASK (1 << 3) |
| 99 | +#define CR4_PSE_MASK (1 << 4) | |
| 100 | + | |
| 101 | +#define PG_PRESENT_BIT 0 | |
| 102 | +#define PG_RW_BIT 1 | |
| 103 | +#define PG_USER_BIT 2 | |
| 104 | +#define PG_PWT_BIT 3 | |
| 105 | +#define PG_PCD_BIT 4 | |
| 106 | +#define PG_ACCESSED_BIT 5 | |
| 107 | +#define PG_DIRTY_BIT 6 | |
| 108 | +#define PG_PSE_BIT 7 | |
| 109 | +#define PG_GLOBAL_BIT 8 | |
| 110 | + | |
| 111 | +#define PG_PRESENT_MASK (1 << PG_PRESENT_BIT) | |
| 112 | +#define PG_RW_MASK (1 << PG_RW_BIT) | |
| 113 | +#define PG_USER_MASK (1 << PG_USER_BIT) | |
| 114 | +#define PG_PWT_MASK (1 << PG_PWT_BIT) | |
| 115 | +#define PG_PCD_MASK (1 << PG_PCD_BIT) | |
| 116 | +#define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT) | |
| 117 | +#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT) | |
| 118 | +#define PG_PSE_MASK (1 << PG_PSE_BIT) | |
| 119 | +#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) | |
| 120 | + | |
| 121 | +#define PG_ERROR_W_BIT 1 | |
| 122 | + | |
| 123 | +#define PG_ERROR_P_MASK 0x01 | |
| 124 | +#define PG_ERROR_W_MASK (1 << PG_ERROR_W_BIT) | |
| 125 | +#define PG_ERROR_U_MASK 0x04 | |
| 126 | +#define PG_ERROR_RSVD_MASK 0x08 | |
| 98 | 127 | |
| 99 | 128 | #define EXCP00_DIVZ 0 |
| 100 | 129 | #define EXCP01_SSTP 1 |
| ... | ... | @@ -116,6 +145,7 @@ |
| 116 | 145 | #define EXCP12_MCHK 18 |
| 117 | 146 | |
| 118 | 147 | #define EXCP_INTERRUPT 256 /* async interruption */ |
| 148 | +#define EXCP_HLT 257 /* hlt instruction reached */ | |
| 119 | 149 | |
| 120 | 150 | enum { |
| 121 | 151 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ |
| ... | ... | @@ -174,8 +204,8 @@ typedef double CPU86_LDouble; |
| 174 | 204 | typedef struct SegmentCache { |
| 175 | 205 | uint32_t selector; |
| 176 | 206 | uint8_t *base; |
| 177 | - unsigned long limit; | |
| 178 | - uint8_t seg_32bit; | |
| 207 | + uint32_t limit; | |
| 208 | + uint32_t flags; | |
| 179 | 209 | } SegmentCache; |
| 180 | 210 | |
| 181 | 211 | typedef struct CPUX86State { |
| ... | ... | @@ -219,9 +249,16 @@ typedef struct CPUX86State { |
| 219 | 249 | jmp_buf jmp_env; |
| 220 | 250 | int exception_index; |
| 221 | 251 | int error_code; |
| 252 | + int exception_is_int; | |
| 253 | + int exception_next_eip; | |
| 254 | + | |
| 222 | 255 | uint32_t cr[5]; /* NOTE: cr1 is unused */ |
| 223 | 256 | uint32_t dr[8]; /* debug registers */ |
| 224 | - int interrupt_request; | |
| 257 | + int interrupt_request; /* if true, will exit from cpu_exec() ASAP */ | |
| 258 | + /* if true, will call cpu_x86_get_pic_interrupt() ASAP to get the | |
| 259 | + request interrupt number */ | |
| 260 | + int hard_interrupt_request; | |
| 261 | + int user_mode_only; /* user mode only simulation */ | |
| 225 | 262 | |
| 226 | 263 | /* user data */ |
| 227 | 264 | void *opaque; |
| ... | ... | @@ -240,6 +277,7 @@ CPUX86State *cpu_x86_init(void); |
| 240 | 277 | int cpu_x86_exec(CPUX86State *s); |
| 241 | 278 | void cpu_x86_interrupt(CPUX86State *s); |
| 242 | 279 | void cpu_x86_close(CPUX86State *s); |
| 280 | +int cpu_x86_get_pic_interrupt(CPUX86State *s); | |
| 243 | 281 | |
| 244 | 282 | /* needed to load some predefinied segment registers */ |
| 245 | 283 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); |
| ... | ... | @@ -255,6 +293,13 @@ struct siginfo; |
| 255 | 293 | int cpu_x86_signal_handler(int host_signum, struct siginfo *info, |
| 256 | 294 | void *puc); |
| 257 | 295 | |
| 296 | +/* MMU defines */ | |
| 297 | +void cpu_x86_init_mmu(CPUX86State *env); | |
| 298 | +extern CPUX86State *global_env; | |
| 299 | +extern int phys_ram_size; | |
| 300 | +extern int phys_ram_fd; | |
| 301 | +extern uint8_t *phys_ram_base; | |
| 302 | + | |
| 258 | 303 | /* used to debug */ |
| 259 | 304 | #define X86_DUMP_FPU 0x0001 /* dump FPU state too */ |
| 260 | 305 | #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */ | ... | ... |
exec.c
| ... | ... | @@ -30,7 +30,7 @@ |
| 30 | 30 | #include "exec.h" |
| 31 | 31 | |
| 32 | 32 | //#define DEBUG_TB_INVALIDATE |
| 33 | -#define DEBUG_FLUSH | |
| 33 | +//#define DEBUG_FLUSH | |
| 34 | 34 | |
| 35 | 35 | /* make various TB consistency checks */ |
| 36 | 36 | //#define DEBUG_TB_CHECK |
| ... | ... | @@ -579,3 +579,33 @@ void cpu_abort(CPUState *env, const char *fmt, ...) |
| 579 | 579 | abort(); |
| 580 | 580 | } |
| 581 | 581 | |
| 582 | +#ifdef TARGET_I386 | |
| 583 | +/* unmap all maped pages and flush all associated code */ | |
| 584 | +void page_unmap(void) | |
| 585 | +{ | |
| 586 | + PageDesc *p, *pmap; | |
| 587 | + unsigned long addr; | |
| 588 | + int i, j, ret; | |
| 589 | + | |
| 590 | + for(i = 0; i < L1_SIZE; i++) { | |
| 591 | + pmap = l1_map[i]; | |
| 592 | + if (pmap) { | |
| 593 | + p = pmap; | |
| 594 | + for(j = 0;j < L2_SIZE; j++) { | |
| 595 | + if (p->flags & PAGE_VALID) { | |
| 596 | + addr = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS); | |
| 597 | + ret = munmap((void *)addr, TARGET_PAGE_SIZE); | |
| 598 | + if (ret != 0) { | |
| 599 | + fprintf(stderr, "Could not unmap page 0x%08lx\n", addr); | |
| 600 | + exit(1); | |
| 601 | + } | |
| 602 | + } | |
| 603 | + p++; | |
| 604 | + } | |
| 605 | + free(pmap); | |
| 606 | + l1_map[i] = NULL; | |
| 607 | + } | |
| 608 | + } | |
| 609 | + tb_flush(); | |
| 610 | +} | |
| 611 | +#endif | ... | ... |
exec.h
| ... | ... | @@ -39,6 +39,7 @@ struct TranslationBlock; |
| 39 | 39 | extern uint16_t gen_opc_buf[OPC_BUF_SIZE]; |
| 40 | 40 | extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; |
| 41 | 41 | extern uint32_t gen_opc_pc[OPC_BUF_SIZE]; |
| 42 | +extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; | |
| 42 | 43 | extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; |
| 43 | 44 | |
| 44 | 45 | #if defined(TARGET_I386) |
| ... | ... | @@ -57,14 +58,16 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; |
| 57 | 58 | extern FILE *logfile; |
| 58 | 59 | extern int loglevel; |
| 59 | 60 | |
| 60 | -int gen_intermediate_code(struct TranslationBlock *tb, int search_pc); | |
| 61 | +int gen_intermediate_code(struct TranslationBlock *tb); | |
| 62 | +int gen_intermediate_code_pc(struct TranslationBlock *tb); | |
| 61 | 63 | void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf); |
| 62 | 64 | int cpu_gen_code(struct TranslationBlock *tb, |
| 63 | 65 | int max_code_size, int *gen_code_size_ptr); |
| 64 | -int cpu_search_pc(struct TranslationBlock *tb, | |
| 65 | - uint32_t *found_pc, unsigned long searched_pc); | |
| 66 | +int cpu_restore_state(struct TranslationBlock *tb, | |
| 67 | + CPUState *env, unsigned long searched_pc); | |
| 66 | 68 | void cpu_exec_init(void); |
| 67 | 69 | int page_unprotect(unsigned long address); |
| 70 | +void page_unmap(void); | |
| 68 | 71 | |
| 69 | 72 | #define CODE_GEN_MAX_SIZE 65536 |
| 70 | 73 | #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ | ... | ... |