Statistics
| Branch: | Revision:

root / kqemu.c @ c45b3c0e

History | View | Annotate | Download (15.2 kB)

1 9df217a3 bellard
/*
2 9df217a3 bellard
 *  KQEMU support
3 9df217a3 bellard
 * 
4 9df217a3 bellard
 *  Copyright (c) 2005 Fabrice Bellard
5 9df217a3 bellard
 *
6 9df217a3 bellard
 * This library is free software; you can redistribute it and/or
7 9df217a3 bellard
 * modify it under the terms of the GNU Lesser General Public
8 9df217a3 bellard
 * License as published by the Free Software Foundation; either
9 9df217a3 bellard
 * version 2 of the License, or (at your option) any later version.
10 9df217a3 bellard
 *
11 9df217a3 bellard
 * This library is distributed in the hope that it will be useful,
12 9df217a3 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 9df217a3 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 9df217a3 bellard
 * Lesser General Public License for more details.
15 9df217a3 bellard
 *
16 9df217a3 bellard
 * You should have received a copy of the GNU Lesser General Public
17 9df217a3 bellard
 * License along with this library; if not, write to the Free Software
18 9df217a3 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 9df217a3 bellard
 */
20 9df217a3 bellard
#include "config.h"
21 9df217a3 bellard
#ifdef _WIN32
22 9df217a3 bellard
#include <windows.h>
23 6e4255f6 bellard
#include <winioctl.h>
24 9df217a3 bellard
#else
25 9df217a3 bellard
#include <sys/types.h>
26 9df217a3 bellard
#include <sys/mman.h>
27 6e4255f6 bellard
#include <sys/ioctl.h>
28 9df217a3 bellard
#endif
29 9df217a3 bellard
#include <stdlib.h>
30 9df217a3 bellard
#include <stdio.h>
31 9df217a3 bellard
#include <stdarg.h>
32 9df217a3 bellard
#include <string.h>
33 9df217a3 bellard
#include <errno.h>
34 9df217a3 bellard
#include <unistd.h>
35 9df217a3 bellard
#include <inttypes.h>
36 9df217a3 bellard
37 9df217a3 bellard
#include "cpu.h"
38 9df217a3 bellard
#include "exec-all.h"
39 9df217a3 bellard
40 9df217a3 bellard
#ifdef USE_KQEMU
41 9df217a3 bellard
42 9df217a3 bellard
#define DEBUG
43 9df217a3 bellard
44 9df217a3 bellard
#include <unistd.h>
45 9df217a3 bellard
#include <fcntl.h>
46 9df217a3 bellard
#include "kqemu/kqemu.h"
47 9df217a3 bellard
48 c28e951f bellard
/* compatibility stuff */
49 c28e951f bellard
#ifndef KQEMU_RET_SYSCALL
50 c28e951f bellard
#define KQEMU_RET_SYSCALL   0x0300 /* syscall insn */
51 c28e951f bellard
#endif
52 c28e951f bellard
53 6e4255f6 bellard
#ifdef _WIN32
54 6e4255f6 bellard
#define KQEMU_DEVICE "\\\\.\\kqemu"
55 6e4255f6 bellard
#else
56 9df217a3 bellard
#define KQEMU_DEVICE "/dev/kqemu"
57 6e4255f6 bellard
#endif
58 6e4255f6 bellard
59 6e4255f6 bellard
#ifdef _WIN32
60 6e4255f6 bellard
#define KQEMU_INVALID_FD INVALID_HANDLE_VALUE
61 6e4255f6 bellard
HANDLE kqemu_fd = KQEMU_INVALID_FD;
62 6e4255f6 bellard
#define kqemu_closefd(x) CloseHandle(x)
63 6e4255f6 bellard
#else
64 6e4255f6 bellard
#define KQEMU_INVALID_FD -1
65 6e4255f6 bellard
int kqemu_fd = KQEMU_INVALID_FD;
66 6e4255f6 bellard
#define kqemu_closefd(x) close(x)
67 6e4255f6 bellard
#endif
68 9df217a3 bellard
69 9df217a3 bellard
int kqemu_allowed = 1;
70 9df217a3 bellard
unsigned long *pages_to_flush;
71 9df217a3 bellard
unsigned int nb_pages_to_flush;
72 9df217a3 bellard
extern uint32_t **l1_phys_map;
73 9df217a3 bellard
74 9df217a3 bellard
#define cpuid(index, eax, ebx, ecx, edx) \
75 9df217a3 bellard
  asm volatile ("cpuid" \
76 9df217a3 bellard
                : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
77 9df217a3 bellard
                : "0" (index))
