Annotation of qemu/target-i386/helper.c, revision 1.1.1.6

1.1       root        1: /*
                      2:  *  i386 helpers
1.1.1.6 ! root        3:  *
1.1       root        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 "exec.h"
1.1.1.6 ! root       21: #include "host-utils.h"
1.1       root       22: 
                     23: //#define DEBUG_PCALL
                     24: 
                     25: #if 0
                     26: #define raise_exception_err(a, b)\
                     27: do {\
1.1.1.3   root       28:     if (logfile)\
                     29:         fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
1.1       root       30:     (raise_exception_err)(a, b);\
                     31: } while (0)
                     32: #endif
                     33: 
                     34: const uint8_t parity_table[256] = {
                     35:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     36:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     37:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     38:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     39:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     40:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     41:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     42:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     43:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     44:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     45:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     46:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     47:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     48:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     49:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     50:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     51:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     52:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     53:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     54:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     55:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     56:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     57:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     58:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     59:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     60:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     61:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     62:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     63:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     64:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     65:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     66:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     67: };
                     68: 
                     69: /* modulo 17 table */
                     70: const uint8_t rclw_table[32] = {
1.1.1.6 ! root       71:     0, 1, 2, 3, 4, 5, 6, 7,
1.1       root       72:     8, 9,10,11,12,13,14,15,
                     73:    16, 0, 1, 2, 3, 4, 5, 6,
                     74:     7, 8, 9,10,11,12,13,14,
                     75: };
                     76: 
                     77: /* modulo 9 table */
                     78: const uint8_t rclb_table[32] = {
1.1.1.6 ! root       79:     0, 1, 2, 3, 4, 5, 6, 7,
1.1       root       80:     8, 0, 1, 2, 3, 4, 5, 6,
1.1.1.6 ! root       81:     7, 8, 0, 1, 2, 3, 4, 5,
1.1       root       82:     6, 7, 8, 0, 1, 2, 3, 4,
                     83: };
                     84: 
                     85: const CPU86_LDouble f15rk[7] =
                     86: {
                     87:     0.00000000000000000000L,
                     88:     1.00000000000000000000L,
                     89:     3.14159265358979323851L,  /*pi*/
                     90:     0.30102999566398119523L,  /*lg2*/
                     91:     0.69314718055994530943L,  /*ln2*/
                     92:     1.44269504088896340739L,  /*l2e*/
                     93:     3.32192809488736234781L,  /*l2t*/
                     94: };
1.1.1.6 ! root       95: 
1.1       root       96: /* thread support */
                     97: 
                     98: spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
                     99: 
                    100: void cpu_lock(void)
                    101: {
                    102:     spin_lock(&global_cpu_lock);
                    103: }
                    104: 
                    105: void cpu_unlock(void)
                    106: {
                    107:     spin_unlock(&global_cpu_lock);
                    108: }
                    109: 
                    110: /* return non zero if error */
                    111: static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
                    112:                                int selector)
                    113: {
                    114:     SegmentCache *dt;
                    115:     int index;
                    116:     target_ulong ptr;
                    117: 
                    118:     if (selector & 0x4)
                    119:         dt = &env->ldt;
                    120:     else
                    121:         dt = &env->gdt;
                    122:     index = selector & ~7;
                    123:     if ((index + 7) > dt->limit)
                    124:         return -1;
                    125:     ptr = dt->base + index;
                    126:     *e1_ptr = ldl_kernel(ptr);
                    127:     *e2_ptr = ldl_kernel(ptr + 4);
                    128:     return 0;
                    129: }
1.1.1.6 ! root      130: 
1.1       root      131: static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
                    132: {
                    133:     unsigned int limit;
                    134:     limit = (e1 & 0xffff) | (e2 & 0x000f0000);
                    135:     if (e2 & DESC_G_MASK)
                    136:         limit = (limit << 12) | 0xfff;
                    137:     return limit;
                    138: }
                    139: 
                    140: static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
                    141: {
                    142:     return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
                    143: }
                    144: 
                    145: static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
                    146: {
                    147:     sc->base = get_seg_base(e1, e2);
                    148:     sc->limit = get_seg_limit(e1, e2);
                    149:     sc->flags = e2;
                    150: }
                    151: 
                    152: /* init the segment cache in vm86 mode. */
                    153: static inline void load_seg_vm(int seg, int selector)
                    154: {
                    155:     selector &= 0xffff;
1.1.1.6 ! root      156:     cpu_x86_load_seg_cache(env, seg, selector,
1.1       root      157:                            (selector << 4), 0xffff, 0);
                    158: }
                    159: 
1.1.1.6 ! root      160: static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
1.1       root      161:                                        uint32_t *esp_ptr, int dpl)
                    162: {
                    163:     int type, index, shift;
1.1.1.6 ! root      164: 
1.1       root      165: #if 0
                    166:     {
                    167:         int i;
                    168:         printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
                    169:         for(i=0;i<env->tr.limit;i++) {
                    170:             printf("%02x ", env->tr.base[i]);
                    171:             if ((i & 7) == 7) printf("\n");
                    172:         }
                    173:         printf("\n");
                    174:     }
                    175: #endif
                    176: 
                    177:     if (!(env->tr.flags & DESC_P_MASK))
                    178:         cpu_abort(env, "invalid tss");
                    179:     type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
                    180:     if ((type & 7) != 1)
                    181:         cpu_abort(env, "invalid tss type");
                    182:     shift = type >> 3;
                    183:     index = (dpl * 4 + 2) << shift;
                    184:     if (index + (4 << shift) - 1 > env->tr.limit)
                    185:         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
                    186:     if (shift == 0) {
                    187:         *esp_ptr = lduw_kernel(env->tr.base + index);
                    188:         *ss_ptr = lduw_kernel(env->tr.base + index + 2);
                    189:     } else {
                    190:         *esp_ptr = ldl_kernel(env->tr.base + index);
                    191:         *ss_ptr = lduw_kernel(env->tr.base + index + 4);
                    192:     }
                    193: }
                    194: 
                    195: /* XXX: merge with load_seg() */
                    196: static void tss_load_seg(int seg_reg, int selector)
                    197: {
                    198:     uint32_t e1, e2;
                    199:     int rpl, dpl, cpl;
                    200: 
                    201:     if ((selector & 0xfffc) != 0) {
                    202:         if (load_segment(&e1, &e2, selector) != 0)
                    203:             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    204:         if (!(e2 & DESC_S_MASK))
                    205:             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    206:         rpl = selector & 3;
                    207:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    208:         cpl = env->hflags & HF_CPL_MASK;
                    209:         if (seg_reg == R_CS) {
                    210:             if (!(e2 & DESC_CS_MASK))
                    211:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
1.1.1.3   root      212:             /* XXX: is it correct ? */
1.1       root      213:             if (dpl != rpl)
                    214:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    215:             if ((e2 & DESC_C_MASK) && dpl > rpl)
                    216:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    217:         } else if (seg_reg == R_SS) {
                    218:             /* SS must be writable data */
                    219:             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
                    220:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    221:             if (dpl != cpl || dpl != rpl)
                    222:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    223:         } else {
                    224:             /* not readable code */
                    225:             if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
                    226:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    227:             /* if data or non conforming code, checks the rights */
                    228:             if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
                    229:                 if (dpl < cpl || dpl < rpl)
                    230:                     raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    231:             }
                    232:         }
                    233:         if (!(e2 & DESC_P_MASK))
                    234:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1.1.1.6 ! root      235:         cpu_x86_load_seg_cache(env, seg_reg, selector,
1.1       root      236:                        get_seg_base(e1, e2),
                    237:                        get_seg_limit(e1, e2),
                    238:                        e2);
                    239:     } else {
1.1.1.6 ! root      240:         if (seg_reg == R_SS || seg_reg == R_CS)
1.1       root      241:             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    242:     }
                    243: }
                    244: 
                    245: #define SWITCH_TSS_JMP  0
                    246: #define SWITCH_TSS_IRET 1
                    247: #define SWITCH_TSS_CALL 2
                    248: 
                    249: /* XXX: restore CPU state in registers (PowerPC case) */
1.1.1.6 ! root      250: static void switch_tss(int tss_selector,
1.1       root      251:                        uint32_t e1, uint32_t e2, int source,
                    252:                        uint32_t next_eip)
                    253: {
                    254:     int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
                    255:     target_ulong tss_base;
                    256:     uint32_t new_regs[8], new_segs[6];
                    257:     uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
                    258:     uint32_t old_eflags, eflags_mask;
                    259:     SegmentCache *dt;
                    260:     int index;
                    261:     target_ulong ptr;
                    262: 
                    263:     type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                    264: #ifdef DEBUG_PCALL
                    265:     if (loglevel & CPU_LOG_PCALL)
                    266:         fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
                    267: #endif
                    268: 
                    269:     /* if task gate, we read the TSS segment and we load it */
                    270:     if (type == 5) {
                    271:         if (!(e2 & DESC_P_MASK))
                    272:             raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
                    273:         tss_selector = e1 >> 16;
                    274:         if (tss_selector & 4)
                    275:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                    276:         if (load_segment(&e1, &e2, tss_selector) != 0)
                    277:             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
                    278:         if (e2 & DESC_S_MASK)
                    279:             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
                    280:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                    281:         if ((type & 7) != 1)
                    282:             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
                    283:     }
                    284: 
                    285:     if (!(e2 & DESC_P_MASK))
                    286:         raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
                    287: 
                    288:     if (type & 8)
                    289:         tss_limit_max = 103;
                    290:     else
                    291:         tss_limit_max = 43;
                    292:     tss_limit = get_seg_limit(e1, e2);
                    293:     tss_base = get_seg_base(e1, e2);
1.1.1.6 ! root      294:     if ((tss_selector & 4) != 0 ||
1.1       root      295:         tss_limit < tss_limit_max)
                    296:         raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                    297:     old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
                    298:     if (old_type & 8)
                    299:         old_tss_limit_max = 103;
                    300:     else
                    301:         old_tss_limit_max = 43;
                    302: 
                    303:     /* read all the registers from the new TSS */
                    304:     if (type & 8) {
                    305:         /* 32 bit */
                    306:         new_cr3 = ldl_kernel(tss_base + 0x1c);
                    307:         new_eip = ldl_kernel(tss_base + 0x20);
                    308:         new_eflags = ldl_kernel(tss_base + 0x24);
                    309:         for(i = 0; i < 8; i++)
                    310:             new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
                    311:         for(i = 0; i < 6; i++)
                    312:             new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
                    313:         new_ldt = lduw_kernel(tss_base + 0x60);
                    314:         new_trap = ldl_kernel(tss_base + 0x64);
                    315:     } else {
                    316:         /* 16 bit */
                    317:         new_cr3 = 0;
                    318:         new_eip = lduw_kernel(tss_base + 0x0e);
                    319:         new_eflags = lduw_kernel(tss_base + 0x10);
                    320:         for(i = 0; i < 8; i++)
                    321:             new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
                    322:         for(i = 0; i < 4; i++)
                    323:             new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
                    324:         new_ldt = lduw_kernel(tss_base + 0x2a);
                    325:         new_segs[R_FS] = 0;
                    326:         new_segs[R_GS] = 0;
                    327:         new_trap = 0;
                    328:     }
1.1.1.6 ! root      329: 
1.1       root      330:     /* NOTE: we must avoid memory exceptions during the task switch,
                    331:        so we make dummy accesses before */
                    332:     /* XXX: it can still fail in some cases, so a bigger hack is
                    333:        necessary to valid the TLB after having done the accesses */
                    334: 
                    335:     v1 = ldub_kernel(env->tr.base);
1.1.1.2   root      336:     v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
1.1       root      337:     stb_kernel(env->tr.base, v1);
                    338:     stb_kernel(env->tr.base + old_tss_limit_max, v2);
1.1.1.6 ! root      339: 
1.1       root      340:     /* clear busy bit (it is restartable) */
                    341:     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
                    342:         target_ulong ptr;
                    343:         uint32_t e2;
                    344:         ptr = env->gdt.base + (env->tr.selector & ~7);
                    345:         e2 = ldl_kernel(ptr + 4);
                    346:         e2 &= ~DESC_TSS_BUSY_MASK;
                    347:         stl_kernel(ptr + 4, e2);
                    348:     }
                    349:     old_eflags = compute_eflags();
                    350:     if (source == SWITCH_TSS_IRET)
                    351:         old_eflags &= ~NT_MASK;
1.1.1.6 ! root      352: 
1.1       root      353:     /* save the current state in the old TSS */
                    354:     if (type & 8) {
                    355:         /* 32 bit */
                    356:         stl_kernel(env->tr.base + 0x20, next_eip);
                    357:         stl_kernel(env->tr.base + 0x24, old_eflags);
                    358:         stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
                    359:         stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
                    360:         stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
                    361:         stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
                    362:         stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
                    363:         stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
                    364:         stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
                    365:         stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
                    366:         for(i = 0; i < 6; i++)
                    367:             stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
                    368:     } else {
                    369:         /* 16 bit */
                    370:         stw_kernel(env->tr.base + 0x0e, next_eip);
                    371:         stw_kernel(env->tr.base + 0x10, old_eflags);
                    372:         stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
                    373:         stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
                    374:         stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
                    375:         stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
                    376:         stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
                    377:         stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
                    378:         stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
                    379:         stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
                    380:         for(i = 0; i < 4; i++)
                    381:             stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
                    382:     }
1.1.1.6 ! root      383: 
1.1       root      384:     /* now if an exception occurs, it will occurs in the next task
                    385:        context */
                    386: 
                    387:     if (source == SWITCH_TSS_CALL) {
                    388:         stw_kernel(tss_base, env->tr.selector);
                    389:         new_eflags |= NT_MASK;
                    390:     }
                    391: 
                    392:     /* set busy bit */
                    393:     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
                    394:         target_ulong ptr;
                    395:         uint32_t e2;
                    396:         ptr = env->gdt.base + (tss_selector & ~7);
                    397:         e2 = ldl_kernel(ptr + 4);
                    398:         e2 |= DESC_TSS_BUSY_MASK;
                    399:         stl_kernel(ptr + 4, e2);
                    400:     }
                    401: 
                    402:     /* set the new CPU state */
                    403:     /* from this point, any exception which occurs can give problems */
                    404:     env->cr[0] |= CR0_TS_MASK;
                    405:     env->hflags |= HF_TS_MASK;
                    406:     env->tr.selector = tss_selector;
                    407:     env->tr.base = tss_base;
                    408:     env->tr.limit = tss_limit;
                    409:     env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
1.1.1.6 ! root      410: 
1.1       root      411:     if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
                    412:         cpu_x86_update_cr3(env, new_cr3);
                    413:     }
1.1.1.6 ! root      414: 
1.1       root      415:     /* load all registers without an exception, then reload them with
                    416:        possible exception */
                    417:     env->eip = new_eip;
1.1.1.6 ! root      418:     eflags_mask = TF_MASK | AC_MASK | ID_MASK |
1.1       root      419:         IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
                    420:     if (!(type & 8))
                    421:         eflags_mask &= 0xffff;
                    422:     load_eflags(new_eflags, eflags_mask);
                    423:     /* XXX: what to do in 16 bit case ? */
                    424:     EAX = new_regs[0];
                    425:     ECX = new_regs[1];
                    426:     EDX = new_regs[2];
                    427:     EBX = new_regs[3];
                    428:     ESP = new_regs[4];
                    429:     EBP = new_regs[5];
                    430:     ESI = new_regs[6];
                    431:     EDI = new_regs[7];
                    432:     if (new_eflags & VM_MASK) {
1.1.1.6 ! root      433:         for(i = 0; i < 6; i++)
1.1       root      434:             load_seg_vm(i, new_segs[i]);
                    435:         /* in vm86, CPL is always 3 */
                    436:         cpu_x86_set_cpl(env, 3);
                    437:     } else {
                    438:         /* CPL is set the RPL of CS */
                    439:         cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
                    440:         /* first just selectors as the rest may trigger exceptions */
                    441:         for(i = 0; i < 6; i++)
                    442:             cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
                    443:     }
1.1.1.6 ! root      444: 
1.1       root      445:     env->ldt.selector = new_ldt & ~4;
                    446:     env->ldt.base = 0;
                    447:     env->ldt.limit = 0;
                    448:     env->ldt.flags = 0;
                    449: 
                    450:     /* load the LDT */
                    451:     if (new_ldt & 4)
                    452:         raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
                    453: 
                    454:     if ((new_ldt & 0xfffc) != 0) {
                    455:         dt = &env->gdt;
                    456:         index = new_ldt & ~7;
                    457:         if ((index + 7) > dt->limit)
                    458:             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
                    459:         ptr = dt->base + index;
                    460:         e1 = ldl_kernel(ptr);
                    461:         e2 = ldl_kernel(ptr + 4);
                    462:         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
                    463:             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
                    464:         if (!(e2 & DESC_P_MASK))
                    465:             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
                    466:         load_seg_cache_raw_dt(&env->ldt, e1, e2);
                    467:     }
1.1.1.6 ! root      468: 
1.1       root      469:     /* load the segments */
                    470:     if (!(new_eflags & VM_MASK)) {
                    471:         tss_load_seg(R_CS, new_segs[R_CS]);
                    472:         tss_load_seg(R_SS, new_segs[R_SS]);
                    473:         tss_load_seg(R_ES, new_segs[R_ES]);
                    474:         tss_load_seg(R_DS, new_segs[R_DS]);
                    475:         tss_load_seg(R_FS, new_segs[R_FS]);
                    476:         tss_load_seg(R_GS, new_segs[R_GS]);
                    477:     }
1.1.1.6 ! root      478: 
1.1       root      479:     /* check that EIP is in the CS segment limits */
                    480:     if (new_eip > env->segs[R_CS].limit) {
                    481:         /* XXX: different exception if CALL ? */
                    482:         raise_exception_err(EXCP0D_GPF, 0);
                    483:     }
                    484: }
                    485: 
                    486: /* check if Port I/O is allowed in TSS */
                    487: static inline void check_io(int addr, int size)
                    488: {
                    489:     int io_offset, val, mask;
1.1.1.6 ! root      490: 
1.1       root      491:     /* TSS must be a valid 32 bit one */
                    492:     if (!(env->tr.flags & DESC_P_MASK) ||
                    493:         ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
                    494:         env->tr.limit < 103)
                    495:         goto fail;
                    496:     io_offset = lduw_kernel(env->tr.base + 0x66);
                    497:     io_offset += (addr >> 3);
                    498:     /* Note: the check needs two bytes */
                    499:     if ((io_offset + 1) > env->tr.limit)
                    500:         goto fail;
                    501:     val = lduw_kernel(env->tr.base + io_offset);
                    502:     val >>= (addr & 7);
                    503:     mask = (1 << size) - 1;
                    504:     /* all bits must be zero to allow the I/O */
                    505:     if ((val & mask) != 0) {
                    506:     fail:
                    507:         raise_exception_err(EXCP0D_GPF, 0);
                    508:     }
                    509: }
                    510: 
                    511: void check_iob_T0(void)
                    512: {
                    513:     check_io(T0, 1);
                    514: }
                    515: 
                    516: void check_iow_T0(void)
                    517: {
                    518:     check_io(T0, 2);
                    519: }
                    520: 
                    521: void check_iol_T0(void)
                    522: {
                    523:     check_io(T0, 4);
                    524: }
                    525: 
                    526: void check_iob_DX(void)
                    527: {
                    528:     check_io(EDX & 0xffff, 1);
                    529: }
                    530: 
                    531: void check_iow_DX(void)
                    532: {
                    533:     check_io(EDX & 0xffff, 2);
                    534: }
                    535: 
                    536: void check_iol_DX(void)
                    537: {
                    538:     check_io(EDX & 0xffff, 4);
                    539: }
                    540: 
                    541: static inline unsigned int get_sp_mask(unsigned int e2)
                    542: {
                    543:     if (e2 & DESC_B_MASK)
                    544:         return 0xffffffff;
                    545:     else
                    546:         return 0xffff;
                    547: }
                    548: 
1.1.1.5   root      549: #ifdef TARGET_X86_64
                    550: #define SET_ESP(val, sp_mask)\
                    551: do {\
                    552:     if ((sp_mask) == 0xffff)\
                    553:         ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
                    554:     else if ((sp_mask) == 0xffffffffLL)\
                    555:         ESP = (uint32_t)(val);\
                    556:     else\
                    557:         ESP = (val);\
                    558: } while (0)
                    559: #else
                    560: #define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
                    561: #endif
                    562: 
1.1       root      563: /* XXX: add a is_user flag to have proper security support */
                    564: #define PUSHW(ssp, sp, sp_mask, val)\
                    565: {\
                    566:     sp -= 2;\
                    567:     stw_kernel((ssp) + (sp & (sp_mask)), (val));\
                    568: }
                    569: 
                    570: #define PUSHL(ssp, sp, sp_mask, val)\
                    571: {\
                    572:     sp -= 4;\
                    573:     stl_kernel((ssp) + (sp & (sp_mask)), (val));\
                    574: }
                    575: 
                    576: #define POPW(ssp, sp, sp_mask, val)\
                    577: {\
                    578:     val = lduw_kernel((ssp) + (sp & (sp_mask)));\
                    579:     sp += 2;\
                    580: }
                    581: 
                    582: #define POPL(ssp, sp, sp_mask, val)\
                    583: {\
                    584:     val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
                    585:     sp += 4;\
                    586: }
                    587: 
                    588: /* protected mode interrupt */
                    589: static void do_interrupt_protected(int intno, int is_int, int error_code,
                    590:                                    unsigned int next_eip, int is_hw)
                    591: {
                    592:     SegmentCache *dt;
                    593:     target_ulong ptr, ssp;
1.1.1.5   root      594:     int type, dpl, selector, ss_dpl, cpl;
1.1       root      595:     int has_error_code, new_stack, shift;
                    596:     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
1.1.1.5   root      597:     uint32_t old_eip, sp_mask;
1.1.1.6 ! root      598:     int svm_should_check = 1;
        !           599: 
        !           600:     if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
        !           601:         next_eip = EIP;
        !           602:         svm_should_check = 0;
        !           603:     }
1.1       root      604: 
1.1.1.6 ! root      605:     if (svm_should_check
        !           606:         && (INTERCEPTEDl(_exceptions, 1 << intno)
        !           607:         && !is_int)) {
        !           608:         raise_interrupt(intno, is_int, error_code, 0);
        !           609:     }
