Statistics
| Branch: | Revision:

root / kqemu.c @ 26a76461

History | View | Annotate | Download (24.9 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 aa062973 bellard
//#define PROFILE
44 9df217a3 bellard
45 9df217a3 bellard
#include <unistd.h>
46 9df217a3 bellard
#include <fcntl.h>
47 b88a3832 bellard
#include "kqemu.h"
48 9df217a3 bellard
49 c28e951f bellard
/* compatibility stuff */
50 c28e951f bellard
#ifndef KQEMU_RET_SYSCALL
51 c28e951f bellard
#define KQEMU_RET_SYSCALL   0x0300 /* syscall insn */
52 c28e951f bellard
#endif
53 aa062973 bellard
#ifndef KQEMU_MAX_RAM_PAGES_TO_UPDATE
54 aa062973 bellard
#define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512
55 aa062973 bellard
#define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)
56 aa062973 bellard
#endif
57 f32fc648 bellard
#ifndef KQEMU_MAX_MODIFIED_RAM_PAGES
58 f32fc648 bellard
#define KQEMU_MAX_MODIFIED_RAM_PAGES 512
59 f32fc648 bellard
#endif
60 c28e951f bellard
61 6e4255f6 bellard
#ifdef _WIN32
62 6e4255f6 bellard
#define KQEMU_DEVICE "\\\\.\\kqemu"
63 6e4255f6 bellard
#else
64 9df217a3 bellard
#define KQEMU_DEVICE "/dev/kqemu"
65 6e4255f6 bellard
#endif
66 6e4255f6 bellard
67 6e4255f6 bellard
#ifdef _WIN32
68 6e4255f6 bellard
#define KQEMU_INVALID_FD INVALID_HANDLE_VALUE
69 6e4255f6 bellard
HANDLE kqemu_fd = KQEMU_INVALID_FD;
70 6e4255f6 bellard
#define kqemu_closefd(x) CloseHandle(x)
71 6e4255f6 bellard
#else
72 6e4255f6 bellard
#define KQEMU_INVALID_FD -1
73 6e4255f6 bellard
int kqemu_fd = KQEMU_INVALID_FD;
74 6e4255f6 bellard
#define kqemu_closefd(x) close(x)
75 6e4255f6 bellard
#endif
76 9df217a3 bellard
77 f32fc648 bellard
/* 0 = not allowed
78 f32fc648 bellard
   1 = user kqemu
79 f32fc648 bellard
   2 = kernel kqemu
80 f32fc648 bellard
*/
81 9df217a3 bellard
int kqemu_allowed = 1;
82 9df217a3 bellard
unsigned long *pages_to_flush;
83 9df217a3 bellard
unsigned int nb_pages_to_flush;
84 aa062973 bellard
unsigned long *ram_pages_to_update;
85 aa062973 bellard
unsigned int nb_ram_pages_to_update;
86 f32fc648 bellard
unsigned long *modified_ram_pages;
87 f32fc648 bellard
unsigned int nb_modified_ram_pages;
88 f32fc648 bellard
uint8_t *modified_ram_pages_table;
89 9df217a3 bellard
extern uint32_t **l1_phys_map;
90 9df217a3 bellard
91 9df217a3 bellard
#define cpuid(index, eax, ebx, ecx, edx) \
92 9df217a3 bellard
  asm volatile ("cpuid" \
93 9df217a3 bellard
                : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
94 9df217a3 bellard
                : "0" (index))
95 9df217a3 bellard
96 c28e951f bellard
#ifdef __x86_64__
97 c28e951f bellard
static int is_cpuid_supported(void)
98 c28e951f bellard
{
99 c28e951f bellard
    return 1;
100 c28e951f bellard
}
101 c28e951f bellard
#else
102 9df217a3 bellard
static int is_cpuid_supported(void)
103 9df217a3 bellard
{
104 9df217a3 bellard
    int v0, v1;
105 9df217a3 bellard
    asm volatile ("pushf\n"
106 9df217a3 bellard
                  "popl %0\n"
107 9df217a3 bellard
                  "movl %0, %1\n"
108 9df217a3 bellard
                  "xorl $0x00200000, %0\n"
109 9df217a3 bellard
                  "pushl %0\n"
110 9df217a3 bellard
                  "popf\n"
111 9df217a3 bellard
                  "pushf\n"
112 9df217a3 bellard
                  "popl %0\n"
113 9df217a3 bellard
                  : "=a" (v0), "=d" (v1)
114 9df217a3 bellard
                  :
115 9df217a3 bellard
                  : "cc");
116 9df217a3 bellard
    return (v0 != v1);
117 9df217a3 bellard
}
118 c28e951f bellard
#endif
119 9df217a3 bellard
120 9df217a3 bellard
static void kqemu_update_cpuid(CPUState *env)
121 9df217a3 bellard
{
122 9df217a3 bellard
    int critical_features_mask, features;
123 9df217a3 bellard
    uint32_t eax, ebx, ecx, edx;
124 9df217a3 bellard
125 9df217a3 bellard
    /* the following features are kept identical on the host and
126 9df217a3 bellard
       target cpus because they are important for user code. Strictly
127 9df217a3 bellard
       speaking, only SSE really matters because the OS must support
128 9df217a3 bellard
       it if the user code uses it. */
129 9df217a3 bellard
    critical_features_mask = 
130 9df217a3 bellard
        CPUID_CMOV | CPUID_CX8 | 
131 9df217a3 bellard
        CPUID_FXSR | CPUID_MMX | CPUID_SSE | 
132 ca0d1734 bellard
        CPUID_SSE2 | CPUID_SEP;
133 9df217a3 bellard
    if (!is_cpuid_supported()) {
134 9df217a3 bellard
        features = 0;
135 9df217a3 bellard
    } else {
136 9df217a3 bellard
        cpuid(1, eax, ebx, ecx, edx);
137 9df217a3 bellard
        features = edx;
138 9df217a3 bellard
    }
139 ca0d1734 bellard
#ifdef __x86_64__
140 ca0d1734 bellard
    /* NOTE: on x86_64 CPUs, SYSENTER is not supported in
141 ca0d1734 bellard
       compatibility mode, so in order to have the best performances
142 ca0d1734 bellard
       it is better not to use it */
143 ca0d1734 bellard
    features &= ~CPUID_SEP;
144 ca0d1734 bellard
#endif
145 9df217a3 bellard
    env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
146 9df217a3 bellard
        (features & critical_features_mask);
147 9df217a3 bellard
    /* XXX: we could update more of the target CPUID state so that the
148 9df217a3 bellard
       non accelerated code sees exactly the same CPU features as the
149 9df217a3 bellard
       accelerated code */
150 9df217a3 bellard
}
151 9df217a3 bellard
152 9df217a3 bellard
int kqemu_init(CPUState *env)
153 9df217a3 bellard
{
154 9df217a3 bellard
    struct kqemu_init init;
155 9df217a3 bellard
    int ret, version;
156 6e4255f6 bellard
#ifdef _WIN32
157 6e4255f6 bellard
    DWORD temp;
158 6e4255f6 bellard
#endif
159 9df217a3 bellard
160 9df217a3 bellard
    if (!kqemu_allowed)
161 9df217a3 bellard
        return -1;
162 9df217a3 bellard
163 6e4255f6 bellard
#ifdef _WIN32
164 6e4255f6 bellard
    kqemu_fd = CreateFile(KQEMU_DEVICE, GENERIC_WRITE | GENERIC_READ,
165 6e4255f6 bellard
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
166 6e4255f6 bellard
                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
167 6e4255f6 bellard
                          NULL);
168 6e4255f6 bellard
#else
169 9df217a3 bellard
    kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
170 6e4255f6 bellard
#endif
171 6e4255f6 bellard
    if (kqemu_fd == KQEMU_INVALID_FD) {
172 9df217a3 bellard
        fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated\n", KQEMU_DEVICE);
173 9df217a3 bellard
        return -1;
174 9df217a3 bellard
    }
175 9df217a3 bellard
    version = 0;
176 6e4255f6 bellard
#ifdef _WIN32
177 6e4255f6 bellard
    DeviceIoControl(kqemu_fd, KQEMU_GET_VERSION, NULL, 0,
178 6e4255f6 bellard
                    &version, sizeof(version), &temp, NULL);
179 6e4255f6 bellard
#else
180 9df217a3 bellard
    ioctl(kqemu_fd, KQEMU_GET_VERSION, &version);
181 6e4255f6 bellard
#endif
182 9df217a3 bellard
    if (version != KQEMU_VERSION) {
183 9df217a3 bellard
        fprintf(stderr, "Version mismatch between kqemu module and qemu (%08x %08x) - disabling kqemu use\n",
184 9df217a3 bellard
                version, KQEMU_VERSION);
185 9df217a3 bellard
        goto fail;
186 9df217a3 bellard
    }
187 9df217a3 bellard
188 9df217a3 bellard
    pages_to_flush = qemu_vmalloc(KQEMU_MAX_PAGES_TO_FLUSH * 
189 9df217a3 bellard
                                  sizeof(unsigned long));
190 9df217a3 bellard
    if (!pages_to_flush)
191 9df217a3 bellard
        goto fail;
192 9df217a3 bellard
193 aa062973 bellard
    ram_pages_to_update = qemu_vmalloc(KQEMU_MAX_RAM_PAGES_TO_UPDATE * 
194 aa062973 bellard
                                       sizeof(unsigned long));
195 aa062973 bellard
    if (!ram_pages_to_update)
196 aa062973 bellard
        goto fail;
197 aa062973 bellard
198 f32fc648 bellard
    modified_ram_pages = qemu_vmalloc(KQEMU_MAX_MODIFIED_RAM_PAGES * 
199 f32fc648 bellard
                                      sizeof(unsigned long));
200 f32fc648 bellard
    if (!modified_ram_pages)
201 f32fc648 bellard
        goto fail;
202 f32fc648 bellard
    modified_ram_pages_table = qemu_mallocz(phys_ram_size >> TARGET_PAGE_BITS);
203 f32fc648 bellard
    if (!modified_ram_pages_table)
204 f32fc648 bellard
        goto fail;
205 f32fc648 bellard
206 9df217a3 bellard
    init.ram_base = phys_ram_base;
207 9df217a3 bellard
    init.ram_size = phys_ram_size;
208 9df217a3 bellard
    init.ram_dirty = phys_ram_dirty;
209 9df217a3 bellard
    init.phys_to_ram_map = l1_phys_map;
210 9df217a3 bellard
    init.pages_to_flush = pages_to_flush;
211 aa062973 bellard
#if KQEMU_VERSION >= 0x010200
212 aa062973 bellard
    init.ram_pages_to_update = ram_pages_to_update;
213 aa062973 bellard
#endif
214 f32fc648 bellard
#if KQEMU_VERSION >= 0x010300
215 f32fc648 bellard
    init.modified_ram_pages = modified_ram_pages;
216 f32fc648 bellard
#endif
217 6e4255f6 bellard
#ifdef _WIN32
218 6e4255f6 bellard
    ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
219 6e4255f6 bellard
                          NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
220 6e4255f6 bellard
#else
221 9df217a3 bellard
    ret = ioctl(kqemu_fd, KQEMU_INIT, &init);
222 6e4255f6 bellard
#endif
223 9df217a3 bellard
    if (ret < 0) {
224 9df217a3 bellard
        fprintf(stderr, "Error %d while initializing QEMU acceleration layer - disabling it for now\n", ret);
225 9df217a3 bellard
    fail:
226 6e4255f6 bellard
        kqemu_closefd(kqemu_fd);
227 6e4255f6 bellard
        kqemu_fd = KQEMU_INVALID_FD;
228 9df217a3 bellard
        return -1;
229 9df217a3 bellard
    }
230 9df217a3 bellard
    kqemu_update_cpuid(env);
231 f32fc648 bellard
    env->kqemu_enabled = kqemu_allowed;
232 9df217a3 bellard
    nb_pages_to_flush = 0;
233 aa062973 bellard
    nb_ram_pages_to_update = 0;
234 9df217a3 bellard
    return 0;
235 9df217a3 bellard
}
236 9df217a3 bellard
237 9df217a3 bellard
void kqemu_flush_page(CPUState *env, target_ulong addr)
238 9df217a3 bellard
{
239 f32fc648 bellard
#if defined(DEBUG)
240 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
241 9df217a3 bellard
        fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
242 9df217a3 bellard
    }
243 9df217a3 bellard
#endif
244 9df217a3 bellard
    if (nb_pages_to_flush >= KQEMU_MAX_PAGES_TO_FLUSH)
245 9df217a3 bellard
        nb_pages_to_flush = KQEMU_FLUSH_ALL;
246 9df217a3 bellard
    else
247 9df217a3 bellard
        pages_to_flush[nb_pages_to_flush++] = addr;
248 9df217a3 bellard
}
249 9df217a3 bellard
250 9df217a3 bellard
void kqemu_flush(CPUState *env, int global)
251 9df217a3 bellard
{
252 9df217a3 bellard
#ifdef DEBUG
253 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
254 9df217a3 bellard
        fprintf(logfile, "kqemu_flush:\n");
255 9df217a3 bellard
    }
