buffer overflow fix
[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 A20=%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             (env->a20_mask >> 20) & 1);
187     for(i = 0; i < 6; i++) {
188         SegmentCache *sc = &env->segs[i];
189         fprintf(f, "%s =%04x %08x %08x %08x\n",
190                 seg_name[i],
191                 sc->selector,
192                 (int)sc->base,
193                 sc->limit,
194                 sc->flags);
195     }
196     fprintf(f, "LDT=%04x %08x %08x %08x\n",
197             env->ldt.selector,
198             (int)env->ldt.base,
199             env->ldt.limit,
200             env->ldt.flags);
201     fprintf(f, "TR =%04x %08x %08x %08x\n",
202             env->tr.selector,
203             (int)env->tr.base,
204             env->tr.limit,
205             env->tr.flags);
206     fprintf(f, "GDT=     %08x %08x\n",
207             (int)env->gdt.base, env->gdt.limit);
208     fprintf(f, "IDT=     %08x %08x\n",
209             (int)env->idt.base, env->idt.limit);
210     fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
211             env->cr[0], env->cr[2], env->cr[3], env->cr[4]);
212     
213     if (flags & X86_DUMP_CCOP) {
214         if ((unsigned)env->cc_op < CC_OP_NB)
215             snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
216         else
217             snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
218         fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
219                 env->cc_src, env->cc_dst, cc_op_name);
220     }
221     if (flags & X86_DUMP_FPU) {
222         fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
223                 (double)env->fpregs[0], 
224                 (double)env->fpregs[1], 
225                 (double)env->fpregs[2], 
226                 (double)env->fpregs[3]);
227         fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
228                 (double)env->fpregs[4], 
229                 (double)env->fpregs[5], 
230                 (double)env->fpregs[7], 
231                 (double)env->fpregs[8]);
232     }
233 }
234
235 /***********************************************************/
236 /* x86 mmu */
237 /* XXX: add PGE support */
238
239 void cpu_x86_set_a20(CPUX86State *env, int a20_state)
240 {
241     a20_state = (a20_state != 0);
242     if (a20_state != ((env->a20_mask >> 20) & 1)) {
243 #if defined(DEBUG_MMU)
244         printf("A20 update: a20=%d\n", a20_state);
245 #endif
246         /* if the cpu is currently executing code, we must unlink it and
247            all the potentially executing TB */
248         cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
249
250         /* when a20 is changed, all the MMU mappings are invalid, so
251            we must flush everything */
252         tlb_flush(env, 1);
253         env->a20_mask = 0xffefffff | (a20_state << 20);
254     }
255 }
256
257 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
258 {
259     int pe_state;
260
261 #if defined(DEBUG_MMU)
262     printf("CR0 update: CR0=0x%08x\n", new_cr0);
263 #endif
264     if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
265         (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
266         tlb_flush(env, 1);
267     }
268     env->cr[0] = new_cr0 | CR0_ET_MASK;
269     
270     /* update PE flag in hidden flags */
271     pe_state = (env->cr[0] & CR0_PE_MASK);
272     env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
273     /* ensure that ADDSEG is always set in real mode */
274     env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
275     /* update FPU flags */
276     env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
277         ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
278 }
279
280 void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3)
281 {
282     env->cr[3] = new_cr3;
283     if (env->cr[0] & CR0_PG_MASK) {
284 #if defined(DEBUG_MMU)
285         printf("CR3 update: CR3=%08x\n", new_cr3);
286 #endif
287         tlb_flush(env, 0);
288     }
289 }
290
291 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
292 {
293 #if defined(DEBUG_MMU)
294     printf("CR4 update: CR4=%08x\n", env->cr[4]);
295 #endif
296     if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
297         (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
298         tlb_flush(env, 1);
299     }
300     env->cr[4] = new_cr4;
301 }
302
303 /* XXX: also flush 4MB pages */
304 void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
305 {
306     tlb_flush_page(env, addr);
307 }
308
309 /* return value:
310    -1 = cannot handle fault 
311    0  = nothing more to do 
312    1  = generate PF fault
313    2  = soft MMU activation required for this block
314 */
315 int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, 
316                              int is_write, int is_user, int is_softmmu)
317 {
318     uint8_t *pde_ptr, *pte_ptr;
319     uint32_t pde, pte, virt_addr, ptep;
320     int error_code, is_dirty, prot, page_size, ret;
321     unsigned long paddr, vaddr, page_offset;
322     
323 #if defined(DEBUG_MMU)
324     printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", 
325            addr, is_write, is_user, env->eip);
326 #endif
327
328     if (env->user_mode_only) {
329         /* user mode only emulation */
330         error_code = 0;
331         goto do_fault;
332     }
333
334     if (!(env->cr[0] & CR0_PG_MASK)) {
335         pte = addr;
336         virt_addr = addr & TARGET_PAGE_MASK;
337         prot = PAGE_READ | PAGE_WRITE;
338         page_size = 4096;
339         goto do_mapping;
340     }
341
342     /* page directory entry */
343     pde_ptr = phys_ram_base + 
344         (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask);
345     pde = ldl_raw(pde_ptr);
346     if (!(pde & PG_PRESENT_MASK)) {
347         error_code = 0;
348         goto do_fault;
349     }
350     /* if PSE bit is set, then we use a 4MB page */
351     if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
352         if (is_user) {
353             if (!(pde & PG_USER_MASK))
354                 goto do_fault_protect;
355             if (is_write && !(pde & PG_RW_MASK))
356                 goto do_fault_protect;
357         } else {
358             if ((env->cr[0] & CR0_WP_MASK) && 
359                 is_write && !(pde & PG_RW_MASK)) 
360                 goto do_fault_protect;
361         }
362         is_dirty = is_write && !(pde & PG_DIRTY_MASK);
363         if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
364             pde |= PG_ACCESSED_MASK;
365             if (is_dirty)
366                 pde |= PG_DIRTY_MASK;
367             stl_raw(pde_ptr, pde);
368         }
369         
370         pte = pde & ~0x003ff000; /* align to 4MB */
371         ptep = pte;
372         page_size = 4096 * 1024;
373         virt_addr = addr & ~0x003fffff;
374     } else {
375         if (!(pde & PG_ACCESSED_MASK)) {
376             pde |= PG_ACCESSED_MASK;
377             stl_raw(pde_ptr, pde);
378         }
379
380         /* page directory entry */
381         pte_ptr = phys_ram_base + 
382             (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask);
383         pte = ldl_raw(pte_ptr);
384         if (!(pte & PG_PRESENT_MASK)) {
385             error_code = 0;
386             goto do_fault;
387         }
388         /* combine pde and pte user and rw protections */
389         ptep = pte & pde;
390         if (is_user) {
391             if (!(ptep & PG_USER_MASK))
392                 goto do_fault_protect;
393             if (is_write && !(ptep & PG_RW_MASK))
394                 goto do_fault_protect;
395         } else {
396             if ((env->cr[0] & CR0_WP_MASK) &&
397                 is_write && !(ptep & PG_RW_MASK)) 
398                 goto do_fault_protect;
399         }
400         is_dirty = is_write && !(pte & PG_DIRTY_MASK);
401         if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
402             pte |= PG_ACCESSED_MASK;
403             if (is_dirty)
404                 pte |= PG_DIRTY_MASK;
405             stl_raw(pte_ptr, pte);
406         }
407         page_size = 4096;
408         virt_addr = addr & ~0xfff;
409     }
410
411     /* the page can be put in the TLB */
412     prot = PAGE_READ;
413     if (pte & PG_DIRTY_MASK) {
414         /* only set write access if already dirty... otherwise wait
415            for dirty access */
416         if (is_user) {
417             if (ptep & PG_RW_MASK)
418                 prot |= PAGE_WRITE;
419         } else {
420             if (!(env->cr[0] & CR0_WP_MASK) ||
421                 (ptep & PG_RW_MASK))
422                 prot |= PAGE_WRITE;
423         }
424     }
425
426  do_mapping:
427     pte = pte & env->a20_mask;
428
429     /* Even if 4MB pages, we map only one 4KB page in the cache to
430        avoid filling it too fast */
431     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
432     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
433     vaddr = virt_addr + page_offset;
434     
435     ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
436     return ret;
437  do_fault_protect:
438     error_code = PG_ERROR_P_MASK;
439  do_fault:
440     env->cr[2] = addr;
441     env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
442     if (is_user)
443         env->error_code |= PG_ERROR_U_MASK;
444     return 1;
445 }
446
447 #if defined(CONFIG_USER_ONLY) 
448 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
449 {
450     return addr;
451 }
452 #else
453 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
454 {
455     uint8_t *pde_ptr, *pte_ptr;
456     uint32_t pde, pte, paddr, page_offset, page_size;
457
458     if (!(env->cr[0] & CR0_PG_MASK)) {
459         pte = addr;
460         page_size = 4096;
461     } else {
462         /* page directory entry */
463         pde_ptr = phys_ram_base + 
464             (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask);
465         pde = ldl_raw(pde_ptr);
466         if (!(pde & PG_PRESENT_MASK)) 
467             return -1;
468         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
469             pte = pde & ~0x003ff000; /* align to 4MB */
470             page_size = 4096 * 1024;
471         } else {
472             /* page directory entry */
473             pte_ptr = phys_ram_base + 
474                 (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask);
475             pte = ldl_raw(pte_ptr);
476             if (!(pte & PG_PRESENT_MASK))
477                 return -1;
478             page_size = 4096;
479         }
480     }
481     pte = pte & env->a20_mask;
482     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
483     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
484     return paddr;
485 }
486 #endif
487
488 #if defined(USE_CODE_COPY)
489 struct fpstate {
490     uint16_t fpuc;
491     uint16_t dummy1;
492     uint16_t fpus;
493     uint16_t dummy2;
494     uint16_t fptag;
495     uint16_t dummy3;
496
497     uint32_t fpip;
498     uint32_t fpcs;
499     uint32_t fpoo;
500     uint32_t fpos;
501     uint8_t fpregs1[8 * 10];
502 };
503
504 void restore_native_fp_state(CPUState *env)
505 {
506     int fptag, i, j;
507     struct fpstate fp1, *fp = &fp1;
508     
509     fp->fpuc = env->fpuc;
510     fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
511     fptag = 0;
512     for (i=7; i>=0; i--) {
513         fptag <<= 2;
514         if (env->fptags[i]) {
515             fptag |= 3;
516         } else {
517             /* the FPU automatically computes it */
518         }
519     }
520     fp->fptag = fptag;
521     j = env->fpstt;
522     for(i = 0;i < 8; i++) {
523         memcpy(&fp->fpregs1[i * 10], &env->fpregs[j], 10);
524         j = (j + 1) & 7;
525     }
526     asm volatile ("frstor %0" : "=m" (*fp));
527     env->native_fp_regs = 1;
528 }
529  
530 void save_native_fp_state(CPUState *env)
531 {
532     int fptag, i, j;
533     uint16_t fpuc;
534     struct fpstate fp1, *fp = &fp1;
535
536     asm volatile ("fsave %0" : : "m" (*fp));
537     env->fpuc = fp->fpuc;
538     env->fpstt = (fp->fpus >> 11) & 7;
539     env->fpus = fp->fpus & ~0x3800;
540     fptag = fp->fptag;
541     for(i = 0;i < 8; i++) {
542         env->fptags[i] = ((fptag & 3) == 3);
543         fptag >>= 2;
544     }
545     j = env->fpstt;
546     for(i = 0;i < 8; i++) {
547         memcpy(&env->fpregs[j], &fp->fpregs1[i * 10], 10);
548         j = (j + 1) & 7;
549     }
550     /* we must restore the default rounding state */
551     /* XXX: we do not restore the exception state */
552     fpuc = 0x037f | (env->fpuc & (3 << 10));
553     asm volatile("fldcw %0" : : "m" (fpuc));
554     env->native_fp_regs = 0;
555 }
556 #endif