78 9df217a3 bellard
79 c28e951f bellard
#ifdef __x86_64__
80 c28e951f bellard
static int is_cpuid_supported(void)
81 c28e951f bellard
{
82 c28e951f bellard
    return 1;
83 c28e951f bellard
}
84 c28e951f bellard
#else
85 9df217a3 bellard
static int is_cpuid_supported(void)
86 9df217a3 bellard
{
87 9df217a3 bellard
    int v0, v1;
88 9df217a3 bellard
    asm volatile ("pushf\n"
89 9df217a3 bellard
                  "popl %0\n"
90 9df217a3 bellard
                  "movl %0, %1\n"
91 9df217a3 bellard
                  "xorl $0x00200000, %0\n"
92 9df217a3 bellard
                  "pushl %0\n"
93 9df217a3 bellard
                  "popf\n"
94 9df217a3 bellard
                  "pushf\n"
95 9df217a3 bellard
                  "popl %0\n"
96 9df217a3 bellard
                  : "=a" (v0), "=d" (v1)
97 9df217a3 bellard
                  :
98 9df217a3 bellard
                  : "cc");
99 9df217a3 bellard
    return (v0 != v1);
100 9df217a3 bellard
}
101 c28e951f bellard
#endif
102 9df217a3 bellard
103 9df217a3 bellard
static void kqemu_update_cpuid(CPUState *env)
104 9df217a3 bellard
{
105 9df217a3 bellard
    int critical_features_mask, features;
106 9df217a3 bellard
    uint32_t eax, ebx, ecx, edx;
107 9df217a3 bellard
108 9df217a3 bellard
    /* the following features are kept identical on the host and
109 9df217a3 bellard
       target cpus because they are important for user code. Strictly
110 9df217a3 bellard
       speaking, only SSE really matters because the OS must support
111 9df217a3 bellard
       it if the user code uses it. */
112 9df217a3 bellard
    critical_features_mask = 
113 9df217a3 bellard
        CPUID_CMOV | CPUID_CX8 | 
114 9df217a3 bellard
        CPUID_FXSR | CPUID_MMX | CPUID_SSE | 
115 9df217a3 bellard
        CPUID_SSE2;
116 9df217a3 bellard
    if (!is_cpuid_supported()) {
117 9df217a3 bellard
        features = 0;
118 9df217a3 bellard
    } else {
119 9df217a3 bellard
        cpuid(1, eax, ebx, ecx, edx);
120 9df217a3 bellard
        features = edx;
121 9df217a3 bellard
    }
122 9df217a3 bellard
    env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
123 9df217a3 bellard
        (features & critical_features_mask);
124 9df217a3 bellard
    /* XXX: we could update more of the target CPUID state so that the
125 9df217a3 bellard
       non accelerated code sees exactly the same CPU features as the
126 9df217a3 bellard
       accelerated code */
127 9df217a3 bellard
}
128 9df217a3 bellard
129 9df217a3 bellard
int kqemu_init(CPUState *env)
130 9df217a3 bellard
{
131 9df217a3 bellard
    struct kqemu_init init;
132 9df217a3 bellard
    int ret, version;
133 6e4255f6 bellard
#ifdef _WIN32
134 6e4255f6 bellard
    DWORD temp;
135 6e4255f6 bellard
#endif
136 9df217a3 bellard
137 9df217a3 bellard
    if (!kqemu_allowed)
138 9df217a3 bellard
        return -1;
139 9df217a3 bellard
140 6e4255f6 bellard
#ifdef _WIN32
141 6e4255f6 bellard
    kqemu_fd = CreateFile(KQEMU_DEVICE, GENERIC_WRITE | GENERIC_READ,
142 6e4255f6 bellard
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
143 6e4255f6 bellard
                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
144 6e4255f6 bellard
                          NULL);
145 6e4255f6 bellard
#else
146 9df217a3 bellard
    kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
147 6e4255f6 bellard
#endif
148 6e4255f6 bellard
    if (kqemu_fd == KQEMU_INVALID_FD) {
149 9df217a3 bellard
        fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated\n", KQEMU_DEVICE);
150 9df217a3 bellard
        return -1;
151 9df217a3 bellard
    }
152 9df217a3 bellard
    version = 0;
153 6e4255f6 bellard
#ifdef _WIN32
154 6e4255f6 bellard
    DeviceIoControl(kqemu_fd, KQEMU_GET_VERSION, NULL, 0,
155 6e4255f6 bellard
                    &version, sizeof(version), &temp, NULL);
156 6e4255f6 bellard
#else
157 9df217a3 bellard
    ioctl(kqemu_fd, KQEMU_GET_VERSION, &version);
158 6e4255f6 bellard
#endif
159 9df217a3 bellard
    if (version != KQEMU_VERSION) {
160 9df217a3 bellard
        fprintf(stderr, "Version mismatch between kqemu module and qemu (%08x %08x) - disabling kqemu use\n",
161 9df217a3 bellard
                version, KQEMU_VERSION);
162 9df217a3 bellard
        goto fail;
163 9df217a3 bellard
    }
164 9df217a3 bellard
165 9df217a3 bellard
    pages_to_flush = qemu_vmalloc(KQEMU_MAX_PAGES_TO_FLUSH * 
166 9df217a3 bellard
                                  sizeof(unsigned long));
167 9df217a3 bellard
    if (!pages_to_flush)
168 9df217a3 bellard
        goto fail;
169 9df217a3 bellard
170 9df217a3 bellard
    init.ram_base = phys_ram_base;
171 9df217a3 bellard
    init.ram_size = phys_ram_size;
172 9df217a3 bellard
    init.ram_dirty = phys_ram_dirty;
173 9df217a3 bellard
    init.phys_to_ram_map = l1_phys_map;
174 9df217a3 bellard
    init.pages_to_flush = pages_to_flush;
175 6e4255f6 bellard
#ifdef _WIN32
176 6e4255f6 bellard
    ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
177 6e4255f6 bellard
                          NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
178 6e4255f6 bellard
#else
179 9df217a3 bellard
    ret = ioctl(kqemu_fd, KQEMU_INIT, &init);
180 6e4255f6 bellard
#endif
181 9df217a3 bellard
    if (ret < 0) {
182 9df217a3 bellard
        fprintf(stderr, "Error %d while initializing QEMU acceleration layer - disabling it for now\n", ret);
183 9df217a3 bellard
    fail:
184 6e4255f6 bellard
        kqemu_closefd(kqemu_fd);
185 6e4255f6 bellard
        kqemu_fd = KQEMU_INVALID_FD;
186 9df217a3 bellard
        return -1;
187 9df217a3 bellard
    }
188 9df217a3 bellard
    kqemu_update_cpuid(env);
189 9df217a3 bellard
    env->kqemu_enabled = 1;
190 9df217a3 bellard
    nb_pages_to_flush = 0;
191 9df217a3 bellard
    return 0;
192 9df217a3 bellard
}
193 9df217a3 bellard
194 9df217a3 bellard
void kqemu_flush_page(CPUState *env, target_ulong addr)
195 9df217a3 bellard
{
196 9df217a3 bellard
#ifdef DEBUG
197 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
198 9df217a3 bellard
        fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
199 9df217a3 bellard
    }