1.1       root      610:     has_error_code = 0;
                    611:     if (!is_int && !is_hw) {
                    612:         switch(intno) {
                    613:         case 8:
                    614:         case 10:
                    615:         case 11:
                    616:         case 12:
                    617:         case 13:
                    618:         case 14:
                    619:         case 17:
                    620:             has_error_code = 1;
                    621:             break;
                    622:         }
                    623:     }
                    624:     if (is_int)
                    625:         old_eip = next_eip;
                    626:     else
                    627:         old_eip = env->eip;
                    628: 
                    629:     dt = &env->idt;
                    630:     if (intno * 8 + 7 > dt->limit)
                    631:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                    632:     ptr = dt->base + intno * 8;
                    633:     e1 = ldl_kernel(ptr);
                    634:     e2 = ldl_kernel(ptr + 4);
                    635:     /* check gate type */
                    636:     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
                    637:     switch(type) {
                    638:     case 5: /* task gate */
                    639:         /* must do that check here to return the correct error code */
                    640:         if (!(e2 & DESC_P_MASK))
                    641:             raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
                    642:         switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
                    643:         if (has_error_code) {
1.1.1.5   root      644:             int type;
                    645:             uint32_t mask;
1.1       root      646:             /* push the error code */
                    647:             type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
                    648:             shift = type >> 3;
                    649:             if (env->segs[R_SS].flags & DESC_B_MASK)
                    650:                 mask = 0xffffffff;
                    651:             else
                    652:                 mask = 0xffff;
                    653:             esp = (ESP - (2 << shift)) & mask;
                    654:             ssp = env->segs[R_SS].base + esp;
                    655:             if (shift)
                    656:                 stl_kernel(ssp, error_code);
                    657:             else
                    658:                 stw_kernel(ssp, error_code);
1.1.1.5   root      659:             SET_ESP(esp, mask);
1.1       root      660:         }
                    661:         return;
                    662:     case 6: /* 286 interrupt gate */
                    663:     case 7: /* 286 trap gate */
                    664:     case 14: /* 386 interrupt gate */
                    665:     case 15: /* 386 trap gate */
                    666:         break;
                    667:     default:
                    668:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                    669:         break;
                    670:     }
                    671:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    672:     cpl = env->hflags & HF_CPL_MASK;
                    673:     /* check privledge if software int */
                    674:     if (is_int && dpl < cpl)
                    675:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                    676:     /* check valid bit */
                    677:     if (!(e2 & DESC_P_MASK))
                    678:         raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
                    679:     selector = e1 >> 16;
                    680:     offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
                    681:     if ((selector & 0xfffc) == 0)
                    682:         raise_exception_err(EXCP0D_GPF, 0);
                    683: 
                    684:     if (load_segment(&e1, &e2, selector) != 0)
                    685:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    686:     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
                    687:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    688:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    689:     if (dpl > cpl)
                    690:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    691:     if (!(e2 & DESC_P_MASK))
                    692:         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                    693:     if (!(e2 & DESC_C_MASK) && dpl < cpl) {
1.1.1.6 ! root      694:         /* to inner privilege */
1.1       root      695:         get_ss_esp_from_tss(&ss, &esp, dpl);
                    696:         if ((ss & 0xfffc) == 0)
                    697:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    698:         if ((ss & 3) != dpl)
                    699:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    700:         if (load_segment(&ss_e1, &ss_e2, ss) != 0)
                    701:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    702:         ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
                    703:         if (ss_dpl != dpl)
                    704:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    705:         if (!(ss_e2 & DESC_S_MASK) ||
                    706:             (ss_e2 & DESC_CS_MASK) ||
                    707:             !(ss_e2 & DESC_W_MASK))
                    708:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    709:         if (!(ss_e2 & DESC_P_MASK))
                    710:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    711:         new_stack = 1;
                    712:         sp_mask = get_sp_mask(ss_e2);
                    713:         ssp = get_seg_base(ss_e1, ss_e2);
                    714:     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
1.1.1.6 ! root      715:         /* to same privilege */
1.1       root      716:         if (env->eflags & VM_MASK)
                    717:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    718:         new_stack = 0;
                    719:         sp_mask = get_sp_mask(env->segs[R_SS].flags);
                    720:         ssp = env->segs[R_SS].base;
                    721:         esp = ESP;
                    722:         dpl = cpl;
                    723:     } else {
                    724:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    725:         new_stack = 0; /* avoid warning */
                    726:         sp_mask = 0; /* avoid warning */
                    727:         ssp = 0; /* avoid warning */
                    728:         esp = 0; /* avoid warning */
                    729:     }
                    730: 
                    731:     shift = type >> 3;
                    732: 
                    733: #if 0
                    734:     /* XXX: check that enough room is available */
                    735:     push_size = 6 + (new_stack << 2) + (has_error_code << 1);
                    736:     if (env->eflags & VM_MASK)
                    737:         push_size += 8;
                    738:     push_size <<= shift;
                    739: #endif
                    740:     if (shift == 1) {
                    741:         if (new_stack) {
                    742:             if (env->eflags & VM_MASK) {
                    743:                 PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
                    744:                 PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
                    745:                 PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
                    746:                 PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
                    747:             }
                    748:             PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
                    749:             PUSHL(ssp, esp, sp_mask, ESP);
                    750:         }
                    751:         PUSHL(ssp, esp, sp_mask, compute_eflags());
                    752:         PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
                    753:         PUSHL(ssp, esp, sp_mask, old_eip);
                    754:         if (has_error_code) {
                    755:             PUSHL(ssp, esp, sp_mask, error_code);
                    756:         }
                    757:     } else {
                    758:         if (new_stack) {
                    759:             if (env->eflags & VM_MASK) {
                    760:                 PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
                    761:                 PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
                    762:                 PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
                    763:                 PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
                    764:             }
                    765:             PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
                    766:             PUSHW(ssp, esp, sp_mask, ESP);
                    767:         }
                    768:         PUSHW(ssp, esp, sp_mask, compute_eflags());
                    769:         PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
                    770:         PUSHW(ssp, esp, sp_mask, old_eip);
                    771:         if (has_error_code) {
                    772:             PUSHW(ssp, esp, sp_mask, error_code);
                    773:         }
                    774:     }
1.1.1.6 ! root      775: 
1.1       root      776:     if (new_stack) {
                    777:         if (env->eflags & VM_MASK) {
                    778:             cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
                    779:             cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
                    780:             cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
                    781:             cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
                    782:         }
                    783:         ss = (ss & ~3) | dpl;
1.1.1.6 ! root      784:         cpu_x86_load_seg_cache(env, R_SS, ss,
1.1       root      785:                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
                    786:     }
1.1.1.5   root      787:     SET_ESP(esp, sp_mask);
1.1       root      788: 
                    789:     selector = (selector & ~3) | dpl;
1.1.1.6 ! root      790:     cpu_x86_load_seg_cache(env, R_CS, selector,
1.1       root      791:                    get_seg_base(e1, e2),
                    792:                    get_seg_limit(e1, e2),
                    793:                    e2);
                    794:     cpu_x86_set_cpl(env, dpl);
                    795:     env->eip = offset;
                    796: 
                    797:     /* interrupt gate clear IF mask */
                    798:     if ((type & 1) == 0) {
                    799:         env->eflags &= ~IF_MASK;
                    800:     }
                    801:     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
                    802: }
                    803: 
                    804: #ifdef TARGET_X86_64
                    805: 
                    806: #define PUSHQ(sp, val)\
                    807: {\
                    808:     sp -= 8;\
                    809:     stq_kernel(sp, (val));\
                    810: }
                    811: 
                    812: #define POPQ(sp, val)\
                    813: {\
                    814:     val = ldq_kernel(sp);\
                    815:     sp += 8;\
                    816: }
                    817: 
                    818: static inline target_ulong get_rsp_from_tss(int level)
                    819: {
                    820:     int index;
1.1.1.6 ! root      821: 
1.1       root      822: #if 0
1.1.1.6 ! root      823:     printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
1.1       root      824:            env->tr.base, env->tr.limit);
                    825: #endif
                    826: 
                    827:     if (!(env->tr.flags & DESC_P_MASK))
                    828:         cpu_abort(env, "invalid tss");
                    829:     index = 8 * level + 4;
                    830:     if ((index + 7) > env->tr.limit)
                    831:         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
                    832:     return ldq_kernel(env->tr.base + index);
                    833: }
                    834: 
                    835: /* 64 bit interrupt */
                    836: static void do_interrupt64(int intno, int is_int, int error_code,
                    837:                            target_ulong next_eip, int is_hw)
                    838: {
                    839:     SegmentCache *dt;
                    840:     target_ulong ptr;
                    841:     int type, dpl, selector, cpl, ist;
                    842:     int has_error_code, new_stack;
                    843:     uint32_t e1, e2, e3, ss;
                    844:     target_ulong old_eip, esp, offset;
1.1.1.6 ! root      845:     int svm_should_check = 1;
1.1       root      846: 
1.1.1.6 ! root      847:     if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
        !           848:         next_eip = EIP;
        !           849:         svm_should_check = 0;
        !           850:     }
        !           851:     if (svm_should_check
        !           852:         && INTERCEPTEDl(_exceptions, 1 << intno)
        !           853:         && !is_int) {
        !           854:         raise_interrupt(intno, is_int, error_code, 0);
        !           855:     }
1.1       root      856:     has_error_code = 0;
                    857:     if (!is_int && !is_hw) {
                    858:         switch(intno) {
                    859:         case 8:
                    860:         case 10:
                    861:         case 11:
                    862:         case 12:
                    863:         case 13:
                    864:         case 14:
                    865:         case 17:
                    866:             has_error_code = 1;
                    867:             break;
                    868:         }
                    869:     }
                    870:     if (is_int)
                    871:         old_eip = next_eip;
                    872:     else
                    873:         old_eip = env->eip;
                    874: 
                    875:     dt = &env->idt;
                    876:     if (intno * 16 + 15 > dt->limit)
                    877:         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
                    878:     ptr = dt->base + intno * 16;
                    879:     e1 = ldl_kernel(ptr);
                    880:     e2 = ldl_kernel(ptr + 4);
                    881:     e3 = ldl_kernel(ptr + 8);
                    882:     /* check gate type */
                    883:     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
                    884:     switch(type) {
                    885:     case 14: /* 386 interrupt gate */
                    886:     case 15: /* 386 trap gate */
                    887:         break;
                    888:     default:
                    889:         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
                    890:         break;
                    891:     }
                    892:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    893:     cpl = env->hflags & HF_CPL_MASK;
                    894:     /* check privledge if software int */
                    895:     if (is_int && dpl < cpl)
                    896:         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
                    897:     /* check valid bit */
                    898:     if (!(e2 & DESC_P_MASK))
                    899:         raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
                    900:     selector = e1 >> 16;
                    901:     offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
                    902:     ist = e2 & 7;
                    903:     if ((selector & 0xfffc) == 0)
                    904:         raise_exception_err(EXCP0D_GPF, 0);
                    905: 
                    906:     if (load_segment(&e1, &e2, selector) != 0)
                    907:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    908:     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
                    909:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    910:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    911:     if (dpl > cpl)
                    912:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    913:     if (!(e2 & DESC_P_MASK))
                    914:         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                    915:     if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
                    916:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    917:     if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
1.1.1.6 ! root      918:         /* to inner privilege */
1.1       root      919:         if (ist != 0)
                    920:             esp = get_rsp_from_tss(ist + 3);
                    921:         else
                    922:             esp = get_rsp_from_tss(dpl);
1.1.1.3   root      923:         esp &= ~0xfLL; /* align stack */
1.1       root      924:         ss = 0;
                    925:         new_stack = 1;
                    926:     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
1.1.1.6 ! root      927:         /* to same privilege */
1.1       root      928:         if (env->eflags & VM_MASK)
                    929:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    930:         new_stack = 0;
1.1.1.3   root      931:         if (ist != 0)
                    932:             esp = get_rsp_from_tss(ist + 3);
                    933:         else
                    934:             esp = ESP;
                    935:         esp &= ~0xfLL; /* align stack */
1.1       root      936:         dpl = cpl;
                    937:     } else {
                    938:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    939:         new_stack = 0; /* avoid warning */
                    940:         esp = 0; /* avoid warning */
                    941:     }
                    942: 
                    943:     PUSHQ(esp, env->segs[R_SS].selector);
                    944:     PUSHQ(esp, ESP);
                    945:     PUSHQ(esp, compute_eflags());
                    946:     PUSHQ(esp, env->segs[R_CS].selector);
                    947:     PUSHQ(esp, old_eip);
                    948:     if (has_error_code) {
                    949:         PUSHQ(esp, error_code);
                    950:     }
1.1.1.6 ! root      951: 
1.1       root      952:     if (new_stack) {
                    953:         ss = 0 | dpl;
                    954:         cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
                    955:     }
                    956:     ESP = esp;
                    957: 
                    958:     selector = (selector & ~3) | dpl;
1.1.1.6 ! root      959:     cpu_x86_load_seg_cache(env, R_CS, selector,
1.1       root      960:                    get_seg_base(e1, e2),
                    961:                    get_seg_limit(e1, e2),
                    962:                    e2);
                    963:     cpu_x86_set_cpl(env, dpl);
                    964:     env->eip = offset;
                    965: 
                    966:     /* interrupt gate clear IF mask */
                    967:     if ((type & 1) == 0) {
                    968:         env->eflags &= ~IF_MASK;
                    969:     }
                    970:     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
                    971: }
                    972: #endif
                    973: 
1.1.1.6 ! root      974: #if defined(CONFIG_USER_ONLY)
        !           975: void helper_syscall(int next_eip_addend)
        !           976: {
        !           977:     env->exception_index = EXCP_SYSCALL;
        !           978:     env->exception_next_eip = env->eip + next_eip_addend;
        !           979:     cpu_loop_exit();
        !           980: }
        !           981: #else
1.1       root      982: void helper_syscall(int next_eip_addend)
                    983: {
                    984:     int selector;
                    985: 
                    986:     if (!(env->efer & MSR_EFER_SCE)) {
                    987:         raise_exception_err(EXCP06_ILLOP, 0);
                    988:     }
                    989:     selector = (env->star >> 32) & 0xffff;
                    990: #ifdef TARGET_X86_64
                    991:     if (env->hflags & HF_LMA_MASK) {
1.1.1.3   root      992:         int code64;
                    993: 
1.1       root      994:         ECX = env->eip + next_eip_addend;
                    995:         env->regs[11] = compute_eflags();
1.1.1.6 ! root      996: 
1.1.1.3   root      997:         code64 = env->hflags & HF_CS64_MASK;
1.1       root      998: 
                    999:         cpu_x86_set_cpl(env, 0);
1.1.1.6 ! root     1000:         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
        !          1001:                            0, 0xffffffff,
1.1.1.5   root     1002:                                DESC_G_MASK | DESC_P_MASK |
1.1       root     1003:                                DESC_S_MASK |
                   1004:                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1.1.1.6 ! root     1005:         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1.1       root     1006:                                0, 0xffffffff,
                   1007:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1008:                                DESC_S_MASK |
                   1009:                                DESC_W_MASK | DESC_A_MASK);
                   1010:         env->eflags &= ~env->fmask;
1.1.1.3   root     1011:         if (code64)
1.1       root     1012:             env->eip = env->lstar;
                   1013:         else
                   1014:             env->eip = env->cstar;
1.1.1.6 ! root     1015:     } else
1.1       root     1016: #endif
                   1017:     {
                   1018:         ECX = (uint32_t)(env->eip + next_eip_addend);
1.1.1.6 ! root     1019: 
1.1       root     1020:         cpu_x86_set_cpl(env, 0);
1.1.1.6 ! root     1021:         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
        !          1022:                            0, 0xffffffff,
1.1       root     1023:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1024:                                DESC_S_MASK |
                   1025:                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1.1.1.6 ! root     1026:         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1.1       root     1027:                                0, 0xffffffff,
                   1028:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1029:                                DESC_S_MASK |
                   1030:                                DESC_W_MASK | DESC_A_MASK);
                   1031:         env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
                   1032:         env->eip = (uint32_t)env->star;
                   1033:     }
                   1034: }
1.1.1.6 ! root     1035: #endif
1.1       root     1036: 
                   1037: void helper_sysret(int dflag)
                   1038: {
                   1039:     int cpl, selector;
                   1040: 
                   1041:     if (!(env->efer & MSR_EFER_SCE)) {
                   1042:         raise_exception_err(EXCP06_ILLOP, 0);
                   1043:     }
                   1044:     cpl = env->hflags & HF_CPL_MASK;
                   1045:     if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
                   1046:         raise_exception_err(EXCP0D_GPF, 0);
                   1047:     }
                   1048:     selector = (env->star >> 48) & 0xffff;
                   1049: #ifdef TARGET_X86_64
                   1050:     if (env->hflags & HF_LMA_MASK) {
                   1051:         if (dflag == 2) {
1.1.1.6 ! root     1052:             cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
        !          1053:                                    0, 0xffffffff,
1.1.1.5   root     1054:                                    DESC_G_MASK | DESC_P_MASK |
1.1       root     1055:                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1.1.1.6 ! root     1056:                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1.1       root     1057:                                    DESC_L_MASK);
                   1058:             env->eip = ECX;
                   1059:         } else {
1.1.1.6 ! root     1060:             cpu_x86_load_seg_cache(env, R_CS, selector | 3,
        !          1061:                                    0, 0xffffffff,
1.1       root     1062:                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1063:                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1064:                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   1065:             env->eip = (uint32_t)ECX;
                   1066:         }
1.1.1.6 ! root     1067:         cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1.1       root     1068:                                0, 0xffffffff,
                   1069:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1070:                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1071:                                DESC_W_MASK | DESC_A_MASK);
1.1.1.6 ! root     1072:         load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |
1.1       root     1073:                     IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
                   1074:         cpu_x86_set_cpl(env, 3);
1.1.1.6 ! root     1075:     } else
1.1       root     1076: #endif
                   1077:     {
1.1.1.6 ! root     1078:         cpu_x86_load_seg_cache(env, R_CS, selector | 3,
        !          1079:                                0, 0xffffffff,
1.1       root     1080:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1081:                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1082:                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   1083:         env->eip = (uint32_t)ECX;
1.1.1.6 ! root     1084:         cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1.1       root     1085:                                0, 0xffffffff,
                   1086:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1087:                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1088:                                DESC_W_MASK | DESC_A_MASK);
                   1089:         env->eflags |= IF_MASK;
                   1090:         cpu_x86_set_cpl(env, 3);
                   1091:     }
                   1092: #ifdef USE_KQEMU
                   1093:     if (kqemu_is_ok(env)) {
                   1094:         if (env->hflags & HF_LMA_MASK)
                   1095:             CC_OP = CC_OP_EFLAGS;
                   1096:         env->exception_index = -1;
                   1097:         cpu_loop_exit();
                   1098:     }
                   1099: #endif
                   1100: }
                   1101: 
                   1102: /* real mode interrupt */
                   1103: static void do_interrupt_real(int intno, int is_int, int error_code,
                   1104:                               unsigned int next_eip)
                   1105: {
                   1106:     SegmentCache *dt;
                   1107:     target_ulong ptr, ssp;
                   1108:     int selector;
                   1109:     uint32_t offset, esp;
                   1110:     uint32_t old_cs, old_eip;
1.1.1.6 ! root     1111:     int svm_should_check = 1;
1.1       root     1112: 
1.1.1.6 ! root     1113:     if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
        !          1114:         next_eip = EIP;
        !          1115:         svm_should_check = 0;
        !          1116:     }
        !          1117:     if (svm_should_check
        !          1118:         && INTERCEPTEDl(_exceptions, 1 << intno)
        !          1119:         && !is_int) {
        !          1120:         raise_interrupt(intno, is_int, error_code, 0);
        !          1121:     }
1.1       root     1122:     /* real mode (simpler !) */
                   1123:     dt = &env->idt;
                   1124:     if (intno * 4 + 3 > dt->limit)
                   1125:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                   1126:     ptr = dt->base + intno * 4;
                   1127:     offset = lduw_kernel(ptr);
                   1128:     selector = lduw_kernel(ptr + 2);
                   1129:     esp = ESP;
                   1130:     ssp = env->segs[R_SS].base;
                   1131:     if (is_int)
                   1132:         old_eip = next_eip;
                   1133:     else
                   1134:         old_eip = env->eip;
                   1135:     old_cs = env->segs[R_CS].selector;
                   1136:     /* XXX: use SS segment size ? */
                   1137:     PUSHW(ssp, esp, 0xffff, compute_eflags());
                   1138:     PUSHW(ssp, esp, 0xffff, old_cs);
                   1139:     PUSHW(ssp, esp, 0xffff, old_eip);
1.1.1.6 ! root     1140: 
1.1       root     1141:     /* update processor state */
                   1142:     ESP = (ESP & ~0xffff) | (esp & 0xffff);
                   1143:     env->eip = offset;
                   1144:     env->segs[R_CS].selector = selector;
                   1145:     env->segs[R_CS].base = (selector << 4);
                   1146:     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
                   1147: }
                   1148: 
                   1149: /* fake user mode interrupt */