256 9df217a3 bellard
#endif
257 9df217a3 bellard
    nb_pages_to_flush = KQEMU_FLUSH_ALL;
258 9df217a3 bellard
}
259 9df217a3 bellard
260 aa062973 bellard
void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
261 aa062973 bellard
{
262 aa062973 bellard
#ifdef DEBUG
263 aa062973 bellard
    if (loglevel & CPU_LOG_INT) {
264 aa062973 bellard
        fprintf(logfile, "kqemu_set_notdirty: addr=%08lx\n", ram_addr);
265 aa062973 bellard
    }
266 aa062973 bellard
#endif
267 fc8dc060 bellard
    /* we only track transitions to dirty state */
268 fc8dc060 bellard
    if (phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] != 0xff)
269 fc8dc060 bellard
        return;
270 aa062973 bellard
    if (nb_ram_pages_to_update >= KQEMU_MAX_RAM_PAGES_TO_UPDATE)
271 aa062973 bellard
        nb_ram_pages_to_update = KQEMU_RAM_PAGES_UPDATE_ALL;
272 aa062973 bellard
    else
273 aa062973 bellard
        ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
274 aa062973 bellard
}
275 aa062973 bellard
276 f32fc648 bellard
static void kqemu_reset_modified_ram_pages(void)
277 f32fc648 bellard
{
278 f32fc648 bellard
    int i;
279 f32fc648 bellard
    unsigned long page_index;
280 f32fc648 bellard
    
281 f32fc648 bellard
    for(i = 0; i < nb_modified_ram_pages; i++) {
282 f32fc648 bellard
        page_index = modified_ram_pages[i] >> TARGET_PAGE_BITS;
283 f32fc648 bellard
        modified_ram_pages_table[page_index] = 0;
284 f32fc648 bellard
    }
285 f32fc648 bellard
    nb_modified_ram_pages = 0;
286 f32fc648 bellard
}
287 f32fc648 bellard
288 f32fc648 bellard
void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr)
289 f32fc648 bellard
{
290 f32fc648 bellard
    unsigned long page_index;
291 f32fc648 bellard
    int ret;
292 f32fc648 bellard
#ifdef _WIN32
293 f32fc648 bellard
    DWORD temp;
294 f32fc648 bellard
#endif
295 f32fc648 bellard
296 f32fc648 bellard
    page_index = ram_addr >> TARGET_PAGE_BITS;
297 f32fc648 bellard
    if (!modified_ram_pages_table[page_index]) {
298 f32fc648 bellard
#if 0
299 f32fc648 bellard
        printf("%d: modify_page=%08lx\n", nb_modified_ram_pages, ram_addr);
300 f32fc648 bellard
#endif
301 f32fc648 bellard
        modified_ram_pages_table[page_index] = 1;
302 f32fc648 bellard
        modified_ram_pages[nb_modified_ram_pages++] = ram_addr;
303 f32fc648 bellard
        if (nb_modified_ram_pages >= KQEMU_MAX_MODIFIED_RAM_PAGES) {
304 f32fc648 bellard
            /* flush */
305 f32fc648 bellard
#ifdef _WIN32
306 f32fc648 bellard
            ret = DeviceIoControl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES, 
307 f32fc648 bellard
                                  &nb_modified_ram_pages, 
308 f32fc648 bellard
                                  sizeof(nb_modified_ram_pages),
309 f32fc648 bellard
                                  NULL, 0, &temp, NULL);
310 f32fc648 bellard
#else
311 f32fc648 bellard
            ret = ioctl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES, 
312 f32fc648 bellard
                        &nb_modified_ram_pages);
313 f32fc648 bellard
#endif
314 f32fc648 bellard
            kqemu_reset_modified_ram_pages();
315 f32fc648 bellard
        }
