added cpu_reset()
[qemu] / target-i386 / helper2.c
1 /*
2  *  i386 helpers (without register variable usage)
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <signal.h>
26 #include <assert.h>
27
28 #include "cpu.h"
29 #include "exec-all.h"
30
31 //#define DEBUG_MMU
32
33 #ifdef USE_CODE_COPY
34 #include <asm/ldt.h>
35 #include <linux/unistd.h>
36 #include <linux/version.h>
37
38 _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
39
40 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
41 #define modify_ldt_ldt_s user_desc
42 #endif
43 #endif /* USE_CODE_COPY */
44
45 CPUX86State *cpu_x86_init(void)
46 {
47     CPUX86State *env;
48     static int inited;
49
50     cpu_exec_init();
51
52     env = malloc(sizeof(CPUX86State));
53     if (!env)
54         return NULL;
55     memset(env, 0, sizeof(CPUX86State));
56     /* init various static tables */
57     if (!inited) {
58         inited = 1;
59         optimize_flags_init();
60     }
61 #ifdef USE_CODE_COPY
62     /* testing code for code copy case */
63     {
64         struct modify_ldt_ldt_s ldt;
65
66         ldt.entry_number = 1;
67         ldt.base_addr = (unsigned long)env;
68         ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
69         ldt.seg_32bit = 1;
70         ldt.contents = MODIFY_LDT_CONTENTS_DATA;
71         ldt.read_exec_only = 0;
72         ldt.limit_in_pages = 1;
73         ldt.seg_not_present = 0;
74         ldt.useable = 1;
75         modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
76         
77         asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
78         cpu_single_env = env;
79     }
80 #endif
81     cpu_reset(env);
82     return env;
83 }
84
85 /* NOTE: must be called outside the CPU execute loop */
86 void cpu_reset(CPUX86State *env)
87 {
88     int i;
89
90     memset(env, 0, offsetof(CPUX86State, breakpoints));
91
92     tlb_flush(env, 1);
93
94     /* init to reset state */
95
96 #ifdef CONFIG_SOFTMMU
97     env->hflags |= HF_SOFTMMU_MASK;
98 #endif
99
100     cpu_x86_update_cr0(env, 0x60000010);
101     env->a20_mask = 0xffffffff;
102     
103     env->idt.limit = 0xffff;
104     env->gdt.limit = 0xffff;
105     env->ldt.limit = 0xffff;
106     env->ldt.flags = DESC_P_MASK;
107     env->tr.limit = 0xffff;
108     env->tr.flags = DESC_P_MASK;
109     
110     /* not correct (CS base=0xffff0000) */
111     cpu_x86_load_seg_cache(env, R_CS, 0xf000, (uint8_t *)0x000f0000, 0xffff, 0); 
112     cpu_x86_load_seg_cache(env, R_DS, 0, NULL, 0xffff, 0);
113     cpu_x86_load_seg_cache(env, R_ES, 0, NULL, 0xffff, 0);
114     cpu_x86_load_seg_cache(env, R_SS, 0, NULL, 0xffff, 0);
115     cpu_x86_load_seg_cache(env, R_FS, 0, NULL, 0xffff, 0);
116     cpu_x86_load_seg_cache(env, R_GS, 0, NULL, 0xffff, 0);
117     
118     env->eip = 0xfff0;
119     env->regs[R_EDX] = 0x600; /* indicate P6 processor */
120     
121     env->eflags = 0x2;
122     
123     /* FPU init */
124     for(i = 0;i < 8; i++)
125         env->fptags[i] = 1;
126     env->fpuc = 0x37f;
127 }
128
129 void cpu_x86_close(CPUX86State *env)
130 {
131     free(env);
132 }
133
134 /***********************************************************/
135 /* x86 debug */
136
137 static const char *cc_op_str[] = {
138     "DYNAMIC",
139     "EFLAGS",
140     "MULB",
141     "MULW",
142     "MULL",
143     "ADDB",
144     "ADDW",
145     "ADDL",
146     "ADCB",
147     "ADCW",
148     "ADCL",
149     "SUBB",
150     "SUBW",
151     "SUBL",
152     "SBBB",
153     "SBBW",
154     "SBBL",
155     "LOGICB",
156     "LOGICW",
157     "LOGICL",
158     "INCB",
159     "INCW",
160     "INCL",
161     "DECB",
162     "DECW",
163     "DECL",
164     "SHLB",
165     "SHLW",
166     "SHLL",
167     "SARB",
168     "SARW",
169     "SARL",
170 };
171
172 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
173 {
174     int eflags, i;
175     char cc_op_name[32];
176     static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
177
178     eflags = env->eflags;
179     fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
180             "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
181             "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]    CPL=%d II=%d A20=%d\n",
182             env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
183             env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
184             env->eip, eflags,
185             eflags & DF_MASK ? 'D' : '-',
186             eflags & CC_O ? 'O' : '-',
187             eflags & CC_S ? 'S' : '-',
188             eflags & CC_Z ? 'Z' : '-',
189             eflags & CC_A ? 'A' : '-',
190             eflags & CC_P ? 'P' : '-',
191             eflags & CC_C ? 'C' : '-',
192             env->hflags & HF_CPL_MASK, 
193             (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
194             (env->a20_mask >> 20) & 1);
195     for(i = 0; i < 6; i++) {
196         SegmentCache *sc = &env->segs[i];
197         fprintf(f, "%s =%04x %08x %08x %08x\n",
198                 seg_name[i],
199                 sc->selector,
200                 (int)sc->base,
201                 sc->limit,
202                 sc->flags);
203     }
204     fprintf(f, "LDT=%04x %08x %08x %08x\n",
205             env->ldt.selector,
206             (int)env->ldt.base,
207             env->ldt.limit,
208             env->ldt.flags);
209     fprintf(f, "TR =%04x %08x %08x %08x\n",
210             env->tr.selector,
211             (int)env->tr.base,
212             env->tr.limit,
213             env->tr.flags);
214     fprintf(f, "GDT=     %08x %08x\n",
215             (int)env->gdt.base, env->gdt.limit);
216     fprintf(f, "IDT=     %08x %08x\n",
217             (int)env->idt.base, env->idt.limit);
218     fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
219             env->cr[0], env->cr[2], env->cr[3], env->cr[4]);
220     
221     if (flags & X86_DUMP_CCOP) {
222         if ((unsigned)env->cc_op < CC_OP_NB)
223             snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
224         else
225             snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
226         fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
227                 env->cc_src, env->cc_dst, cc_op_name);
228     }
229     if (flags & X86_DUMP_FPU) {
230         fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
231                 (double)env->fpregs[0], 
232                 (double)env->fpregs[1], 
233                 (double)env->fpregs[2], 
234                 (double)env->fpregs[3]);
235         fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
236                 (double)env->fpregs[4], 
237                 (double)env->fpregs[5], 
238                 (double)env->fpregs[7], 
239                 (double)env->fpregs[8]);
240     }
241 }
242
243 /***********************************************************/
244 /* x86 mmu */
245 /* XXX: add PGE support */
246
247 void cpu_x86_set_a20(CPUX86State *env, int a20_state)
248 {
249     a20_state = (a20_state != 0);
250     if (a20_state != ((env->a20_mask >> 20) & 1)) {
251 #if defined(DEBUG_MMU)
252         printf("A20 update: a20=%d\n", a20_state);
253 #endif
254         /* if the cpu is currently executing code, we must unlink it and
255            all the potentially executing TB */
256         cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
257
258         /* when a20 is changed, all the MMU mappings are invalid, so
259            we must flush everything */
260         tlb_flush(env, 1);
261         env->a20_mask = 0xffefffff | (a20_state << 20);
262     }
263 }
264
265 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
266 {
267     int pe_state;
268
269 #if defined(DEBUG_MMU)
270     printf("CR0 update: CR0=0x%08x\n", new_cr0);
271 #endif
272     if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
273         (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
274         tlb_flush(env, 1);
275     }
276     env->cr[0] = new_cr0 | CR0_ET_MASK;
277     
278     /* update PE flag in hidden flags */
279     pe_state = (env->cr[0] & CR0_PE_MASK);
280     env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
281     /* ensure that ADDSEG is always set in real mode */
282     env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
283     /* update FPU flags */
284     env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
285         ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
286 }
287
288 void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3)
289 {
290     env->cr[3] = new_cr3;
291     if (env->cr[0] & CR0_PG_MASK) {
292 #if defined(DEBUG_MMU)
293         printf("CR3 update: CR3=%08x\n", new_cr3);
294 #endif
295         tlb_flush(env, 0);
296     }
297 }
298
299 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
300 {
301 #if defined(DEBUG_MMU)
302     printf("CR4 update: CR4=%08x\n", env->cr[4]);
303 #endif
304     if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
305         (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
306         tlb_flush(env, 1);
307     }
308     env->cr[4] = new_cr4;
309 }
310
311 /* XXX: also flush 4MB pages */
312 void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
313 {
314     tlb_flush_page(env, addr);
315 }
316
317 /* return value:
318    -1 = cannot handle fault 
319    0  = nothing more to do 
320    1  = generate PF fault
321    2  = soft MMU activation required for this block
322 */
323 int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, 
324                              int is_write, int is_user, int is_softmmu)
325 {
326     uint8_t *pde_ptr, *pte_ptr;
327     uint32_t pde, pte, virt_addr, ptep;
328     int error_code, is_dirty, prot, page_size, ret;
329     unsigned long paddr, vaddr, page_offset;
330     
331 #if defined(DEBUG_MMU)
332     printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", 
333            addr, is_write, is_user, env->eip);
334 #endif
335
336     if (env->user_mode_only) {
337         /* user mode only emulation */
338         error_code = 0;
339         goto do_fault;
340     }
341
342     if (!(env->cr[0] & CR0_PG_MASK)) {
343         pte = addr;
344         virt_addr = addr & TARGET_PAGE_MASK;
345         prot = PAGE_READ | PAGE_WRITE;
346         page_size = 4096;
347         goto do_mapping;
348     }
349
350     /* page directory entry */
351     pde_ptr = phys_ram_base + 
352         (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask);
353     pde = ldl_raw(pde_ptr);
354     if (!(pde & PG_PRESENT_MASK)) {
355         error_code = 0;
356         goto do_fault;
357     }
358     /* if PSE bit is set, then we use a 4MB page */
359     if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
360         if (is_user) {
361             if (!(pde & PG_USER_MASK))
362                 goto do_fault_protect;
363             if (is_write && !(pde & PG_RW_MASK))
364                 goto do_fault_protect;
365         } else {
366             if ((env->cr[0] & CR0_WP_MASK) && 
367                 is_write && !(pde & PG_RW_MASK)) 
368                 goto do_fault_protect;
369         }
370         is_dirty = is_write && !(pde & PG_DIRTY_MASK);
371         if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
372             pde |= PG_ACCESSED_MASK;
373             if (is_dirty)
374                 pde |= PG_DIRTY_MASK;
375             stl_raw(pde_ptr, pde);
376         }
377         
378         pte = pde & ~0x003ff000; /* align to 4MB */
379         ptep = pte;
380         page_size = 4096 * 1024;
381         virt_addr = addr & ~0x003fffff;
382     } else {
383         if (!(pde & PG_ACCESSED_MASK)) {
384             pde |= PG_ACCESSED_MASK;
385             stl_raw(pde_ptr, pde);
386         }
387
388         /* page directory entry */
389         pte_ptr = phys_ram_base + 
390             (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask);
391         pte = ldl_raw(pte_ptr);
392         if (!(pte & PG_PRESENT_MASK)) {
393             error_code = 0;
394             goto do_fault;
395         }
396         /* combine pde and pte user and rw protections */
397         ptep = pte & pde;
398         if (is_user) {
399             if (!(ptep & PG_USER_MASK))
400                 goto do_fault_protect;
401             if (is_write && !(ptep & PG_RW_MASK))
402                 goto do_fault_protect;
403         } else {
404             if ((env->cr[0] & CR0_WP_MASK) &&
405                 is_write && !(ptep & PG_RW_MASK)) 
406                 goto do_fault_protect;
407         }
408         is_dirty = is_write && !(pte & PG_DIRTY_MASK);
409         if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
410             pte |= PG_ACCESSED_MASK;
411             if (is_dirty)
412                 pte |= PG_DIRTY_MASK;
413             stl_raw(pte_ptr, pte);
414         }
415         page_size = 4096;
416         virt_addr = addr & ~0xfff;
417     }
418
419     /* the page can be put in the TLB */
420     prot = PAGE_READ;
421     if (pte & PG_DIRTY_MASK) {
422         /* only set write access if already dirty... otherwise wait
423            for dirty access */
424         if (is_user) {
425             if (ptep & PG_RW_MASK)
426                 prot |= PAGE_WRITE;
427         } else {
428             if (!(env->cr[0] & CR0_WP_MASK) ||
429                 (ptep & PG_RW_MASK))
430                 prot |= PAGE_WRITE;
431         }
432     }
433
434  do_mapping:
435     pte = pte & env->a20_mask;
436
437     /* Even if 4MB pages, we map only one 4KB page in the cache to
438        avoid filling it too fast */
439     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
440     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
441     vaddr = virt_addr + page_offset;
442     
443     ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
444     return ret;
445  do_fault_protect:
446     error_code = PG_ERROR_P_MASK;
447  do_fault:
448     env->cr[2] = addr;
449     env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
450     if (is_user)
451         env->error_code |= PG_ERROR_U_MASK;
452     return 1;
453 }
454
455 #if defined(CONFIG_USER_ONLY) 
456 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
457 {
458     return addr;
459 }
460 #else
461 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
462 {
463     uint8_t *pde_ptr, *pte_ptr;
464     uint32_t pde, pte, paddr, page_offset, page_size;
465
466     if (!(env->cr[0] & CR0_PG_MASK)) {
467         pte = addr;
468         page_size = 4096;
469     } else {
470         /* page directory entry */
471         pde_ptr = phys_ram_base + 
472             (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask);
473         pde = ldl_raw(pde_ptr);
474         if (!(pde & PG_PRESENT_MASK)) 
475             return -1;
476         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
477             pte = pde & ~0x003ff000; /* align to 4MB */
478             page_size = 4096 * 1024;
479         } else {
480             /* page directory entry */
481             pte_ptr = phys_ram_base + 
482                 (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask);
483             pte = ldl_raw(pte_ptr);
484             if (!(pte & PG_PRESENT_MASK))
485                 return -1;
486             page_size = 4096;
487         }
488     }
489     pte = pte & env->a20_mask;
490     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
491     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
492     return paddr;
493 }
494 #endif
495
496 #if defined(USE_CODE_COPY)
497 struct fpstate {
498     uint16_t fpuc;
499     uint16_t dummy1;
500     uint16_t fpus;
501     uint16_t dummy2;
502     uint16_t fptag;
503     uint16_t dummy3;
504
505     uint32_t fpip;
506     uint32_t fpcs;
507     uint32_t fpoo;
508     uint32_t fpos;
509     uint8_t fpregs1[8 * 10];
510 };
511
512 void restore_native_fp_state(CPUState *env)
513 {
514     int fptag, i, j;
515     struct fpstate fp1, *fp = &fp1;
516     
517     fp->fpuc = env->fpuc;
518     fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
519     fptag = 0;
520     for (i=7; i>=0; i--) {
521         fptag <<= 2;
522         if (env->fptags[i]) {
523             fptag |= 3;
524         } else {
525             /* the FPU automatically computes it */
526         }
527     }
528     fp->fptag = fptag;
529     j = env->fpstt;
530     for(i = 0;i < 8; i++) {
531         memcpy(&fp->fpregs1[i * 10], &env->fpregs[j], 10);
532         j = (j + 1) & 7;
533     }
534     asm volatile ("frstor %0" : "=m" (*fp));
535     env->native_fp_regs = 1;
536 }
537  
538 void save_native_fp_state(CPUState *env)
539 {
540     int fptag, i, j;
541     uint16_t fpuc;
542     struct fpstate fp1, *fp = &fp1;
543
544     asm volatile ("fsave %0" : : "m" (*fp));
545     env->fpuc = fp->fpuc;
546     env->fpstt = (fp->fpus >> 11) & 7;
547     env->fpus = fp->fpus & ~0x3800;
548     fptag = fp->fptag;
549     for(i = 0;i < 8; i++) {
550         env->fptags[i] = ((fptag & 3) == 3);
551         fptag >>= 2;
552     }
553     j = env->fpstt;
554     for(i = 0;i < 8; i++) {
555         memcpy(&env->fpregs[j], &fp->fpregs1[i * 10], 10);
556         j = (j + 1) & 7;
557     }
558     /* we must restore the default rounding state */
559     /* XXX: we do not restore the exception state */
560     fpuc = 0x037f | (env->fpuc & (3 << 10));
561     asm volatile("fldcw %0" : : "m" (fpuc));
562     env->native_fp_regs = 0;
563 }
564 #endif