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