added vm86.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@143 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
9d27abd94f
commit
631271d716
@ -54,6 +54,8 @@ typedef struct TaskState {
|
|||||||
struct TaskState *next;
|
struct TaskState *next;
|
||||||
struct target_vm86plus_struct *target_v86;
|
struct target_vm86plus_struct *target_v86;
|
||||||
struct vm86_saved_state vm86_saved_regs;
|
struct vm86_saved_state vm86_saved_regs;
|
||||||
|
uint32_t v86flags;
|
||||||
|
uint32_t v86mask;
|
||||||
int used; /* non zero if used */
|
int used; /* non zero if used */
|
||||||
uint8_t stack[0];
|
uint8_t stack[0];
|
||||||
} __attribute__((aligned(16))) TaskState;
|
} __attribute__((aligned(16))) TaskState;
|
||||||
@ -73,9 +75,17 @@ void cpu_loop(CPUX86State *env);
|
|||||||
void process_pending_signals(void *cpu_env);
|
void process_pending_signals(void *cpu_env);
|
||||||
void signal_init(void);
|
void signal_init(void);
|
||||||
int queue_signal(int sig, target_siginfo_t *info);
|
int queue_signal(int sig, target_siginfo_t *info);
|
||||||
void save_v86_state(CPUX86State *env);
|
|
||||||
void init_paths(const char *prefix);
|
void init_paths(const char *prefix);
|
||||||
const char *path(const char *pathname);
|
const char *path(const char *pathname);
|
||||||
|
|
||||||
extern int loglevel;
|
extern int loglevel;
|
||||||
|
extern FILE *logfile;
|
||||||
|
|
||||||
|
/* vm86.c */
|
||||||
|
void save_v86_state(CPUX86State *env);
|
||||||
|
void do_int(CPUX86State *env, int intno);
|
||||||
|
void handle_vm86_fault(CPUX86State *env);
|
||||||
|
int do_vm86(CPUX86State *env, long subfunction,
|
||||||
|
struct target_vm86plus_struct * target_v86);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1058,78 +1058,6 @@ int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vm86 emulation */
|
|
||||||
|
|
||||||
#define SAFE_MASK (0xDD5)
|
|
||||||
|
|
||||||
int do_vm86(CPUX86State *env, long subfunction,
|
|
||||||
struct target_vm86plus_struct * target_v86)
|
|
||||||
{
|
|
||||||
TaskState *ts = env->opaque;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
switch (subfunction) {
|
|
||||||
case TARGET_VM86_REQUEST_IRQ:
|
|
||||||
case TARGET_VM86_FREE_IRQ:
|
|
||||||
case TARGET_VM86_GET_IRQ_BITS:
|
|
||||||
case TARGET_VM86_GET_AND_RESET_IRQ:
|
|
||||||
gemu_log("qemu: unsupported vm86 subfunction (%ld)\n", subfunction);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
case TARGET_VM86_PLUS_INSTALL_CHECK:
|
|
||||||
/* NOTE: on old vm86 stuff this will return the error
|
|
||||||
from verify_area(), because the subfunction is
|
|
||||||
interpreted as (invalid) address to vm86_struct.
|
|
||||||
So the installation check works.
|
|
||||||
*/
|
|
||||||
ret = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ts->target_v86 = target_v86;
|
|
||||||
/* save current CPU regs */
|
|
||||||
ts->vm86_saved_regs.eax = 0; /* default vm86 syscall return code */
|
|
||||||
ts->vm86_saved_regs.ebx = env->regs[R_EBX];
|
|
||||||
ts->vm86_saved_regs.ecx = env->regs[R_ECX];
|
|
||||||
ts->vm86_saved_regs.edx = env->regs[R_EDX];
|
|
||||||
ts->vm86_saved_regs.esi = env->regs[R_ESI];
|
|
||||||
ts->vm86_saved_regs.edi = env->regs[R_EDI];
|
|
||||||
ts->vm86_saved_regs.ebp = env->regs[R_EBP];
|
|
||||||
ts->vm86_saved_regs.esp = env->regs[R_ESP];
|
|
||||||
ts->vm86_saved_regs.eflags = env->eflags;
|
|
||||||
ts->vm86_saved_regs.eip = env->eip;
|
|
||||||
ts->vm86_saved_regs.cs = env->segs[R_CS];
|
|
||||||
ts->vm86_saved_regs.ss = env->segs[R_SS];
|
|
||||||
ts->vm86_saved_regs.ds = env->segs[R_DS];
|
|
||||||
ts->vm86_saved_regs.es = env->segs[R_ES];
|
|
||||||
ts->vm86_saved_regs.fs = env->segs[R_FS];
|
|
||||||
ts->vm86_saved_regs.gs = env->segs[R_GS];
|
|
||||||
|
|
||||||
/* build vm86 CPU state */
|
|
||||||
env->eflags = (env->eflags & ~SAFE_MASK) |
|
|
||||||
(tswap32(target_v86->regs.eflags) & SAFE_MASK) | VM_MASK;
|
|
||||||
|
|
||||||
env->regs[R_EBX] = tswap32(target_v86->regs.ebx);
|
|
||||||
env->regs[R_ECX] = tswap32(target_v86->regs.ecx);
|
|
||||||
env->regs[R_EDX] = tswap32(target_v86->regs.edx);
|
|
||||||
env->regs[R_ESI] = tswap32(target_v86->regs.esi);
|
|
||||||
env->regs[R_EDI] = tswap32(target_v86->regs.edi);
|
|
||||||
env->regs[R_EBP] = tswap32(target_v86->regs.ebp);
|
|
||||||
env->regs[R_ESP] = tswap32(target_v86->regs.esp);
|
|
||||||
env->eip = tswap32(target_v86->regs.eip);
|
|
||||||
cpu_x86_load_seg(env, R_CS, tswap16(target_v86->regs.cs));
|
|
||||||
cpu_x86_load_seg(env, R_SS, tswap16(target_v86->regs.ss));
|
|
||||||
cpu_x86_load_seg(env, R_DS, tswap16(target_v86->regs.ds));
|
|
||||||
cpu_x86_load_seg(env, R_ES, tswap16(target_v86->regs.es));
|
|
||||||
cpu_x86_load_seg(env, R_FS, tswap16(target_v86->regs.fs));
|
|
||||||
cpu_x86_load_seg(env, R_GS, tswap16(target_v86->regs.gs));
|
|
||||||
ret = tswap32(target_v86->regs.eax); /* eax will be restored at
|
|
||||||
the end of the syscall */
|
|
||||||
/* now the virtual CPU is ready for vm86 execution ! */
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this stack is the equivalent of the kernel stack associated with a
|
/* this stack is the equivalent of the kernel stack associated with a
|
||||||
thread/process */
|
thread/process */
|
||||||
#define NEW_STACK_SIZE 8192
|
#define NEW_STACK_SIZE 8192
|
||||||
|
Loading…
Reference in New Issue
Block a user