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