Commit 89e957e7a292aa698fac77b53b5d80c7760161a8
1 parent
982b4315
moved vm86 stuff to vm86.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@135 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
4 additions
and
158 deletions
linux-user/main.c
| @@ -119,129 +119,7 @@ void write_dt(void *ptr, unsigned long addr, unsigned long limit, | @@ -119,129 +119,7 @@ void write_dt(void *ptr, unsigned long addr, unsigned long limit, | ||
| 119 | 119 | ||
| 120 | uint64_t gdt_table[6]; | 120 | uint64_t gdt_table[6]; |
| 121 | 121 | ||
| 122 | -//#define DEBUG_VM86 | ||
| 123 | - | ||
| 124 | -static inline int is_revectored(int nr, struct target_revectored_struct *bitmap) | ||
| 125 | -{ | ||
| 126 | - return (tswap32(bitmap->__map[nr >> 5]) >> (nr & 0x1f)) & 1; | ||
| 127 | -} | ||
| 128 | - | ||
| 129 | -static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) | ||
| 130 | -{ | ||
| 131 | - return (uint8_t *)((seg << 4) + (reg & 0xffff)); | ||
| 132 | -} | ||
| 133 | - | ||
| 134 | -static inline void pushw(CPUX86State *env, int val) | ||
| 135 | -{ | ||
| 136 | - env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | | ||
| 137 | - ((env->regs[R_ESP] - 2) & 0xffff); | ||
| 138 | - *(uint16_t *)seg_to_linear(env->segs[R_SS], env->regs[R_ESP]) = val; | ||
| 139 | -} | ||
| 140 | - | ||
| 141 | -static inline unsigned int get_vflags(CPUX86State *env) | ||
| 142 | -{ | ||
| 143 | - unsigned int eflags; | ||
| 144 | - eflags = env->eflags & ~(VM_MASK | RF_MASK | IF_MASK); | ||
| 145 | - if (eflags & VIF_MASK) | ||
| 146 | - eflags |= IF_MASK; | ||
| 147 | - return eflags; | ||
| 148 | -} | ||
| 149 | - | ||
| 150 | -void save_v86_state(CPUX86State *env) | ||
| 151 | -{ | ||
| 152 | - TaskState *ts = env->opaque; | ||
| 153 | -#ifdef DEBUG_VM86 | ||
| 154 | - printf("save_v86_state\n"); | ||
| 155 | -#endif | ||
| 156 | - | ||
| 157 | - /* put the VM86 registers in the userspace register structure */ | ||
| 158 | - ts->target_v86->regs.eax = tswap32(env->regs[R_EAX]); | ||
| 159 | - ts->target_v86->regs.ebx = tswap32(env->regs[R_EBX]); | ||
| 160 | - ts->target_v86->regs.ecx = tswap32(env->regs[R_ECX]); | ||
| 161 | - ts->target_v86->regs.edx = tswap32(env->regs[R_EDX]); | ||
| 162 | - ts->target_v86->regs.esi = tswap32(env->regs[R_ESI]); | ||
| 163 | - ts->target_v86->regs.edi = tswap32(env->regs[R_EDI]); | ||
| 164 | - ts->target_v86->regs.ebp = tswap32(env->regs[R_EBP]); | ||
| 165 | - ts->target_v86->regs.esp = tswap32(env->regs[R_ESP]); | ||
| 166 | - ts->target_v86->regs.eip = tswap32(env->eip); | ||
| 167 | - ts->target_v86->regs.cs = tswap16(env->segs[R_CS]); | ||
| 168 | - ts->target_v86->regs.ss = tswap16(env->segs[R_SS]); | ||
| 169 | - ts->target_v86->regs.ds = tswap16(env->segs[R_DS]); | ||
| 170 | - ts->target_v86->regs.es = tswap16(env->segs[R_ES]); | ||
| 171 | - ts->target_v86->regs.fs = tswap16(env->segs[R_FS]); | ||
| 172 | - ts->target_v86->regs.gs = tswap16(env->segs[R_GS]); | ||
| 173 | - ts->target_v86->regs.eflags = tswap32(env->eflags); | ||
| 174 | - | ||
| 175 | - /* restore 32 bit registers */ | ||
| 176 | - env->regs[R_EAX] = ts->vm86_saved_regs.eax; | ||
| 177 | - env->regs[R_EBX] = ts->vm86_saved_regs.ebx; | ||
| 178 | - env->regs[R_ECX] = ts->vm86_saved_regs.ecx; | ||
| 179 | - env->regs[R_EDX] = ts->vm86_saved_regs.edx; | ||
| 180 | - env->regs[R_ESI] = ts->vm86_saved_regs.esi; | ||
| 181 | - env->regs[R_EDI] = ts->vm86_saved_regs.edi; | ||
| 182 | - env->regs[R_EBP] = ts->vm86_saved_regs.ebp; | ||
| 183 | - env->regs[R_ESP] = ts->vm86_saved_regs.esp; | ||
| 184 | - env->eflags = ts->vm86_saved_regs.eflags; | ||
| 185 | - env->eip = ts->vm86_saved_regs.eip; | ||
| 186 | - | ||
| 187 | - cpu_x86_load_seg(env, R_CS, ts->vm86_saved_regs.cs); | ||
| 188 | - cpu_x86_load_seg(env, R_SS, ts->vm86_saved_regs.ss); | ||
| 189 | - cpu_x86_load_seg(env, R_DS, ts->vm86_saved_regs.ds); | ||
| 190 | - cpu_x86_load_seg(env, R_ES, ts->vm86_saved_regs.es); | ||
| 191 | - cpu_x86_load_seg(env, R_FS, ts->vm86_saved_regs.fs); | ||
| 192 | - cpu_x86_load_seg(env, R_GS, ts->vm86_saved_regs.gs); | ||
| 193 | -} | ||
| 194 | - | ||
| 195 | -/* return from vm86 mode to 32 bit. The vm86() syscall will return | ||
| 196 | - 'retval' */ | ||
| 197 | -static inline void return_to_32bit(CPUX86State *env, int retval) | ||
| 198 | -{ | ||
| 199 | -#ifdef DEBUG_VM86 | ||
| 200 | - printf("return_to_32bit: ret=0x%x\n", retval); | ||
| 201 | -#endif | ||
| 202 | - save_v86_state(env); | ||
| 203 | - env->regs[R_EAX] = retval; | ||
| 204 | -} | ||
| 205 | - | ||
| 206 | -/* handle VM86 interrupt (NOTE: the CPU core currently does not | ||
| 207 | - support TSS interrupt revectoring, so this code is always executed) */ | ||
| 208 | -static void do_int(CPUX86State *env, int intno) | ||
| 209 | -{ | ||
| 210 | - TaskState *ts = env->opaque; | ||
| 211 | - uint32_t *int_ptr, segoffs; | ||
| 212 | - | ||
| 213 | - if (env->segs[R_CS] == TARGET_BIOSSEG) | ||
| 214 | - goto cannot_handle; /* XXX: I am not sure this is really useful */ | ||
| 215 | - if (is_revectored(intno, &ts->target_v86->int_revectored)) | ||
| 216 | - goto cannot_handle; | ||
| 217 | - if (intno == 0x21 && is_revectored((env->regs[R_EAX] >> 8) & 0xff, | ||
| 218 | - &ts->target_v86->int21_revectored)) | ||
| 219 | - goto cannot_handle; | ||
| 220 | - int_ptr = (uint32_t *)(intno << 2); | ||
| 221 | - segoffs = tswap32(*int_ptr); | ||
| 222 | - if ((segoffs >> 16) == TARGET_BIOSSEG) | ||
| 223 | - goto cannot_handle; | ||
| 224 | -#ifdef DEBUG_VM86 | ||
| 225 | - printf("VM86: emulating int 0x%x. CS:IP=%04x:%04x\n", | ||
| 226 | - intno, segoffs >> 16, segoffs & 0xffff); | ||
| 227 | -#endif | ||
| 228 | - /* save old state */ | ||
| 229 | - pushw(env, get_vflags(env)); | ||
| 230 | - pushw(env, env->segs[R_CS]); | ||
| 231 | - pushw(env, env->eip); | ||
| 232 | - /* goto interrupt handler */ | ||
| 233 | - env->eip = segoffs & 0xffff; | ||
| 234 | - cpu_x86_load_seg(env, R_CS, segoffs >> 16); | ||
| 235 | - env->eflags &= ~(VIF_MASK | TF_MASK); | ||
| 236 | - return; | ||
| 237 | - cannot_handle: | ||
| 238 | -#ifdef DEBUG_VM86 | ||
| 239 | - printf("VM86: return to 32 bits int 0x%x\n", intno); | ||
| 240 | -#endif | ||
| 241 | - return_to_32bit(env, TARGET_VM86_INTx | (intno << 8)); | ||
| 242 | -} | ||
| 243 | - | ||
| 244 | -void cpu_loop(struct CPUX86State *env) | 122 | +void cpu_loop(CPUX86State *env) |
| 245 | { | 123 | { |
| 246 | int trapnr; | 124 | int trapnr; |
| 247 | uint8_t *pc; | 125 | uint8_t *pc; |
| @@ -249,45 +127,12 @@ void cpu_loop(struct CPUX86State *env) | @@ -249,45 +127,12 @@ void cpu_loop(struct CPUX86State *env) | ||
| 249 | 127 | ||
| 250 | for(;;) { | 128 | for(;;) { |
| 251 | trapnr = cpu_x86_exec(env); | 129 | trapnr = cpu_x86_exec(env); |
| 252 | - pc = env->seg_cache[R_CS].base + env->eip; | ||
| 253 | switch(trapnr) { | 130 | switch(trapnr) { |
| 254 | case EXCP0D_GPF: | 131 | case EXCP0D_GPF: |
| 255 | if (env->eflags & VM_MASK) { | 132 | if (env->eflags & VM_MASK) { |
| 256 | -#ifdef DEBUG_VM86 | ||
| 257 | - printf("VM86 exception %04x:%08x %02x %02x\n", | ||
| 258 | - env->segs[R_CS], env->eip, pc[0], pc[1]); | ||
| 259 | -#endif | ||
| 260 | - /* VM86 mode */ | ||
| 261 | - switch(pc[0]) { | ||
| 262 | - case 0xcd: /* int */ | ||
| 263 | - env->eip += 2; | ||
| 264 | - do_int(env, pc[1]); | ||
| 265 | - break; | ||
| 266 | - case 0x66: | ||
| 267 | - switch(pc[1]) { | ||
| 268 | - case 0xfb: /* sti */ | ||
| 269 | - case 0x9d: /* popf */ | ||
| 270 | - case 0xcf: /* iret */ | ||
| 271 | - env->eip += 2; | ||
| 272 | - return_to_32bit(env, TARGET_VM86_STI); | ||
| 273 | - break; | ||
| 274 | - default: | ||
| 275 | - goto vm86_gpf; | ||
| 276 | - } | ||
| 277 | - break; | ||
| 278 | - case 0xfb: /* sti */ | ||
| 279 | - case 0x9d: /* popf */ | ||
| 280 | - case 0xcf: /* iret */ | ||
| 281 | - env->eip++; | ||
| 282 | - return_to_32bit(env, TARGET_VM86_STI); | ||
| 283 | - break; | ||
| 284 | - default: | ||
| 285 | - vm86_gpf: | ||
| 286 | - /* real VM86 GPF exception */ | ||
| 287 | - return_to_32bit(env, TARGET_VM86_UNKNOWN); | ||
| 288 | - break; | ||
| 289 | - } | 133 | + handle_vm86_fault(env); |
| 290 | } else { | 134 | } else { |
| 135 | + pc = env->seg_cache[R_CS].base + env->eip; | ||
| 291 | if (pc[0] == 0xcd && pc[1] == 0x80) { | 136 | if (pc[0] == 0xcd && pc[1] == 0x80) { |
| 292 | /* syscall */ | 137 | /* syscall */ |
| 293 | env->eip += 2; | 138 | env->eip += 2; |
| @@ -354,6 +199,7 @@ void cpu_loop(struct CPUX86State *env) | @@ -354,6 +199,7 @@ void cpu_loop(struct CPUX86State *env) | ||
| 354 | /* just indicate that signals should be handled asap */ | 199 | /* just indicate that signals should be handled asap */ |
| 355 | break; | 200 | break; |
| 356 | default: | 201 | default: |
| 202 | + pc = env->seg_cache[R_CS].base + env->eip; | ||
| 357 | fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", | 203 | fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", |
| 358 | (long)pc, trapnr); | 204 | (long)pc, trapnr); |
| 359 | abort(); | 205 | abort(); |