1.1.1.6 ! root     1150: void do_interrupt_user(int intno, int is_int, int error_code,
1.1       root     1151:                        target_ulong next_eip)
                   1152: {
                   1153:     SegmentCache *dt;
                   1154:     target_ulong ptr;
1.1.1.6 ! root     1155:     int dpl, cpl, shift;
1.1       root     1156:     uint32_t e2;
                   1157: 
                   1158:     dt = &env->idt;
1.1.1.6 ! root     1159:     if (env->hflags & HF_LMA_MASK) {
        !          1160:         shift = 4;
        !          1161:     } else {
        !          1162:         shift = 3;
        !          1163:     }
        !          1164:     ptr = dt->base + (intno << shift);
1.1       root     1165:     e2 = ldl_kernel(ptr + 4);
1.1.1.6 ! root     1166: 
1.1       root     1167:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1168:     cpl = env->hflags & HF_CPL_MASK;
                   1169:     /* check privledge if software int */
                   1170:     if (is_int && dpl < cpl)
1.1.1.6 ! root     1171:         raise_exception_err(EXCP0D_GPF, (intno << shift) + 2);
1.1       root     1172: 
                   1173:     /* Since we emulate only user space, we cannot do more than
                   1174:        exiting the emulation with the suitable exception and error
                   1175:        code */
                   1176:     if (is_int)
                   1177:         EIP = next_eip;
                   1178: }
                   1179: 
                   1180: /*
                   1181:  * Begin execution of an interruption. is_int is TRUE if coming from
                   1182:  * the int instruction. next_eip is the EIP value AFTER the interrupt
1.1.1.6 ! root     1183:  * instruction. It is only relevant if is_int is TRUE.
1.1       root     1184:  */
1.1.1.6 ! root     1185: void do_interrupt(int intno, int is_int, int error_code,
1.1       root     1186:                   target_ulong next_eip, int is_hw)
                   1187: {
1.1.1.3   root     1188:     if (loglevel & CPU_LOG_INT) {
1.1       root     1189:         if ((env->cr[0] & CR0_PE_MASK)) {
                   1190:             static int count;
                   1191:             fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
                   1192:                     count, intno, error_code, is_int,
                   1193:                     env->hflags & HF_CPL_MASK,
                   1194:                     env->segs[R_CS].selector, EIP,
                   1195:                     (int)env->segs[R_CS].base + EIP,
                   1196:                     env->segs[R_SS].selector, ESP);
                   1197:             if (intno == 0x0e) {
                   1198:                 fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
                   1199:             } else {
                   1200:                 fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
                   1201:             }
                   1202:             fprintf(logfile, "\n");
                   1203:             cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1.1.1.3   root     1204: #if 0
1.1       root     1205:             {
                   1206:                 int i;
                   1207:                 uint8_t *ptr;
                   1208:                 fprintf(logfile, "       code=");
                   1209:                 ptr = env->segs[R_CS].base + env->eip;
                   1210:                 for(i = 0; i < 16; i++) {
                   1211:                     fprintf(logfile, " %02x", ldub(ptr + i));
                   1212:                 }
                   1213:                 fprintf(logfile, "\n");
                   1214:             }
                   1215: #endif
                   1216:             count++;
                   1217:         }
                   1218:     }
                   1219:     if (env->cr[0] & CR0_PE_MASK) {
                   1220: #if TARGET_X86_64
                   1221:         if (env->hflags & HF_LMA_MASK) {
                   1222:             do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
                   1223:         } else
                   1224: #endif
                   1225:         {
                   1226:             do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
                   1227:         }
                   1228:     } else {
                   1229:         do_interrupt_real(intno, is_int, error_code, next_eip);
                   1230:     }
                   1231: }
                   1232: 
                   1233: /*
1.1.1.6 ! root     1234:  * Check nested exceptions and change to double or triple fault if
        !          1235:  * needed. It should only be called, if this is not an interrupt.
        !          1236:  * Returns the new exception number.
        !          1237:  */
        !          1238: static int check_exception(int intno, int *error_code)
        !          1239: {
        !          1240:     char first_contributory = env->old_exception == 0 ||
        !          1241:                               (env->old_exception >= 10 &&
        !          1242:                                env->old_exception <= 13);
        !          1243:     char second_contributory = intno == 0 ||
        !          1244:                                (intno >= 10 && intno <= 13);
        !          1245: 
        !          1246:     if (loglevel & CPU_LOG_INT)
        !          1247:         fprintf(logfile, "check_exception old: %x new %x\n",
        !          1248:                 env->old_exception, intno);
        !          1249: 
        !          1250:     if (env->old_exception == EXCP08_DBLE)
        !          1251:         cpu_abort(env, "triple fault");
        !          1252: 
        !          1253:     if ((first_contributory && second_contributory)
        !          1254:         || (env->old_exception == EXCP0E_PAGE &&
        !          1255:             (second_contributory || (intno == EXCP0E_PAGE)))) {
        !          1256:         intno = EXCP08_DBLE;
        !          1257:         *error_code = 0;
        !          1258:     }
        !          1259: 
        !          1260:     if (second_contributory || (intno == EXCP0E_PAGE) ||
        !          1261:         (intno == EXCP08_DBLE))
        !          1262:         env->old_exception = intno;
        !          1263: 
        !          1264:     return intno;
        !          1265: }
        !          1266: 
        !          1267: /*
1.1       root     1268:  * Signal an interruption. It is executed in the main CPU loop.
                   1269:  * is_int is TRUE if coming from the int instruction. next_eip is the
                   1270:  * EIP value AFTER the interrupt instruction. It is only relevant if
1.1.1.6 ! root     1271:  * is_int is TRUE.
1.1       root     1272:  */
1.1.1.6 ! root     1273: void raise_interrupt(int intno, int is_int, int error_code,
1.1       root     1274:                      int next_eip_addend)
                   1275: {
1.1.1.6 ! root     1276:     if (!is_int) {
        !          1277:         svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
        !          1278:         intno = check_exception(intno, &error_code);
        !          1279:     }
        !          1280: 
1.1       root     1281:     env->exception_index = intno;
                   1282:     env->error_code = error_code;
                   1283:     env->exception_is_int = is_int;
                   1284:     env->exception_next_eip = env->eip + next_eip_addend;
                   1285:     cpu_loop_exit();
                   1286: }
                   1287: 
                   1288: /* same as raise_exception_err, but do not restore global registers */
                   1289: static void raise_exception_err_norestore(int exception_index, int error_code)
                   1290: {
1.1.1.6 ! root     1291:     exception_index = check_exception(exception_index, &error_code);
        !          1292: 
1.1       root     1293:     env->exception_index = exception_index;
                   1294:     env->error_code = error_code;
                   1295:     env->exception_is_int = 0;
                   1296:     env->exception_next_eip = 0;
                   1297:     longjmp(env->jmp_env, 1);
                   1298: }
                   1299: 
                   1300: /* shortcuts to generate exceptions */
                   1301: 
                   1302: void (raise_exception_err)(int exception_index, int error_code)
                   1303: {
                   1304:     raise_interrupt(exception_index, 0, error_code, 0);
                   1305: }
                   1306: 
                   1307: void raise_exception(int exception_index)
                   1308: {
                   1309:     raise_interrupt(exception_index, 0, 0, 0);
                   1310: }
                   1311: 
1.1.1.5   root     1312: /* SMM support */
                   1313: 