316 f32fc648 bellard
    }
317 f32fc648 bellard
}
318 f32fc648 bellard
319 9df217a3 bellard
struct fpstate {
320 9df217a3 bellard
    uint16_t fpuc;
321 9df217a3 bellard
    uint16_t dummy1;
322 9df217a3 bellard
    uint16_t fpus;
323 9df217a3 bellard
    uint16_t dummy2;
324 9df217a3 bellard
    uint16_t fptag;
325 9df217a3 bellard
    uint16_t dummy3;
326 9df217a3 bellard
327 9df217a3 bellard
    uint32_t fpip;
328 9df217a3 bellard
    uint32_t fpcs;
329 9df217a3 bellard
    uint32_t fpoo;
330 9df217a3 bellard
    uint32_t fpos;
331 9df217a3 bellard
    uint8_t fpregs1[8 * 10];
332 9df217a3 bellard
};
333 9df217a3 bellard
334 9df217a3 bellard
struct fpxstate {
335 9df217a3 bellard
    uint16_t fpuc;
336 9df217a3 bellard
    uint16_t fpus;
337 9df217a3 bellard
    uint16_t fptag;
338 9df217a3 bellard
    uint16_t fop;
339 9df217a3 bellard
    uint32_t fpuip;
340 9df217a3 bellard
    uint16_t cs_sel;
341 9df217a3 bellard
    uint16_t dummy0;
342 9df217a3 bellard
    uint32_t fpudp;
343 9df217a3 bellard
    uint16_t ds_sel;
344 9df217a3 bellard
    uint16_t dummy1;
345 9df217a3 bellard
    uint32_t mxcsr;
346 9df217a3 bellard
    uint32_t mxcsr_mask;
347 9df217a3 bellard
    uint8_t fpregs1[8 * 16];
348 c28e951f bellard
    uint8_t xmm_regs[16 * 16];
349 c28e951f bellard
    uint8_t dummy2[96];
350 9df217a3 bellard
};
351 9df217a3 bellard
352 9df217a3 bellard
static struct fpxstate fpx1 __attribute__((aligned(16)));
353 9df217a3 bellard
354 9df217a3 bellard
static void restore_native_fp_frstor(CPUState *env)
355 9df217a3 bellard
{
356 9df217a3 bellard
    int fptag, i, j;
357 9df217a3 bellard
    struct fpstate fp1, *fp = &fp1;
358 9df217a3 bellard
    
359 9df217a3 bellard
    fp->fpuc = env->fpuc;
360 9df217a3 bellard
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
361 9df217a3 bellard
    fptag = 0;
362 9df217a3 bellard
    for (i=7; i>=0; i--) {
363 9df217a3 bellard
        fptag <<= 2;
364 9df217a3 bellard
        if (env->fptags[i]) {
365 9df217a3 bellard
            fptag |= 3;
366 9df217a3 bellard
        } else {
367 9df217a3 bellard
            /* the FPU automatically computes it */
368 9df217a3 bellard
        }
369 9df217a3 bellard
    }
370 9df217a3 bellard
    fp->fptag = fptag;
371 9df217a3 bellard
    j = env->fpstt;
372 9df217a3 bellard
    for(i = 0;i < 8; i++) {
373 9df217a3 bellard
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
374 9df217a3 bellard
        j = (j + 1) & 7;
375 9df217a3 bellard
    }
376 9df217a3 bellard
    asm volatile ("frstor %0" : "=m" (*fp));
377 9df217a3 bellard
}
378 9df217a3 bellard
 
