Revision 8e682019 target-i386/helper.c

b/target-i386/helper.c
676 676
        ssp = get_seg_base(ss_e1, ss_e2);
677 677
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
678 678
        /* to same priviledge */
679
        if (env->eflags & VM_MASK)
680
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
679 681
        new_stack = 0;
680 682
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
681 683
        ssp = env->segs[R_SS].base;
......
702 704
    else
703 705
        old_eip = env->eip;
704 706
    if (shift == 1) {
705
        if (env->eflags & VM_MASK) {
706
            PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
707
            PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
708
            PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
709
            PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
710
        }
711 707
        if (new_stack) {
708
            if (env->eflags & VM_MASK) {
709
                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
710
                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
711
                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
712
                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
713
            }
712 714
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
713 715
            PUSHL(ssp, esp, sp_mask, ESP);
714 716
        }
......
720 722
        }
721 723
    } else {
722 724
        if (new_stack) {
725
            if (env->eflags & VM_MASK) {
726
                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
727
                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
728
                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
729
                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
730
            }
723 731
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
724 732
            PUSHW(ssp, esp, sp_mask, ESP);
725 733
        }
......
732 740
    }
733 741
    
734 742
    if (new_stack) {
743
        if (env->eflags & VM_MASK) {
744
            /* XXX: explain me why W2K hangs if the whole segment cache is
745
               reset ? */
746
            env->segs[R_ES].selector = 0;
747
            env->segs[R_ES].flags = 0;
748
            env->segs[R_DS].selector = 0;
749
            env->segs[R_DS].flags = 0;
750
            env->segs[R_FS].selector = 0;
751
            env->segs[R_FS].flags = 0;
752
            env->segs[R_GS].selector = 0;
753
            env->segs[R_GS].flags = 0;
754
        }
735 755
        ss = (ss & ~3) | dpl;
736 756
        cpu_x86_load_seg_cache(env, R_SS, ss, 
737 757
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
......
824 844
void do_interrupt(int intno, int is_int, int error_code, 
825 845
                  unsigned int next_eip, int is_hw)
826 846
{
847
#if 0
848
    {
849
        extern FILE *stdout;
850
        static int count;
851
        if (env->cr[0] & CR0_PE_MASK) {
852
            fprintf(stdout, "%d: interrupt: vector=%02x error_code=%04x int=%d\n",
853
                    count, intno, error_code, is_int);
854
            count++;
855
        }
856
    }
857
    if ((env->cr[0] & CR0_PE_MASK) && intno == 0x10) {
858
        tb_flush(env);
859
        cpu_set_log(CPU_LOG_ALL);
860
    }
861
#endif
827 862
#ifdef DEBUG_PCALL
828 863
    if (loglevel) {
829 864
        static int count;
830 865
        fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d\n",
831 866
                count, intno, error_code, is_int);
832 867
        cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
833
#if 0
868
#if 1
834 869
        {
835 870
            int i;
836 871
            uint8_t *ptr;
837
            printf("       code=");
872
            fprintf(logfile, "       code=");
838 873
            ptr = env->segs[R_CS].base + env->eip;
839 874
            for(i = 0; i < 16; i++) {
840
                printf(" %02x", ldub(ptr + i));
875
                fprintf(logfile, " %02x", ldub(ptr + i));
841 876
            }
842
            printf("\n");
877
            fprintf(logfile, "\n");
843 878
        }
844 879
#endif
845 880
        count++;
......
955 990
    CC_SRC = eflags;
956 991
}
957 992

  
958
/* We simulate a pre-MMX pentium as in valgrind */
959 993
#define CPUID_FP87 (1 << 0)
960 994
#define CPUID_VME  (1 << 1)
961 995
#define CPUID_DE   (1 << 2)
......
979 1013

  
980 1014
void helper_cpuid(void)
981 1015
{
982
    if (EAX == 0) {
983
        EAX = 1; /* max EAX index supported */
1016
    switch(EAX) {
1017
    case 0:
1018
        EAX = 2; /* max EAX index supported */
984 1019
        EBX = 0x756e6547;
985 1020
        ECX = 0x6c65746e;
986 1021
        EDX = 0x49656e69;
987
    } else if (EAX == 1) {
988
        int family, model, stepping;
989
        /* EAX = 1 info */
1022
        break;
1023
    case 1:
1024
        {
1025
            int family, model, stepping;
1026
            /* EAX = 1 info */
990 1027
#if 0
991
        /* pentium 75-200 */
992
        family = 5;
993
        model = 2;
994
        stepping = 11;
1028
            /* pentium 75-200 */
1029
            family = 5;
1030
            model = 2;
1031
            stepping = 11;
995 1032
#else
996
        /* pentium pro */
997
        family = 6;
998
        model = 1;
999
        stepping = 3;
1033
            /* pentium pro */
1034
            family = 6;
1035
            model = 1;
1036
            stepping = 3;
1000 1037
#endif
1001
        EAX = (family << 8) | (model << 4) | stepping;
1038
            EAX = (family << 8) | (model << 4) | stepping;
1039
            EBX = 0;
1040
            ECX = 0;
1041
            EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |
1042
                CPUID_TSC | CPUID_MSR | CPUID_MCE |
1043
                CPUID_CX8 | CPUID_PGE | CPUID_CMOV;
1044
        }
1045
        break;
1046
    default:
1047
        /* cache info: needed for Pentium Pro compatibility */
1048
        EAX = 0x410601;
1002 1049
        EBX = 0;
1003 1050
        ECX = 0;
1004
        EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |
1005
            CPUID_TSC | CPUID_MSR | CPUID_MCE |
1006
            CPUID_CX8 | CPUID_PGE | CPUID_CMOV;
1051
        EDX = 0;
1052
        break;
1007 1053
    }
1008 1054
}
1009 1055

  
......
1070 1116
        if (!(e2 & DESC_P_MASK))
1071 1117
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1072 1118
        load_seg_cache_raw_dt(&env->tr, e1, e2);
1073
        e2 |= 0x00000200; /* set the busy bit */
1119
        e2 |= DESC_TSS_BUSY_MASK;
1074 1120
        stl_kernel(ptr + 4, e2);
1075 1121
    }
1076 1122
    env->tr.selector = selector;
1077 1123
}
1078 1124

  
1079 1125
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
1080
void load_seg(int seg_reg, int selector, unsigned int cur_eip)
1126
void load_seg(int seg_reg, int selector)
1081 1127
{
1082 1128
    uint32_t e1, e2;
1083 1129
    int cpl, dpl, rpl;
......
1085 1131
    int index;
1086 1132
    uint8_t *ptr;
1087 1133

  
1134
    selector &= 0xffff;
1088 1135
    if ((selector & 0xfffc) == 0) {
1089 1136
        /* null selector case */
1090
        if (seg_reg == R_SS) {
1091
            EIP = cur_eip;
1137
        if (seg_reg == R_SS)
1092 1138
            raise_exception_err(EXCP0D_GPF, 0);
1093
        } else {
1094
            cpu_x86_load_seg_cache(env, seg_reg, selector, NULL, 0, 0);
1095
        }
1139
        cpu_x86_load_seg_cache(env, seg_reg, selector, NULL, 0, 0);
1096 1140
    } else {
1097 1141
        
1098 1142
        if (selector & 0x4)
......
1100 1144
        else
1101 1145
            dt = &env->gdt;
1102 1146
        index = selector & ~7;
1103
        if ((index + 7) > dt->limit) {
1104
            EIP = cur_eip;
1147
        if ((index + 7) > dt->limit)
1105 1148
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1106
        }
1107 1149
        ptr = dt->base + index;
1108 1150
        e1 = ldl_kernel(ptr);
1109 1151
        e2 = ldl_kernel(ptr + 4);
1110 1152

  
1111
        if (!(e2 & DESC_S_MASK)) {
1112
            EIP = cur_eip;
1153
        if (!(e2 & DESC_S_MASK))
1113 1154
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1114
        }
1115 1155
        rpl = selector & 3;
1116 1156
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1117 1157
        cpl = env->hflags & HF_CPL_MASK;
1118 1158
        if (seg_reg == R_SS) {
1119 1159
            /* must be writable segment */
1120
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) {
1121
                EIP = cur_eip;
1160
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
1122 1161
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1123
            }
1124
            if (rpl != cpl || dpl != cpl) {
1125
                EIP = cur_eip;
1162
            if (rpl != cpl || dpl != cpl)
1126 1163
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1127
            }
1128 1164
        } else {
1129 1165
            /* must be readable segment */
1130
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
1131
                EIP = cur_eip;
1166
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
1132 1167
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1133
            }
1134 1168
            
1135 1169
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1136 1170
                /* if not conforming code, test rights */
1137
                if (dpl < cpl || dpl < rpl) {
1138
                    EIP = cur_eip;
1171
                if (dpl < cpl || dpl < rpl)
1139 1172
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1140
                }
1141 1173
            }
1142 1174
        }