1.1.1.6 ! root     1314: #if defined(CONFIG_USER_ONLY)
1.1.1.5   root     1315: 
                   1316: void do_smm_enter(void)
                   1317: {
                   1318: }
                   1319: 
                   1320: void helper_rsm(void)
                   1321: {
                   1322: }
                   1323: 
                   1324: #else
                   1325: 
                   1326: #ifdef TARGET_X86_64
                   1327: #define SMM_REVISION_ID 0x00020064
                   1328: #else
                   1329: #define SMM_REVISION_ID 0x00020000
                   1330: #endif
                   1331: 
                   1332: void do_smm_enter(void)
                   1333: {
                   1334:     target_ulong sm_state;
                   1335:     SegmentCache *dt;
                   1336:     int i, offset;
                   1337: 
                   1338:     if (loglevel & CPU_LOG_INT) {
                   1339:         fprintf(logfile, "SMM: enter\n");
                   1340:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                   1341:     }
                   1342: 
                   1343:     env->hflags |= HF_SMM_MASK;
                   1344:     cpu_smm_update(env);
                   1345: 
                   1346:     sm_state = env->smbase + 0x8000;
1.1.1.6 ! root     1347: 
1.1.1.5   root     1348: #ifdef TARGET_X86_64
                   1349:     for(i = 0; i < 6; i++) {
                   1350:         dt = &env->segs[i];
                   1351:         offset = 0x7e00 + i * 16;
                   1352:         stw_phys(sm_state + offset, dt->selector);
                   1353:         stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
                   1354:         stl_phys(sm_state + offset + 4, dt->limit);
                   1355:         stq_phys(sm_state + offset + 8, dt->base);
                   1356:     }
                   1357: 
                   1358:     stq_phys(sm_state + 0x7e68, env->gdt.base);
                   1359:     stl_phys(sm_state + 0x7e64, env->gdt.limit);
                   1360: 
                   1361:     stw_phys(sm_state + 0x7e70, env->ldt.selector);
                   1362:     stq_phys(sm_state + 0x7e78, env->ldt.base);
                   1363:     stl_phys(sm_state + 0x7e74, env->ldt.limit);
                   1364:     stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1.1.1.6 ! root     1365: 
1.1.1.5   root     1366:     stq_phys(sm_state + 0x7e88, env->idt.base);
                   1367:     stl_phys(sm_state + 0x7e84, env->idt.limit);
                   1368: 
                   1369:     stw_phys(sm_state + 0x7e90, env->tr.selector);
                   1370:     stq_phys(sm_state + 0x7e98, env->tr.base);
                   1371:     stl_phys(sm_state + 0x7e94, env->tr.limit);
                   1372:     stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1.1.1.6 ! root     1373: 
1.1.1.5   root     1374:     stq_phys(sm_state + 0x7ed0, env->efer);
                   1375: 
                   1376:     stq_phys(sm_state + 0x7ff8, EAX);
                   1377:     stq_phys(sm_state + 0x7ff0, ECX);
                   1378:     stq_phys(sm_state + 0x7fe8, EDX);
                   1379:     stq_phys(sm_state + 0x7fe0, EBX);
                   1380:     stq_phys(sm_state + 0x7fd8, ESP);
                   1381:     stq_phys(sm_state + 0x7fd0, EBP);
                   1382:     stq_phys(sm_state + 0x7fc8, ESI);
                   1383:     stq_phys(sm_state + 0x7fc0, EDI);
1.1.1.6 ! root     1384:     for(i = 8; i < 16; i++)
1.1.1.5   root     1385:         stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
                   1386:     stq_phys(sm_state + 0x7f78, env->eip);
                   1387:     stl_phys(sm_state + 0x7f70, compute_eflags());
                   1388:     stl_phys(sm_state + 0x7f68, env->dr[6]);
                   1389:     stl_phys(sm_state + 0x7f60, env->dr[7]);
                   1390: 
                   1391:     stl_phys(sm_state + 0x7f48, env->cr[4]);
                   1392:     stl_phys(sm_state + 0x7f50, env->cr[3]);
                   1393:     stl_phys(sm_state + 0x7f58, env->cr[0]);
                   1394: 
                   1395:     stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
                   1396:     stl_phys(sm_state + 0x7f00, env->smbase);
                   1397: #else
                   1398:     stl_phys(sm_state + 0x7ffc, env->cr[0]);
                   1399:     stl_phys(sm_state + 0x7ff8, env->cr[3]);
                   1400:     stl_phys(sm_state + 0x7ff4, compute_eflags());
                   1401:     stl_phys(sm_state + 0x7ff0, env->eip);
                   1402:     stl_phys(sm_state + 0x7fec, EDI);
                   1403:     stl_phys(sm_state + 0x7fe8, ESI);
                   1404:     stl_phys(sm_state + 0x7fe4, EBP);
                   1405:     stl_phys(sm_state + 0x7fe0, ESP);
                   1406:     stl_phys(sm_state + 0x7fdc, EBX);
                   1407:     stl_phys(sm_state + 0x7fd8, EDX);
                   1408:     stl_phys(sm_state + 0x7fd4, ECX);
                   1409:     stl_phys(sm_state + 0x7fd0, EAX);
                   1410:     stl_phys(sm_state + 0x7fcc, env->dr[6]);
                   1411:     stl_phys(sm_state + 0x7fc8, env->dr[7]);
1.1.1.6 ! root     1412: 
1.1.1.5   root     1413:     stl_phys(sm_state + 0x7fc4, env->tr.selector);
                   1414:     stl_phys(sm_state + 0x7f64, env->tr.base);
                   1415:     stl_phys(sm_state + 0x7f60, env->tr.limit);
                   1416:     stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1.1.1.6 ! root     1417: 
1.1.1.5   root     1418:     stl_phys(sm_state + 0x7fc0, env->ldt.selector);
                   1419:     stl_phys(sm_state + 0x7f80, env->ldt.base);
                   1420:     stl_phys(sm_state + 0x7f7c, env->ldt.limit);
                   1421:     stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1.1.1.6 ! root     1422: 
1.1.1.5   root     1423:     stl_phys(sm_state + 0x7f74, env->gdt.base);
                   1424:     stl_phys(sm_state + 0x7f70, env->gdt.limit);
                   1425: 
                   1426:     stl_phys(sm_state + 0x7f58, env->idt.base);
                   1427:     stl_phys(sm_state + 0x7f54, env->idt.limit);
                   1428: 
                   1429:     for(i = 0; i < 6; i++) {
                   1430:         dt = &env->segs[i];
                   1431:         if (i < 3)
                   1432:             offset = 0x7f84 + i * 12;
                   1433:         else
                   1434:             offset = 0x7f2c + (i - 3) * 12;
                   1435:         stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
                   1436:         stl_phys(sm_state + offset + 8, dt->base);
                   1437:         stl_phys(sm_state + offset + 4, dt->limit);
                   1438:         stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
                   1439:     }
                   1440:     stl_phys(sm_state + 0x7f14, env->cr[4]);
                   1441: 
                   1442:     stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
                   1443:     stl_phys(sm_state + 0x7ef8, env->smbase);
                   1444: #endif
                   1445:     /* init SMM cpu state */
                   1446: 
                   1447: #ifdef TARGET_X86_64
                   1448:     env->efer = 0;
                   1449:     env->hflags &= ~HF_LMA_MASK;
                   1450: #endif
                   1451:     load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
                   1452:     env->eip = 0x00008000;
                   1453:     cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
                   1454:                            0xffffffff, 0);
                   1455:     cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
                   1456:     cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
                   1457:     cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
                   1458:     cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
                   1459:     cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1.1.1.6 ! root     1460: 
        !          1461:     cpu_x86_update_cr0(env,
1.1.1.5   root     1462:                        env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
                   1463:     cpu_x86_update_cr4(env, 0);
                   1464:     env->dr[7] = 0x00000400;
                   1465:     CC_OP = CC_OP_EFLAGS;
                   1466: }
                   1467: 
                   1468: void helper_rsm(void)
                   1469: {
                   1470:     target_ulong sm_state;
                   1471:     int i, offset;
                   1472:     uint32_t val;
                   1473: 
                   1474:     sm_state = env->smbase + 0x8000;
                   1475: #ifdef TARGET_X86_64
                   1476:     env->efer = ldq_phys(sm_state + 0x7ed0);
                   1477:     if (env->efer & MSR_EFER_LMA)
                   1478:         env->hflags |= HF_LMA_MASK;
                   1479:     else
                   1480:         env->hflags &= ~HF_LMA_MASK;
                   1481: 
                   1482:     for(i = 0; i < 6; i++) {
                   1483:         offset = 0x7e00 + i * 16;
1.1.1.6 ! root     1484:         cpu_x86_load_seg_cache(env, i,
1.1.1.5   root     1485:                                lduw_phys(sm_state + offset),
                   1486:                                ldq_phys(sm_state + offset + 8),
                   1487:                                ldl_phys(sm_state + offset + 4),
                   1488:                                (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
                   1489:     }
                   1490: 
                   1491:     env->gdt.base = ldq_phys(sm_state + 0x7e68);
                   1492:     env->gdt.limit = ldl_phys(sm_state + 0x7e64);
                   1493: 
                   1494:     env->ldt.selector = lduw_phys(sm_state + 0x7e70);
                   1495:     env->ldt.base = ldq_phys(sm_state + 0x7e78);
                   1496:     env->ldt.limit = ldl_phys(sm_state + 0x7e74);
                   1497:     env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1.1.1.6 ! root     1498: 
1.1.1.5   root     1499:     env->idt.base = ldq_phys(sm_state + 0x7e88);
                   1500:     env->idt.limit = ldl_phys(sm_state + 0x7e84);
                   1501: 
                   1502:     env->tr.selector = lduw_phys(sm_state + 0x7e90);
                   1503:     env->tr.base = ldq_phys(sm_state + 0x7e98);
                   1504:     env->tr.limit = ldl_phys(sm_state + 0x7e94);
                   1505:     env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1.1.1.6 ! root     1506: 
1.1.1.5   root     1507:     EAX = ldq_phys(sm_state + 0x7ff8);
                   1508:     ECX = ldq_phys(sm_state + 0x7ff0);
                   1509:     EDX = ldq_phys(sm_state + 0x7fe8);
                   1510:     EBX = ldq_phys(sm_state + 0x7fe0);
                   1511:     ESP = ldq_phys(sm_state + 0x7fd8);
                   1512:     EBP = ldq_phys(sm_state + 0x7fd0);
                   1513:     ESI = ldq_phys(sm_state + 0x7fc8);
                   1514:     EDI = ldq_phys(sm_state + 0x7fc0);
1.1.1.6 ! root     1515:     for(i = 8; i < 16; i++)
1.1.1.5   root     1516:         env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
                   1517:     env->eip = ldq_phys(sm_state + 0x7f78);
1.1.1.6 ! root     1518:     load_eflags(ldl_phys(sm_state + 0x7f70),
1.1.1.5   root     1519:                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
                   1520:     env->dr[6] = ldl_phys(sm_state + 0x7f68);
                   1521:     env->dr[7] = ldl_phys(sm_state + 0x7f60);
                   1522: 
                   1523:     cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
                   1524:     cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
                   1525:     cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
                   1526: 
                   1527:     val = ldl_phys(sm_state + 0x7efc); /* revision ID */
                   1528:     if (val & 0x20000) {
                   1529:         env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
                   1530:     }
                   1531: #else
                   1532:     cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
                   1533:     cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1.1.1.6 ! root     1534:     load_eflags(ldl_phys(sm_state + 0x7ff4),
1.1.1.5   root     1535:                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
                   1536:     env->eip = ldl_phys(sm_state + 0x7ff0);
                   1537:     EDI = ldl_phys(sm_state + 0x7fec);
                   1538:     ESI = ldl_phys(sm_state + 0x7fe8);
                   1539:     EBP = ldl_phys(sm_state + 0x7fe4);
                   1540:     ESP = ldl_phys(sm_state + 0x7fe0);
                   1541:     EBX = ldl_phys(sm_state + 0x7fdc);
                   1542:     EDX = ldl_phys(sm_state + 0x7fd8);
                   1543:     ECX = ldl_phys(sm_state + 0x7fd4);
                   1544:     EAX = ldl_phys(sm_state + 0x7fd0);
                   1545:     env->dr[6] = ldl_phys(sm_state + 0x7fcc);
                   1546:     env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1.1.1.6 ! root     1547: 
1.1.1.5   root     1548:     env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
                   1549:     env->tr.base = ldl_phys(sm_state + 0x7f64);
                   1550:     env->tr.limit = ldl_phys(sm_state + 0x7f60);
                   1551:     env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1.1.1.6 ! root     1552: 
1.1.1.5   root     1553:     env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
                   1554:     env->ldt.base = ldl_phys(sm_state + 0x7f80);
                   1555:     env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
                   1556:     env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1.1.1.6 ! root     1557: 
1.1.1.5   root     1558:     env->gdt.base = ldl_phys(sm_state + 0x7f74);
                   1559:     env->gdt.limit = ldl_phys(sm_state + 0x7f70);
                   1560: 
                   1561:     env->idt.base = ldl_phys(sm_state + 0x7f58);
                   1562:     env->idt.limit = ldl_phys(sm_state + 0x7f54);
                   1563: 
                   1564:     for(i = 0; i < 6; i++) {
                   1565:         if (i < 3)
                   1566:             offset = 0x7f84 + i * 12;
                   1567:         else
                   1568:             offset = 0x7f2c + (i - 3) * 12;
1.1.1.6 ! root     1569:         cpu_x86_load_seg_cache(env, i,
1.1.1.5   root     1570:                                ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
                   1571:                                ldl_phys(sm_state + offset + 8),
                   1572:                                ldl_phys(sm_state + offset + 4),
                   1573:                                (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
                   1574:     }
                   1575:     cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
                   1576: 
                   1577:     val = ldl_phys(sm_state + 0x7efc); /* revision ID */
                   1578:     if (val & 0x20000) {
                   1579:         env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
                   1580:     }
                   1581: #endif
                   1582:     CC_OP = CC_OP_EFLAGS;
                   1583:     env->hflags &= ~HF_SMM_MASK;
                   1584:     cpu_smm_update(env);
                   1585: 
                   1586:     if (loglevel & CPU_LOG_INT) {
                   1587:         fprintf(logfile, "SMM: after RSM\n");
                   1588:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                   1589:     }
                   1590: }
                   1591: 
                   1592: #endif /* !CONFIG_USER_ONLY */
                   1593: 
                   1594: 
1.1       root     1595: #ifdef BUGGY_GCC_DIV64
                   1596: /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
                   1597:    call it from another function */
                   1598: uint32_t div32(uint64_t *q_ptr, uint64_t num, uint32_t den)
                   1599: {
                   1600:     *q_ptr = num / den;
                   1601:     return num % den;
                   1602: }
                   1603: 
                   1604: int32_t idiv32(int64_t *q_ptr, int64_t num, int32_t den)
                   1605: {
                   1606:     *q_ptr = num / den;
                   1607:     return num % den;
                   1608: }
                   1609: #endif
                   1610: 
                   1611: void helper_divl_EAX_T0(void)
                   1612: {
                   1613:     unsigned int den, r;
                   1614:     uint64_t num, q;
1.1.1.6 ! root     1615: 
1.1       root     1616:     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
                   1617:     den = T0;
                   1618:     if (den == 0) {
                   1619:         raise_exception(EXCP00_DIVZ);
                   1620:     }
                   1621: #ifdef BUGGY_GCC_DIV64
                   1622:     r = div32(&q, num, den);
                   1623: #else
                   1624:     q = (num / den);
                   1625:     r = (num % den);
                   1626: #endif
                   1627:     if (q > 0xffffffff)
                   1628:         raise_exception(EXCP00_DIVZ);
                   1629:     EAX = (uint32_t)q;
                   1630:     EDX = (uint32_t)r;
                   1631: }
                   1632: 
                   1633: void helper_idivl_EAX_T0(void)
                   1634: {
                   1635:     int den, r;
                   1636:     int64_t num, q;
1.1.1.6 ! root     1637: 
1.1       root     1638:     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
                   1639:     den = T0;
                   1640:     if (den == 0) {
                   1641:         raise_exception(EXCP00_DIVZ);
                   1642:     }
                   1643: #ifdef BUGGY_GCC_DIV64
                   1644:     r = idiv32(&q, num, den);
                   1645: #else
                   1646:     q = (num / den);
                   1647:     r = (num % den);
                   1648: #endif
                   1649:     if (q != (int32_t)q)
                   1650:         raise_exception(EXCP00_DIVZ);
                   1651:     EAX = (uint32_t)q;
                   1652:     EDX = (uint32_t)r;
                   1653: }
                   1654: 
                   1655: void helper_cmpxchg8b(void)
                   1656: {
                   1657:     uint64_t d;
                   1658:     int eflags;
                   1659: 
                   1660:     eflags = cc_table[CC_OP].compute_all();
                   1661:     d = ldq(A0);
                   1662:     if (d == (((uint64_t)EDX << 32) | EAX)) {
                   1663:         stq(A0, ((uint64_t)ECX << 32) | EBX);
                   1664:         eflags |= CC_Z;
                   1665:     } else {
                   1666:         EDX = d >> 32;
                   1667:         EAX = d;
                   1668:         eflags &= ~CC_Z;
                   1669:     }
                   1670:     CC_SRC = eflags;
                   1671: }
                   1672: 
1.1.1.6 ! root     1673: void helper_single_step()
        !          1674: {
        !          1675:     env->dr[6] |= 0x4000;
        !          1676:     raise_exception(EXCP01_SSTP);
        !          1677: }
        !          1678: 
1.1       root     1679: void helper_cpuid(void)
                   1680: {
                   1681:     uint32_t index;
                   1682:     index = (uint32_t)EAX;
1.1.1.6 ! root     1683: 
1.1       root     1684:     /* test if maximum index reached */
                   1685:     if (index & 0x80000000) {
1.1.1.6 ! root     1686:         if (index > env->cpuid_xlevel)
1.1       root     1687:             index = env->cpuid_level;
                   1688:     } else {
1.1.1.6 ! root     1689:         if (index > env->cpuid_level)
1.1       root     1690:             index = env->cpuid_level;
                   1691:     }
1.1.1.6 ! root     1692: 
1.1       root     1693:     switch(index) {
                   1694:     case 0:
                   1695:         EAX = env->cpuid_level;
                   1696:         EBX = env->cpuid_vendor1;
                   1697:         EDX = env->cpuid_vendor2;
                   1698:         ECX = env->cpuid_vendor3;
                   1699:         break;
                   1700:     case 1:
                   1701:         EAX = env->cpuid_version;
1.1.1.6 ! root     1702:         EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
1.1       root     1703:         ECX = env->cpuid_ext_features;
                   1704:         EDX = env->cpuid_features;
                   1705:         break;
                   1706:     case 2:
                   1707:         /* cache info: needed for Pentium Pro compatibility */
1.1.1.6 ! root     1708:         EAX = 1;
1.1       root     1709:         EBX = 0;
                   1710:         ECX = 0;
1.1.1.6 ! root     1711:         EDX = 0x2c307d;
1.1       root     1712:         break;
                   1713:     case 0x80000000:
                   1714:         EAX = env->cpuid_xlevel;
                   1715:         EBX = env->cpuid_vendor1;
                   1716:         EDX = env->cpuid_vendor2;
                   1717:         ECX = env->cpuid_vendor3;
                   1718:         break;
                   1719:     case 0x80000001:
                   1720:         EAX = env->cpuid_features;
                   1721:         EBX = 0;
1.1.1.6 ! root     1722:         ECX = env->cpuid_ext3_features;
1.1       root     1723:         EDX = env->cpuid_ext2_features;
                   1724:         break;
                   1725:     case 0x80000002:
                   1726:     case 0x80000003:
                   1727:     case 0x80000004:
                   1728:         EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
                   1729:         EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
                   1730:         ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
                   1731:         EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
                   1732:         break;
                   1733:     case 0x80000005:
                   1734:         /* cache info (L1 cache) */
                   1735:         EAX = 0x01ff01ff;
                   1736:         EBX = 0x01ff01ff;
                   1737:         ECX = 0x40020140;
                   1738:         EDX = 0x40020140;
                   1739:         break;
                   1740:     case 0x80000006:
                   1741:         /* cache info (L2 cache) */
                   1742:         EAX = 0;
                   1743:         EBX = 0x42004200;
                   1744:         ECX = 0x02008140;
                   1745:         EDX = 0;
                   1746:         break;
                   1747:     case 0x80000008:
                   1748:         /* virtual & phys address size in low 2 bytes. */
                   1749:         EAX = 0x00003028;
                   1750:         EBX = 0;
                   1751:         ECX = 0;
                   1752:         EDX = 0;
                   1753:         break;
1.1.1.6 ! root     1754:     case 0x8000000A:
        !          1755:         EAX = 0x00000001;
        !          1756:         EBX = 0;
        !          1757:         ECX = 0;
        !          1758:         EDX = 0;
        !          1759:         break;
1.1       root     1760:     default:
                   1761:         /* reserved values: zero */
                   1762:         EAX = 0;
                   1763:         EBX = 0;
                   1764:         ECX = 0;
                   1765:         EDX = 0;
                   1766:         break;
                   1767:     }
                   1768: }
                   1769: 
                   1770: void helper_enter_level(int level, int data32)
                   1771: {
                   1772:     target_ulong ssp;
                   1773:     uint32_t esp_mask, esp, ebp;
                   1774: 
                   1775:     esp_mask = get_sp_mask(env->segs[R_SS].flags);
                   1776:     ssp = env->segs[R_SS].base;
                   1777:     ebp = EBP;
                   1778:     esp = ESP;
                   1779:     if (data32) {
                   1780:         /* 32 bit */
                   1781:         esp -= 4;
                   1782:         while (--level) {
                   1783:             esp -= 4;
                   1784:             ebp -= 4;
                   1785:             stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
                   1786:         }
                   1787:         esp -= 4;
                   1788:         stl(ssp + (esp & esp_mask), T1);
                   1789:     } else {
                   1790:         /* 16 bit */
                   1791:         esp -= 2;
                   1792:         while (--level) {
                   1793:             esp -= 2;
                   1794:             ebp -= 2;
                   1795:             stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
                   1796:         }
                   1797:         esp -= 2;
                   1798:         stw(ssp + (esp & esp_mask), T1);
                   1799:     }
                   1800: }
                   1801: 
                   1802: #ifdef TARGET_X86_64
                   1803: void helper_enter64_level(int level, int data64)
                   1804: {
                   1805:     target_ulong esp, ebp;
                   1806:     ebp = EBP;
                   1807:     esp = ESP;
                   1808: 
                   1809:     if (data64) {
                   1810:         /* 64 bit */
                   1811:         esp -= 8;
                   1812:         while (--level) {
                   1813:             esp -= 8;
                   1814:             ebp -= 8;
                   1815:             stq(esp, ldq(ebp));
                   1816:         }
                   1817:         esp -= 8;
                   1818:         stq(esp, T1);
                   1819:     } else {
                   1820:         /* 16 bit */
                   1821:         esp -= 2;
                   1822:         while (--level) {
                   1823:             esp -= 2;
                   1824:             ebp -= 2;
                   1825:             stw(esp, lduw(ebp));
                   1826:         }
                   1827:         esp -= 2;
                   1828:         stw(esp, T1);
                   1829:     }
                   1830: }
                   1831: #endif
                   1832: 
                   1833: void helper_lldt_T0(void)
                   1834: {
                   1835:     int selector;
                   1836:     SegmentCache *dt;
                   1837:     uint32_t e1, e2;
                   1838:     int index, entry_limit;
                   1839:     target_ulong ptr;
1.1.1.6 ! root     1840: 
1.1       root     1841:     selector = T0 & 0xffff;
                   1842:     if ((selector & 0xfffc) == 0) {
                   1843:         /* XXX: NULL selector case: invalid LDT */
                   1844:         env->ldt.base = 0;
                   1845:         env->ldt.limit = 0;
                   1846:     } else {
                   1847:         if (selector & 0x4)
                   1848:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1849:         dt = &env->gdt;
                   1850:         index = selector & ~7;
                   1851: #ifdef TARGET_X86_64
                   1852:         if (env->hflags & HF_LMA_MASK)
                   1853:             entry_limit = 15;
                   1854:         else
1.1.1.6 ! root     1855: #endif
1.1       root     1856:             entry_limit = 7;
                   1857:         if ((index + entry_limit) > dt->limit)
                   1858:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1859:         ptr = dt->base + index;
                   1860:         e1 = ldl_kernel(ptr);
                   1861:         e2 = ldl_kernel(ptr + 4);
                   1862:         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
                   1863:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1864:         if (!(e2 & DESC_P_MASK))
                   1865:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1866: #ifdef TARGET_X86_64
                   1867:         if (env->hflags & HF_LMA_MASK) {
                   1868:             uint32_t e3;
                   1869:             e3 = ldl_kernel(ptr + 8);
                   1870:             load_seg_cache_raw_dt(&env->ldt, e1, e2);
                   1871:             env->ldt.base |= (target_ulong)e3 << 32;
                   1872:         } else
                   1873: #endif
                   1874:         {
                   1875:             load_seg_cache_raw_dt(&env->ldt, e1, e2);
                   1876:         }
                   1877:     }
                   1878:     env->ldt.selector = selector;
                   1879: }
                   1880: 
                   1881: void helper_ltr_T0(void)
                   1882: {
                   1883:     int selector;
                   1884:     SegmentCache *dt;
                   1885:     uint32_t e1, e2;
                   1886:     int index, type, entry_limit;
                   1887:     target_ulong ptr;
1.1.1.6 ! root     1888: 
1.1       root     1889:     selector = T0 & 0xffff;
                   1890:     if ((selector & 0xfffc) == 0) {
                   1891:         /* NULL selector case: invalid TR */
                   1892:         env->tr.base = 0;
                   1893:         env->tr.limit = 0;
                   1894:         env->tr.flags = 0;
                   1895:     } else {
                   1896:         if (selector & 0x4)
                   1897:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1898:         dt = &env->gdt;
                   1899:         index = selector & ~7;
                   1900: #ifdef TARGET_X86_64
                   1901:         if (env->hflags & HF_LMA_MASK)
                   1902:             entry_limit = 15;
                   1903:         else
1.1.1.6 ! root     1904: #endif
1.1       root     1905:             entry_limit = 7;
                   1906:         if ((index + entry_limit) > dt->limit)
                   1907:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1908:         ptr = dt->base + index;
                   1909:         e1 = ldl_kernel(ptr);
                   1910:         e2 = ldl_kernel(ptr + 4);
                   1911:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1.1.1.6 ! root     1912:         if ((e2 & DESC_S_MASK) ||
1.1       root     1913:             (type != 1 && type != 9))
                   1914:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1915:         if (!(e2 & DESC_P_MASK))
                   1916:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1917: #ifdef TARGET_X86_64
                   1918:         if (env->hflags & HF_LMA_MASK) {
1.1.1.6 ! root     1919:             uint32_t e3, e4;
1.1       root     1920:             e3 = ldl_kernel(ptr + 8);
1.1.1.6 ! root     1921:             e4 = ldl_kernel(ptr + 12);
        !          1922:             if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
        !          1923:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1.1       root     1924:             load_seg_cache_raw_dt(&env->tr, e1, e2);
                   1925:             env->tr.base |= (target_ulong)e3 << 32;
1.1.1.6 ! root     1926:         } else
1.1       root     1927: #endif
                   1928:         {
                   1929:             load_seg_cache_raw_dt(&env->tr, e1, e2);
                   1930:         }
                   1931:         e2 |= DESC_TSS_BUSY_MASK;
                   1932:         stl_kernel(ptr + 4, e2);
                   1933:     }
                   1934:     env->tr.selector = selector;
                   1935: }
                   1936: 
                   1937: /* only works if protected mode and not VM86. seg_reg must be != R_CS */
                   1938: void load_seg(int seg_reg, int selector)
                   1939: {
                   1940:     uint32_t e1, e2;
                   1941:     int cpl, dpl, rpl;
                   1942:     SegmentCache *dt;
                   1943:     int index;
                   1944:     target_ulong ptr;
                   1945: 
                   1946:     selector &= 0xffff;
                   1947:     cpl = env->hflags & HF_CPL_MASK;
                   1948:     if ((selector & 0xfffc) == 0) {
                   1949:         /* null selector case */
                   1950:         if (seg_reg == R_SS
                   1951: #ifdef TARGET_X86_64
                   1952:             && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
                   1953: #endif
                   1954:             )
                   1955:             raise_exception_err(EXCP0D_GPF, 0);
                   1956:         cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
                   1957:     } else {
1.1.1.6 ! root     1958: 
1.1       root     1959:         if (selector & 0x4)
                   1960:             dt = &env->ldt;
                   1961:         else
                   1962:             dt = &env->gdt;
                   1963:         index = selector & ~7;
                   1964:         if ((index + 7) > dt->limit)
                   1965:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1966:         ptr = dt->base + index;
                   1967:         e1 = ldl_kernel(ptr);
                   1968:         e2 = ldl_kernel(ptr + 4);
1.1.1.6 ! root     1969: 
1.1       root     1970:         if (!(e2 & DESC_S_MASK))
                   1971:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1972:         rpl = selector & 3;
                   1973:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1974:         if (seg_reg == R_SS) {
                   1975:             /* must be writable segment */
                   1976:             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
                   1977:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1978:             if (rpl != cpl || dpl != cpl)
                   1979:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1980:         } else {
                   1981:             /* must be readable segment */
                   1982:             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
                   1983:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1.1.1.6 ! root     1984: 
1.1       root     1985:             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
                   1986:                 /* if not conforming code, test rights */
1.1.1.6 ! root     1987:                 if (dpl < cpl || dpl < rpl)
1.1       root     1988:                     raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1989:             }
                   1990:         }
                   1991: 
                   1992:         if (!(e2 & DESC_P_MASK)) {
                   1993:             if (seg_reg == R_SS)
                   1994:                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
                   1995:             else
                   1996:                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1997:         }
                   1998: 
                   1999:         /* set the access bit if not already set */
                   2000:         if (!(e2 & DESC_A_MASK)) {
                   2001:             e2 |= DESC_A_MASK;
                   2002:             stl_kernel(ptr + 4, e2);
                   2003:         }
                   2004: 
1.1.1.6 ! root     2005:         cpu_x86_load_seg_cache(env, seg_reg, selector,
1.1       root     2006:                        get_seg_base(e1, e2),
                   2007:                        get_seg_limit(e1, e2),
                   2008:                        e2);
                   2009: #if 0
1.1.1.6 ! root     2010:         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
1.1       root     2011:                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
                   2012: #endif
                   2013:     }
                   2014: }
                   2015: 
                   2016: /* protected mode jump */
                   2017: void helper_ljmp_protected_T0_T1(int next_eip_addend)
                   2018: {
                   2019:     int new_cs, gate_cs, type;
                   2020:     uint32_t e1, e2, cpl, dpl, rpl, limit;
                   2021:     target_ulong new_eip, next_eip;
1.1.1.6 ! root     2022: 
1.1       root     2023:     new_cs = T0;
                   2024:     new_eip = T1;
                   2025:     if ((new_cs & 0xfffc) == 0)
                   2026:         raise_exception_err(EXCP0D_GPF, 0);
                   2027:     if (load_segment(&e1, &e2, new_cs) != 0)
                   2028:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2029:     cpl = env->hflags & HF_CPL_MASK;
                   2030:     if (e2 & DESC_S_MASK) {
                   2031:         if (!(e2 & DESC_CS_MASK))
                   2032:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2033:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2034:         if (e2 & DESC_C_MASK) {
                   2035:             /* conforming code segment */
                   2036:             if (dpl > cpl)
                   2037:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2038:         } else {
                   2039:             /* non conforming code segment */
                   2040:             rpl = new_cs & 3;
                   2041:             if (rpl > cpl)
                   2042:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2043:             if (dpl != cpl)
                   2044:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2045:         }
                   2046:         if (!(e2 & DESC_P_MASK))
                   2047:             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   2048:         limit = get_seg_limit(e1, e2);
1.1.1.6 ! root     2049:         if (new_eip > limit &&
1.1       root     2050:             !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
                   2051:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2052:         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
                   2053:                        get_seg_base(e1, e2), limit, e2);
                   2054:         EIP = new_eip;
                   2055:     } else {
                   2056:         /* jump to call or task gate */
                   2057:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2058:         rpl = new_cs & 3;
                   2059:         cpl = env->hflags & HF_CPL_MASK;
                   2060:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   2061:         switch(type) {
                   2062:         case 1: /* 286 TSS */
                   2063:         case 9: /* 386 TSS */
                   2064:         case 5: /* task gate */
                   2065:             if (dpl < cpl || dpl < rpl)
                   2066:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2067:             next_eip = env->eip + next_eip_addend;
                   2068:             switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
1.1.1.4   root     2069:             CC_OP = CC_OP_EFLAGS;
1.1       root     2070:             break;
                   2071:         case 4: /* 286 call gate */
                   2072:         case 12: /* 386 call gate */
                   2073:             if ((dpl < cpl) || (dpl < rpl))
                   2074:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2075:             if (!(e2 & DESC_P_MASK))
                   2076:                 raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   2077:             gate_cs = e1 >> 16;
                   2078:             new_eip = (e1 & 0xffff);
                   2079:             if (type == 12)
                   2080:                 new_eip |= (e2 & 0xffff0000);
                   2081:             if (load_segment(&e1, &e2, gate_cs) != 0)
                   2082:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   2083:             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2084:             /* must be code segment */
1.1.1.6 ! root     2085:             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
1.1       root     2086:                  (DESC_S_MASK | DESC_CS_MASK)))
                   2087:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1.1.1.6 ! root     2088:             if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
1.1       root     2089:                 (!(e2 & DESC_C_MASK) && (dpl != cpl)))
                   2090:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   2091:             if (!(e2 & DESC_P_MASK))
                   2092:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   2093:             limit = get_seg_limit(e1, e2);
                   2094:             if (new_eip > limit)
                   2095:                 raise_exception_err(EXCP0D_GPF, 0);
                   2096:             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
                   2097:                                    get_seg_base(e1, e2), limit, e2);
                   2098:             EIP = new_eip;
                   2099:             break;
                   2100:         default:
                   2101:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2102:             break;
                   2103:         }
                   2104:     }
                   2105: }
                   2106: 
                   2107: /* real mode call */
                   2108: void helper_lcall_real_T0_T1(int shift, int next_eip)
                   2109: {
                   2110:     int new_cs, new_eip;
                   2111:     uint32_t esp, esp_mask;
                   2112:     target_ulong ssp;
                   2113: 
                   2114:     new_cs = T0;
                   2115:     new_eip = T1;
                   2116:     esp = ESP;
                   2117:     esp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2118:     ssp = env->segs[R_SS].base;
                   2119:     if (shift) {
                   2120:         PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
                   2121:         PUSHL(ssp, esp, esp_mask, next_eip);
                   2122:     } else {
                   2123:         PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
                   2124:         PUSHW(ssp, esp, esp_mask, next_eip);
                   2125:     }
                   2126: 
1.1.1.5   root     2127:     SET_ESP(esp, esp_mask);
1.1       root     2128:     env->eip = new_eip;
                   2129:     env->segs[R_CS].selector = new_cs;
                   2130:     env->segs[R_CS].base = (new_cs << 4);
                   2131: }
                   2132: 
                   2133: /* protected mode call */
                   2134: void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
                   2135: {
1.1.1.2   root     2136:     int new_cs, new_stack, i;
1.1       root     2137:     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
                   2138:     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
                   2139:     uint32_t val, limit, old_sp_mask;
1.1.1.2   root     2140:     target_ulong ssp, old_ssp, next_eip, new_eip;
1.1.1.6 ! root     2141: 
1.1       root     2142:     new_cs = T0;
                   2143:     new_eip = T1;
                   2144:     next_eip = env->eip + next_eip_addend;
                   2145: #ifdef DEBUG_PCALL
                   2146:     if (loglevel & CPU_LOG_PCALL) {
                   2147:         fprintf(logfile, "lcall %04x:%08x s=%d\n",
1.1.1.2   root     2148:                 new_cs, (uint32_t)new_eip, shift);
1.1       root     2149:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                   2150:     }
                   2151: #endif
                   2152:     if ((new_cs & 0xfffc) == 0)
                   2153:         raise_exception_err(EXCP0D_GPF, 0);
                   2154:     if (load_segment(&e1, &e2, new_cs) != 0)
                   2155:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2156:     cpl = env->hflags & HF_CPL_MASK;
                   2157: #ifdef DEBUG_PCALL
                   2158:     if (loglevel & CPU_LOG_PCALL) {
                   2159:         fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
                   2160:     }
                   2161: #endif
                   2162:     if (e2 & DESC_S_MASK) {
                   2163:         if (!(e2 & DESC_CS_MASK))
                   2164:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2165:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2166:         if (e2 & DESC_C_MASK) {
                   2167:             /* conforming code segment */
                   2168:             if (dpl > cpl)
                   2169:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2170:         } else {
                   2171:             /* non conforming code segment */
                   2172:             rpl = new_cs & 3;
                   2173:             if (rpl > cpl)
                   2174:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2175:             if (dpl != cpl)
                   2176:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2177:         }
                   2178:         if (!(e2 & DESC_P_MASK))
                   2179:             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   2180: 
                   2181: #ifdef TARGET_X86_64
                   2182:         /* XXX: check 16/32 bit cases in long mode */
                   2183:         if (shift == 2) {
                   2184:             target_ulong rsp;
                   2185:             /* 64 bit case */
                   2186:             rsp = ESP;
                   2187:             PUSHQ(rsp, env->segs[R_CS].selector);
                   2188:             PUSHQ(rsp, next_eip);
                   2189:             /* from this point, not restartable */
                   2190:             ESP = rsp;
                   2191:             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1.1.1.6 ! root     2192:                                    get_seg_base(e1, e2),
1.1       root     2193:                                    get_seg_limit(e1, e2), e2);
                   2194:             EIP = new_eip;
1.1.1.6 ! root     2195:         } else
1.1       root     2196: #endif
                   2197:         {
                   2198:             sp = ESP;
                   2199:             sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2200:             ssp = env->segs[R_SS].base;
                   2201:             if (shift) {
                   2202:                 PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   2203:                 PUSHL(ssp, sp, sp_mask, next_eip);
                   2204:             } else {
                   2205:                 PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   2206:                 PUSHW(ssp, sp, sp_mask, next_eip);
                   2207:             }
1.1.1.6 ! root     2208: 
1.1       root     2209:             limit = get_seg_limit(e1, e2);
                   2210:             if (new_eip > limit)
                   2211:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2212:             /* from this point, not restartable */
1.1.1.5   root     2213:             SET_ESP(sp, sp_mask);
1.1       root     2214:             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
                   2215:                                    get_seg_base(e1, e2), limit, e2);
                   2216:             EIP = new_eip;
                   2217:         }
                   2218:     } else {
                   2219:         /* check gate type */
                   2220:         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
                   2221:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2222:         rpl = new_cs & 3;
                   2223:         switch(type) {
                   2224:         case 1: /* available 286 TSS */
                   2225:         case 9: /* available 386 TSS */
                   2226:         case 5: /* task gate */
                   2227:             if (dpl < cpl || dpl < rpl)
                   2228:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2229:             switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
1.1.1.4   root     2230:             CC_OP = CC_OP_EFLAGS;
1.1       root     2231:             return;
                   2232:         case 4: /* 286 call gate */
                   2233:         case 12: /* 386 call gate */
                   2234:             break;
                   2235:         default:
                   2236:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2237:             break;
                   2238:         }
                   2239:         shift = type >> 3;
                   2240: 
                   2241:         if (dpl < cpl || dpl < rpl)
                   2242:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2243:         /* check valid bit */
                   2244:         if (!(e2 & DESC_P_MASK))
                   2245:             raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
                   2246:         selector = e1 >> 16;
                   2247:         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
                   2248:         param_count = e2 & 0x1f;
                   2249:         if ((selector & 0xfffc) == 0)
                   2250:             raise_exception_err(EXCP0D_GPF, 0);
                   2251: 
                   2252:         if (load_segment(&e1, &e2, selector) != 0)
                   2253:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   2254:         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
                   2255:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   2256:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2257:         if (dpl > cpl)
                   2258:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   2259:         if (!(e2 & DESC_P_MASK))
                   2260:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   2261: 
                   2262:         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
1.1.1.6 ! root     2263:             /* to inner privilege */
1.1       root     2264:             get_ss_esp_from_tss(&ss, &sp, dpl);
                   2265: #ifdef DEBUG_PCALL
                   2266:             if (loglevel & CPU_LOG_PCALL)
1.1.1.6 ! root     2267:                 fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
1.1       root     2268:                         ss, sp, param_count, ESP);
                   2269: #endif
                   2270:             if ((ss & 0xfffc) == 0)
                   2271:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2272:             if ((ss & 3) != dpl)
                   2273:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2274:             if (load_segment(&ss_e1, &ss_e2, ss) != 0)
                   2275:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2276:             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
                   2277:             if (ss_dpl != dpl)
                   2278:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2279:             if (!(ss_e2 & DESC_S_MASK) ||
                   2280:                 (ss_e2 & DESC_CS_MASK) ||
                   2281:                 !(ss_e2 & DESC_W_MASK))
                   2282:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2283:             if (!(ss_e2 & DESC_P_MASK))
                   2284:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1.1.1.6 ! root     2285: 
