Commit 1ac157da77c863b62b1d2f467626a440d57cf17d
1 parent
64a595f2
more precise TLB invalidation - init cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@596 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
74 additions
and
48 deletions
target-i386/exec.h
... | ... | @@ -134,8 +134,9 @@ void helper_ltr_T0(void); |
134 | 134 | void helper_movl_crN_T0(int reg); |
135 | 135 | void helper_movl_drN_T0(int reg); |
136 | 136 | void helper_invlpg(unsigned int addr); |
137 | -void cpu_x86_update_cr0(CPUX86State *env); | |
138 | -void cpu_x86_update_cr3(CPUX86State *env); | |
137 | +void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); | |
138 | +void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3); | |
139 | +void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4); | |
139 | 140 | void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr); |
140 | 141 | int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, |
141 | 142 | int is_write, int is_user, int is_softmmu); | ... | ... |
target-i386/helper.c
... | ... | @@ -424,8 +424,7 @@ static void switch_tss(int tss_selector, |
424 | 424 | env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK; |
425 | 425 | |
426 | 426 | if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) { |
427 | - env->cr[3] = new_cr3; | |
428 | - cpu_x86_update_cr3(env); | |
427 | + cpu_x86_update_cr3(env, new_cr3); | |
429 | 428 | } |
430 | 429 | |
431 | 430 | /* load all registers without an exception, then reload them with |
... | ... | @@ -1775,13 +1774,18 @@ void helper_lret_protected(int shift, int addend) |
1775 | 1774 | |
1776 | 1775 | void helper_movl_crN_T0(int reg) |
1777 | 1776 | { |
1778 | - env->cr[reg] = T0; | |
1779 | 1777 | switch(reg) { |
1780 | 1778 | case 0: |
1781 | - cpu_x86_update_cr0(env); | |
1779 | + cpu_x86_update_cr0(env, T0); | |
1782 | 1780 | break; |
1783 | 1781 | case 3: |
1784 | - cpu_x86_update_cr3(env); | |
1782 | + cpu_x86_update_cr3(env, T0); | |
1783 | + break; | |
1784 | + case 4: | |
1785 | + cpu_x86_update_cr4(env, T0); | |
1786 | + break; | |
1787 | + default: | |
1788 | + env->cr[reg] = T0; | |
1785 | 1789 | break; |
1786 | 1790 | } |
1787 | 1791 | } | ... | ... |
target-i386/helper2.c
... | ... | @@ -43,17 +43,42 @@ CPUX86State *cpu_x86_init(void) |
43 | 43 | if (!env) |
44 | 44 | return NULL; |
45 | 45 | memset(env, 0, sizeof(CPUX86State)); |
46 | - /* basic FPU init */ | |
47 | - for(i = 0;i < 8; i++) | |
48 | - env->fptags[i] = 1; | |
49 | - env->fpuc = 0x37f; | |
50 | - /* flags setup : we activate the IRQs by default as in user mode */ | |
51 | - env->eflags = 0x2 | IF_MASK; | |
52 | 46 | |
53 | - tlb_flush(env); | |
47 | + /* init to reset state */ | |
48 | + | |
49 | + tlb_flush(env, 1); | |
54 | 50 | #ifdef CONFIG_SOFTMMU |
55 | 51 | env->hflags |= HF_SOFTMMU_MASK; |
56 | 52 | #endif |
53 | + | |
54 | + cpu_x86_update_cr0(env, 0x60000010); | |
55 | + env->a20_mask = 0xffffffff; | |
56 | + | |
57 | + env->idt.limit = 0xffff; | |
58 | + env->gdt.limit = 0xffff; | |
59 | + env->ldt.limit = 0xffff; | |
60 | + env->ldt.flags = DESC_P_MASK; | |
61 | + env->tr.limit = 0xffff; | |
62 | + env->tr.flags = DESC_P_MASK; | |
63 | + | |
64 | + /* not correct (CS base=0xffff0000) */ | |
65 | + cpu_x86_load_seg_cache(env, R_CS, 0xf000, (uint8_t *)0x000f0000, 0xffff, 0); | |
66 | + cpu_x86_load_seg_cache(env, R_DS, 0, NULL, 0xffff, 0); | |
67 | + cpu_x86_load_seg_cache(env, R_ES, 0, NULL, 0xffff, 0); | |
68 | + cpu_x86_load_seg_cache(env, R_SS, 0, NULL, 0xffff, 0); | |
69 | + cpu_x86_load_seg_cache(env, R_FS, 0, NULL, 0xffff, 0); | |
70 | + cpu_x86_load_seg_cache(env, R_GS, 0, NULL, 0xffff, 0); | |
71 | + | |
72 | + env->eip = 0xfff0; | |
73 | + env->regs[R_EDX] = 0x600; /* indicate P6 processor */ | |
74 | + | |
75 | + env->eflags = 0x2; | |
76 | + | |
77 | + /* FPU init */ | |
78 | + for(i = 0;i < 8; i++) | |
79 | + env->fptags[i] = 1; | |
80 | + env->fpuc = 0x37f; | |
81 | + | |
57 | 82 | /* init various static tables */ |
58 | 83 | if (!inited) { |
59 | 84 | inited = 1; |
... | ... | @@ -179,15 +204,10 @@ void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags) |
179 | 204 | /* x86 mmu */ |
180 | 205 | /* XXX: add PGE support */ |
181 | 206 | |
182 | -/* called when cr3 or PG bit are modified */ | |
183 | -static int last_pg_state = -1; | |
184 | -static uint32_t a20_mask; | |
185 | -int a20_enabled; | |
186 | - | |
187 | 207 | void cpu_x86_set_a20(CPUX86State *env, int a20_state) |
188 | 208 | { |
189 | 209 | a20_state = (a20_state != 0); |
190 | - if (a20_state != a20_enabled) { | |
210 | + if (a20_state != ((env->a20_mask >> 20) & 1)) { | |
191 | 211 | #if defined(DEBUG_MMU) |
192 | 212 | printf("A20 update: a20=%d\n", a20_state); |
193 | 213 | #endif |
... | ... | @@ -197,27 +217,24 @@ void cpu_x86_set_a20(CPUX86State *env, int a20_state) |
197 | 217 | |
198 | 218 | /* when a20 is changed, all the MMU mappings are invalid, so |
199 | 219 | we must flush everything */ |
200 | - tlb_flush(env); | |
201 | - a20_enabled = a20_state; | |
202 | - if (a20_enabled) | |
203 | - a20_mask = 0xffffffff; | |
204 | - else | |
205 | - a20_mask = 0xffefffff; | |
220 | + tlb_flush(env, 1); | |
221 | + env->a20_mask = 0xffefffff | (a20_state << 20); | |
206 | 222 | } |
207 | 223 | } |
208 | 224 | |
209 | -void cpu_x86_update_cr0(CPUX86State *env) | |
225 | +void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0) | |
210 | 226 | { |
211 | - int pg_state, pe_state; | |
227 | + int pe_state; | |
212 | 228 | |
213 | 229 | #if defined(DEBUG_MMU) |
214 | - printf("CR0 update: CR0=0x%08x\n", env->cr[0]); | |
230 | + printf("CR0 update: CR0=0x%08x\n", new_cr0); | |
215 | 231 | #endif |
216 | - pg_state = env->cr[0] & CR0_PG_MASK; | |
217 | - if (pg_state != last_pg_state) { | |
218 | - tlb_flush(env); | |
219 | - last_pg_state = pg_state; | |
232 | + if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) != | |
233 | + (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) { | |
234 | + tlb_flush(env, 1); | |
220 | 235 | } |
236 | + env->cr[0] = new_cr0; | |
237 | + | |
221 | 238 | /* update PE flag in hidden flags */ |
222 | 239 | pe_state = (env->cr[0] & CR0_PE_MASK); |
223 | 240 | env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT); |
... | ... | @@ -225,23 +242,27 @@ void cpu_x86_update_cr0(CPUX86State *env) |
225 | 242 | env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT); |
226 | 243 | } |
227 | 244 | |
228 | -void cpu_x86_update_cr3(CPUX86State *env) | |
245 | +void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3) | |
229 | 246 | { |
247 | + env->cr[3] = new_cr3; | |
230 | 248 | if (env->cr[0] & CR0_PG_MASK) { |
231 | 249 | #if defined(DEBUG_MMU) |
232 | - printf("CR3 update: CR3=%08x\n", env->cr[3]); | |
250 | + printf("CR3 update: CR3=%08x\n", new_cr3); | |
233 | 251 | #endif |
234 | - tlb_flush(env); | |
252 | + tlb_flush(env, 0); | |
235 | 253 | } |
236 | 254 | } |
237 | 255 | |
238 | -void cpu_x86_init_mmu(CPUX86State *env) | |
256 | +void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) | |
239 | 257 | { |
240 | - a20_enabled = 1; | |
241 | - a20_mask = 0xffffffff; | |
242 | - | |
243 | - last_pg_state = -1; | |
244 | - cpu_x86_update_cr0(env); | |
258 | +#if defined(DEBUG_MMU) | |
259 | + printf("CR4 update: CR4=%08x\n", env->cr[4]); | |
260 | +#endif | |
261 | + if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) != | |
262 | + (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) { | |
263 | + tlb_flush(env, 1); | |
264 | + } | |
265 | + env->cr[4] = new_cr4; | |
245 | 266 | } |
246 | 267 | |
247 | 268 | /* XXX: also flush 4MB pages */ |
... | ... | @@ -285,7 +306,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, |
285 | 306 | |
286 | 307 | /* page directory entry */ |
287 | 308 | pde_ptr = phys_ram_base + |
288 | - (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & a20_mask); | |
309 | + (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask); | |
289 | 310 | pde = ldl_raw(pde_ptr); |
290 | 311 | if (!(pde & PG_PRESENT_MASK)) { |
291 | 312 | error_code = 0; |
... | ... | @@ -323,7 +344,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, |
323 | 344 | |
324 | 345 | /* page directory entry */ |
325 | 346 | pte_ptr = phys_ram_base + |
326 | - (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask); | |
347 | + (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask); | |
327 | 348 | pte = ldl_raw(pte_ptr); |
328 | 349 | if (!(pte & PG_PRESENT_MASK)) { |
329 | 350 | error_code = 0; |
... | ... | @@ -368,7 +389,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, |
368 | 389 | } |
369 | 390 | |
370 | 391 | do_mapping: |
371 | - pte = pte & a20_mask; | |
392 | + pte = pte & env->a20_mask; | |
372 | 393 | |
373 | 394 | /* Even if 4MB pages, we map only one 4KB page in the cache to |
374 | 395 | avoid filling it too fast */ |
... | ... | @@ -405,7 +426,7 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
405 | 426 | } else { |
406 | 427 | /* page directory entry */ |
407 | 428 | pde_ptr = phys_ram_base + |
408 | - (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & a20_mask); | |
429 | + (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask); | |
409 | 430 | pde = ldl_raw(pde_ptr); |
410 | 431 | if (!(pde & PG_PRESENT_MASK)) |
411 | 432 | return -1; |
... | ... | @@ -415,14 +436,14 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
415 | 436 | } else { |
416 | 437 | /* page directory entry */ |
417 | 438 | pte_ptr = phys_ram_base + |
418 | - (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask); | |
439 | + (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask); | |
419 | 440 | pte = ldl_raw(pte_ptr); |
420 | 441 | if (!(pte & PG_PRESENT_MASK)) |
421 | 442 | return -1; |
422 | 443 | page_size = 4096; |
423 | 444 | } |
424 | 445 | } |
425 | - pte = pte & a20_mask; | |
446 | + pte = pte & env->a20_mask; | |
426 | 447 | page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1); |
427 | 448 | paddr = (pte & TARGET_PAGE_MASK) + page_offset; |
428 | 449 | return paddr; | ... | ... |