200 9df217a3 bellard
#endif
201 9df217a3 bellard
    if (nb_pages_to_flush >= KQEMU_MAX_PAGES_TO_FLUSH)
202 9df217a3 bellard
        nb_pages_to_flush = KQEMU_FLUSH_ALL;
203 9df217a3 bellard
    else
204 9df217a3 bellard
        pages_to_flush[nb_pages_to_flush++] = addr;
205 9df217a3 bellard
}
206 9df217a3 bellard
207 9df217a3 bellard
void kqemu_flush(CPUState *env, int global)
208 9df217a3 bellard
{
209 9df217a3 bellard
#ifdef DEBUG
210 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
211 9df217a3 bellard
        fprintf(logfile, "kqemu_flush:\n");
212 9df217a3 bellard
    }
213 9df217a3 bellard
#endif
214 9df217a3 bellard
    nb_pages_to_flush = KQEMU_FLUSH_ALL;
215 9df217a3 bellard
}
216 9df217a3 bellard
217 9df217a3 bellard
struct fpstate {
218 9df217a3 bellard
    uint16_t fpuc;
219 9df217a3 bellard
    uint16_t dummy1;
220 9df217a3 bellard
    uint16_t fpus;
221 9df217a3 bellard
    uint16_t dummy2;
222 9df217a3 bellard
    uint16_t fptag;
223 9df217a3 bellard
    uint16_t dummy3;
224 9df217a3 bellard
225 9df217a3 bellard
    uint32_t fpip;
226 9df217a3 bellard
    uint32_t fpcs;
227 9df217a3 bellard
    uint32_t fpoo;
228 9df217a3 bellard
    uint32_t fpos;
229 9df217a3 bellard
    uint8_t fpregs1[8 * 10];
230 9df217a3 bellard
};
231 9df217a3 bellard
232 9df217a3 bellard
struct fpxstate {
233 9df217a3 bellard
    uint16_t fpuc;
234 9df217a3 bellard
    uint16_t fpus;
235 9df217a3 bellard
    uint16_t fptag;
236 9df217a3 bellard
    uint16_t fop;
237 9df217a3 bellard
    uint32_t fpuip;
238 9df217a3 bellard
    uint16_t cs_sel;
239 9df217a3 bellard
    uint16_t dummy0;
240 9df217a3 bellard
    uint32_t fpudp;
241 9df217a3 bellard
    uint16_t ds_sel;
242 9df217a3 bellard
    uint16_t dummy1;
243 9df217a3 bellard
    uint32_t mxcsr;
244 9df217a3 bellard
    uint32_t mxcsr_mask;
245 9df217a3 bellard
    uint8_t fpregs1[8 * 16];
246 c28e951f bellard
    uint8_t xmm_regs[16 * 16];
247 c28e951f bellard
    uint8_t dummy2[96];
248 9df217a3 bellard
};
249 9df217a3 bellard
250 9df217a3 bellard
static struct fpxstate fpx1 __attribute__((aligned(16)));
251 9df217a3 bellard
252 9df217a3 bellard
static void restore_native_fp_frstor(CPUState *env)
253 9df217a3 bellard
{
254 9df217a3 bellard
    int fptag, i, j;
255 9df217a3 bellard
    struct fpstate fp1, *fp = &fp1;
256 9df217a3 bellard
    
257 9df217a3 bellard
    fp->fpuc = env->fpuc;
258 9df217a3 bellard
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
259 9df217a3 bellard
    fptag = 0;
260 9df217a3 bellard
    for (i=7; i>=0; i--) {
261 9df217a3 bellard
        fptag <<= 2;
262 9df217a3 bellard
        if (env->fptags[i]) {
263 9df217a3 bellard
            fptag |= 3;
264 9df217a3 bellard
        } else {
265 9df217a3 bellard
            /* the FPU automatically computes it */
266 9df217a3 bellard
        }
267 9df217a3 bellard
    }
268 9df217a3 bellard
    fp->fptag = fptag;
269 9df217a3 bellard
    j = env->fpstt;
270 9df217a3 bellard
    for(i = 0;i < 8; i++) {
271 9df217a3 bellard
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
272 9df217a3 bellard
        j = (j + 1) & 7;
273 9df217a3 bellard
    }
274 9df217a3 bellard
    asm volatile ("frstor %0" : "=m" (*fp));
275 9df217a3 bellard
}
276 9df217a3 bellard
 
