/[qemu]/qemu/tests/test-i386.c
ViewVC logotype

Diff of /qemu/tests/test-i386.c

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

revision 1.15 by bellard, Sat May 10 21:39:12 2003 UTC revision 1.16 by bellard, Fri May 16 13:43:31 2003 UTC
# Line 1  Line 1 
1    #define _GNU_SOURCE
2  #include <stdlib.h>  #include <stdlib.h>
3  #include <stdio.h>  #include <stdio.h>
4  #include <inttypes.h>  #include <inttypes.h>
5  #include <math.h>  #include <math.h>
6    #include <signal.h>
7    #include <setjmp.h>
8    #include <sys/ucontext.h>
9    #include <sys/mman.h>
10    #include <asm/vm86.h>
11    
12  #define TEST_CMOV 0  #define TEST_CMOV 0
13    
# Line 913  void test_string(void) Line 919  void test_string(void)
919     TEST_STRING(cmps, "repnz ");     TEST_STRING(cmps, "repnz ");
920  }  }
921    
922    /* VM86 test */
923    
924    static inline void set_bit(uint8_t *a, unsigned int bit)
925    {
926        a[bit / 8] |= (1 << (bit % 8));
927    }
928    
929    static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
930    {
931        return (uint8_t *)((seg << 4) + (reg & 0xffff));
932    }
933    
934    static inline void pushw(struct vm86_regs *r, int val)
935    {
936        r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
937        *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
938    }
939    
940    #undef __syscall_return
941    #define __syscall_return(type, res) \
942    do { \
943            return (type) (res); \
944    } while (0)
945    
946    _syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
947    
948    extern char vm86_code_start;
949    extern char vm86_code_end;
950    
951    #define VM86_CODE_CS 0x100
952    #define VM86_CODE_IP 0x100
953    
954    void test_vm86(void)
955    {
956        struct vm86plus_struct ctx;
957        struct vm86_regs *r;
958        uint8_t *vm86_mem;
959        int seg, ret;
960    
961        vm86_mem = mmap((void *)0x00000000, 0x110000,
962                        PROT_WRITE | PROT_READ | PROT_EXEC,
963                        MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
964        if (vm86_mem == MAP_FAILED) {
965            printf("ERROR: could not map vm86 memory");
966            return;
967        }
968        memset(&ctx, 0, sizeof(ctx));
969    
970        /* init basic registers */
971        r = &ctx.regs;
972        r->eip = VM86_CODE_IP;
973        r->esp = 0xfffe;
974        seg = VM86_CODE_CS;
975        r->cs = seg;
976        r->ss = seg;
977        r->ds = seg;
978        r->es = seg;
979        r->fs = seg;
980        r->gs = seg;
981        r->eflags = VIF_MASK;
982    
983        /* move code to proper address. We use the same layout as a .com
984           dos program. */
985        memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
986               &vm86_code_start, &vm86_code_end - &vm86_code_start);
987    
988        /* mark int 0x21 as being emulated */
989        set_bit((uint8_t *)&ctx.int_revectored, 0x21);
990    
991        for(;;) {
992            ret = vm86(VM86_ENTER, &ctx);
993            switch(VM86_TYPE(ret)) {
994            case VM86_INTx:
995                {
996                    int int_num, ah;
997                    
998                    int_num = VM86_ARG(ret);
999                    if (int_num != 0x21)
1000                        goto unknown_int;
1001                    ah = (r->eax >> 8) & 0xff;
1002                    switch(ah) {
1003                    case 0x00: /* exit */
1004                        goto the_end;
1005                    case 0x02: /* write char */
1006                        {
1007                            uint8_t c = r->edx;
1008                            putchar(c);
1009                        }
1010                        break;
1011                    case 0x09: /* write string */
1012                        {
1013                            uint8_t c, *ptr;
1014                            ptr = seg_to_linear(r->ds, r->edx);
1015                            for(;;) {
1016                                c = *ptr++;
1017                                if (c == '$')
1018                                    break;
1019                                putchar(c);
1020                            }
1021                            r->eax = (r->eax & ~0xff) | '$';
1022                        }
1023                        break;
1024                    case 0xff: /* extension: write hex number in edx */
1025                        printf("%08x\n", (int)r->edx);
1026                        break;
1027                    default:
1028                    unknown_int:
1029                        printf("unsupported int 0x%02x\n", int_num);
1030                        goto the_end;
1031                    }
1032                }
1033                break;
1034            case VM86_SIGNAL:
1035                /* a signal came, we just ignore that */
1036                break;
1037            case VM86_STI:
1038                break;
1039            default:
1040                printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
1041                goto the_end;
1042            }
1043        }
1044     the_end:
1045        printf("VM86 end\n");
1046        munmap(vm86_mem, 0x110000);
1047    }
1048    
1049    /* exception tests */
1050    #ifndef REG_EAX
1051    #define REG_EAX EAX
1052    #define REG_EBX EBX
1053    #define REG_ECX ECX
1054    #define REG_EDX EDX
1055    #define REG_ESI ESI
1056    #define REG_EDI EDI
1057    #define REG_EBP EBP
1058    #define REG_ESP ESP
1059    #define REG_EIP EIP
1060    #define REG_EFL EFL
1061    #define REG_TRAPNO TRAPNO
1062    #define REG_ERR ERR
1063    #endif
1064    
1065    jmp_buf jmp_env;
1066    int dump_eip;
1067    int dump_si_addr;
1068    int v1;
1069    int tab[2];
1070    
1071    void sig_handler(int sig, siginfo_t *info, void *puc)
1072    {
1073        struct ucontext *uc = puc;
1074    
1075        printf("si_signo=%d si_errno=%d si_code=%d",
1076               info->si_signo, info->si_errno, info->si_code);
1077        if (dump_si_addr) {
1078            printf(" si_addr=0x%08lx",
1079                   (unsigned long)info->si_addr);
1080        }
1081        printf("\n");
1082    
1083        printf("trapno=0x%02x err=0x%08x",
1084               uc->uc_mcontext.gregs[REG_TRAPNO],
1085               uc->uc_mcontext.gregs[REG_ERR]);
1086        if (dump_eip)
1087            printf(" EIP=0x%08x", uc->uc_mcontext.gregs[REG_EIP]);
1088        printf("\n");
1089        longjmp(jmp_env, 1);
1090    }
1091    
1092    void test_exceptions(void)
1093    {
1094        struct sigaction act;
1095        volatile int val;
1096        
1097        act.sa_sigaction = sig_handler;
1098        sigemptyset(&act.sa_mask);
1099        act.sa_flags = SA_SIGINFO;
1100        sigaction(SIGFPE, &act, NULL);
1101        sigaction(SIGILL, &act, NULL);
1102        sigaction(SIGSEGV, &act, NULL);
1103        sigaction(SIGTRAP, &act, NULL);
1104    
1105        /* test division by zero reporting */
1106        dump_eip = 0;
1107        dump_si_addr = 0;
1108        printf("DIVZ exception (currently imprecise):\n");
1109        if (setjmp(jmp_env) == 0) {
1110            /* now divide by zero */
1111            v1 = 0;
1112            v1 = 2 / v1;
1113        }
1114    
1115        dump_si_addr = 1;
1116        printf("BOUND exception (currently imprecise):\n");
1117        if (setjmp(jmp_env) == 0) {
1118            /* bound exception */
1119            tab[0] = 1;
1120            tab[1] = 10;
1121            asm volatile ("bound %0, %1" : : "r" (11), "m" (tab));
1122        }
1123    
1124        /* test SEGV reporting */
1125        printf("PF exception (currently imprecise):\n");
1126        if (setjmp(jmp_env) == 0) {
1127            /* now store in an invalid address */
1128            *(char *)0x1234 = 1;
1129        }
1130    
1131        /* test SEGV reporting */
1132        printf("PF exception (currently imprecise):\n");
1133        if (setjmp(jmp_env) == 0) {
1134            /* read from an invalid address */
1135            v1 = *(char *)0x1234;
1136        }
1137        
1138        printf("segment GPF exception (currently imprecise):\n");
1139        if (setjmp(jmp_env) == 0) {
1140            /* load an invalid segment */
1141            asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 0));
1142        }
1143    
1144        dump_eip = 1;
1145        /* test illegal instruction reporting */
1146        printf("UD2 exception:\n");
1147        if (setjmp(jmp_env) == 0) {
1148            /* now execute an invalid instruction */
1149            asm volatile("ud2");
1150        }
1151        
1152        printf("INT exception:\n");
1153        if (setjmp(jmp_env) == 0) {
1154            asm volatile ("int $0xfd");
1155        }
1156    
1157        printf("INT3 exception:\n");
1158        if (setjmp(jmp_env) == 0) {
1159            asm volatile ("int3");
1160        }
1161    
1162        printf("CLI exception:\n");
1163        if (setjmp(jmp_env) == 0) {
1164            asm volatile ("cli");
1165        }
1166    
1167        printf("STI exception:\n");
1168        if (setjmp(jmp_env) == 0) {
1169            asm volatile ("cli");
1170        }
1171    
1172        printf("INTO exception:\n");
1173        if (setjmp(jmp_env) == 0) {
1174            /* overflow exception */
1175            asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
1176        }
1177    
1178        printf("OUTB exception:\n");
1179        if (setjmp(jmp_env) == 0) {
1180            asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
1181        }
1182    
1183        printf("INB exception:\n");
1184        if (setjmp(jmp_env) == 0) {
1185            asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
1186        }
1187    
1188        printf("REP OUTSB exception:\n");
1189        if (setjmp(jmp_env) == 0) {
1190            asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
1191        }
1192    
1193        printf("REP INSB exception:\n");
1194        if (setjmp(jmp_env) == 0) {
1195            asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
1196        }
1197    
1198        printf("HLT exception:\n");
1199        if (setjmp(jmp_env) == 0) {
1200            asm volatile ("hlt");
1201        }
1202    
1203        printf("single step exception:\n");
1204        val = 0;
1205        if (setjmp(jmp_env) == 0) {
1206            asm volatile ("pushf\n"
1207                          "orl $0x00100, (%%esp)\n"
1208                          "popf\n"
1209                          "movl $0xabcd, %0\n"
1210                          "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
1211        }
1212        printf("val=0x%x\n", val);
1213    }
1214    
1215    /* self modifying code test */
1216    uint8_t code[] = {
1217        0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
1218        0xc3, /* ret */
1219    };
1220    
1221    void test_self_modifying_code(void)
1222    {
1223        int (*func)(void);
1224    
1225        func = (void *)code;
1226        printf("self modifying code:\n");
1227        printf("func1 = 0x%x\n", func());
1228        code[1] = 0x2;
1229        printf("func1 = 0x%x\n", func());
1230    }
1231        
1232  static void *call_end __init_call = NULL;  static void *call_end __init_call = NULL;
1233    
1234  int main(int argc, char **argv)  int main(int argc, char **argv)
# Line 936  int main(int argc, char **argv) Line 1252  int main(int argc, char **argv)
1252      test_lea();      test_lea();
1253      test_segs();      test_segs();
1254      test_code16();      test_code16();
1255        test_vm86();
1256        test_exceptions();
1257        test_self_modifying_code();
1258      return 0;      return 0;
1259  }  }

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.16

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