379 9df217a3 bellard
static void save_native_fp_fsave(CPUState *env)
380 9df217a3 bellard
{
381 9df217a3 bellard
    int fptag, i, j;
382 9df217a3 bellard
    uint16_t fpuc;
383 9df217a3 bellard
    struct fpstate fp1, *fp = &fp1;
384 9df217a3 bellard
385 9df217a3 bellard
    asm volatile ("fsave %0" : : "m" (*fp));
386 9df217a3 bellard
    env->fpuc = fp->fpuc;
387 9df217a3 bellard
    env->fpstt = (fp->fpus >> 11) & 7;
388 9df217a3 bellard
    env->fpus = fp->fpus & ~0x3800;
389 9df217a3 bellard
    fptag = fp->fptag;
390 9df217a3 bellard
    for(i = 0;i < 8; i++) {
391 9df217a3 bellard
        env->fptags[i] = ((fptag & 3) == 3);
392 9df217a3 bellard
        fptag >>= 2;
393 9df217a3 bellard
    }
394 9df217a3 bellard
    j = env->fpstt;
395 9df217a3 bellard
    for(i = 0;i < 8; i++) {
396 9df217a3 bellard
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
397 9df217a3 bellard
        j = (j + 1) & 7;
398 9df217a3 bellard
    }
399 9df217a3 bellard
    /* we must restore the default rounding state */
400 9df217a3 bellard
    fpuc = 0x037f | (env->fpuc & (3 << 10));
401 9df217a3 bellard
    asm volatile("fldcw %0" : : "m" (fpuc));
402 9df217a3 bellard
}
403 9df217a3 bellard
404 9df217a3 bellard
static void restore_native_fp_fxrstor(CPUState *env)
405 9df217a3 bellard
{
406 9df217a3 bellard
    struct fpxstate *fp = &fpx1;
407 9df217a3 bellard
    int i, j, fptag;
408 9df217a3 bellard
409 9df217a3 bellard
    fp->fpuc = env->fpuc;
410 9df217a3 bellard
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
411 9df217a3 bellard
    fptag = 0;
412 9df217a3 bellard
    for(i = 0; i < 8; i++)
413 9df217a3 bellard
        fptag |= (env->fptags[i] << i);
414 9df217a3 bellard
    fp->fptag = fptag ^ 0xff;
415 9df217a3 bellard
416 9df217a3 bellard
    j = env->fpstt;
417 9df217a3 bellard
    for(i = 0;i < 8; i++) {
418 9df217a3 bellard
        memcpy(&fp->fpregs1[i * 16], &env->fpregs[j].d, 10);
419 9df217a3 bellard
        j = (j + 1) & 7;
420 9df217a3 bellard
    }
421 9df217a3 bellard
    if (env->cpuid_features & CPUID_SSE) {
422 9df217a3 bellard
        fp->mxcsr = env->mxcsr;
423 9df217a3 bellard
        /* XXX: check if DAZ is not available */
424 9df217a3 bellard
        fp->mxcsr_mask = 0xffff;
425 c28e951f bellard
        memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16);
426 9df217a3 bellard
    }
427 9df217a3 bellard
    asm volatile ("fxrstor %0" : "=m" (*fp));
428 9df217a3 bellard
}
429 9df217a3 bellard
430 9df217a3 bellard
static void save_native_fp_fxsave(CPUState *env)
431 9df217a3 bellard
{
432 9df217a3 bellard
    struct fpxstate *fp = &fpx1;
433 9df217a3 bellard
    int fptag, i, j;
434 9df217a3 bellard
    uint16_t fpuc;
435 9df217a3 bellard
436 9df217a3 bellard
    asm volatile ("fxsave %0" : : "m" (*fp));
437 9df217a3 bellard
    env->fpuc = fp->fpuc;
438 9df217a3 bellard
    env->fpstt = (fp->fpus >> 11) & 7;
439 9df217a3 bellard
    env->fpus = fp->fpus & ~0x3800;
440 9df217a3 bellard
    fptag = fp->fptag ^ 0xff;
441 9df217a3 bellard
    for(i = 0;i < 8; i++) {
442 9df217a3 bellard
        env->fptags[i] = (fptag >> i) & 1;
443 9df217a3 bellard
    }
444 9df217a3 bellard
    j = env->fpstt;
445 9df217a3 bellard
    for(i = 0;i < 8; i++) {
446 9df217a3 bellard
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 16], 10);
447 9df217a3 bellard
        j = (j + 1) & 7;
448 9df217a3 bellard
    }
449 9df217a3 bellard
    if (env->cpuid_features & CPUID_SSE) {
450 9df217a3 bellard
        env->mxcsr = fp->mxcsr;
451 c28e951f bellard
        memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
452 9df217a3 bellard
    }
453 9df217a3 bellard
454 9df217a3 bellard
    /* we must restore the default rounding state */
455 9df217a3 bellard
    asm volatile ("fninit");
456 9df217a3 bellard
    fpuc = 0x037f | (env->fpuc & (3 << 10));
457 9df217a3 bellard
    asm volatile("fldcw %0" : : "m" (fpuc));
458 9df217a3 bellard
}
459 9df217a3 bellard
460 c28e951f bellard
static int do_syscall(CPUState *env,
461 c28e951f bellard
                      struct kqemu_cpu_state *kenv)