277 9df217a3 bellard
static void save_native_fp_fsave(CPUState *env)
278 9df217a3 bellard
{
279 9df217a3 bellard
    int fptag, i, j;
280 9df217a3 bellard
    uint16_t fpuc;
281 9df217a3 bellard
    struct fpstate fp1, *fp = &fp1;
282 9df217a3 bellard
283 9df217a3 bellard
    asm volatile ("fsave %0" : : "m" (*fp));
284 9df217a3 bellard
    env->fpuc = fp->fpuc;
285 9df217a3 bellard
    env->fpstt = (fp->fpus >> 11) & 7;
286 9df217a3 bellard
    env->fpus = fp->fpus & ~0x3800;
287 9df217a3 bellard
    fptag = fp->fptag;
288 9df217a3 bellard
    for(i = 0;i < 8; i++) {
289 9df217a3 bellard
        env->fptags[i] = ((fptag & 3) == 3);
290 9df217a3 bellard
        fptag >>= 2;
291 9df217a3 bellard
    }
292 9df217a3 bellard
    j = env->fpstt;
293 9df217a3 bellard
    for(i = 0;i < 8; i++) {
294 9df217a3 bellard
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
295 9df217a3 bellard
        j = (j + 1) & 7;
296 9df217a3 bellard
    }
297 9df217a3 bellard
    /* we must restore the default rounding state */
298 9df217a3 bellard
    fpuc = 0x037f | (env->fpuc & (3 << 10));
299 9df217a3 bellard
    asm volatile("fldcw %0" : : "m" (fpuc));
300 9df217a3 bellard
}
301 9df217a3 bellard
302 9df217a3 bellard
static void restore_native_fp_fxrstor(CPUState *env)
303 9df217a3 bellard
{
304 9df217a3 bellard
    struct fpxstate *fp = &fpx1;
305 9df217a3 bellard
    int i, j, fptag;
306 9df217a3 bellard
307 9df217a3 bellard
    fp->fpuc = env->fpuc;
308 9df217a3 bellard
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
309 9df217a3 bellard
    fptag = 0;
310 9df217a3 bellard
    for(i = 0; i < 8; i++)
311 9df217a3 bellard
        fptag |= (env->fptags[i] << i);
312 9df217a3 bellard
    fp->fptag = fptag ^ 0xff;
313 9df217a3 bellard
314 9df217a3 bellard
    j = env->fpstt;
315 9df217a3 bellard
    for(i = 0;i < 8; i++) {
316 9df217a3 bellard
        memcpy(&fp->fpregs1[i * 16], &env->fpregs[j].d, 10);
317 9df217a3 bellard
        j = (j + 1) & 7;
318 9df217a3 bellard
    }
319 9df217a3 bellard
    if (env->cpuid_features & CPUID_SSE) {
320 9df217a3 bellard
        fp->mxcsr = env->mxcsr;
321 9df217a3 bellard
        /* XXX: check if DAZ is not available */
322 9df217a3 bellard
        fp->mxcsr_mask = 0xffff;
323 c28e951f bellard
        memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16);
324 9df217a3 bellard
    }
