Statistics
| Branch: | Revision:

root / kqemu.c @ ea785922

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