462 c28e951f bellard
{
463 c28e951f bellard
    int selector;
464 c28e951f bellard
    
465 c28e951f bellard
    selector = (env->star >> 32) & 0xffff;
466 c28e951f bellard
#ifdef __x86_64__
467 c28e951f bellard
    if (env->hflags & HF_LMA_MASK) {
468 c28e951f bellard
        env->regs[R_ECX] = kenv->next_eip;
469 c28e951f bellard
        env->regs[11] = env->eflags;
470 c28e951f bellard
471 c28e951f bellard
        cpu_x86_set_cpl(env, 0);
472 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
473 c28e951f bellard
                               0, 0xffffffff, 
474 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
475 c28e951f bellard
                               DESC_S_MASK |
476 c28e951f bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
477 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
478 c28e951f bellard
                               0, 0xffffffff,
479 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
480 c28e951f bellard
                               DESC_S_MASK |
481 c28e951f bellard
                               DESC_W_MASK | DESC_A_MASK);
482 c28e951f bellard
        env->eflags &= ~env->fmask;
483 c28e951f bellard
        if (env->hflags & HF_CS64_MASK)
484 c28e951f bellard
            env->eip = env->lstar;
485 c28e951f bellard
        else
486 c28e951f bellard
            env->eip = env->cstar;
487 c28e951f bellard
    } else 
488 c28e951f bellard
#endif
489 c28e951f bellard
    {
490 c28e951f bellard
        env->regs[R_ECX] = (uint32_t)kenv->next_eip;
491 c28e951f bellard
        
492 c28e951f bellard
        cpu_x86_set_cpl(env, 0);
493 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
494 c28e951f bellard
                           0, 0xffffffff, 
495 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
496 c28e951f bellard
                               DESC_S_MASK |
497 c28e951f bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
498 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
499 c28e951f bellard
                               0, 0xffffffff,
500 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
501 c28e951f bellard
                               DESC_S_MASK |
502 c28e951f bellard
                               DESC_W_MASK | DESC_A_MASK);
503 c28e951f bellard
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
504 c28e951f bellard
        env->eip = (uint32_t)env->star;
505 c28e951f bellard
    }
506 c28e951f bellard
    return 2;
507 c28e951f bellard
}
508 c28e951f bellard
509 f32fc648 bellard
#ifdef CONFIG_PROFILER
510 aa062973 bellard
511 aa062973 bellard
#define PC_REC_SIZE 1
512 aa062973 bellard
#define PC_REC_HASH_BITS 16
513 aa062973 bellard
#define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
514 aa062973 bellard
515 aa062973 bellard
typedef struct PCRecord {
516 aa062973 bellard
    unsigned long pc;
517 aa062973 bellard
    int64_t count;
518 aa062973 bellard
    struct PCRecord *next;
519 aa062973 bellard
} PCRecord;
520 aa062973 bellard
521 f32fc648 bellard
static PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
522 f32fc648 bellard
static int nb_pc_records;
523 aa062973 bellard
524 f32fc648 bellard
static void kqemu_record_pc(unsigned long pc)
525 aa062973 bellard
{
526 aa062973 bellard
    unsigned long h;
527 aa062973 bellard
    PCRecord **pr, *r;
528 aa062973 bellard
529 aa062973 bellard
    h = pc / PC_REC_SIZE;
530 aa062973 bellard
    h = h ^ (h >> PC_REC_HASH_BITS);
531 aa062973 bellard
    h &= (PC_REC_HASH_SIZE - 1);
532 aa062973 bellard
    pr = &pc_rec_hash[h];
533 aa062973 bellard
    for(;;) {
534 aa062973 bellard
        r = *pr;
535 aa062973 bellard
        if (r == NULL)
536 aa062973 bellard
            break;
537 aa062973 bellard
        if (r->pc == pc) {
538 aa062973 bellard
            r->count++;
539 aa062973 bellard
            return;
540 aa062973 bellard
        }
541 aa062973 bellard
        pr = &r->next;
542 aa062973 bellard
    }
543 aa062973 bellard
    r = malloc(sizeof(PCRecord));
544 aa062973 bellard
    r->count = 1;
545 aa062973 bellard
    r->pc = pc;
546 aa062973 bellard
    r->next = NULL;
547 aa062973 bellard
    *pr = r;
548 aa062973 bellard
    nb_pc_records++;
549 aa062973 bellard
}
550 aa062973 bellard
551 f32fc648 bellard
static int pc_rec_cmp(const void *p1, const void *p2)
552 aa062973 bellard
{
553 aa062973 bellard
    PCRecord *r1 = *(PCRecord **)p1;
554 aa062973 bellard
    PCRecord *r2 = *(PCRecord **)p2;
555 aa062973 bellard
    if (r1->count < r2->count)
556 aa062973 bellard
        return 1;
557 aa062973 bellard
    else if (r1->count == r2->count)
558 aa062973 bellard
        return 0;
559 aa062973 bellard
    else
560 aa062973 bellard
        return -1;
561 aa062973 bellard
}
562 aa062973 bellard
563 f32fc648 bellard
static void kqemu_record_flush(void)
564 f32fc648 bellard
{
565 f32fc648 bellard
    PCRecord *r, *r_next;
566 f32fc648 bellard
    int h;
567 f32fc648 bellard
568 f32fc648 bellard
    for(h = 0; h < PC_REC_HASH_SIZE; h++) {
569 f32fc648 bellard
        for(r = pc_rec_hash[h]; r != NULL; r = r_next) {
570 f32fc648 bellard
            r_next = r->next;
571 f32fc648 bellard
            free(r);
572 f32fc648 bellard
        }
573 f32fc648 bellard
        pc_rec_hash[h] = NULL;
574 f32fc648 bellard
    }
575 f32fc648 bellard
    nb_pc_records = 0;
576 f32fc648 bellard
}
577 f32fc648 bellard
578 aa062973 bellard
void kqemu_record_dump(void)
579 aa062973 bellard
{
580 aa062973 bellard
    PCRecord **pr, *r;
581 aa062973 bellard
    int i, h;
582 aa062973 bellard
    FILE *f;
583 aa062973 bellard
    int64_t total, sum;
584 aa062973 bellard
585 aa062973 bellard
    pr = malloc(sizeof(PCRecord *) * nb_pc_records);
586 aa062973 bellard
    i = 0;
587 aa062973 bellard
    total = 0;
588 aa062973 bellard
    for(h = 0; h < PC_REC_HASH_SIZE; h++) {
589 aa062973 bellard
        for(r = pc_rec_hash[h]; r != NULL; r = r->next) {
590 aa062973 bellard
            pr[i++] = r;
591 aa062973 bellard
            total += r->count;
592 aa062973 bellard
        }
593 aa062973 bellard
    }
594 aa062973 bellard
    qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
595 aa062973 bellard
    
596 aa062973 bellard
    f = fopen("/tmp/kqemu.stats", "w");
597 aa062973 bellard
    if (!f) {
598 aa062973 bellard
        perror("/tmp/kqemu.stats");
599 aa062973 bellard
        exit(1);
600 aa062973 bellard
    }
601 26a76461 bellard
    fprintf(f, "total: %" PRId64 "\n", total);
602 aa062973 bellard
    sum = 0;
603 aa062973 bellard
    for(i = 0; i < nb_pc_records; i++) {
604 aa062973 bellard
        r = pr[i];
605 aa062973 bellard
        sum += r->count;
606 26a76461 bellard
        fprintf(f, "%08lx: %" PRId64 " %0.2f%% %0.2f%%\n", 
607 aa062973 bellard
                r->pc, 
608 aa062973 bellard
                r->count, 
609 aa062973 bellard
                (double)r->count / (double)total * 100.0,
610 aa062973 bellard
                (double)sum / (double)total * 100.0);
611 aa062973 bellard
    }
612 aa062973 bellard
    fclose(f);
613 aa062973 bellard
    free(pr);
614 f32fc648 bellard
615 f32fc648 bellard
    kqemu_record_flush();
616 aa062973 bellard
}
617 aa062973 bellard
#endif
618 aa062973 bellard
619 9df217a3 bellard
int kqemu_cpu_exec(CPUState *env)
620 9df217a3 bellard
{
621 9df217a3 bellard
    struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
622 f32fc648 bellard
    int ret, cpl, i;
623 f32fc648 bellard
#ifdef CONFIG_PROFILER
624 f32fc648 bellard
    int64_t ti;
625 f32fc648 bellard
#endif
626 f32fc648 bellard
627 6e4255f6 bellard
#ifdef _WIN32
628 6e4255f6 bellard
    DWORD temp;
629 6e4255f6 bellard
#endif
630 9df217a3 bellard
631 f32fc648 bellard
#ifdef CONFIG_PROFILER
632 f32fc648 bellard
    ti = profile_getclock();
633 f32fc648 bellard
#endif
634 9df217a3 bellard
#ifdef DEBUG
635 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
636 9df217a3 bellard
        fprintf(logfile, "kqemu: cpu_exec: enter\n");
637 9df217a3 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
638 9df217a3 bellard
    }