325 9df217a3 bellard
    asm volatile ("fxrstor %0" : "=m" (*fp));
326 9df217a3 bellard
}
327 9df217a3 bellard
328 9df217a3 bellard
static void save_native_fp_fxsave(CPUState *env)
329 9df217a3 bellard
{
330 9df217a3 bellard
    struct fpxstate *fp = &fpx1;
331 9df217a3 bellard
    int fptag, i, j;
332 9df217a3 bellard
    uint16_t fpuc;
333 9df217a3 bellard
334 9df217a3 bellard
    asm volatile ("fxsave %0" : : "m" (*fp));
335 9df217a3 bellard
    env->fpuc = fp->fpuc;
336 9df217a3 bellard
    env->fpstt = (fp->fpus >> 11) & 7;
337 9df217a3 bellard
    env->fpus = fp->fpus & ~0x3800;
338 9df217a3 bellard
    fptag = fp->fptag ^ 0xff;
339 9df217a3 bellard
    for(i = 0;i < 8; i++) {
340 9df217a3 bellard
        env->fptags[i] = (fptag >> i) & 1;
341 9df217a3 bellard
    }
342 9df217a3 bellard
    j = env->fpstt;
343 9df217a3 bellard
    for(i = 0;i < 8; i++) {
344 9df217a3 bellard
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 16], 10);
345 9df217a3 bellard
        j = (j + 1) & 7;