1.1       root     2286:             //            push_size = ((param_count * 2) + 8) << shift;
                   2287: 
                   2288:             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2289:             old_ssp = env->segs[R_SS].base;
1.1.1.6 ! root     2290: 
1.1       root     2291:             sp_mask = get_sp_mask(ss_e2);
                   2292:             ssp = get_seg_base(ss_e1, ss_e2);
                   2293:             if (shift) {
                   2294:                 PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
                   2295:                 PUSHL(ssp, sp, sp_mask, ESP);
                   2296:                 for(i = param_count - 1; i >= 0; i--) {
                   2297:                     val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
                   2298:                     PUSHL(ssp, sp, sp_mask, val);
                   2299:                 }
                   2300:             } else {
                   2301:                 PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
                   2302:                 PUSHW(ssp, sp, sp_mask, ESP);
                   2303:                 for(i = param_count - 1; i >= 0; i--) {
                   2304:                     val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
                   2305:                     PUSHW(ssp, sp, sp_mask, val);
                   2306:                 }
                   2307:             }
                   2308:             new_stack = 1;
                   2309:         } else {
1.1.1.6 ! root     2310:             /* to same privilege */
1.1       root     2311:             sp = ESP;
                   2312:             sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2313:             ssp = env->segs[R_SS].base;
                   2314:             //            push_size = (4 << shift);
                   2315:             new_stack = 0;
                   2316:         }
                   2317: 
                   2318:         if (shift) {
                   2319:             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   2320:             PUSHL(ssp, sp, sp_mask, next_eip);
                   2321:         } else {
                   2322:             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   2323:             PUSHW(ssp, sp, sp_mask, next_eip);
                   2324:         }
                   2325: 
                   2326:         /* from this point, not restartable */
                   2327: 
                   2328:         if (new_stack) {
                   2329:             ss = (ss & ~3) | dpl;
1.1.1.6 ! root     2330:             cpu_x86_load_seg_cache(env, R_SS, ss,
1.1       root     2331:                                    ssp,
                   2332:                                    get_seg_limit(ss_e1, ss_e2),
                   2333:                                    ss_e2);
                   2334:         }
                   2335: 
                   2336:         selector = (selector & ~3) | dpl;
1.1.1.6 ! root     2337:         cpu_x86_load_seg_cache(env, R_CS, selector,
1.1       root     2338:                        get_seg_base(e1, e2),
                   2339:                        get_seg_limit(e1, e2),
                   2340:                        e2);
                   2341:         cpu_x86_set_cpl(env, dpl);
1.1.1.5   root     2342:         SET_ESP(sp, sp_mask);
1.1       root     2343:         EIP = offset;
                   2344:     }
                   2345: #ifdef USE_KQEMU
                   2346:     if (kqemu_is_ok(env)) {
                   2347:         env->exception_index = -1;
                   2348:         cpu_loop_exit();
                   2349:     }
                   2350: #endif
                   2351: }
                   2352: 
                   2353: /* real and vm86 mode iret */
                   2354: void helper_iret_real(int shift)
                   2355: {
                   2356:     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
                   2357:     target_ulong ssp;
                   2358:     int eflags_mask;
                   2359: 
                   2360:     sp_mask = 0xffff; /* XXXX: use SS segment size ? */
                   2361:     sp = ESP;
                   2362:     ssp = env->segs[R_SS].base;
                   2363:     if (shift == 1) {
                   2364:         /* 32 bits */
                   2365:         POPL(ssp, sp, sp_mask, new_eip);
                   2366:         POPL(ssp, sp, sp_mask, new_cs);
                   2367:         new_cs &= 0xffff;
                   2368:         POPL(ssp, sp, sp_mask, new_eflags);
                   2369:     } else {
                   2370:         /* 16 bits */
                   2371:         POPW(ssp, sp, sp_mask, new_eip);
                   2372:         POPW(ssp, sp, sp_mask, new_cs);
                   2373:         POPW(ssp, sp, sp_mask, new_eflags);
                   2374:     }
                   2375:     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
                   2376:     load_seg_vm(R_CS, new_cs);
                   2377:     env->eip = new_eip;
                   2378:     if (env->eflags & VM_MASK)
                   2379:         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
                   2380:     else
                   2381:         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
                   2382:     if (shift == 0)
                   2383:         eflags_mask &= 0xffff;
                   2384:     load_eflags(new_eflags, eflags_mask);
                   2385: }
                   2386: 
                   2387: static inline void validate_seg(int seg_reg, int cpl)
                   2388: {
                   2389:     int dpl;
                   2390:     uint32_t e2;
1.1.1.2   root     2391: 
                   2392:     /* XXX: on x86_64, we do not want to nullify FS and GS because
                   2393:        they may still contain a valid base. I would be interested to
                   2394:        know how a real x86_64 CPU behaves */
1.1.1.6 ! root     2395:     if ((seg_reg == R_FS || seg_reg == R_GS) &&
1.1.1.2   root     2396:         (env->segs[seg_reg].selector & 0xfffc) == 0)
                   2397:         return;
                   2398: 
1.1       root     2399:     e2 = env->segs[seg_reg].flags;
                   2400:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2401:     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
                   2402:         /* data or non conforming code segment */
                   2403:         if (dpl < cpl) {
                   2404:             cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
                   2405:         }
                   2406:     }
                   2407: }
                   2408: 
                   2409: /* protected mode iret */
                   2410: static inline void helper_ret_protected(int shift, int is_iret, int addend)
                   2411: {
                   2412:     uint32_t new_cs, new_eflags, new_ss;
                   2413:     uint32_t new_es, new_ds, new_fs, new_gs;
                   2414:     uint32_t e1, e2, ss_e1, ss_e2;
                   2415:     int cpl, dpl, rpl, eflags_mask, iopl;
                   2416:     target_ulong ssp, sp, new_eip, new_esp, sp_mask;
1.1.1.6 ! root     2417: 
1.1       root     2418: #ifdef TARGET_X86_64
                   2419:     if (shift == 2)
                   2420:         sp_mask = -1;
                   2421:     else
                   2422: #endif
                   2423:         sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2424:     sp = ESP;
                   2425:     ssp = env->segs[R_SS].base;
                   2426:     new_eflags = 0; /* avoid warning */
                   2427: #ifdef TARGET_X86_64
                   2428:     if (shift == 2) {
                   2429:         POPQ(sp, new_eip);
                   2430:         POPQ(sp, new_cs);
                   2431:         new_cs &= 0xffff;
                   2432:         if (is_iret) {
                   2433:             POPQ(sp, new_eflags);
                   2434:         }
                   2435:     } else
                   2436: #endif
                   2437:     if (shift == 1) {
                   2438:         /* 32 bits */
                   2439:         POPL(ssp, sp, sp_mask, new_eip);
                   2440:         POPL(ssp, sp, sp_mask, new_cs);
                   2441:         new_cs &= 0xffff;
                   2442:         if (is_iret) {
                   2443:             POPL(ssp, sp, sp_mask, new_eflags);
                   2444:             if (new_eflags & VM_MASK)
                   2445:                 goto return_to_vm86;
                   2446:         }
                   2447:     } else {
                   2448:         /* 16 bits */
                   2449:         POPW(ssp, sp, sp_mask, new_eip);
                   2450:         POPW(ssp, sp, sp_mask, new_cs);
                   2451:         if (is_iret)
                   2452:             POPW(ssp, sp, sp_mask, new_eflags);
                   2453:     }
                   2454: #ifdef DEBUG_PCALL
                   2455:     if (loglevel & CPU_LOG_PCALL) {
                   2456:         fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
                   2457:                 new_cs, new_eip, shift, addend);
                   2458:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                   2459:     }
                   2460: #endif
                   2461:     if ((new_cs & 0xfffc) == 0)
                   2462:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2463:     if (load_segment(&e1, &e2, new_cs) != 0)
                   2464:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2465:     if (!(e2 & DESC_S_MASK) ||
                   2466:         !(e2 & DESC_CS_MASK))
                   2467:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2468:     cpl = env->hflags & HF_CPL_MASK;
1.1.1.6 ! root     2469:     rpl = new_cs & 3;
1.1       root     2470:     if (rpl < cpl)
                   2471:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2472:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2473:     if (e2 & DESC_C_MASK) {
                   2474:         if (dpl > rpl)
                   2475:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2476:     } else {
                   2477:         if (dpl != rpl)
                   2478:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2479:     }
                   2480:     if (!(e2 & DESC_P_MASK))
                   2481:         raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1.1.1.6 ! root     2482: 
1.1       root     2483:     sp += addend;
1.1.1.6 ! root     2484:     if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
1.1       root     2485:                        ((env->hflags & HF_CS64_MASK) && !is_iret))) {
                   2486:         /* return to same priledge level */
1.1.1.6 ! root     2487:         cpu_x86_load_seg_cache(env, R_CS, new_cs,
1.1       root     2488:                        get_seg_base(e1, e2),
                   2489:                        get_seg_limit(e1, e2),
                   2490:                        e2);
                   2491:     } else {
1.1.1.6 ! root     2492:         /* return to different privilege level */
1.1       root     2493: #ifdef TARGET_X86_64
                   2494:         if (shift == 2) {
                   2495:             POPQ(sp, new_esp);
                   2496:             POPQ(sp, new_ss);
                   2497:             new_ss &= 0xffff;
                   2498:         } else
                   2499: #endif
                   2500:         if (shift == 1) {
                   2501:             /* 32 bits */
                   2502:             POPL(ssp, sp, sp_mask, new_esp);
                   2503:             POPL(ssp, sp, sp_mask, new_ss);
                   2504:             new_ss &= 0xffff;
                   2505:         } else {
                   2506:             /* 16 bits */
                   2507:             POPW(ssp, sp, sp_mask, new_esp);
                   2508:             POPW(ssp, sp, sp_mask, new_ss);
                   2509:         }
                   2510: #ifdef DEBUG_PCALL
                   2511:         if (loglevel & CPU_LOG_PCALL) {
                   2512:             fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
                   2513:                     new_ss, new_esp);
                   2514:         }
                   2515: #endif
                   2516:         if ((new_ss & 0xfffc) == 0) {
                   2517: #ifdef TARGET_X86_64
                   2518:             /* NULL ss is allowed in long mode if cpl != 3*/
1.1.1.5   root     2519:             /* XXX: test CS64 ? */
1.1       root     2520:             if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
1.1.1.6 ! root     2521:                 cpu_x86_load_seg_cache(env, R_SS, new_ss,
1.1       root     2522:                                        0, 0xffffffff,
                   2523:                                        DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2524:                                        DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
                   2525:                                        DESC_W_MASK | DESC_A_MASK);
1.1.1.5   root     2526:                 ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
1.1.1.6 ! root     2527:             } else
1.1       root     2528: #endif
                   2529:             {
                   2530:                 raise_exception_err(EXCP0D_GPF, 0);
                   2531:             }
                   2532:         } else {
                   2533:             if ((new_ss & 3) != rpl)
                   2534:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2535:             if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
                   2536:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2537:             if (!(ss_e2 & DESC_S_MASK) ||
                   2538:                 (ss_e2 & DESC_CS_MASK) ||
                   2539:                 !(ss_e2 & DESC_W_MASK))
                   2540:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2541:             dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
                   2542:             if (dpl != rpl)
                   2543:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2544:             if (!(ss_e2 & DESC_P_MASK))
                   2545:                 raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
1.1.1.6 ! root     2546:             cpu_x86_load_seg_cache(env, R_SS, new_ss,
1.1       root     2547:                                    get_seg_base(ss_e1, ss_e2),
                   2548:                                    get_seg_limit(ss_e1, ss_e2),
                   2549:                                    ss_e2);
                   2550:         }
                   2551: 
1.1.1.6 ! root     2552:         cpu_x86_load_seg_cache(env, R_CS, new_cs,
1.1       root     2553:                        get_seg_base(e1, e2),
                   2554:                        get_seg_limit(e1, e2),
                   2555:                        e2);
                   2556:         cpu_x86_set_cpl(env, rpl);
                   2557:         sp = new_esp;
                   2558: #ifdef TARGET_X86_64
                   2559:         if (env->hflags & HF_CS64_MASK)
                   2560:             sp_mask = -1;
                   2561:         else
                   2562: #endif
                   2563:             sp_mask = get_sp_mask(ss_e2);
                   2564: 
                   2565:         /* validate data segments */
1.1.1.2   root     2566:         validate_seg(R_ES, rpl);
                   2567:         validate_seg(R_DS, rpl);
                   2568:         validate_seg(R_FS, rpl);
                   2569:         validate_seg(R_GS, rpl);
1.1       root     2570: 
                   2571:         sp += addend;
                   2572:     }
1.1.1.5   root     2573:     SET_ESP(sp, sp_mask);
1.1       root     2574:     env->eip = new_eip;
                   2575:     if (is_iret) {
                   2576:         /* NOTE: 'cpl' is the _old_ CPL */
                   2577:         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
                   2578:         if (cpl == 0)
                   2579:             eflags_mask |= IOPL_MASK;
                   2580:         iopl = (env->eflags >> IOPL_SHIFT) & 3;
                   2581:         if (cpl <= iopl)
                   2582:             eflags_mask |= IF_MASK;
                   2583:         if (shift == 0)
                   2584:             eflags_mask &= 0xffff;
                   2585:         load_eflags(new_eflags, eflags_mask);
                   2586:     }
                   2587:     return;
                   2588: 
                   2589:  return_to_vm86:
                   2590:     POPL(ssp, sp, sp_mask, new_esp);
                   2591:     POPL(ssp, sp, sp_mask, new_ss);
                   2592:     POPL(ssp, sp, sp_mask, new_es);
                   2593:     POPL(ssp, sp, sp_mask, new_ds);
                   2594:     POPL(ssp, sp, sp_mask, new_fs);
                   2595:     POPL(ssp, sp, sp_mask, new_gs);
1.1.1.6 ! root     2596: 
1.1       root     2597:     /* modify processor state */
1.1.1.6 ! root     2598:     load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
1.1       root     2599:                 IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
                   2600:     load_seg_vm(R_CS, new_cs & 0xffff);
                   2601:     cpu_x86_set_cpl(env, 3);
                   2602:     load_seg_vm(R_SS, new_ss & 0xffff);
                   2603:     load_seg_vm(R_ES, new_es & 0xffff);
                   2604:     load_seg_vm(R_DS, new_ds & 0xffff);
                   2605:     load_seg_vm(R_FS, new_fs & 0xffff);
                   2606:     load_seg_vm(R_GS, new_gs & 0xffff);
                   2607: 
                   2608:     env->eip = new_eip & 0xffff;
                   2609:     ESP = new_esp;
                   2610: }
                   2611: 
                   2612: void helper_iret_protected(int shift, int next_eip)
                   2613: {
                   2614:     int tss_selector, type;
                   2615:     uint32_t e1, e2;
1.1.1.6 ! root     2616: 
1.1       root     2617:     /* specific case for TSS */
                   2618:     if (env->eflags & NT_MASK) {
                   2619: #ifdef TARGET_X86_64
                   2620:         if (env->hflags & HF_LMA_MASK)
                   2621:             raise_exception_err(EXCP0D_GPF, 0);
                   2622: #endif
                   2623:         tss_selector = lduw_kernel(env->tr.base + 0);
                   2624:         if (tss_selector & 4)
                   2625:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                   2626:         if (load_segment(&e1, &e2, tss_selector) != 0)
                   2627:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                   2628:         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
                   2629:         /* NOTE: we check both segment and busy TSS */
                   2630:         if (type != 3)
                   2631:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                   2632:         switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
                   2633:     } else {
                   2634:         helper_ret_protected(shift, 1, 0);
                   2635:     }
                   2636: #ifdef USE_KQEMU
                   2637:     if (kqemu_is_ok(env)) {
                   2638:         CC_OP = CC_OP_EFLAGS;
                   2639:         env->exception_index = -1;
                   2640:         cpu_loop_exit();
                   2641:     }
                   2642: #endif
                   2643: }
                   2644: 
                   2645: void helper_lret_protected(int shift, int addend)
                   2646: {
                   2647:     helper_ret_protected(shift, 0, addend);
                   2648: #ifdef USE_KQEMU
                   2649:     if (kqemu_is_ok(env)) {
                   2650:         env->exception_index = -1;
                   2651:         cpu_loop_exit();
                   2652:     }
                   2653: #endif
                   2654: }
                   2655: 
                   2656: void helper_sysenter(void)
                   2657: {
                   2658:     if (env->sysenter_cs == 0) {
                   2659:         raise_exception_err(EXCP0D_GPF, 0);
                   2660:     }
                   2661:     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
                   2662:     cpu_x86_set_cpl(env, 0);
1.1.1.6 ! root     2663:     cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
        !          2664:                            0, 0xffffffff,
1.1       root     2665:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2666:                            DESC_S_MASK |
                   2667:                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1.1.1.6 ! root     2668:     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
1.1       root     2669:                            0, 0xffffffff,
                   2670:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2671:                            DESC_S_MASK |
                   2672:                            DESC_W_MASK | DESC_A_MASK);
                   2673:     ESP = env->sysenter_esp;
                   2674:     EIP = env->sysenter_eip;
                   2675: }
                   2676: 
                   2677: void helper_sysexit(void)
                   2678: {
                   2679:     int cpl;
                   2680: 
                   2681:     cpl = env->hflags & HF_CPL_MASK;
                   2682:     if (env->sysenter_cs == 0 || cpl != 0) {
                   2683:         raise_exception_err(EXCP0D_GPF, 0);
                   2684:     }
                   2685:     cpu_x86_set_cpl(env, 3);
1.1.1.6 ! root     2686:     cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
        !          2687:                            0, 0xffffffff,
1.1       root     2688:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2689:                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   2690:                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1.1.1.6 ! root     2691:     cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
1.1       root     2692:                            0, 0xffffffff,
                   2693:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2694:                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   2695:                            DESC_W_MASK | DESC_A_MASK);
                   2696:     ESP = ECX;
                   2697:     EIP = EDX;
                   2698: #ifdef USE_KQEMU
                   2699:     if (kqemu_is_ok(env)) {
                   2700:         env->exception_index = -1;
                   2701:         cpu_loop_exit();
                   2702:     }
                   2703: #endif
                   2704: }
                   2705: 
                   2706: void helper_movl_crN_T0(int reg)
                   2707: {
1.1.1.6 ! root     2708: #if !defined(CONFIG_USER_ONLY)
1.1       root     2709:     switch(reg) {
                   2710:     case 0:
                   2711:         cpu_x86_update_cr0(env, T0);
                   2712:         break;
                   2713:     case 3:
                   2714:         cpu_x86_update_cr3(env, T0);
                   2715:         break;
                   2716:     case 4:
                   2717:         cpu_x86_update_cr4(env, T0);
                   2718:         break;
                   2719:     case 8:
                   2720:         cpu_set_apic_tpr(env, T0);
                   2721:         break;
                   2722:     default:
                   2723:         env->cr[reg] = T0;
                   2724:         break;
                   2725:     }
                   2726: #endif
                   2727: }
                   2728: 
                   2729: /* XXX: do more */
                   2730: void helper_movl_drN_T0(int reg)
                   2731: {
                   2732:     env->dr[reg] = T0;
                   2733: }
                   2734: 
                   2735: void helper_invlpg(target_ulong addr)
                   2736: {
                   2737:     cpu_x86_flush_tlb(env, addr);
                   2738: }
                   2739: 
                   2740: void helper_rdtsc(void)
                   2741: {
                   2742:     uint64_t val;
                   2743: 
                   2744:     if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
                   2745:         raise_exception(EXCP0D_GPF);
                   2746:     }
                   2747:     val = cpu_get_tsc(env);
                   2748:     EAX = (uint32_t)(val);
                   2749:     EDX = (uint32_t)(val >> 32);
                   2750: }
                   2751: 
