Statistics
| Branch: | Revision:

root / kqemu.c @ 19f329ad

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