/[qemu]/qemu/target-i386/helper.c
ViewVC logotype

Diff of /qemu/target-i386/helper.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.47 by bellard, Sun Apr 17 19:50:21 2005 UTC revision 1.48 by bellard, Sat Apr 23 17:48:47 2005 UTC
# Line 933  static void do_interrupt64(int intno, in Line 933  static void do_interrupt64(int intno, in
933      }      }
934      env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);      env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
935  }  }
936    #endif
937    
938  void helper_syscall(int next_eip_addend)  void helper_syscall(int next_eip_addend)
939  {  {
# Line 942  void helper_syscall(int next_eip_addend) Line 943  void helper_syscall(int next_eip_addend)
943          raise_exception_err(EXCP06_ILLOP, 0);          raise_exception_err(EXCP06_ILLOP, 0);
944      }      }
945      selector = (env->star >> 32) & 0xffff;      selector = (env->star >> 32) & 0xffff;
946    #ifdef TARGET_X86_64
947      if (env->hflags & HF_LMA_MASK) {      if (env->hflags & HF_LMA_MASK) {
948          ECX = env->eip + next_eip_addend;          ECX = env->eip + next_eip_addend;
949          env->regs[11] = compute_eflags();          env->regs[11] = compute_eflags();
# Line 962  void helper_syscall(int next_eip_addend) Line 964  void helper_syscall(int next_eip_addend)
964              env->eip = env->lstar;              env->eip = env->lstar;
965          else          else
966              env->eip = env->cstar;              env->eip = env->cstar;
967      } else {      } else
968    #endif
969        {
970          ECX = (uint32_t)(env->eip + next_eip_addend);          ECX = (uint32_t)(env->eip + next_eip_addend);
971                    
972          cpu_x86_set_cpl(env, 0);          cpu_x86_set_cpl(env, 0);
# Line 985  void helper_sysret(int dflag) Line 989  void helper_sysret(int dflag)
989  {  {
990      int cpl, selector;      int cpl, selector;
991    
992        if (!(env->efer & MSR_EFER_SCE)) {
993            raise_exception_err(EXCP06_ILLOP, 0);
994        }
995      cpl = env->hflags & HF_CPL_MASK;      cpl = env->hflags & HF_CPL_MASK;
996      if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {      if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
997          raise_exception_err(EXCP0D_GPF, 0);          raise_exception_err(EXCP0D_GPF, 0);
998      }      }
999      selector = (env->star >> 48) & 0xffff;      selector = (env->star >> 48) & 0xffff;
1000    #ifdef TARGET_X86_64
1001      if (env->hflags & HF_LMA_MASK) {      if (env->hflags & HF_LMA_MASK) {
1002          if (dflag == 2) {          if (dflag == 2) {
1003              cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,              cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
# Line 1015  void helper_sysret(int dflag) Line 1023  void helper_sysret(int dflag)
1023          load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |          load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |
1024                      IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);                      IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
1025          cpu_x86_set_cpl(env, 3);          cpu_x86_set_cpl(env, 3);
1026      } else {      } else
1027    #endif
1028        {
1029          cpu_x86_load_seg_cache(env, R_CS, selector | 3,          cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1030                                 0, 0xffffffff,                                 0, 0xffffffff,
1031                                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
# Line 1030  void helper_sysret(int dflag) Line 1040  void helper_sysret(int dflag)
1040          env->eflags |= IF_MASK;          env->eflags |= IF_MASK;
1041          cpu_x86_set_cpl(env, 3);          cpu_x86_set_cpl(env, 3);
1042      }      }
1043  }  #ifdef USE_KQEMU
1044        if (kqemu_is_ok(env)) {
1045            if (env->hflags & HF_LMA_MASK)
1046                CC_OP = CC_OP_EFLAGS;
1047            env->exception_index = -1;
1048            cpu_loop_exit();
1049        }
1050  #endif  #endif
1051    }
1052    
1053  /* real mode interrupt */  /* real mode interrupt */
1054  static void do_interrupt_real(int intno, int is_int, int error_code,  static void do_interrupt_real(int intno, int is_int, int error_code,
# Line 1265  void helper_cmpxchg8b(void) Line 1282  void helper_cmpxchg8b(void)
1282    
1283  void helper_cpuid(void)  void helper_cpuid(void)
1284  {  {
1285      switch((uint32_t)EAX) {      uint32_t index;
1286        index = (uint32_t)EAX;
1287        
1288        /* test if maximum index reached */
1289        if (index & 0x80000000) {
1290            if (index > env->cpuid_xlevel)
1291                index = env->cpuid_level;
1292        } else {
1293            if (index > env->cpuid_level)
1294                index = env->cpuid_level;
1295        }
1296            
1297        switch(index) {
1298      case 0:      case 0:
1299          EAX = 2; /* max EAX index supported */          EAX = env->cpuid_level;
1300          EBX = env->cpuid_vendor1;          EBX = env->cpuid_vendor1;
1301          EDX = env->cpuid_vendor2;          EDX = env->cpuid_vendor2;
1302          ECX = env->cpuid_vendor3;          ECX = env->cpuid_vendor3;
# Line 1278  void helper_cpuid(void) Line 1307  void helper_cpuid(void)
1307          ECX = env->cpuid_ext_features;          ECX = env->cpuid_ext_features;
1308          EDX = env->cpuid_features;          EDX = env->cpuid_features;
1309          break;          break;
1310      default:      case 2:
1311          /* cache info: needed for Pentium Pro compatibility */          /* cache info: needed for Pentium Pro compatibility */
1312          EAX = 0x410601;          EAX = 0x410601;
1313          EBX = 0;          EBX = 0;
1314          ECX = 0;          ECX = 0;
1315          EDX = 0;          EDX = 0;
1316          break;          break;
 #ifdef TARGET_X86_64  
1317      case 0x80000000:      case 0x80000000:
1318          EAX = 0x80000008;          EAX = env->cpuid_xlevel;
1319          EBX = env->cpuid_vendor1;          EBX = env->cpuid_vendor1;
1320          EDX = env->cpuid_vendor2;          EDX = env->cpuid_vendor2;
1321          ECX = env->cpuid_vendor3;          ECX = env->cpuid_vendor3;
# Line 1296  void helper_cpuid(void) Line 1324  void helper_cpuid(void)
1324          EAX = env->cpuid_features;          EAX = env->cpuid_features;
1325          EBX = 0;          EBX = 0;
1326          ECX = 0;          ECX = 0;
1327          /* long mode + syscall/sysret features */          EDX = env->cpuid_ext2_features;
1328          EDX = (env->cpuid_features & 0x0183F3FF) | (1 << 29) | (1 << 11);          break;
1329        case 0x80000002:
1330        case 0x80000003:
1331        case 0x80000004:
1332            EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
1333            EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
1334            ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
1335            EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
1336          break;          break;
1337      case 0x80000008:      case 0x80000008:
1338          /* virtual & phys address size in low 2 bytes. */          /* virtual & phys address size in low 2 bytes. */
# Line 1306  void helper_cpuid(void) Line 1341  void helper_cpuid(void)
1341          ECX = 0;          ECX = 0;
1342          EDX = 0;          EDX = 0;
1343          break;          break;
1344  #endif      default:
1345            /* reserved values: zero */
1346            EAX = 0;
1347            EBX = 0;
1348            ECX = 0;
1349            EDX = 0;
1350            break;
1351      }      }
1352  }  }
1353    
# Line 1523  void load_seg(int seg_reg, int selector) Line 1564  void load_seg(int seg_reg, int selector)
1564  }  }
1565    
1566  /* protected mode jump */  /* protected mode jump */
1567  void helper_ljmp_protected_T0_T1(int next_eip)  void helper_ljmp_protected_T0_T1(int next_eip_addend)
1568  {  {
1569      int new_cs, gate_cs, type;      int new_cs, gate_cs, type;
1570      uint32_t e1, e2, cpl, dpl, rpl, limit;      uint32_t e1, e2, cpl, dpl, rpl, limit;
1571      target_ulong new_eip;      target_ulong new_eip, next_eip;
1572            
1573      new_cs = T0;      new_cs = T0;
1574      new_eip = T1;      new_eip = T1;
# Line 1573  void helper_ljmp_protected_T0_T1(int nex Line 1614  void helper_ljmp_protected_T0_T1(int nex
1614          case 5: /* task gate */          case 5: /* task gate */
1615              if (dpl < cpl || dpl < rpl)              if (dpl < cpl || dpl < rpl)
1616                  raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);                  raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1617                next_eip = env->eip + next_eip_addend;
1618              switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);              switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
1619              break;              break;
1620          case 4: /* 286 call gate */          case 4: /* 286 call gate */
# Line 1638  void helper_lcall_real_T0_T1(int shift, Line 1680  void helper_lcall_real_T0_T1(int shift,
1680  }  }
1681    
1682  /* protected mode call */  /* protected mode call */
1683  void helper_lcall_protected_T0_T1(int shift, int next_eip)  void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
1684  {  {
1685      int new_cs, new_eip, new_stack, i;      int new_cs, new_eip, new_stack, i;
1686      uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;      uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
1687      uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;      uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
1688      uint32_t val, limit, old_sp_mask;      uint32_t val, limit, old_sp_mask;
1689      target_ulong ssp, old_ssp;      target_ulong ssp, old_ssp, next_eip;
1690            
1691      new_cs = T0;      new_cs = T0;
1692      new_eip = T1;      new_eip = T1;
1693        next_eip = env->eip + next_eip_addend;
1694  #ifdef DEBUG_PCALL  #ifdef DEBUG_PCALL
1695      if (loglevel & CPU_LOG_PCALL) {      if (loglevel & CPU_LOG_PCALL) {
1696          fprintf(logfile, "lcall %04x:%08x s=%d\n",          fprintf(logfile, "lcall %04x:%08x s=%d\n",
# Line 1684  void helper_lcall_protected_T0_T1(int sh Line 1727  void helper_lcall_protected_T0_T1(int sh
1727          if (!(e2 & DESC_P_MASK))          if (!(e2 & DESC_P_MASK))
1728              raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);              raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1729    
1730          sp = ESP;  #ifdef TARGET_X86_64
1731          sp_mask = get_sp_mask(env->segs[R_SS].flags);          /* XXX: check 16/32 bit cases in long mode */
1732          ssp = env->segs[R_SS].base;          if (shift == 2) {
1733          if (shift) {              target_ulong rsp;
1734              PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);              /* 64 bit case */
1735              PUSHL(ssp, sp, sp_mask, next_eip);              rsp = ESP;
1736          } else {              PUSHQ(rsp, env->segs[R_CS].selector);
1737              PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);              PUSHQ(rsp, next_eip);
1738              PUSHW(ssp, sp, sp_mask, next_eip);              /* from this point, not restartable */
1739                ESP = rsp;
1740                cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1741                                       get_seg_base(e1, e2),
1742                                       get_seg_limit(e1, e2), e2);
1743                EIP = new_eip;
1744            } else
1745    #endif
1746            {
1747                sp = ESP;
1748                sp_mask = get_sp_mask(env->segs[R_SS].flags);
1749                ssp = env->segs[R_SS].base;
1750                if (shift) {
1751                    PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1752                    PUSHL(ssp, sp, sp_mask, next_eip);
1753                } else {
1754                    PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1755                    PUSHW(ssp, sp, sp_mask, next_eip);
1756                }
1757                
1758                limit = get_seg_limit(e1, e2);
1759                if (new_eip > limit)
1760                    raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1761                /* from this point, not restartable */
1762                ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1763                cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1764                                       get_seg_base(e1, e2), limit, e2);
1765                EIP = new_eip;
1766          }          }
           
         limit = get_seg_limit(e1, e2);  
         if (new_eip > limit)  
             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);  
         /* from this point, not restartable */  
         ESP = (ESP & ~sp_mask) | (sp & sp_mask);  
         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,  
                        get_seg_base(e1, e2), limit, e2);  
         EIP = new_eip;  
