Statistics
| Branch: | Revision:

root / kqemu.c @ 5439779e

History | View | Annotate | Download (25.2 kB)

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