45 |
#include <fcntl.h> |
#include <fcntl.h> |
46 |
#include "kqemu/kqemu.h" |
#include "kqemu/kqemu.h" |
47 |
|
|
48 |
|
/* compatibility stuff */ |
49 |
|
#ifndef KQEMU_RET_SYSCALL |
50 |
|
#define KQEMU_RET_SYSCALL 0x0300 /* syscall insn */ |
51 |
|
#endif |
52 |
|
|
53 |
#ifdef _WIN32 |
#ifdef _WIN32 |
54 |
#define KQEMU_DEVICE "\\\\.\\kqemu" |
#define KQEMU_DEVICE "\\\\.\\kqemu" |
55 |
#else |
#else |
76 |
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ |
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ |
77 |
: "0" (index)) |
: "0" (index)) |
78 |
|
|
79 |
|
#ifdef __x86_64__ |
80 |
|
static int is_cpuid_supported(void) |
81 |
|
{ |
82 |
|
return 1; |
83 |
|
} |
84 |
|
#else |
85 |
static int is_cpuid_supported(void) |
static int is_cpuid_supported(void) |
86 |
{ |
{ |
87 |
int v0, v1; |
int v0, v1; |
98 |
: "cc"); |
: "cc"); |
99 |
return (v0 != v1); |
return (v0 != v1); |
100 |
} |
} |
101 |
|
#endif |
102 |
|
|
103 |
static void kqemu_update_cpuid(CPUState *env) |
static void kqemu_update_cpuid(CPUState *env) |
104 |
{ |
{ |
243 |
uint32_t mxcsr; |
uint32_t mxcsr; |
244 |
uint32_t mxcsr_mask; |
uint32_t mxcsr_mask; |
245 |
uint8_t fpregs1[8 * 16]; |
uint8_t fpregs1[8 * 16]; |
246 |
uint8_t xmm_regs[8 * 16]; |
uint8_t xmm_regs[16 * 16]; |
247 |
uint8_t dummy2[224]; |
uint8_t dummy2[96]; |
248 |
}; |
}; |
249 |
|
|
250 |
static struct fpxstate fpx1 __attribute__((aligned(16))); |
static struct fpxstate fpx1 __attribute__((aligned(16))); |
320 |
fp->mxcsr = env->mxcsr; |
fp->mxcsr = env->mxcsr; |
321 |
/* XXX: check if DAZ is not available */ |
/* XXX: check if DAZ is not available */ |
322 |
fp->mxcsr_mask = 0xffff; |
fp->mxcsr_mask = 0xffff; |
323 |
memcpy(fp->xmm_regs, env->xmm_regs, 8 * 16); |
memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16); |
324 |
} |
} |
325 |
asm volatile ("fxrstor %0" : "=m" (*fp)); |
asm volatile ("fxrstor %0" : "=m" (*fp)); |
326 |
} |
} |
346 |
} |
} |
347 |
if (env->cpuid_features & CPUID_SSE) { |
if (env->cpuid_features & CPUID_SSE) { |
348 |
env->mxcsr = fp->mxcsr; |
env->mxcsr = fp->mxcsr; |
349 |
memcpy(env->xmm_regs, fp->xmm_regs, 8 * 16); |
memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16); |
350 |
} |
} |
351 |
|
|
352 |
/* we must restore the default rounding state */ |
/* we must restore the default rounding state */ |
355 |
asm volatile("fldcw %0" : : "m" (fpuc)); |
asm volatile("fldcw %0" : : "m" (fpuc)); |
356 |
} |
} |
357 |
|
|
358 |
|
static int do_syscall(CPUState *env, |
359 |
|
struct kqemu_cpu_state *kenv) |
360 |
|
{ |
361 |
|
int selector; |
362 |
|
|
363 |
|
selector = (env->star >> 32) & 0xffff; |
364 |
|
#ifdef __x86_64__ |
365 |
|
if (env->hflags & HF_LMA_MASK) { |
366 |
|
env->regs[R_ECX] = kenv->next_eip; |
367 |
|
env->regs[11] = env->eflags; |
368 |
|
|
369 |
|
cpu_x86_set_cpl(env, 0); |
370 |
|
cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, |
371 |
|
0, 0xffffffff, |
372 |
|
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
373 |
|
DESC_S_MASK | |
374 |
|
DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK); |
375 |
|
cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, |
376 |
|
0, 0xffffffff, |
377 |
|
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
378 |
|
DESC_S_MASK | |
379 |
|
DESC_W_MASK | DESC_A_MASK); |
380 |
|
env->eflags &= ~env->fmask; |
381 |
|
if (env->hflags & HF_CS64_MASK) |
382 |
|
env->eip = env->lstar; |
383 |
|
else |
384 |
|
env->eip = env->cstar; |
385 |
|
} else |
386 |
|
#endif |
387 |
|
{ |
388 |
|
env->regs[R_ECX] = (uint32_t)kenv->next_eip; |
389 |
|
|
390 |
|
cpu_x86_set_cpl(env, 0); |
391 |
|
cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, |
392 |
|
0, 0xffffffff, |
393 |
|
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
394 |
|
DESC_S_MASK | |
395 |
|
DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); |
396 |
|
cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, |
397 |
|
0, 0xffffffff, |
398 |
|
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
399 |
|
DESC_S_MASK | |
400 |
|
DESC_W_MASK | DESC_A_MASK); |
401 |
|
env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK); |
402 |
|
env->eip = (uint32_t)env->star; |
403 |
|
} |
404 |
|
return 2; |
405 |
|
} |
406 |
|
|
407 |
int kqemu_cpu_exec(CPUState *env) |
int kqemu_cpu_exec(CPUState *env) |
408 |
{ |
{ |
409 |
struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state; |
struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state; |
431 |
kenv->cr3 = env->cr[3]; |
kenv->cr3 = env->cr[3]; |
432 |
kenv->cr4 = env->cr[4]; |
kenv->cr4 = env->cr[4]; |
433 |
kenv->a20_mask = env->a20_mask; |
kenv->a20_mask = env->a20_mask; |
434 |
|
#ifdef __x86_64__ |
435 |
|
kenv->efer = env->efer; |
436 |
|
#endif |
437 |
if (env->dr[7] & 0xff) { |
if (env->dr[7] & 0xff) { |
438 |
kenv->dr7 = env->dr[7]; |
kenv->dr7 = env->dr[7]; |
439 |
kenv->dr0 = env->dr[0]; |
kenv->dr0 = env->dr[0]; |
499 |
fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret); |
fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret); |
500 |
} |
} |
501 |
#endif |
#endif |
502 |
|
if (ret == KQEMU_RET_SYSCALL) { |
503 |
|
/* syscall instruction */ |
504 |
|
return do_syscall(env, kenv); |
505 |
|
} else |
506 |
if ((ret & 0xff00) == KQEMU_RET_INT) { |
if ((ret & 0xff00) == KQEMU_RET_INT) { |
507 |
env->exception_index = ret & 0xff; |
env->exception_index = ret & 0xff; |
508 |
env->error_code = 0; |
env->error_code = 0; |
509 |
env->exception_is_int = 1; |
env->exception_is_int = 1; |
510 |
env->exception_next_eip = kenv->next_eip; |
env->exception_next_eip = kenv->next_eip; |
511 |
#ifdef DEBUG |
#ifdef DEBUG |
512 |
if (loglevel & CPU_LOG_INT) { |
if (loglevel & CPU_LOG_INT) { |
513 |
fprintf(logfile, "kqemu: interrupt v=%02x:\n", |
fprintf(logfile, "kqemu: interrupt v=%02x:\n", |
514 |
env->exception_index); |
env->exception_index); |
515 |
cpu_dump_state(env, logfile, fprintf, 0); |
cpu_dump_state(env, logfile, fprintf, 0); |
516 |
} |
} |
517 |
#endif |
#endif |
518 |
return 1; |
return 1; |
519 |
} else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) { |
} else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) { |