1767      } else {      } else {
1768          /* check gate type */          /* check gate type */
1769          type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;          type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
# Line 2245  void helper_wrmsr(void) Line 2306  void helper_wrmsr(void)
2306      case MSR_IA32_APICBASE:      case MSR_IA32_APICBASE:
2307          cpu_set_apic_base(env, val);          cpu_set_apic_base(env, val);
2308          break;          break;
 #ifdef TARGET_X86_64  
2309      case MSR_EFER:      case MSR_EFER:
2310  #define MSR_EFER_UPDATE_MASK (MSR_EFER_SCE | MSR_EFER_LME | \          {
2311                                MSR_EFER_NXE | MSR_EFER_FFXSR)              uint64_t update_mask;
2312          env->efer = (env->efer & ~MSR_EFER_UPDATE_MASK) |              update_mask = 0;
2313              (val & MSR_EFER_UPDATE_MASK);              if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
2314                    update_mask |= MSR_EFER_SCE;
2315                if (env->cpuid_ext2_features & CPUID_EXT2_LM)
2316                    update_mask |= MSR_EFER_LME;
2317                if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
2318                    update_mask |= MSR_EFER_FFXSR;
2319                if (env->cpuid_ext2_features & CPUID_EXT2_NX)
2320                    update_mask |= MSR_EFER_NXE;
2321                env->efer = (env->efer & ~update_mask) |
2322                (val & update_mask);
2323            }
2324          break;          break;
2325      case MSR_STAR:      case MSR_STAR:
2326          env->star = val;          env->star = val;
2327          break;          break;
2328    #ifdef TARGET_X86_64
2329      case MSR_LSTAR:      case MSR_LSTAR:
2330          env->lstar = val;          env->lstar = val;
2331          break;          break;
# Line 2296  void helper_rdmsr(void) Line 2367  void helper_rdmsr(void)
2367      case MSR_IA32_APICBASE:      case MSR_IA32_APICBASE:
2368          val = cpu_get_apic_base(env);          val = cpu_get_apic_base(env);
2369          break;          break;
 #ifdef TARGET_X86_64  
2370      case MSR_EFER:      case MSR_EFER:
2371          val = env->efer;          val = env->efer;
2372          break;          break;
2373      case MSR_STAR:      case MSR_STAR:
2374          val = env->star;          val = env->star;
2375          break;          break;
2376    #ifdef TARGET_X86_64
2377      case MSR_LSTAR:      case MSR_LSTAR:
2378          val = env->lstar;          val = env->lstar;
2379          break;          break;

Legend:
Removed from v.1.47  
changed lines
  Added in v.1.48

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26