639 9df217a3 bellard
#endif
640 9df217a3 bellard
    memcpy(kenv->regs, env->regs, sizeof(kenv->regs));
641 9df217a3 bellard
    kenv->eip = env->eip;
642 9df217a3 bellard
    kenv->eflags = env->eflags;
643 9df217a3 bellard
    memcpy(&kenv->segs, &env->segs, sizeof(env->segs));
644 9df217a3 bellard
    memcpy(&kenv->ldt, &env->ldt, sizeof(env->ldt));
645 9df217a3 bellard
    memcpy(&kenv->tr, &env->tr, sizeof(env->tr));
646 9df217a3 bellard
    memcpy(&kenv->gdt, &env->gdt, sizeof(env->gdt));
647 9df217a3 bellard
    memcpy(&kenv->idt, &env->idt, sizeof(env->idt));
648 9df217a3 bellard
    kenv->cr0 = env->cr[0];
649 9df217a3 bellard
    kenv->cr2 = env->cr[2];
650 9df217a3 bellard
    kenv->cr3 = env->cr[3];
651 9df217a3 bellard
    kenv->cr4 = env->cr[4];
652 9df217a3 bellard
    kenv->a20_mask = env->a20_mask;
653 c45b3c0e bellard
#if KQEMU_VERSION >= 0x010100
654 c28e951f bellard
    kenv->efer = env->efer;
655 c28e951f bellard
#endif
656 f32fc648 bellard
#if KQEMU_VERSION >= 0x010300
657 f32fc648 bellard
    kenv->tsc_offset = 0;
658 f32fc648 bellard
    kenv->star = env->star;
659 f32fc648 bellard
    kenv->sysenter_cs = env->sysenter_cs;
660 f32fc648 bellard
    kenv->sysenter_esp = env->sysenter_esp;
661 f32fc648 bellard
    kenv->sysenter_eip = env->sysenter_eip;
662 f32fc648 bellard
#ifdef __x86_64__
663 f32fc648 bellard
    kenv->lstar = env->lstar;
664 f32fc648 bellard
    kenv->cstar = env->cstar;
665 f32fc648 bellard
    kenv->fmask = env->fmask;
666 f32fc648 bellard
    kenv->kernelgsbase = env->kernelgsbase;
667 f32fc648 bellard
#endif
668 f32fc648 bellard
#endif
669 9df217a3 bellard
    if (env->dr[7] & 0xff) {
670 9df217a3 bellard
        kenv->dr7 = env->dr[7];
671 9df217a3 bellard
        kenv->dr0 = env->dr[0];
672 9df217a3 bellard
        kenv->dr1 = env->dr[1];
673 9df217a3 bellard
        kenv->dr2 = env->dr[2];
674 9df217a3 bellard
        kenv->dr3 = env->dr[3];
675 9df217a3 bellard
    } else {
676 9df217a3 bellard
        kenv->dr7 = 0;
677 9df217a3 bellard
    }
678 9df217a3 bellard
    kenv->dr6 = env->dr[6];
679 f32fc648 bellard
    cpl = (env->hflags & HF_CPL_MASK);
680 f32fc648 bellard
    kenv->cpl = cpl;
681 9df217a3 bellard
    kenv->nb_pages_to_flush = nb_pages_to_flush;
682 aa062973 bellard
#if KQEMU_VERSION >= 0x010200
683 f32fc648 bellard
    kenv->user_only = (env->kqemu_enabled == 1);
684 aa062973 bellard
    kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
685 aa062973 bellard
#endif
686 aa062973 bellard
    nb_ram_pages_to_update = 0;
687 9df217a3 bellard
    
688 f32fc648 bellard
#if KQEMU_VERSION >= 0x010300
689 f32fc648 bellard
    kenv->nb_modified_ram_pages = nb_modified_ram_pages;
690 f32fc648 bellard
#endif
691 f32fc648 bellard
    kqemu_reset_modified_ram_pages();