346 9df217a3 bellard
    }
347 9df217a3 bellard
    if (env->cpuid_features & CPUID_SSE) {
348 9df217a3 bellard
        env->mxcsr = fp->mxcsr;
349 c28e951f bellard
        memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
350 9df217a3 bellard
    }
351 9df217a3 bellard
352 9df217a3 bellard
    /* we must restore the default rounding state */
353 9df217a3 bellard
    asm volatile ("fninit");
354 9df217a3 bellard
    fpuc = 0x037f | (env->fpuc & (3 << 10));
355 9df217a3 bellard
    asm volatile("fldcw %0" : : "m" (fpuc));
356 9df217a3 bellard
}
357 9df217a3 bellard
358 c28e951f bellard
static int do_syscall(CPUState *env,
359 c28e951f bellard
                      struct kqemu_cpu_state *kenv)
360 c28e951f bellard
{
361 c28e951f bellard
    int selector;
362 c28e951f bellard
    
363 c28e951f bellard
    selector = (env->star >> 32) & 0xffff;
364 c28e951f bellard
#ifdef __x86_64__
365 c28e951f bellard
    if (env->hflags & HF_LMA_MASK) {
366 c28e951f bellard
        env->regs[R_ECX] = kenv->next_eip;
367 c28e951f bellard
        env->regs[11] = env->eflags;
368 c28e951f bellard
369 c28e951f bellard
        cpu_x86_set_cpl(env, 0);
370 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
371 c28e951f bellard
                               0, 0xffffffff, 
372 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
373 c28e951f bellard
                               DESC_S_MASK |
374 c28e951f bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
375 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
376 c28e951f bellard
                               0, 0xffffffff,
377 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
378 c28e951f bellard
                               DESC_S_MASK |
379 c28e951f bellard
                               DESC_W_MASK | DESC_A_MASK);
380 c28e951f bellard
        env->eflags &= ~env->fmask;
381 c28e951f bellard
        if (env->hflags & HF_CS64_MASK)
382 c28e951f bellard
            env->eip = env->lstar;
383 c28e951f bellard
        else
384 c28e951f bellard
            env->eip = env->cstar;
385 c28e951f bellard
    } else 
386 c28e951f bellard
#endif
387 c28e951f bellard
    {
388 c28e951f bellard
        env->regs[R_ECX] = (uint32_t)kenv->next_eip;
389 c28e951f bellard
        
390 c28e951f bellard
        cpu_x86_set_cpl(env, 0);
391 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
392 c28e951f bellard
                           0, 0xffffffff, 
393 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
394 c28e951f bellard
                               DESC_S_MASK |
395 c28e951f bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
396 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
397 c28e951f bellard
                               0, 0xffffffff,
398 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
399 c28e951f bellard
                               DESC_S_MASK |
400 c28e951f bellard
                               DESC_W_MASK | DESC_A_MASK);
401 c28e951f bellard
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
402 c28e951f bellard
        env->eip = (uint32_t)env->star;
403 c28e951f bellard
    }
404 c28e951f bellard
    return 2;
405 c28e951f bellard
}
406 c28e951f bellard
407 9df217a3 bellard
int kqemu_cpu_exec(CPUState *env)
408 9df217a3 bellard
{
409 9df217a3 bellard
    struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
410 9df217a3 bellard
    int ret;
411 6e4255f6 bellard
#ifdef _WIN32
412 6e4255f6 bellard
    DWORD temp;
413 6e4255f6 bellard
#endif
414 9df217a3 bellard
415 9df217a3 bellard
#ifdef DEBUG
416 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
417 9df217a3 bellard
        fprintf(logfile, "kqemu: cpu_exec: enter\n");
418 9df217a3 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
419 9df217a3 bellard
    }
420 9df217a3 bellard
#endif
421 9df217a3 bellard
    memcpy(kenv->regs, env->regs, sizeof(kenv->regs));
422 9df217a3 bellard
    kenv->eip = env->eip;
423 9df217a3 bellard
    kenv->eflags = env->eflags;
424 9df217a3 bellard
    memcpy(&kenv->segs, &env->segs, sizeof(env->segs));
