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(); | ... | ... |