692 f32fc648 bellard
693 f32fc648 bellard
    if (env->cpuid_features & CPUID_FXSR)
694 f32fc648 bellard
        restore_native_fp_fxrstor(env);
695 f32fc648 bellard
    else
696 f32fc648 bellard
        restore_native_fp_frstor(env);
697 9df217a3 bellard
698 6e4255f6 bellard
#ifdef _WIN32
699 a332e112 bellard
    if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,
700 a332e112 bellard
                        kenv, sizeof(struct kqemu_cpu_state),
701 a332e112 bellard
                        kenv, sizeof(struct kqemu_cpu_state),
702 a332e112 bellard
                        &temp, NULL)) {
703 a332e112 bellard
        ret = kenv->retval;
704 a332e112 bellard
    } else {
705 a332e112 bellard
        ret = -1;
706 a332e112 bellard
    }
707 6e4255f6 bellard
#else
708 6e4255f6 bellard
#if KQEMU_VERSION >= 0x010100
709 6e4255f6 bellard
    ioctl(kqemu_fd, KQEMU_EXEC, kenv);
710 6e4255f6 bellard
    ret = kenv->retval;
711 6e4255f6 bellard
#else
712 9df217a3 bellard
    ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
713 6e4255f6 bellard
#endif
714 6e4255f6 bellard
#endif
715 f32fc648 bellard
    if (env->cpuid_features & CPUID_FXSR)
716 f32fc648 bellard
        save_native_fp_fxsave(env);
717 f32fc648 bellard
    else
718 f32fc648 bellard
        save_native_fp_fsave(env);
719 9df217a3 bellard
720 9df217a3 bellard
    memcpy(env->regs, kenv->regs, sizeof(env->regs));
721 9df217a3 bellard
    env->eip = kenv->eip;
722 9df217a3 bellard
    env->eflags = kenv->eflags;
723 9df217a3 bellard
    memcpy(env->segs, kenv->segs, sizeof(env->segs));
724 f32fc648 bellard
    cpu_x86_set_cpl(env, kenv->cpl);
725 f32fc648 bellard
    memcpy(&env->ldt, &kenv->ldt, sizeof(env->ldt));
726 9df217a3 bellard
#if 0
727 9df217a3 bellard
    /* no need to restore that */
728 9df217a3 bellard
    memcpy(env->tr, kenv->tr, sizeof(env->tr));
729 9df217a3 bellard
    memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
730 9df217a3 bellard
    memcpy(env->idt, kenv->idt, sizeof(env->idt));
731 9df217a3 bellard
    env->a20_mask = kenv->a20_mask;
732 9df217a3 bellard
#endif
733 f32fc648 bellard
    env->cr[0] = kenv->cr0;
734 f32fc648 bellard
    env->cr[4] = kenv->cr4;
735 f32fc648 bellard
    env->cr[3] = kenv->cr3;
736 9df217a3 bellard
    env->cr[2] = kenv->cr2;
737 9df217a3 bellard
    env->dr[6] = kenv->dr6;
738 f32fc648 bellard
#if KQEMU_VERSION >= 0x010300
739 f32fc648 bellard
#ifdef __x86_64__
740 f32fc648 bellard
    env->kernelgsbase = kenv->kernelgsbase;
741 f32fc648 bellard
#endif
742 f32fc648 bellard
#endif
743 f32fc648 bellard
744 f32fc648 bellard
    /* flush pages as indicated by kqemu */
745 f32fc648 bellard
    if (kenv->nb_pages_to_flush >= KQEMU_FLUSH_ALL) {
746 f32fc648 bellard
        tlb_flush(env, 1);
747 f32fc648 bellard
    } else {
748 f32fc648 bellard
        for(i = 0; i < kenv->nb_pages_to_flush; i++) {
749 f32fc648 bellard
            tlb_flush_page(env, pages_to_flush[i]);
750 f32fc648 bellard
        }
751 f32fc648 bellard
    }
752 f32fc648 bellard
    nb_pages_to_flush = 0;
753 f32fc648 bellard
754 f32fc648 bellard
#ifdef CONFIG_PROFILER
755 f32fc648 bellard
    kqemu_time += profile_getclock() - ti;
756 f32fc648 bellard
    kqemu_exec_count++;
757 f32fc648 bellard
#endif
758 9df217a3 bellard
759 aa062973 bellard
#if KQEMU_VERSION >= 0x010200
760 aa062973 bellard
    if (kenv->nb_ram_pages_to_update > 0) {
761 aa062973 bellard
        cpu_tlb_update_dirty(env);
762 aa062973 bellard
    }
763 aa062973 bellard
#endif
764 aa062973 bellard
765 f32fc648 bellard
#if KQEMU_VERSION >= 0x010300
766 f32fc648 bellard
    if (kenv->nb_modified_ram_pages > 0) {
767 f32fc648 bellard
        for(i = 0; i < kenv->nb_modified_ram_pages; i++) {
768 f32fc648 bellard
            unsigned long addr;
769 f32fc648 bellard
            addr = modified_ram_pages[i];
770 f32fc648 bellard
            tb_invalidate_phys_page_range(addr, addr + TARGET_PAGE_SIZE, 0);
771 f32fc648 bellard
        }
772 f32fc648 bellard
    }
773 f32fc648 bellard
#endif
774 f32fc648 bellard
775 aa062973 bellard
    /* restore the hidden flags */