425 9df217a3 bellard
    memcpy(&kenv->ldt, &env->ldt, sizeof(env->ldt));
426 9df217a3 bellard
    memcpy(&kenv->tr, &env->tr, sizeof(env->tr));
427 9df217a3 bellard
    memcpy(&kenv->gdt, &env->gdt, sizeof(env->gdt));
428 9df217a3 bellard
    memcpy(&kenv->idt, &env->idt, sizeof(env->idt));
429 9df217a3 bellard
    kenv->cr0 = env->cr[0];
430 9df217a3 bellard
    kenv->cr2 = env->cr[2];
431 9df217a3 bellard
    kenv->cr3 = env->cr[3];
432 9df217a3 bellard
    kenv->cr4 = env->cr[4];
433 9df217a3 bellard
    kenv->a20_mask = env->a20_mask;
434 c45b3c0e bellard
#if KQEMU_VERSION >= 0x010100
435 c28e951f bellard
    kenv->efer = env->efer;
436 c28e951f bellard
#endif
437 9df217a3 bellard
    if (env->dr[7] & 0xff) {
438 9df217a3 bellard
        kenv->dr7 = env->dr[7];
439 9df217a3 bellard
        kenv->dr0 = env->dr[0];
440 9df217a3 bellard
        kenv->dr1 = env->dr[1];
441 9df217a3 bellard
        kenv->dr2 = env->dr[2];
442 9df217a3 bellard
        kenv->dr3 = env->dr[3];
443 9df217a3 bellard
    } else {
444 9df217a3 bellard
        kenv->dr7 = 0;
445 9df217a3 bellard
    }
446 9df217a3 bellard
    kenv->dr6 = env->dr[6];
447 9df217a3 bellard
    kenv->cpl = 3;
448 9df217a3 bellard
    kenv->nb_pages_to_flush = nb_pages_to_flush;
449 9df217a3 bellard
    nb_pages_to_flush = 0;
450 9df217a3 bellard
    
451 9df217a3 bellard
    if (!(kenv->cr0 & CR0_TS_MASK)) {
452 9df217a3 bellard
        if (env->cpuid_features & CPUID_FXSR)
453 9df217a3 bellard
            restore_native_fp_fxrstor(env);
454 9df217a3 bellard
        else
455 9df217a3 bellard
            restore_native_fp_frstor(env);
456 9df217a3 bellard
    }
457 9df217a3 bellard
458 6e4255f6 bellard
#ifdef _WIN32
459 6e4255f6 bellard
    DeviceIoControl(kqemu_fd, KQEMU_EXEC,
460 6e4255f6 bellard
                    kenv, sizeof(struct kqemu_cpu_state),
461 6e4255f6 bellard
                    kenv, sizeof(struct kqemu_cpu_state),
462 6e4255f6 bellard
                    &temp, NULL);
463 6e4255f6 bellard
    ret = kenv->retval;
464 6e4255f6 bellard
#else
465 6e4255f6 bellard
#if KQEMU_VERSION >= 0x010100
466 6e4255f6 bellard
    ioctl(kqemu_fd, KQEMU_EXEC, kenv);
467 6e4255f6 bellard
    ret = kenv->retval;
468 6e4255f6 bellard
#else
469 9df217a3 bellard
    ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
470 6e4255f6 bellard
#endif
471 6e4255f6 bellard
#endif
472 9df217a3 bellard
    if (!(kenv->cr0 & CR0_TS_MASK)) {
473 9df217a3 bellard
        if (env->cpuid_features & CPUID_FXSR)
474 9df217a3 bellard
            save_native_fp_fxsave(env);
475 9df217a3 bellard
        else
476 9df217a3 bellard
            save_native_fp_fsave(env);
477 9df217a3 bellard
    }
478 9df217a3 bellard
479 9df217a3 bellard
    memcpy(env->regs, kenv->regs, sizeof(env->regs));
480 9df217a3 bellard
    env->eip = kenv->eip;
481 9df217a3 bellard
    env->eflags = kenv->eflags;
482 9df217a3 bellard
    memcpy(env->segs, kenv->segs, sizeof(env->segs));