1143 1175

  
1144 1176
        if (!(e2 & DESC_P_MASK)) {
1145
            EIP = cur_eip;
1146 1177
            if (seg_reg == R_SS)
1147 1178
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
1148 1179
            else
......
1507 1538
    load_eflags(new_eflags, eflags_mask);
1508 1539
}
1509 1540

  
1541
static inline void validate_seg(int seg_reg, int cpl)
1542
{
1543
    int dpl;
1544
    uint32_t e2;
1545
    
1546
    e2 = env->segs[seg_reg].flags;
1547
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1548
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1549
        /* data or non conforming code segment */
1550
        if (dpl < cpl) {
1551
            cpu_x86_load_seg_cache(env, seg_reg, 0, NULL, 0, 0);
1552
        }
1553
    }
1554
}
1555

  
1510 1556
/* protected mode iret */
1511 1557
static inline void helper_ret_protected(int shift, int is_iret, int addend)
1512 1558
{
......
1610 1656
        cpu_x86_set_cpl(env, rpl);
1611 1657
        sp = new_esp;
1612 1658
        /* XXX: change sp_mask according to old segment ? */
1659

  
1660
        /* validate data segments */
1661
        validate_seg(R_ES, cpl);
1662
        validate_seg(R_DS, cpl);
1663
        validate_seg(R_FS, cpl);
1664
        validate_seg(R_GS, cpl);
1613 1665
    }
1614 1666
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1615 1667
    env->eip = new_eip;

Also available in: Unified diff