1.1.1.6 ! root     2752: void helper_rdpmc(void)
        !          2753: {
        !          2754:     if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
        !          2755:         raise_exception(EXCP0D_GPF);
        !          2756:     }
        !          2757: 
        !          2758:     if (!svm_check_intercept_param(SVM_EXIT_RDPMC, 0)) {
        !          2759:         /* currently unimplemented */
        !          2760:         raise_exception_err(EXCP06_ILLOP, 0);
        !          2761:     }
        !          2762: }
        !          2763: 
        !          2764: #if defined(CONFIG_USER_ONLY)
1.1       root     2765: void helper_wrmsr(void)
                   2766: {
                   2767: }
                   2768: 
                   2769: void helper_rdmsr(void)
                   2770: {
                   2771: }
                   2772: #else
                   2773: void helper_wrmsr(void)
                   2774: {
                   2775:     uint64_t val;
                   2776: 
                   2777:     val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
                   2778: 
                   2779:     switch((uint32_t)ECX) {
                   2780:     case MSR_IA32_SYSENTER_CS:
                   2781:         env->sysenter_cs = val & 0xffff;
                   2782:         break;
                   2783:     case MSR_IA32_SYSENTER_ESP:
                   2784:         env->sysenter_esp = val;
                   2785:         break;
                   2786:     case MSR_IA32_SYSENTER_EIP:
                   2787:         env->sysenter_eip = val;
                   2788:         break;
                   2789:     case MSR_IA32_APICBASE:
                   2790:         cpu_set_apic_base(env, val);
                   2791:         break;
                   2792:     case MSR_EFER:
                   2793:         {
                   2794:             uint64_t update_mask;
                   2795:             update_mask = 0;
                   2796:             if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
                   2797:                 update_mask |= MSR_EFER_SCE;
                   2798:             if (env->cpuid_ext2_features & CPUID_EXT2_LM)
                   2799:                 update_mask |= MSR_EFER_LME;
                   2800:             if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
                   2801:                 update_mask |= MSR_EFER_FFXSR;
                   2802:             if (env->cpuid_ext2_features & CPUID_EXT2_NX)
                   2803:                 update_mask |= MSR_EFER_NXE;
1.1.1.6 ! root     2804:             env->efer = (env->efer & ~update_mask) |
1.1       root     2805:             (val & update_mask);
                   2806:         }
                   2807:         break;
                   2808:     case MSR_STAR:
                   2809:         env->star = val;
                   2810:         break;
                   2811:     case MSR_PAT:
                   2812:         env->pat = val;
                   2813:         break;
1.1.1.6 ! root     2814:     case MSR_VM_HSAVE_PA:
        !          2815:         env->vm_hsave = val;
        !          2816:         break;
1.1       root     2817: #ifdef TARGET_X86_64
                   2818:     case MSR_LSTAR:
                   2819:         env->lstar = val;
                   2820:         break;
                   2821:     case MSR_CSTAR:
                   2822:         env->cstar = val;
                   2823:         break;
                   2824:     case MSR_FMASK:
                   2825:         env->fmask = val;
                   2826:         break;
                   2827:     case MSR_FSBASE:
                   2828:         env->segs[R_FS].base = val;
                   2829:         break;
                   2830:     case MSR_GSBASE:
                   2831:         env->segs[R_GS].base = val;
                   2832:         break;
                   2833:     case MSR_KERNELGSBASE:
                   2834:         env->kernelgsbase = val;
                   2835:         break;
                   2836: #endif
                   2837:     default:
                   2838:         /* XXX: exception ? */
1.1.1.6 ! root     2839:         break;
1.1       root     2840:     }
                   2841: }
                   2842: 
                   2843: void helper_rdmsr(void)
                   2844: {
                   2845:     uint64_t val;
                   2846:     switch((uint32_t)ECX) {
                   2847:     case MSR_IA32_SYSENTER_CS:
                   2848:         val = env->sysenter_cs;
                   2849:         break;
                   2850:     case MSR_IA32_SYSENTER_ESP:
                   2851:         val = env->sysenter_esp;
                   2852:         break;
                   2853:     case MSR_IA32_SYSENTER_EIP:
                   2854:         val = env->sysenter_eip;
                   2855:         break;
                   2856:     case MSR_IA32_APICBASE:
                   2857:         val = cpu_get_apic_base(env);
                   2858:         break;
                   2859:     case MSR_EFER:
                   2860:         val = env->efer;
                   2861:         break;
                   2862:     case MSR_STAR:
                   2863:         val = env->star;
                   2864:         break;
                   2865:     case MSR_PAT:
                   2866:         val = env->pat;
                   2867:         break;
1.1.1.6 ! root     2868:     case MSR_VM_HSAVE_PA:
        !          2869:         val = env->vm_hsave;
        !          2870:         break;
1.1       root     2871: #ifdef TARGET_X86_64
                   2872:     case MSR_LSTAR:
                   2873:         val = env->lstar;
                   2874:         break;
                   2875:     case MSR_CSTAR:
                   2876:         val = env->cstar;
                   2877:         break;
                   2878:     case MSR_FMASK:
                   2879:         val = env->fmask;
                   2880:         break;
                   2881:     case MSR_FSBASE:
                   2882:         val = env->segs[R_FS].base;
                   2883:         break;
                   2884:     case MSR_GSBASE:
                   2885:         val = env->segs[R_GS].base;
                   2886:         break;
                   2887:     case MSR_KERNELGSBASE:
                   2888:         val = env->kernelgsbase;
                   2889:         break;
                   2890: #endif
                   2891:     default:
                   2892:         /* XXX: exception ? */
                   2893:         val = 0;
1.1.1.6 ! root     2894:         break;
1.1       root     2895:     }
                   2896:     EAX = (uint32_t)(val);
                   2897:     EDX = (uint32_t)(val >> 32);
                   2898: }
                   2899: #endif
                   2900: 
                   2901: void helper_lsl(void)
                   2902: {
                   2903:     unsigned int selector, limit;
                   2904:     uint32_t e1, e2, eflags;
                   2905:     int rpl, dpl, cpl, type;
                   2906: 
                   2907:     eflags = cc_table[CC_OP].compute_all();
                   2908:     selector = T0 & 0xffff;
                   2909:     if (load_segment(&e1, &e2, selector) != 0)
                   2910:         goto fail;
                   2911:     rpl = selector & 3;
                   2912:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2913:     cpl = env->hflags & HF_CPL_MASK;
                   2914:     if (e2 & DESC_S_MASK) {
                   2915:         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
                   2916:             /* conforming */
                   2917:         } else {
                   2918:             if (dpl < cpl || dpl < rpl)
                   2919:                 goto fail;
                   2920:         }
                   2921:     } else {
                   2922:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   2923:         switch(type) {
                   2924:         case 1:
                   2925:         case 2:
                   2926:         case 3:
                   2927:         case 9:
                   2928:         case 11:
                   2929:             break;
                   2930:         default:
                   2931:             goto fail;
                   2932:         }
                   2933:         if (dpl < cpl || dpl < rpl) {
                   2934:         fail:
                   2935:             CC_SRC = eflags & ~CC_Z;
                   2936:             return;
                   2937:         }
                   2938:     }
                   2939:     limit = get_seg_limit(e1, e2);
                   2940:     T1 = limit;
                   2941:     CC_SRC = eflags | CC_Z;
                   2942: }
                   2943: 
                   2944: void helper_lar(void)
                   2945: {
                   2946:     unsigned int selector;
                   2947:     uint32_t e1, e2, eflags;
                   2948:     int rpl, dpl, cpl, type;
                   2949: 
                   2950:     eflags = cc_table[CC_OP].compute_all();
                   2951:     selector = T0 & 0xffff;
                   2952:     if ((selector & 0xfffc) == 0)
                   2953:         goto fail;
                   2954:     if (load_segment(&e1, &e2, selector) != 0)
                   2955:         goto fail;
                   2956:     rpl = selector & 3;
                   2957:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2958:     cpl = env->hflags & HF_CPL_MASK;
                   2959:     if (e2 & DESC_S_MASK) {
                   2960:         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
                   2961:             /* conforming */
                   2962:         } else {
                   2963:             if (dpl < cpl || dpl < rpl)
                   2964:                 goto fail;
                   2965:         }
                   2966:     } else {
                   2967:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   2968:         switch(type) {
                   2969:         case 1:
                   2970:         case 2:
                   2971:         case 3:
                   2972:         case 4:
                   2973:         case 5:
                   2974:         case 9:
                   2975:         case 11:
                   2976:         case 12:
                   2977:             break;
                   2978:         default:
                   2979:             goto fail;
                   2980:         }
                   2981:         if (dpl < cpl || dpl < rpl) {
                   2982:         fail:
                   2983:             CC_SRC = eflags & ~CC_Z;
                   2984:             return;
                   2985:         }
                   2986:     }
                   2987:     T1 = e2 & 0x00f0ff00;
                   2988:     CC_SRC = eflags | CC_Z;
                   2989: }
                   2990: 
                   2991: void helper_verr(void)
                   2992: {
                   2993:     unsigned int selector;
                   2994:     uint32_t e1, e2, eflags;
                   2995:     int rpl, dpl, cpl;
                   2996: 
                   2997:     eflags = cc_table[CC_OP].compute_all();
                   2998:     selector = T0 & 0xffff;
                   2999:     if ((selector & 0xfffc) == 0)
                   3000:         goto fail;
                   3001:     if (load_segment(&e1, &e2, selector) != 0)
                   3002:         goto fail;
                   3003:     if (!(e2 & DESC_S_MASK))
                   3004:         goto fail;
                   3005:     rpl = selector & 3;
                   3006:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   3007:     cpl = env->hflags & HF_CPL_MASK;
                   3008:     if (e2 & DESC_CS_MASK) {
                   3009:         if (!(e2 & DESC_R_MASK))
                   3010:             goto fail;
                   3011:         if (!(e2 & DESC_C_MASK)) {
                   3012:             if (dpl < cpl || dpl < rpl)
                   3013:                 goto fail;
                   3014:         }
                   3015:     } else {
                   3016:         if (dpl < cpl || dpl < rpl) {
                   3017:         fail:
                   3018:             CC_SRC = eflags & ~CC_Z;
                   3019:             return;
                   3020:         }
                   3021:     }
                   3022:     CC_SRC = eflags | CC_Z;
                   3023: }
                   3024: 
                   3025: void helper_verw(void)
                   3026: {
                   3027:     unsigned int selector;
                   3028:     uint32_t e1, e2, eflags;
                   3029:     int rpl, dpl, cpl;
                   3030: 
                   3031:     eflags = cc_table[CC_OP].compute_all();
                   3032:     selector = T0 & 0xffff;
                   3033:     if ((selector & 0xfffc) == 0)
                   3034:         goto fail;
                   3035:     if (load_segment(&e1, &e2, selector) != 0)
                   3036:         goto fail;
                   3037:     if (!(e2 & DESC_S_MASK))
                   3038:         goto fail;
                   3039:     rpl = selector & 3;
                   3040:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   3041:     cpl = env->hflags & HF_CPL_MASK;
                   3042:     if (e2 & DESC_CS_MASK) {
                   3043:         goto fail;
                   3044:     } else {
                   3045:         if (dpl < cpl || dpl < rpl)
                   3046:             goto fail;
                   3047:         if (!(e2 & DESC_W_MASK)) {
                   3048:         fail:
                   3049:             CC_SRC = eflags & ~CC_Z;
                   3050:             return;
                   3051:         }
                   3052:     }
                   3053:     CC_SRC = eflags | CC_Z;
                   3054: }
                   3055: 
                   3056: /* FPU helpers */
                   3057: 
                   3058: void helper_fldt_ST0_A0(void)
                   3059: {
                   3060:     int new_fpstt;
                   3061:     new_fpstt = (env->fpstt - 1) & 7;
                   3062:     env->fpregs[new_fpstt].d = helper_fldt(A0);
                   3063:     env->fpstt = new_fpstt;
                   3064:     env->fptags[new_fpstt] = 0; /* validate stack entry */
                   3065: }
                   3066: 
                   3067: void helper_fstt_ST0_A0(void)
                   3068: {
                   3069:     helper_fstt(ST0, A0);
                   3070: }
                   3071: 
1.1.1.6 ! root     3072: static void fpu_set_exception(int mask)
1.1       root     3073: {
                   3074:     env->fpus |= mask;
                   3075:     if (env->fpus & (~env->fpuc & FPUC_EM))
                   3076:         env->fpus |= FPUS_SE | FPUS_B;
                   3077: }
                   3078: 
                   3079: CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
                   3080: {
1.1.1.6 ! root     3081:     if (b == 0.0)
1.1       root     3082:         fpu_set_exception(FPUS_ZE);
                   3083:     return a / b;
                   3084: }
                   3085: 
                   3086: void fpu_raise_exception(void)
                   3087: {
                   3088:     if (env->cr[0] & CR0_NE_MASK) {
                   3089:         raise_exception(EXCP10_COPR);
1.1.1.6 ! root     3090:     }
        !          3091: #if !defined(CONFIG_USER_ONLY)
1.1       root     3092:     else {
                   3093:         cpu_set_ferr(env);
                   3094:     }
                   3095: #endif
                   3096: }
                   3097: 
                   3098: /* BCD ops */
                   3099: 
                   3100: void helper_fbld_ST0_A0(void)
                   3101: {
                   3102:     CPU86_LDouble tmp;
                   3103:     uint64_t val;
                   3104:     unsigned int v;
                   3105:     int i;
                   3106: 
                   3107:     val = 0;
                   3108:     for(i = 8; i >= 0; i--) {
                   3109:         v = ldub(A0 + i);
                   3110:         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
                   3111:     }
                   3112:     tmp = val;
                   3113:     if (ldub(A0 + 9) & 0x80)
                   3114:         tmp = -tmp;
                   3115:     fpush();
                   3116:     ST0 = tmp;
                   3117: }
                   3118: 
                   3119: void helper_fbst_ST0_A0(void)
                   3120: {
                   3121:     int v;
                   3122:     target_ulong mem_ref, mem_end;
                   3123:     int64_t val;
                   3124: 
                   3125:     val = floatx_to_int64(ST0, &env->fp_status);
                   3126:     mem_ref = A0;
                   3127:     mem_end = mem_ref + 9;
                   3128:     if (val < 0) {
                   3129:         stb(mem_end, 0x80);
                   3130:         val = -val;
                   3131:     } else {
                   3132:         stb(mem_end, 0x00);
                   3133:     }
                   3134:     while (mem_ref < mem_end) {
                   3135:         if (val == 0)
                   3136:             break;
                   3137:         v = val % 100;
                   3138:         val = val / 100;
                   3139:         v = ((v / 10) << 4) | (v % 10);
                   3140:         stb(mem_ref++, v);
                   3141:     }
                   3142:     while (mem_ref < mem_end) {
                   3143:         stb(mem_ref++, 0);
                   3144:     }
                   3145: }
                   3146: 
                   3147: void helper_f2xm1(void)
                   3148: {
                   3149:     ST0 = pow(2.0,ST0) - 1.0;
                   3150: }
                   3151: 
                   3152: void helper_fyl2x(void)
                   3153: {
                   3154:     CPU86_LDouble fptemp;
1.1.1.6 ! root     3155: 
1.1       root     3156:     fptemp = ST0;
                   3157:     if (fptemp>0.0){
                   3158:         fptemp = log(fptemp)/log(2.0);  /* log2(ST) */
                   3159:         ST1 *= fptemp;
                   3160:         fpop();
1.1.1.6 ! root     3161:     } else {
1.1       root     3162:         env->fpus &= (~0x4700);
                   3163:         env->fpus |= 0x400;
                   3164:     }
                   3165: }
                   3166: 
                   3167: void helper_fptan(void)
                   3168: {
                   3169:     CPU86_LDouble fptemp;
                   3170: 
                   3171:     fptemp = ST0;
                   3172:     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   3173:         env->fpus |= 0x400;
                   3174:     } else {
                   3175:         ST0 = tan(fptemp);
                   3176:         fpush();
                   3177:         ST0 = 1.0;
                   3178:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   3179:         /* the above code is for  |arg| < 2**52 only */
                   3180:     }
                   3181: }
                   3182: 
                   3183: void helper_fpatan(void)
                   3184: {
                   3185:     CPU86_LDouble fptemp, fpsrcop;
                   3186: 
                   3187:     fpsrcop = ST1;
                   3188:     fptemp = ST0;
                   3189:     ST1 = atan2(fpsrcop,fptemp);
                   3190:     fpop();
                   3191: }
                   3192: 
                   3193: void helper_fxtract(void)
                   3194: {
                   3195:     CPU86_LDoubleU temp;
                   3196:     unsigned int expdif;
                   3197: 
                   3198:     temp.d = ST0;
                   3199:     expdif = EXPD(temp) - EXPBIAS;
                   3200:     /*DP exponent bias*/
                   3201:     ST0 = expdif;
                   3202:     fpush();
                   3203:     BIASEXPONENT(temp);
                   3204:     ST0 = temp.d;
                   3205: }
                   3206: 
                   3207: void helper_fprem1(void)
                   3208: {
                   3209:     CPU86_LDouble dblq, fpsrcop, fptemp;
                   3210:     CPU86_LDoubleU fpsrcop1, fptemp1;
                   3211:     int expdif;
1.1.1.6 ! root     3212:     signed long long int q;
        !          3213: 
        !          3214:     if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
        !          3215:         ST0 = 0.0 / 0.0; /* NaN */
        !          3216:         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
        !          3217:         return;
        !          3218:     }
1.1       root     3219: 
                   3220:     fpsrcop = ST0;
                   3221:     fptemp = ST1;
                   3222:     fpsrcop1.d = fpsrcop;
                   3223:     fptemp1.d = fptemp;
                   3224:     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1.1.1.6 ! root     3225: 
        !          3226:     if (expdif < 0) {
        !          3227:         /* optimisation? taken from the AMD docs */
        !          3228:         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
        !          3229:         /* ST0 is unchanged */
        !          3230:         return;
        !          3231:     }
        !          3232: 
1.1       root     3233:     if (expdif < 53) {
                   3234:         dblq = fpsrcop / fptemp;
1.1.1.6 ! root     3235:         /* round dblq towards nearest integer */
        !          3236:         dblq = rint(dblq);
        !          3237:         ST0 = fpsrcop - fptemp * dblq;
        !          3238: 
        !          3239:         /* convert dblq to q by truncating towards zero */
        !          3240:         if (dblq < 0.0)
        !          3241:            q = (signed long long int)(-dblq);
        !          3242:         else
        !          3243:            q = (signed long long int)dblq;
        !          3244: 
1.1       root     3245:         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1.1.1.6 ! root     3246:                                 /* (C0,C3,C1) <-- (q2,q1,q0) */
        !          3247:         env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
        !          3248:         env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
        !          3249:         env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
1.1       root     3250:     } else {
                   3251:         env->fpus |= 0x400;  /* C2 <-- 1 */
1.1.1.6 ! root     3252:         fptemp = pow(2.0, expdif - 50);
1.1       root     3253:         fpsrcop = (ST0 / ST1) / fptemp;
1.1.1.6 ! root     3254:         /* fpsrcop = integer obtained by chopping */
        !          3255:         fpsrcop = (fpsrcop < 0.0) ?
        !          3256:                   -(floor(fabs(fpsrcop))) : floor(fpsrcop);
1.1       root     3257:         ST0 -= (ST1 * fpsrcop * fptemp);
                   3258:     }
                   3259: }
                   3260: 
                   3261: void helper_fprem(void)
                   3262: {
                   3263:     CPU86_LDouble dblq, fpsrcop, fptemp;
                   3264:     CPU86_LDoubleU fpsrcop1, fptemp1;
                   3265:     int expdif;
1.1.1.6 ! root     3266:     signed long long int q;
        !          3267: 
        !          3268:     if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
        !          3269:        ST0 = 0.0 / 0.0; /* NaN */
        !          3270:        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
        !          3271:        return;
        !          3272:     }
        !          3273: 
        !          3274:     fpsrcop = (CPU86_LDouble)ST0;
        !          3275:     fptemp = (CPU86_LDouble)ST1;
1.1       root     3276:     fpsrcop1.d = fpsrcop;
                   3277:     fptemp1.d = fptemp;
                   3278:     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
1.1.1.6 ! root     3279: 
        !          3280:     if (expdif < 0) {
        !          3281:         /* optimisation? taken from the AMD docs */
        !          3282:         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
        !          3283:         /* ST0 is unchanged */
        !          3284:         return;
        !          3285:     }
        !          3286: 