483 9df217a3 bellard
#if 0
484 9df217a3 bellard
    /* no need to restore that */
485 9df217a3 bellard
    memcpy(env->ldt, kenv->ldt, sizeof(env->ldt));
486 9df217a3 bellard
    memcpy(env->tr, kenv->tr, sizeof(env->tr));
487 9df217a3 bellard
    memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
488 9df217a3 bellard
    memcpy(env->idt, kenv->idt, sizeof(env->idt));
489 9df217a3 bellard
    env->cr[0] = kenv->cr0;
490 9df217a3 bellard
    env->cr[3] = kenv->cr3;
491 9df217a3 bellard
    env->cr[4] = kenv->cr4;
492 9df217a3 bellard
    env->a20_mask = kenv->a20_mask;
493 9df217a3 bellard
#endif
494 9df217a3 bellard
    env->cr[2] = kenv->cr2;
495 9df217a3 bellard
    env->dr[6] = kenv->dr6;
496 9df217a3 bellard
497 9df217a3 bellard
#ifdef DEBUG
498 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
499 9df217a3 bellard
        fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
500 9df217a3 bellard
    }
501 9df217a3 bellard
#endif
502 c28e951f bellard
    if (ret == KQEMU_RET_SYSCALL) {
503 c28e951f bellard
        /* syscall instruction */
504 c28e951f bellard
        return do_syscall(env, kenv);
505 c28e951f bellard
    } else 
506 9df217a3 bellard
    if ((ret & 0xff00) == KQEMU_RET_INT) {
507 9df217a3 bellard
        env->exception_index = ret & 0xff;
508 9df217a3 bellard
        env->error_code = 0;
509 9df217a3 bellard
        env->exception_is_int = 1;
510 9df217a3 bellard
        env->exception_next_eip = kenv->next_eip;
511 9df217a3 bellard
#ifdef DEBUG
512 c28e951f bellard
        if (loglevel & CPU_LOG_INT) {
513 c28e951f bellard
            fprintf(logfile, "kqemu: interrupt v=%02x:\n", 
514 c28e951f bellard
                    env->exception_index);
515 c28e951f bellard
            cpu_dump_state(env, logfile, fprintf, 0);
516 c28e951f bellard
        }
517 9df217a3 bellard
#endif
518 9df217a3 bellard
        return 1;
519 9df217a3 bellard
    } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {
520 9df217a3 bellard
        env->exception_index = ret & 0xff;
521 9df217a3 bellard
        env->error_code = kenv->error_code;
522 9df217a3 bellard
        env->exception_is_int = 0;
523 9df217a3 bellard
        env->exception_next_eip = 0;
524 9df217a3 bellard
#ifdef DEBUG
525 9df217a3 bellard
        if (loglevel & CPU_LOG_INT) {
526 9df217a3 bellard
            fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
527 9df217a3 bellard
                    env->exception_index, env->error_code);
528 9df217a3 bellard
            cpu_dump_state(env, logfile, fprintf, 0);
529 9df217a3 bellard
        }
530 9df217a3 bellard
#endif
531 9df217a3 bellard
        return 1;
532 9df217a3 bellard
    } else if (ret == KQEMU_RET_INTR) {
533 c45b3c0e bellard
#ifdef DEBUG
534 c45b3c0e bellard
        if (loglevel & CPU_LOG_INT) {
535 c45b3c0e bellard
            cpu_dump_state(env, logfile, fprintf, 0);
536 c45b3c0e bellard
        }
537 c45b3c0e bellard
#endif
538 9df217a3 bellard
        return 0;
539 9df217a3 bellard
    } else if (ret == KQEMU_RET_SOFTMMU) { 
540 9df217a3 bellard
        return 2;
541 9df217a3 bellard
    } else {
542 9df217a3 bellard
        cpu_dump_state(env, stderr, fprintf, 0);
543 9df217a3 bellard
        fprintf(stderr, "Unsupported return value: 0x%x\n", ret);
544 9df217a3 bellard
        exit(1);
545 9df217a3 bellard
    }
546 9df217a3 bellard
    return 0;
547 9df217a3 bellard
}
548 9df217a3 bellard
549 9df217a3 bellard
#endif