Statistics
| Branch: | Revision:

root / kqemu.c @ 5fafdf24

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