1.1       root     3287:     if ( expdif < 53 ) {
1.1.1.6 ! root     3288:         dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
        !          3289:         /* round dblq towards zero */
        !          3290:         dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
        !          3291:         ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
        !          3292: 
        !          3293:         /* convert dblq to q by truncating towards zero */
        !          3294:         if (dblq < 0.0)
        !          3295:            q = (signed long long int)(-dblq);
        !          3296:         else
        !          3297:            q = (signed long long int)dblq;
        !          3298: 
1.1       root     3299:         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
1.1.1.6 ! root     3300:                                 /* (C0,C3,C1) <-- (q2,q1,q0) */
        !          3301:         env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
        !          3302:         env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
        !          3303:         env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
1.1       root     3304:     } else {
1.1.1.6 ! root     3305:         int N = 32 + (expdif % 32); /* as per AMD docs */
1.1       root     3306:         env->fpus |= 0x400;  /* C2 <-- 1 */
1.1.1.6 ! root     3307:         fptemp = pow(2.0, (double)(expdif - N));
1.1       root     3308:         fpsrcop = (ST0 / ST1) / fptemp;
                   3309:         /* fpsrcop = integer obtained by chopping */
1.1.1.6 ! root     3310:         fpsrcop = (fpsrcop < 0.0) ?
        !          3311:                   -(floor(fabs(fpsrcop))) : floor(fpsrcop);
1.1       root     3312:         ST0 -= (ST1 * fpsrcop * fptemp);
                   3313:     }
                   3314: }
                   3315: 
                   3316: void helper_fyl2xp1(void)
                   3317: {
                   3318:     CPU86_LDouble fptemp;
                   3319: 
                   3320:     fptemp = ST0;
                   3321:     if ((fptemp+1.0)>0.0) {
                   3322:         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
                   3323:         ST1 *= fptemp;
                   3324:         fpop();
1.1.1.6 ! root     3325:     } else {
1.1       root     3326:         env->fpus &= (~0x4700);
                   3327:         env->fpus |= 0x400;
                   3328:     }
                   3329: }
                   3330: 
                   3331: void helper_fsqrt(void)
                   3332: {
                   3333:     CPU86_LDouble fptemp;
                   3334: 
                   3335:     fptemp = ST0;
1.1.1.6 ! root     3336:     if (fptemp<0.0) {
1.1       root     3337:         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
                   3338:         env->fpus |= 0x400;
                   3339:     }
                   3340:     ST0 = sqrt(fptemp);
                   3341: }
                   3342: 
                   3343: void helper_fsincos(void)
                   3344: {
                   3345:     CPU86_LDouble fptemp;
                   3346: 
                   3347:     fptemp = ST0;
                   3348:     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   3349:         env->fpus |= 0x400;
                   3350:     } else {
                   3351:         ST0 = sin(fptemp);
                   3352:         fpush();
                   3353:         ST0 = cos(fptemp);
                   3354:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   3355:         /* the above code is for  |arg| < 2**63 only */
                   3356:     }
                   3357: }
                   3358: 
                   3359: void helper_frndint(void)
                   3360: {
                   3361:     ST0 = floatx_round_to_int(ST0, &env->fp_status);
                   3362: }
                   3363: 
                   3364: void helper_fscale(void)
                   3365: {
1.1.1.6 ! root     3366:     ST0 = ldexp (ST0, (int)(ST1));
1.1       root     3367: }
                   3368: 
                   3369: void helper_fsin(void)
                   3370: {
                   3371:     CPU86_LDouble fptemp;
                   3372: 
                   3373:     fptemp = ST0;
                   3374:     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   3375:         env->fpus |= 0x400;
                   3376:     } else {
                   3377:         ST0 = sin(fptemp);
                   3378:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   3379:         /* the above code is for  |arg| < 2**53 only */
                   3380:     }
                   3381: }
                   3382: 
                   3383: void helper_fcos(void)
                   3384: {
                   3385:     CPU86_LDouble fptemp;
                   3386: 
                   3387:     fptemp = ST0;
                   3388:     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   3389:         env->fpus |= 0x400;
                   3390:     } else {
                   3391:         ST0 = cos(fptemp);
                   3392:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   3393:         /* the above code is for  |arg5 < 2**63 only */
                   3394:     }
                   3395: }
                   3396: 
                   3397: void helper_fxam_ST0(void)
                   3398: {
                   3399:     CPU86_LDoubleU temp;
                   3400:     int expdif;
                   3401: 
                   3402:     temp.d = ST0;
                   3403: 
                   3404:     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
                   3405:     if (SIGND(temp))
                   3406:         env->fpus |= 0x200; /* C1 <-- 1 */
                   3407: 
1.1.1.4   root     3408:     /* XXX: test fptags too */
1.1       root     3409:     expdif = EXPD(temp);
                   3410:     if (expdif == MAXEXPD) {
1.1.1.4   root     3411: #ifdef USE_X86LDOUBLE
                   3412:         if (MANTD(temp) == 0x8000000000000000ULL)
                   3413: #else
1.1       root     3414:         if (MANTD(temp) == 0)
1.1.1.4   root     3415: #endif
1.1       root     3416:             env->fpus |=  0x500 /*Infinity*/;
                   3417:         else
                   3418:             env->fpus |=  0x100 /*NaN*/;
                   3419:     } else if (expdif == 0) {
                   3420:         if (MANTD(temp) == 0)
                   3421:             env->fpus |=  0x4000 /*Zero*/;
                   3422:         else
                   3423:             env->fpus |= 0x4400 /*Denormal*/;
                   3424:     } else {
                   3425:         env->fpus |= 0x400;
                   3426:     }
                   3427: }
                   3428: 
                   3429: void helper_fstenv(target_ulong ptr, int data32)
                   3430: {
                   3431:     int fpus, fptag, exp, i;
                   3432:     uint64_t mant;
                   3433:     CPU86_LDoubleU tmp;
                   3434: 
                   3435:     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
                   3436:     fptag = 0;
                   3437:     for (i=7; i>=0; i--) {
                   3438:        fptag <<= 2;
                   3439:        if (env->fptags[i]) {
                   3440:             fptag |= 3;
                   3441:        } else {
                   3442:             tmp.d = env->fpregs[i].d;
                   3443:             exp = EXPD(tmp);
                   3444:             mant = MANTD(tmp);
                   3445:             if (exp == 0 && mant == 0) {
                   3446:                 /* zero */
                   3447:                fptag |= 1;
                   3448:            } else if (exp == 0 || exp == MAXEXPD
                   3449: #ifdef USE_X86LDOUBLE
                   3450:                        || (mant & (1LL << 63)) == 0
                   3451: #endif
                   3452:                        ) {
                   3453:                 /* NaNs, infinity, denormal */
                   3454:                 fptag |= 2;
                   3455:             }
                   3456:         }
                   3457:     }
                   3458:     if (data32) {
                   3459:         /* 32 bit */
                   3460:         stl(ptr, env->fpuc);
                   3461:         stl(ptr + 4, fpus);
                   3462:         stl(ptr + 8, fptag);
                   3463:         stl(ptr + 12, 0); /* fpip */
                   3464:         stl(ptr + 16, 0); /* fpcs */
                   3465:         stl(ptr + 20, 0); /* fpoo */
                   3466:         stl(ptr + 24, 0); /* fpos */
                   3467:     } else {
                   3468:         /* 16 bit */
                   3469:         stw(ptr, env->fpuc);
                   3470:         stw(ptr + 2, fpus);
                   3471:         stw(ptr + 4, fptag);
                   3472:         stw(ptr + 6, 0);
                   3473:         stw(ptr + 8, 0);
                   3474:         stw(ptr + 10, 0);
                   3475:         stw(ptr + 12, 0);
                   3476:     }
                   3477: }
                   3478: 
                   3479: void helper_fldenv(target_ulong ptr, int data32)
                   3480: {
                   3481:     int i, fpus, fptag;
                   3482: 
                   3483:     if (data32) {
                   3484:        env->fpuc = lduw(ptr);
                   3485:         fpus = lduw(ptr + 4);
                   3486:         fptag = lduw(ptr + 8);
                   3487:     }
                   3488:     else {
                   3489:        env->fpuc = lduw(ptr);
                   3490:         fpus = lduw(ptr + 2);
                   3491:         fptag = lduw(ptr + 4);
                   3492:     }
                   3493:     env->fpstt = (fpus >> 11) & 7;
                   3494:     env->fpus = fpus & ~0x3800;
                   3495:     for(i = 0;i < 8; i++) {
                   3496:         env->fptags[i] = ((fptag & 3) == 3);
                   3497:         fptag >>= 2;
                   3498:     }
                   3499: }
                   3500: 
                   3501: void helper_fsave(target_ulong ptr, int data32)
                   3502: {
                   3503:     CPU86_LDouble tmp;
                   3504:     int i;
                   3505: 
                   3506:     helper_fstenv(ptr, data32);
                   3507: 
                   3508:     ptr += (14 << data32);
                   3509:     for(i = 0;i < 8; i++) {
                   3510:         tmp = ST(i);
                   3511:         helper_fstt(tmp, ptr);
                   3512:         ptr += 10;
                   3513:     }
                   3514: 
                   3515:     /* fninit */
                   3516:     env->fpus = 0;
                   3517:     env->fpstt = 0;
                   3518:     env->fpuc = 0x37f;
                   3519:     env->fptags[0] = 1;
                   3520:     env->fptags[1] = 1;
                   3521:     env->fptags[2] = 1;
                   3522:     env->fptags[3] = 1;
                   3523:     env->fptags[4] = 1;
                   3524:     env->fptags[5] = 1;
                   3525:     env->fptags[6] = 1;
                   3526:     env->fptags[7] = 1;
                   3527: }
                   3528: 
                   3529: void helper_frstor(target_ulong ptr, int data32)
                   3530: {
                   3531:     CPU86_LDouble tmp;
                   3532:     int i;
                   3533: 
                   3534:     helper_fldenv(ptr, data32);
                   3535:     ptr += (14 << data32);
                   3536: 
                   3537:     for(i = 0;i < 8; i++) {
                   3538:         tmp = helper_fldt(ptr);
                   3539:         ST(i) = tmp;
                   3540:         ptr += 10;
                   3541:     }
                   3542: }
                   3543: 
                   3544: void helper_fxsave(target_ulong ptr, int data64)
                   3545: {
                   3546:     int fpus, fptag, i, nb_xmm_regs;
                   3547:     CPU86_LDouble tmp;
                   3548:     target_ulong addr;
                   3549: 
                   3550:     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
                   3551:     fptag = 0;
                   3552:     for(i = 0; i < 8; i++) {
                   3553:         fptag |= (env->fptags[i] << i);
                   3554:     }
                   3555:     stw(ptr, env->fpuc);
                   3556:     stw(ptr + 2, fpus);
                   3557:     stw(ptr + 4, fptag ^ 0xff);
                   3558: 
                   3559:     addr = ptr + 0x20;
                   3560:     for(i = 0;i < 8; i++) {
                   3561:         tmp = ST(i);
                   3562:         helper_fstt(tmp, addr);
                   3563:         addr += 16;
                   3564:     }
1.1.1.6 ! root     3565: 
1.1       root     3566:     if (env->cr[4] & CR4_OSFXSR_MASK) {
                   3567:         /* XXX: finish it */
                   3568:         stl(ptr + 0x18, env->mxcsr); /* mxcsr */
                   3569:         stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
                   3570:         nb_xmm_regs = 8 << data64;
                   3571:         addr = ptr + 0xa0;
                   3572:         for(i = 0; i < nb_xmm_regs; i++) {
                   3573:             stq(addr, env->xmm_regs[i].XMM_Q(0));
                   3574:             stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
                   3575:             addr += 16;
                   3576:         }
                   3577:     }
                   3578: }
                   3579: 
                   3580: void helper_fxrstor(target_ulong ptr, int data64)
                   3581: {
                   3582:     int i, fpus, fptag, nb_xmm_regs;
                   3583:     CPU86_LDouble tmp;
                   3584:     target_ulong addr;
                   3585: 
                   3586:     env->fpuc = lduw(ptr);
                   3587:     fpus = lduw(ptr + 2);
                   3588:     fptag = lduw(ptr + 4);
                   3589:     env->fpstt = (fpus >> 11) & 7;
                   3590:     env->fpus = fpus & ~0x3800;
                   3591:     fptag ^= 0xff;
                   3592:     for(i = 0;i < 8; i++) {
                   3593:         env->fptags[i] = ((fptag >> i) & 1);
                   3594:     }
                   3595: 
                   3596:     addr = ptr + 0x20;
                   3597:     for(i = 0;i < 8; i++) {
                   3598:         tmp = helper_fldt(addr);
                   3599:         ST(i) = tmp;
                   3600:         addr += 16;
                   3601:     }
                   3602: 
                   3603:     if (env->cr[4] & CR4_OSFXSR_MASK) {
                   3604:         /* XXX: finish it */
                   3605:         env->mxcsr = ldl(ptr + 0x18);
                   3606:         //ldl(ptr + 0x1c);
                   3607:         nb_xmm_regs = 8 << data64;
                   3608:         addr = ptr + 0xa0;
                   3609:         for(i = 0; i < nb_xmm_regs; i++) {
                   3610:             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
                   3611:             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
                   3612:             addr += 16;
                   3613:         }
                   3614:     }
                   3615: }
                   3616: 
                   3617: #ifndef USE_X86LDOUBLE
                   3618: 
                   3619: void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
                   3620: {
                   3621:     CPU86_LDoubleU temp;
                   3622:     int e;
                   3623: 
                   3624:     temp.d = f;
                   3625:     /* mantissa */
                   3626:     *pmant = (MANTD(temp) << 11) | (1LL << 63);
                   3627:     /* exponent + sign */
                   3628:     e = EXPD(temp) - EXPBIAS + 16383;
                   3629:     e |= SIGND(temp) >> 16;
                   3630:     *pexp = e;
                   3631: }
                   3632: 
                   3633: CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
                   3634: {
                   3635:     CPU86_LDoubleU temp;
                   3636:     int e;
                   3637:     uint64_t ll;
                   3638: 
                   3639:     /* XXX: handle overflow ? */
                   3640:     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
                   3641:     e |= (upper >> 4) & 0x800; /* sign */
                   3642:     ll = (mant >> 11) & ((1LL << 52) - 1);
                   3643: #ifdef __arm__
                   3644:     temp.l.upper = (e << 20) | (ll >> 32);
                   3645:     temp.l.lower = ll;
                   3646: #else
                   3647:     temp.ll = ll | ((uint64_t)e << 52);
                   3648: #endif
                   3649:     return temp.d;
                   3650: }
                   3651: 
                   3652: #else
                   3653: 
                   3654: void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
                   3655: {
                   3656:     CPU86_LDoubleU temp;
                   3657: 
                   3658:     temp.d = f;
                   3659:     *pmant = temp.l.lower;
                   3660:     *pexp = temp.l.upper;
                   3661: }
                   3662: 
                   3663: CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
                   3664: {
                   3665:     CPU86_LDoubleU temp;
                   3666: 
                   3667:     temp.l.upper = upper;
                   3668:     temp.l.lower = mant;
                   3669:     return temp.d;
                   3670: }
                   3671: #endif
                   3672: 
                   3673: #ifdef TARGET_X86_64
                   3674: 
                   3675: //#define DEBUG_MULDIV
                   3676: 
                   3677: static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
                   3678: {
                   3679:     *plow += a;
                   3680:     /* carry test */
                   3681:     if (*plow < a)
                   3682:         (*phigh)++;
                   3683:     *phigh += b;
                   3684: }
                   3685: 
                   3686: static void neg128(uint64_t *plow, uint64_t *phigh)
                   3687: {
                   3688:     *plow = ~ *plow;
                   3689:     *phigh = ~ *phigh;
                   3690:     add128(plow, phigh, 1, 0);
                   3691: }
                   3692: 
                   3693: /* return TRUE if overflow */
                   3694: static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
                   3695: {
                   3696:     uint64_t q, r, a1, a0;
1.1.1.2   root     3697:     int i, qb, ab;
1.1       root     3698: 
                   3699:     a0 = *plow;
                   3700:     a1 = *phigh;
                   3701:     if (a1 == 0) {
                   3702:         q = a0 / b;
                   3703:         r = a0 % b;
                   3704:         *plow = q;
                   3705:         *phigh = r;
                   3706:     } else {
                   3707:         if (a1 >= b)
                   3708:             return 1;
                   3709:         /* XXX: use a better algorithm */
                   3710:         for(i = 0; i < 64; i++) {
1.1.1.2   root     3711:             ab = a1 >> 63;
1.1       root     3712:             a1 = (a1 << 1) | (a0 >> 63);
1.1.1.2   root     3713:             if (ab || a1 >= b) {
1.1       root     3714:                 a1 -= b;
                   3715:                 qb = 1;
                   3716:             } else {
                   3717:                 qb = 0;
                   3718:             }
                   3719:             a0 = (a0 << 1) | qb;
                   3720:         }
                   3721: #if defined(DEBUG_MULDIV)
1.1.1.4   root     3722:         printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
1.1       root     3723:                *phigh, *plow, b, a0, a1);
                   3724: #endif
                   3725:         *plow = a0;
                   3726:         *phigh = a1;
                   3727:     }
                   3728:     return 0;
                   3729: }
                   3730: 
                   3731: /* return TRUE if overflow */
                   3732: static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
                   3733: {
                   3734:     int sa, sb;
                   3735:     sa = ((int64_t)*phigh < 0);
                   3736:     if (sa)
                   3737:         neg128(plow, phigh);
                   3738:     sb = (b < 0);
                   3739:     if (sb)
                   3740:         b = -b;
                   3741:     if (div64(plow, phigh, b) != 0)
                   3742:         return 1;
                   3743:     if (sa ^ sb) {
                   3744:         if (*plow > (1ULL << 63))
                   3745:             return 1;
                   3746:         *plow = - *plow;
                   3747:     } else {
                   3748:         if (*plow >= (1ULL << 63))
                   3749:             return 1;
                   3750:     }
                   3751:     if (sa)
                   3752:         *phigh = - *phigh;
                   3753:     return 0;
                   3754: }
                   3755: 
                   3756: void helper_mulq_EAX_T0(void)
                   3757: {
                   3758:     uint64_t r0, r1;
                   3759: 
1.1.1.6 ! root     3760:     mulu64(&r0, &r1, EAX, T0);
1.1       root     3761:     EAX = r0;
                   3762:     EDX = r1;
                   3763:     CC_DST = r0;
                   3764:     CC_SRC = r1;
                   3765: }
                   3766: 
                   3767: void helper_imulq_EAX_T0(void)
                   3768: {
                   3769:     uint64_t r0, r1;
                   3770: 
1.1.1.6 ! root     3771:     muls64(&r0, &r1, EAX, T0);
1.1       root     3772:     EAX = r0;
                   3773:     EDX = r1;
                   3774:     CC_DST = r0;
                   3775:     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
                   3776: }
                   3777: 
                   3778: void helper_imulq_T0_T1(void)
                   3779: {
                   3780:     uint64_t r0, r1;
                   3781: 
1.1.1.6 ! root     3782:     muls64(&r0, &r1, T0, T1);
1.1       root     3783:     T0 = r0;
                   3784:     CC_DST = r0;
                   3785:     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
                   3786: }
                   3787: 
                   3788: void helper_divq_EAX_T0(void)
                   3789: {
                   3790:     uint64_t r0, r1;
                   3791:     if (T0 == 0) {
                   3792:         raise_exception(EXCP00_DIVZ);
                   3793:     }
                   3794:     r0 = EAX;
                   3795:     r1 = EDX;
                   3796:     if (div64(&r0, &r1, T0))
                   3797:         raise_exception(EXCP00_DIVZ);
                   3798:     EAX = r0;
                   3799:     EDX = r1;
                   3800: }
                   3801: 
                   3802: void helper_idivq_EAX_T0(void)
                   3803: {
                   3804:     uint64_t r0, r1;
                   3805:     if (T0 == 0) {
                   3806:         raise_exception(EXCP00_DIVZ);
                   3807:     }
                   3808:     r0 = EAX;
                   3809:     r1 = EDX;
                   3810:     if (idiv64(&r0, &r1, T0))
                   3811:         raise_exception(EXCP00_DIVZ);
                   3812:     EAX = r0;
                   3813:     EDX = r1;
                   3814: }
                   3815: 
1.1.1.3   root     3816: void helper_bswapq_T0(void)
                   3817: {
                   3818:     T0 = bswap64(T0);
                   3819: }
1.1       root     3820: #endif
                   3821: 
1.1.1.4   root     3822: void helper_hlt(void)
                   3823: {
                   3824:     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
                   3825:     env->hflags |= HF_HALTED_MASK;
                   3826:     env->exception_index = EXCP_HLT;
                   3827:     cpu_loop_exit();
                   3828: }
                   3829: 
                   3830: void helper_monitor(void)
                   3831: {
1.1.1.5   root     3832:     if ((uint32_t)ECX != 0)
1.1.1.4   root     3833:         raise_exception(EXCP0D_GPF);
                   3834:     /* XXX: store address ? */
                   3835: }
                   3836: 
                   3837: void helper_mwait(void)
                   3838: {
1.1.1.5   root     3839:     if ((uint32_t)ECX != 0)
1.1.1.4   root     3840:         raise_exception(EXCP0D_GPF);
                   3841:     /* XXX: not complete but not completely erroneous */
                   3842:     if (env->cpu_index != 0 || env->next_cpu != NULL) {
                   3843:         /* more than one CPU: do not sleep because another CPU may
                   3844:            wake this one */
                   3845:     } else {
                   3846:         helper_hlt();
                   3847:     }
                   3848: }
                   3849: 
1.1       root     3850: float approx_rsqrt(float a)
                   3851: {
                   3852:     return 1.0 / sqrt(a);
                   3853: }
                   3854: 
                   3855: float approx_rcp(float a)
                   3856: {
                   3857:     return 1.0 / a;
                   3858: }
                   3859: 
                   3860: void update_fp_status(void)
                   3861: {
                   3862:     int rnd_type;
                   3863: 
                   3864:     /* set rounding mode */
                   3865:     switch(env->fpuc & RC_MASK) {
                   3866:     default:
                   3867:     case RC_NEAR:
                   3868:         rnd_type = float_round_nearest_even;
                   3869:         break;
                   3870:     case RC_DOWN:
                   3871:         rnd_type = float_round_down;
                   3872:         break;
                   3873:     case RC_UP:
                   3874:         rnd_type = float_round_up;
                   3875:         break;
                   3876:     case RC_CHOP:
                   3877:         rnd_type = float_round_to_zero;
                   3878:         break;
                   3879:     }
                   3880:     set_float_rounding_mode(rnd_type, &env->fp_status);
                   3881: #ifdef FLOATX80
                   3882:     switch((env->fpuc >> 8) & 3) {
                   3883:     case 0:
                   3884:         rnd_type = 32;
                   3885:         break;
                   3886:     case 2:
                   3887:         rnd_type = 64;
                   3888:         break;
                   3889:     case 3:
                   3890:     default:
                   3891:         rnd_type = 80;
                   3892:         break;
                   3893:     }
                   3894:     set_floatx80_rounding_precision(rnd_type, &env->fp_status);
                   3895: #endif
                   3896: }
                   3897: 
