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 | 119 | |
| 120 | 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 | 124 | int trapnr; |
| 247 | 125 | uint8_t *pc; |
| ... | ... | @@ -249,45 +127,12 @@ void cpu_loop(struct CPUX86State *env) |
| 249 | 127 | |
| 250 | 128 | for(;;) { |
| 251 | 129 | trapnr = cpu_x86_exec(env); |
| 252 | - pc = env->seg_cache[R_CS].base + env->eip; | |
| 253 | 130 | switch(trapnr) { |
| 254 | 131 | case EXCP0D_GPF: |
| 255 | 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 | 134 | } else { |
| 135 | + pc = env->seg_cache[R_CS].base + env->eip; | |
| 291 | 136 | if (pc[0] == 0xcd && pc[1] == 0x80) { |
| 292 | 137 | /* syscall */ |
| 293 | 138 | env->eip += 2; |
| ... | ... | @@ -354,6 +199,7 @@ void cpu_loop(struct CPUX86State *env) |
| 354 | 199 | /* just indicate that signals should be handled asap */ |
| 355 | 200 | break; |
| 356 | 201 | default: |
| 202 | + pc = env->seg_cache[R_CS].base + env->eip; | |
| 357 | 203 | fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", |
| 358 | 204 | (long)pc, trapnr); |
| 359 | 205 | abort(); | ... | ... |