776 aa062973 bellard
    {
777 aa062973 bellard
        unsigned int new_hflags;
778 aa062973 bellard
#ifdef TARGET_X86_64
779 aa062973 bellard
        if ((env->hflags & HF_LMA_MASK) && 
780 aa062973 bellard
            (env->segs[R_CS].flags & DESC_L_MASK)) {
781 aa062973 bellard
            /* long mode */
782 aa062973 bellard
            new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
783 aa062973 bellard
        } else
784 aa062973 bellard
#endif
785 aa062973 bellard
        {
786 aa062973 bellard
            /* legacy / compatibility case */
787 aa062973 bellard
            new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
788 aa062973 bellard
                >> (DESC_B_SHIFT - HF_CS32_SHIFT);
789 aa062973 bellard
            new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
790 aa062973 bellard
                >> (DESC_B_SHIFT - HF_SS32_SHIFT);
791 aa062973 bellard
            if (!(env->cr[0] & CR0_PE_MASK) || 
792 aa062973 bellard
                   (env->eflags & VM_MASK) ||
793 aa062973 bellard
                   !(env->hflags & HF_CS32_MASK)) {
794 aa062973 bellard
                /* XXX: try to avoid this test. The problem comes from the
795 aa062973 bellard
                   fact that is real mode or vm86 mode we only modify the
796 aa062973 bellard
                   'base' and 'selector' fields of the segment cache to go
797 aa062973 bellard
                   faster. A solution may be to force addseg to one in
798 aa062973 bellard
                   translate-i386.c. */
799 aa062973 bellard
                new_hflags |= HF_ADDSEG_MASK;
800 aa062973 bellard
            } else {
801 aa062973 bellard
                new_hflags |= ((env->segs[R_DS].base | 
802 aa062973 bellard
                                env->segs[R_ES].base |
803 aa062973 bellard
                                env->segs[R_SS].base) != 0) << 
804 aa062973 bellard
                    HF_ADDSEG_SHIFT;
805 aa062973 bellard
            }
806 aa062973 bellard
        }
807 aa062973 bellard
        env->hflags = (env->hflags & 
808 aa062973 bellard
           ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
809 aa062973 bellard
            new_hflags;
810 aa062973 bellard
    }
811 f32fc648 bellard
    /* update FPU flags */
812 f32fc648 bellard
    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
813 f32fc648 bellard
        ((env->cr[0] << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
814 f32fc648 bellard
    if (env->cr[4] & CR4_OSFXSR_MASK)
815 f32fc648 bellard
        env->hflags |= HF_OSFXSR_MASK;
816 f32fc648 bellard
    else
817 f32fc648 bellard
        env->hflags &= ~HF_OSFXSR_MASK;
818 f32fc648 bellard
        
819 9df217a3 bellard
#ifdef DEBUG
820 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
821 9df217a3 bellard
        fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
822 9df217a3 bellard
    }
823 9df217a3 bellard
#endif
824 c28e951f bellard
    if (ret == KQEMU_RET_SYSCALL) {
825 c28e951f bellard
        /* syscall instruction */
826 c28e951f bellard
        return do_syscall(env, kenv);
827 c28e951f bellard
    } else 
828 9df217a3 bellard
    if ((ret & 0xff00) == KQEMU_RET_INT) {
829 9df217a3 bellard
        env->exception_index = ret & 0xff;
830 9df217a3 bellard
        env->error_code = 0;
831 9df217a3 bellard
        env->exception_is_int = 1;
832 9df217a3 bellard
        env->exception_next_eip = kenv->next_eip;
833 f32fc648 bellard
#ifdef CONFIG_PROFILER
834 f32fc648 bellard
        kqemu_ret_int_count++;
835 f32fc648 bellard
#endif
836 9df217a3 bellard
#ifdef DEBUG
837 c28e951f bellard
        if (loglevel & CPU_LOG_INT) {
838 c28e951f bellard
            fprintf(logfile, "kqemu: interrupt v=%02x:\n", 
839 c28e951f bellard
                    env->exception_index);
840 c28e951f bellard
            cpu_dump_state(env, logfile, fprintf, 0);
841 c28e951f bellard
        }
842 9df217a3 bellard
#endif
843 9df217a3 bellard
        return 1;
844 9df217a3 bellard
    } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {
845 9df217a3 bellard
        env->exception_index = ret & 0xff;
846 9df217a3 bellard
        env->error_code = kenv->error_code;
847 9df217a3 bellard
        env->exception_is_int = 0;
848 9df217a3 bellard
        env->exception_next_eip = 0;
849 f32fc648 bellard
#ifdef CONFIG_PROFILER
850 f32fc648 bellard
        kqemu_ret_excp_count++;
851 f32fc648 bellard
#endif
852 9df217a3 bellard
#ifdef DEBUG
853 9df217a3 bellard
        if (loglevel & CPU_LOG_INT) {
854 9df217a3 bellard
            fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
855 9df217a3 bellard
                    env->exception_index, env->error_code);
856 9df217a3 bellard
            cpu_dump_state(env, logfile, fprintf, 0);
857 9df217a3 bellard
        }
858 9df217a3 bellard
#endif
859 9df217a3 bellard
        return 1;
860 9df217a3 bellard
    } else if (ret == KQEMU_RET_INTR) {
861 f32fc648 bellard
#ifdef CONFIG_PROFILER
862 f32fc648 bellard
        kqemu_ret_intr_count++;
863 f32fc648 bellard
#endif
864 c45b3c0e bellard
#ifdef DEBUG
865 c45b3c0e bellard
        if (loglevel & CPU_LOG_INT) {
866 c45b3c0e bellard
            cpu_dump_state(env, logfile, fprintf, 0);
867 c45b3c0e bellard
        }
868 c45b3c0e bellard
#endif
869 9df217a3 bellard
        return 0;
870 9df217a3 bellard
    } else if (ret == KQEMU_RET_SOFTMMU) { 
871 f32fc648 bellard
#ifdef CONFIG_PROFILER
872 f32fc648 bellard
        {
873 f32fc648 bellard
            unsigned long pc = env->eip + env->segs[R_CS].base;
874 f32fc648 bellard
            kqemu_record_pc(pc);
875 f32fc648 bellard
        }
876 aa062973 bellard
#endif
877 aa062973 bellard
#ifdef DEBUG
878 aa062973 bellard
        if (loglevel & CPU_LOG_INT) {
879 aa062973 bellard
            cpu_dump_state(env, logfile, fprintf, 0);
880 aa062973 bellard
        }
881 aa062973 bellard
#endif
882 9df217a3 bellard
        return 2;
883 9df217a3 bellard
    } else {
884 9df217a3 bellard
        cpu_dump_state(env, stderr, fprintf, 0);
885 9df217a3 bellard
        fprintf(stderr, "Unsupported return value: 0x%x\n", ret);
886 9df217a3 bellard
        exit(1);
887 9df217a3 bellard
    }
888 9df217a3 bellard
    return 0;
889 9df217a3 bellard
}
890 9df217a3 bellard
891 a332e112 bellard
void kqemu_cpu_interrupt(CPUState *env)
892 a332e112 bellard
{
893 a332e112 bellard
#if defined(_WIN32) && KQEMU_VERSION >= 0x010101
894 a332e112 bellard
    /* cancelling the I/O request causes KQEMU to finish executing the 
895 a332e112 bellard
       current block and successfully returning. */
896 a332e112 bellard
    CancelIo(kqemu_fd);
897 a332e112 bellard
#endif
898 a332e112 bellard
}
899 a332e112 bellard
900 9df217a3 bellard
#endif