1.1.1.6 ! root     3898: #if !defined(CONFIG_USER_ONLY)
1.1       root     3899: 
                   3900: #define MMUSUFFIX _mmu
1.1.1.6 ! root     3901: #ifdef __s390__
        !          3902: # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
        !          3903: #else
        !          3904: # define GETPC() (__builtin_return_address(0))
        !          3905: #endif
1.1       root     3906: 
                   3907: #define SHIFT 0
                   3908: #include "softmmu_template.h"
                   3909: 
                   3910: #define SHIFT 1
                   3911: #include "softmmu_template.h"
                   3912: 
                   3913: #define SHIFT 2
                   3914: #include "softmmu_template.h"
                   3915: 
                   3916: #define SHIFT 3
                   3917: #include "softmmu_template.h"
                   3918: 
                   3919: #endif
                   3920: 
                   3921: /* try to fill the TLB and return an exception if error. If retaddr is
                   3922:    NULL, it means that the function was called in C code (i.e. not
                   3923:    from generated code or from helper.c) */
                   3924: /* XXX: fix it to restore all registers */
1.1.1.6 ! root     3925: void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1       root     3926: {
                   3927:     TranslationBlock *tb;
                   3928:     int ret;
                   3929:     unsigned long pc;
                   3930:     CPUX86State *saved_env;
                   3931: 
                   3932:     /* XXX: hack to restore env in all cases, even if not called from
                   3933:        generated code */
                   3934:     saved_env = env;
                   3935:     env = cpu_single_env;
                   3936: 
1.1.1.6 ! root     3937:     ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1       root     3938:     if (ret) {
                   3939:         if (retaddr) {
                   3940:             /* now we have a real cpu fault */
                   3941:             pc = (unsigned long)retaddr;
                   3942:             tb = tb_find_pc(pc);
                   3943:             if (tb) {
                   3944:                 /* the PC is inside the translated code. It means that we have
                   3945:                    a virtual CPU fault */
                   3946:                 cpu_restore_state(tb, env, pc, NULL);
                   3947:             }
                   3948:         }
                   3949:         if (retaddr)
1.1.1.2   root     3950:             raise_exception_err(env->exception_index, env->error_code);
1.1       root     3951:         else
1.1.1.2   root     3952:             raise_exception_err_norestore(env->exception_index, env->error_code);
1.1       root     3953:     }
                   3954:     env = saved_env;
                   3955: }
1.1.1.6 ! root     3956: 
        !          3957: 
        !          3958: /* Secure Virtual Machine helpers */
        !          3959: 
        !          3960: void helper_stgi(void)
        !          3961: {
        !          3962:     env->hflags |= HF_GIF_MASK;
        !          3963: }
        !          3964: 
        !          3965: void helper_clgi(void)
        !          3966: {
        !          3967:     env->hflags &= ~HF_GIF_MASK;
        !          3968: }
        !          3969: 
        !          3970: #if defined(CONFIG_USER_ONLY)
        !          3971: 
        !          3972: void helper_vmrun(target_ulong addr) { }
        !          3973: void helper_vmmcall(void) { }
        !          3974: void helper_vmload(target_ulong addr) { }
        !          3975: void helper_vmsave(target_ulong addr) { }
        !          3976: void helper_skinit(void) { }
        !          3977: void helper_invlpga(void) { }
        !          3978: void vmexit(uint64_t exit_code, uint64_t exit_info_1) { }
        !          3979: int svm_check_intercept_param(uint32_t type, uint64_t param)
        !          3980: {
        !          3981:     return 0;
        !          3982: }
        !          3983: 
        !          3984: #else
        !          3985: 
        !          3986: static inline uint32_t
        !          3987: vmcb2cpu_attrib(uint16_t vmcb_attrib, uint32_t vmcb_base, uint32_t vmcb_limit)
        !          3988: {
        !          3989:     return    ((vmcb_attrib & 0x00ff) << 8)          /* Type, S, DPL, P */
        !          3990:            | ((vmcb_attrib & 0x0f00) << 12)         /* AVL, L, DB, G */
        !          3991:            | ((vmcb_base >> 16) & 0xff)             /* Base 23-16 */
        !          3992:            | (vmcb_base & 0xff000000)               /* Base 31-24 */
        !          3993:            | (vmcb_limit & 0xf0000);                /* Limit 19-16 */
        !          3994: }
        !          3995: 
        !          3996: static inline uint16_t cpu2vmcb_attrib(uint32_t cpu_attrib)
        !          3997: {
        !          3998:     return    ((cpu_attrib >> 8) & 0xff)             /* Type, S, DPL, P */
        !          3999:            | ((cpu_attrib & 0xf00000) >> 12);       /* AVL, L, DB, G */
        !          4000: }
        !          4001: 
        !          4002: extern uint8_t *phys_ram_base;
        !          4003: void helper_vmrun(target_ulong addr)
        !          4004: {
        !          4005:     uint32_t event_inj;
        !          4006:     uint32_t int_ctl;
        !          4007: 
        !          4008:     if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4009:         fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
        !          4010: 
        !          4011:     env->vm_vmcb = addr;
        !          4012:     regs_to_env();
        !          4013: 
        !          4014:     /* save the current CPU state in the hsave page */
        !          4015:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
        !          4016:     stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
        !          4017: 
        !          4018:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
        !          4019:     stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
        !          4020: 
        !          4021:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
        !          4022:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
        !          4023:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
        !          4024:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
        !          4025:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8), env->cr[8]);
        !          4026:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
        !          4027:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
        !          4028: 
        !          4029:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
        !          4030:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
        !          4031: 
        !          4032:     SVM_SAVE_SEG(env->vm_hsave, segs[R_ES], es);
        !          4033:     SVM_SAVE_SEG(env->vm_hsave, segs[R_CS], cs);
        !          4034:     SVM_SAVE_SEG(env->vm_hsave, segs[R_SS], ss);
        !          4035:     SVM_SAVE_SEG(env->vm_hsave, segs[R_DS], ds);
        !          4036: 
        !          4037:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP);
        !          4038:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
        !          4039:     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
        !          4040: 
        !          4041:     /* load the interception bitmaps so we do not need to access the
        !          4042:        vmcb in svm mode */
        !          4043:     /* We shift all the intercept bits so we can OR them with the TB
        !          4044:        flags later on */
        !          4045:     env->intercept            = (ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept)) << INTERCEPT_INTR) | INTERCEPT_SVM_MASK;
        !          4046:     env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
        !          4047:     env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
        !          4048:     env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
        !          4049:     env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
        !          4050:     env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
        !          4051: 
        !          4052:     env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
        !          4053:     env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
        !          4054: 
        !          4055:     env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
        !          4056:     env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
        !          4057: 
        !          4058:     /* clear exit_info_2 so we behave like the real hardware */
        !          4059:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
        !          4060: 
        !          4061:     cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
        !          4062:     cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
        !          4063:     cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
        !          4064:     env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
        !          4065:     int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
        !          4066:     if (int_ctl & V_INTR_MASKING_MASK) {
        !          4067:         env->cr[8] = int_ctl & V_TPR_MASK;
        !          4068:         if (env->eflags & IF_MASK)
        !          4069:             env->hflags |= HF_HIF_MASK;
        !          4070:     }
        !          4071: 
        !          4072: #ifdef TARGET_X86_64
        !          4073:     env->efer = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer));
        !          4074:     env->hflags &= ~HF_LMA_MASK;
        !          4075:     if (env->efer & MSR_EFER_LMA)
        !          4076:        env->hflags |= HF_LMA_MASK;
        !          4077: #endif
        !          4078:     env->eflags = 0;
        !          4079:     load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
        !          4080:                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
        !          4081:     CC_OP = CC_OP_EFLAGS;
        !          4082:     CC_DST = 0xffffffff;
        !          4083: 
        !          4084:     SVM_LOAD_SEG(env->vm_vmcb, ES, es);
        !          4085:     SVM_LOAD_SEG(env->vm_vmcb, CS, cs);
        !          4086:     SVM_LOAD_SEG(env->vm_vmcb, SS, ss);
        !          4087:     SVM_LOAD_SEG(env->vm_vmcb, DS, ds);
        !          4088: 
        !          4089:     EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
        !          4090:     env->eip = EIP;
        !          4091:     ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
        !          4092:     EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
        !          4093:     env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
        !          4094:     env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
        !          4095:     cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
        !          4096: 
        !          4097:     /* FIXME: guest state consistency checks */
        !          4098: 
        !          4099:     switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
        !          4100:         case TLB_CONTROL_DO_NOTHING:
        !          4101:             break;
        !          4102:         case TLB_CONTROL_FLUSH_ALL_ASID:
        !          4103:             /* FIXME: this is not 100% correct but should work for now */
        !          4104:             tlb_flush(env, 1);
        !          4105:         break;
        !          4106:     }
        !          4107: 
        !          4108:     helper_stgi();
        !          4109: 
        !          4110:     regs_to_env();
        !          4111: 
        !          4112:     /* maybe we need to inject an event */
        !          4113:     event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
        !          4114:     if (event_inj & SVM_EVTINJ_VALID) {
        !          4115:         uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
        !          4116:         uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
        !          4117:         uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
        !          4118:         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
        !          4119: 
        !          4120:         if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4121:             fprintf(logfile, "Injecting(%#hx): ", valid_err);
        !          4122:         /* FIXME: need to implement valid_err */
        !          4123:         switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
        !          4124:         case SVM_EVTINJ_TYPE_INTR:
        !          4125:                 env->exception_index = vector;
        !          4126:                 env->error_code = event_inj_err;
        !          4127:                 env->exception_is_int = 1;
        !          4128:                 env->exception_next_eip = -1;
        !          4129:                 if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4130:                     fprintf(logfile, "INTR");
        !          4131:                 break;
        !          4132:         case SVM_EVTINJ_TYPE_NMI:
        !          4133:                 env->exception_index = vector;
        !          4134:                 env->error_code = event_inj_err;
        !          4135:                 env->exception_is_int = 1;
        !          4136:                 env->exception_next_eip = EIP;
        !          4137:                 if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4138:                     fprintf(logfile, "NMI");
        !          4139:                 break;
        !          4140:         case SVM_EVTINJ_TYPE_EXEPT:
        !          4141:                 env->exception_index = vector;
        !          4142:                 env->error_code = event_inj_err;
        !          4143:                 env->exception_is_int = 0;
        !          4144:                 env->exception_next_eip = -1;
        !          4145:                 if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4146:                     fprintf(logfile, "EXEPT");
        !          4147:                 break;
        !          4148:         case SVM_EVTINJ_TYPE_SOFT:
        !          4149:                 env->exception_index = vector;
        !          4150:                 env->error_code = event_inj_err;
        !          4151:                 env->exception_is_int = 1;
        !          4152:                 env->exception_next_eip = EIP;
        !          4153:                 if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4154:                     fprintf(logfile, "SOFT");
        !          4155:                 break;
        !          4156:         }
        !          4157:         if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4158:             fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
        !          4159:     }
        !          4160:     if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) {
        !          4161:         env->interrupt_request |= CPU_INTERRUPT_VIRQ;
        !          4162:     }
        !          4163: 
        !          4164:     cpu_loop_exit();
        !          4165: }
        !          4166: 
        !          4167: void helper_vmmcall(void)
        !          4168: {
        !          4169:     if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4170:         fprintf(logfile,"vmmcall!\n");
        !          4171: }
        !          4172: 
        !          4173: void helper_vmload(target_ulong addr)
        !          4174: {
        !          4175:     if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4176:         fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
        !          4177:                 addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
        !          4178:                 env->segs[R_FS].base);
        !          4179: 
        !          4180:     SVM_LOAD_SEG2(addr, segs[R_FS], fs);
        !          4181:     SVM_LOAD_SEG2(addr, segs[R_GS], gs);
        !          4182:     SVM_LOAD_SEG2(addr, tr, tr);
        !          4183:     SVM_LOAD_SEG2(addr, ldt, ldtr);
        !          4184: 
        !          4185: #ifdef TARGET_X86_64
        !          4186:     env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
        !          4187:     env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
        !          4188:     env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
        !          4189:     env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
        !          4190: #endif
        !          4191:     env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
        !          4192:     env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
        !          4193:     env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
        !          4194:     env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
        !          4195: }
        !          4196: 
        !          4197: void helper_vmsave(target_ulong addr)
        !          4198: {
        !          4199:     if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4200:         fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
        !          4201:                 addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
        !          4202:                 env->segs[R_FS].base);
        !          4203: 
        !          4204:     SVM_SAVE_SEG(addr, segs[R_FS], fs);
        !          4205:     SVM_SAVE_SEG(addr, segs[R_GS], gs);
        !          4206:     SVM_SAVE_SEG(addr, tr, tr);
        !          4207:     SVM_SAVE_SEG(addr, ldt, ldtr);
        !          4208: 
        !          4209: #ifdef TARGET_X86_64
        !          4210:     stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
        !          4211:     stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
        !          4212:     stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
        !          4213:     stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
        !          4214: #endif
        !          4215:     stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
        !          4216:     stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
        !          4217:     stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
        !          4218:     stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
        !          4219: }
        !          4220: 
        !          4221: void helper_skinit(void)
        !          4222: {
        !          4223:     if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4224:         fprintf(logfile,"skinit!\n");
        !          4225: }
        !          4226: 
        !          4227: void helper_invlpga(void)
        !          4228: {
        !          4229:     tlb_flush(env, 0);
        !          4230: }
        !          4231: 
        !          4232: int svm_check_intercept_param(uint32_t type, uint64_t param)
        !          4233: {
        !          4234:     switch(type) {
        !          4235:     case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
        !          4236:         if (INTERCEPTEDw(_cr_read, (1 << (type - SVM_EXIT_READ_CR0)))) {
        !          4237:             vmexit(type, param);
        !          4238:             return 1;
        !          4239:         }
        !          4240:         break;
        !          4241:     case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 8:
        !          4242:         if (INTERCEPTEDw(_dr_read, (1 << (type - SVM_EXIT_READ_DR0)))) {
        !          4243:             vmexit(type, param);
        !          4244:             return 1;
        !          4245:         }
        !          4246:         break;
        !          4247:     case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
        !          4248:         if (INTERCEPTEDw(_cr_write, (1 << (type - SVM_EXIT_WRITE_CR0)))) {
        !          4249:             vmexit(type, param);
        !          4250:             return 1;
        !          4251:         }
        !          4252:         break;
        !          4253:     case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 8:
        !          4254:         if (INTERCEPTEDw(_dr_write, (1 << (type - SVM_EXIT_WRITE_DR0)))) {
        !          4255:             vmexit(type, param);
        !          4256:             return 1;
        !          4257:         }
        !          4258:         break;
        !          4259:     case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 16:
        !          4260:         if (INTERCEPTEDl(_exceptions, (1 << (type - SVM_EXIT_EXCP_BASE)))) {
        !          4261:             vmexit(type, param);
        !          4262:             return 1;
        !          4263:         }
        !          4264:         break;
        !          4265:     case SVM_EXIT_IOIO:
        !          4266:         if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) {
        !          4267:             /* FIXME: this should be read in at vmrun (faster this way?) */
        !          4268:             uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
        !          4269:             uint16_t port = (uint16_t) (param >> 16);
        !          4270: 
        !          4271:             uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
        !          4272:             if(lduw_phys(addr + port / 8) & (mask << (port & 7)))
        !          4273:                 vmexit(type, param);
        !          4274:         }
        !          4275:         break;
        !          4276: 
        !          4277:     case SVM_EXIT_MSR:
        !          4278:         if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) {
        !          4279:             /* FIXME: this should be read in at vmrun (faster this way?) */
        !          4280:             uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
        !          4281:             switch((uint32_t)ECX) {
        !          4282:             case 0 ... 0x1fff:
        !          4283:                 T0 = (ECX * 2) % 8;
        !          4284:                 T1 = ECX / 8;
        !          4285:                 break;
        !          4286:             case 0xc0000000 ... 0xc0001fff:
        !          4287:                 T0 = (8192 + ECX - 0xc0000000) * 2;
        !          4288:                 T1 = (T0 / 8);
        !          4289:                 T0 %= 8;
        !          4290:                 break;
        !          4291:             case 0xc0010000 ... 0xc0011fff:
        !          4292:                 T0 = (16384 + ECX - 0xc0010000) * 2;
        !          4293:                 T1 = (T0 / 8);
        !          4294:                 T0 %= 8;
        !          4295:                 break;
        !          4296:             default:
        !          4297:                 vmexit(type, param);
        !          4298:                 return 1;
        !          4299:             }
        !          4300:             if (ldub_phys(addr + T1) & ((1 << param) << T0))
        !          4301:                 vmexit(type, param);
        !          4302:             return 1;
        !          4303:         }
        !          4304:         break;
        !          4305:     default:
        !          4306:         if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) {
        !          4307:             vmexit(type, param);
        !          4308:             return 1;
        !          4309:         }
        !          4310:         break;
        !          4311:     }
        !          4312:     return 0;
        !          4313: }
        !          4314: 
        !          4315: void vmexit(uint64_t exit_code, uint64_t exit_info_1)
        !          4316: {
        !          4317:     uint32_t int_ctl;
        !          4318: 
        !          4319:     if (loglevel & CPU_LOG_TB_IN_ASM)
        !          4320:         fprintf(logfile,"vmexit(%016" PRIx64 ", %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
        !          4321:                 exit_code, exit_info_1,
        !          4322:                 ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
        !          4323:                 EIP);
        !          4324: 
        !          4325:     if(env->hflags & HF_INHIBIT_IRQ_MASK) {
        !          4326:         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
        !          4327:         env->hflags &= ~HF_INHIBIT_IRQ_MASK;
        !          4328:     } else {
        !          4329:         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
        !          4330:     }
        !          4331: 
        !          4332:     /* Save the VM state in the vmcb */
        !          4333:     SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es);
        !          4334:     SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs);
        !          4335:     SVM_SAVE_SEG(env->vm_vmcb, segs[R_SS], ss);
        !          4336:     SVM_SAVE_SEG(env->vm_vmcb, segs[R_DS], ds);
        !          4337: 
        !          4338:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
        !          4339:     stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
        !          4340: 
        !          4341:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
        !          4342:     stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
        !          4343: 
        !          4344:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
        !          4345:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
        !          4346:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
        !          4347:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
        !          4348:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
        !          4349: 
        !          4350:     if ((int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl))) & V_INTR_MASKING_MASK) {
        !          4351:         int_ctl &= ~V_TPR_MASK;
        !          4352:         int_ctl |= env->cr[8] & V_TPR_MASK;
        !          4353:         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
        !          4354:     }
        !          4355: 
        !          4356:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
        !          4357:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
        !          4358:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
        !          4359:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
        !          4360:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
        !          4361:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
        !          4362:     stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
        !          4363: 
        !          4364:     /* Reload the host state from vm_hsave */
        !          4365:     env->hflags &= ~HF_HIF_MASK;
        !          4366:     env->intercept = 0;
        !          4367:     env->intercept_exceptions = 0;
        !          4368:     env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
        !          4369: 
        !          4370:     env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
        !          4371:     env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
        !          4372: 
        !          4373:     env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
        !          4374:     env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
        !          4375: 
        !          4376:     cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
        !          4377:     cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
        !          4378:     cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
        !          4379:     if (int_ctl & V_INTR_MASKING_MASK)
        !          4380:         env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8));
        !          4381:     /* we need to set the efer after the crs so the hidden flags get set properly */
        !          4382: #ifdef TARGET_X86_64
        !          4383:     env->efer  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer));
        !          4384:     env->hflags &= ~HF_LMA_MASK;
        !          4385:     if (env->efer & MSR_EFER_LMA)
        !          4386:        env->hflags |= HF_LMA_MASK;
        !          4387: #endif
        !          4388: 
        !          4389:     env->eflags = 0;
        !          4390:     load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
        !          4391:                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
        !          4392:     CC_OP = CC_OP_EFLAGS;
        !          4393: 
        !          4394:     SVM_LOAD_SEG(env->vm_hsave, ES, es);
        !          4395:     SVM_LOAD_SEG(env->vm_hsave, CS, cs);
        !          4396:     SVM_LOAD_SEG(env->vm_hsave, SS, ss);
        !          4397:     SVM_LOAD_SEG(env->vm_hsave, DS, ds);
        !          4398: 
        !          4399:     EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
        !          4400:     ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
        !          4401:     EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
        !          4402: 
        !          4403:     env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
        !          4404:     env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
        !          4405: 
        !          4406:     /* other setups */
        !          4407:     cpu_x86_set_cpl(env, 0);
        !          4408:     stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code_hi), (uint32_t)(exit_code >> 32));
        !          4409:     stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
        !          4410:     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
        !          4411: 
        !          4412:     helper_clgi();
        !          4413:     /* FIXME: Resets the current ASID register to zero (host ASID). */
        !          4414: 
        !          4415:     /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
        !          4416: 
        !          4417:     /* Clears the TSC_OFFSET inside the processor. */
        !          4418: 
        !          4419:     /* If the host is in PAE mode, the processor reloads the host's PDPEs
        !          4420:        from the page table indicated the host's CR3. If the PDPEs contain
        !          4421:        illegal state, the processor causes a shutdown. */
        !          4422: 
        !          4423:     /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
        !          4424:     env->cr[0] |= CR0_PE_MASK;
        !          4425:     env->eflags &= ~VM_MASK;
        !          4426: 
        !          4427:     /* Disables all breakpoints in the host DR7 register. */
        !          4428: 
        !          4429:     /* Checks the reloaded host state for consistency. */
        !          4430: 
        !          4431:     /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
        !          4432:        host's code segment or non-canonical (in the case of long mode), a
        !          4433:        #GP fault is delivered inside the host.) */
        !          4434: 
        !          4435:     /* remove any pending exception */
        !          4436:     env->exception_index = -1;
        !          4437:     env->error_code = 0;
        !          4438:     env->old_exception = -1;
        !          4439: 
        !          4440:     regs_to_env();
        !          4441:     cpu_loop_exit();
        !          4442: }
        !          4443: 
        !          4444: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.