Statistics
| Branch: | Revision:

root / kqemu.c @ ca0d1734

History | View | Annotate | Download (20.4 kB)

1 9df217a3 bellard
/*
2 9df217a3 bellard
 *  KQEMU support
3 9df217a3 bellard
 * 
4 9df217a3 bellard
 *  Copyright (c) 2005 Fabrice Bellard
5 9df217a3 bellard
 *
6 9df217a3 bellard
 * This library is free software; you can redistribute it and/or
7 9df217a3 bellard
 * modify it under the terms of the GNU Lesser General Public
8 9df217a3 bellard
 * License as published by the Free Software Foundation; either
9 9df217a3 bellard
 * version 2 of the License, or (at your option) any later version.
10 9df217a3 bellard
 *
11 9df217a3 bellard
 * This library is distributed in the hope that it will be useful,
12 9df217a3 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 9df217a3 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 9df217a3 bellard
 * Lesser General Public License for more details.
15 9df217a3 bellard
 *
16 9df217a3 bellard
 * You should have received a copy of the GNU Lesser General Public
17 9df217a3 bellard
 * License along with this library; if not, write to the Free Software
18 9df217a3 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 9df217a3 bellard
 */
20 9df217a3 bellard
#include "config.h"
21 9df217a3 bellard
#ifdef _WIN32
22 9df217a3 bellard
#include <windows.h>
23 6e4255f6 bellard
#include <winioctl.h>
24 9df217a3 bellard
#else
25 9df217a3 bellard
#include <sys/types.h>
26 9df217a3 bellard
#include <sys/mman.h>
27 6e4255f6 bellard
#include <sys/ioctl.h>
28 9df217a3 bellard
#endif
29 9df217a3 bellard
#include <stdlib.h>
30 9df217a3 bellard
#include <stdio.h>
31 9df217a3 bellard
#include <stdarg.h>
32 9df217a3 bellard
#include <string.h>
33 9df217a3 bellard
#include <errno.h>
34 9df217a3 bellard
#include <unistd.h>
35 9df217a3 bellard
#include <inttypes.h>
36 9df217a3 bellard
37 9df217a3 bellard
#include "cpu.h"
38 9df217a3 bellard
#include "exec-all.h"
39 9df217a3 bellard
40 9df217a3 bellard
#ifdef USE_KQEMU
41 9df217a3 bellard
42 9df217a3 bellard
#define DEBUG
43 aa062973 bellard
//#define PROFILE
44 9df217a3 bellard
45 9df217a3 bellard
#include <unistd.h>
46 9df217a3 bellard
#include <fcntl.h>
47 9df217a3 bellard
#include "kqemu/kqemu.h"
48 9df217a3 bellard
49 c28e951f bellard
/* compatibility stuff */
50 c28e951f bellard
#ifndef KQEMU_RET_SYSCALL
51 c28e951f bellard
#define KQEMU_RET_SYSCALL   0x0300 /* syscall insn */
52 c28e951f bellard
#endif
53 aa062973 bellard
#ifndef KQEMU_MAX_RAM_PAGES_TO_UPDATE
54 aa062973 bellard
#define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512
55 aa062973 bellard
#define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)
56 aa062973 bellard
#endif
57 c28e951f bellard
58 6e4255f6 bellard
#ifdef _WIN32
59 6e4255f6 bellard
#define KQEMU_DEVICE "\\\\.\\kqemu"
60 6e4255f6 bellard
#else
61 9df217a3 bellard
#define KQEMU_DEVICE "/dev/kqemu"
62 6e4255f6 bellard
#endif
63 6e4255f6 bellard
64 6e4255f6 bellard
#ifdef _WIN32
65 6e4255f6 bellard
#define KQEMU_INVALID_FD INVALID_HANDLE_VALUE
66 6e4255f6 bellard
HANDLE kqemu_fd = KQEMU_INVALID_FD;
67 6e4255f6 bellard
#define kqemu_closefd(x) CloseHandle(x)
68 6e4255f6 bellard
#else
69 6e4255f6 bellard
#define KQEMU_INVALID_FD -1
70 6e4255f6 bellard
int kqemu_fd = KQEMU_INVALID_FD;
71 6e4255f6 bellard
#define kqemu_closefd(x) close(x)
72 6e4255f6 bellard
#endif
73 9df217a3 bellard
74 9df217a3 bellard
int kqemu_allowed = 1;
75 9df217a3 bellard
unsigned long *pages_to_flush;
76 9df217a3 bellard
unsigned int nb_pages_to_flush;
77 aa062973 bellard
unsigned long *ram_pages_to_update;
78 aa062973 bellard
unsigned int nb_ram_pages_to_update;
79 9df217a3 bellard
extern uint32_t **l1_phys_map;
80 9df217a3 bellard
81 9df217a3 bellard
#define cpuid(index, eax, ebx, ecx, edx) \
82 9df217a3 bellard
  asm volatile ("cpuid" \
83 9df217a3 bellard
                : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
84 9df217a3 bellard
                : "0" (index))
85 9df217a3 bellard
86 c28e951f bellard
#ifdef __x86_64__
87 c28e951f bellard
static int is_cpuid_supported(void)
88 c28e951f bellard
{
89 c28e951f bellard
    return 1;
90 c28e951f bellard
}
91 c28e951f bellard
#else
92 9df217a3 bellard
static int is_cpuid_supported(void)
93 9df217a3 bellard
{
94 9df217a3 bellard
    int v0, v1;
95 9df217a3 bellard
    asm volatile ("pushf\n"
96 9df217a3 bellard
                  "popl %0\n"
97 9df217a3 bellard
                  "movl %0, %1\n"
98 9df217a3 bellard
                  "xorl $0x00200000, %0\n"
99 9df217a3 bellard
                  "pushl %0\n"
100 9df217a3 bellard
                  "popf\n"
101 9df217a3 bellard
                  "pushf\n"
102 9df217a3 bellard
                  "popl %0\n"
103 9df217a3 bellard
                  : "=a" (v0), "=d" (v1)
104 9df217a3 bellard
                  :
105 9df217a3 bellard
                  : "cc");
106 9df217a3 bellard
    return (v0 != v1);
107 9df217a3 bellard
}
108 c28e951f bellard
#endif
109 9df217a3 bellard
110 9df217a3 bellard
static void kqemu_update_cpuid(CPUState *env)
111 9df217a3 bellard
{
112 9df217a3 bellard
    int critical_features_mask, features;
113 9df217a3 bellard
    uint32_t eax, ebx, ecx, edx;
114 9df217a3 bellard
115 9df217a3 bellard
    /* the following features are kept identical on the host and
116 9df217a3 bellard
       target cpus because they are important for user code. Strictly
117 9df217a3 bellard
       speaking, only SSE really matters because the OS must support
118 9df217a3 bellard
       it if the user code uses it. */
119 9df217a3 bellard
    critical_features_mask = 
120 9df217a3 bellard
        CPUID_CMOV | CPUID_CX8 | 
121 9df217a3 bellard
        CPUID_FXSR | CPUID_MMX | CPUID_SSE | 
122 ca0d1734 bellard
        CPUID_SSE2 | CPUID_SEP;
123 9df217a3 bellard
    if (!is_cpuid_supported()) {
124 9df217a3 bellard
        features = 0;
125 9df217a3 bellard
    } else {
126 9df217a3 bellard
        cpuid(1, eax, ebx, ecx, edx);
127 9df217a3 bellard
        features = edx;
128 9df217a3 bellard
    }
129 ca0d1734 bellard
#ifdef __x86_64__
130 ca0d1734 bellard
    /* NOTE: on x86_64 CPUs, SYSENTER is not supported in
131 ca0d1734 bellard
       compatibility mode, so in order to have the best performances
132 ca0d1734 bellard
       it is better not to use it */
133 ca0d1734 bellard
    features &= ~CPUID_SEP;
134 ca0d1734 bellard
#endif
135 9df217a3 bellard
    env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
136 9df217a3 bellard
        (features & critical_features_mask);
137 9df217a3 bellard
    /* XXX: we could update more of the target CPUID state so that the
138 9df217a3 bellard
       non accelerated code sees exactly the same CPU features as the
139 9df217a3 bellard
       accelerated code */
140 9df217a3 bellard
}
141 9df217a3 bellard
142 9df217a3 bellard
int kqemu_init(CPUState *env)
143 9df217a3 bellard
{
144 9df217a3 bellard
    struct kqemu_init init;
145 9df217a3 bellard
    int ret, version;
146 6e4255f6 bellard
#ifdef _WIN32
147 6e4255f6 bellard
    DWORD temp;
148 6e4255f6 bellard
#endif
149 9df217a3 bellard
150 9df217a3 bellard
    if (!kqemu_allowed)
151 9df217a3 bellard
        return -1;
152 9df217a3 bellard
153 6e4255f6 bellard
#ifdef _WIN32
154 6e4255f6 bellard
    kqemu_fd = CreateFile(KQEMU_DEVICE, GENERIC_WRITE | GENERIC_READ,
155 6e4255f6 bellard
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
156 6e4255f6 bellard
                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
157 6e4255f6 bellard
                          NULL);
158 6e4255f6 bellard
#else
159 9df217a3 bellard
    kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
160 6e4255f6 bellard
#endif
161 6e4255f6 bellard
    if (kqemu_fd == KQEMU_INVALID_FD) {
162 9df217a3 bellard
        fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated\n", KQEMU_DEVICE);
163 9df217a3 bellard
        return -1;
164 9df217a3 bellard
    }
165 9df217a3 bellard
    version = 0;
166 6e4255f6 bellard
#ifdef _WIN32
167 6e4255f6 bellard
    DeviceIoControl(kqemu_fd, KQEMU_GET_VERSION, NULL, 0,
168 6e4255f6 bellard
                    &version, sizeof(version), &temp, NULL);
169 6e4255f6 bellard
#else
170 9df217a3 bellard
    ioctl(kqemu_fd, KQEMU_GET_VERSION, &version);
171 6e4255f6 bellard
#endif
172 9df217a3 bellard
    if (version != KQEMU_VERSION) {
173 9df217a3 bellard
        fprintf(stderr, "Version mismatch between kqemu module and qemu (%08x %08x) - disabling kqemu use\n",
174 9df217a3 bellard
                version, KQEMU_VERSION);
175 9df217a3 bellard
        goto fail;
176 9df217a3 bellard
    }
177 9df217a3 bellard
178 9df217a3 bellard
    pages_to_flush = qemu_vmalloc(KQEMU_MAX_PAGES_TO_FLUSH * 
179 9df217a3 bellard
                                  sizeof(unsigned long));
180 9df217a3 bellard
    if (!pages_to_flush)
181 9df217a3 bellard
        goto fail;
182 9df217a3 bellard
183 aa062973 bellard
    ram_pages_to_update = qemu_vmalloc(KQEMU_MAX_RAM_PAGES_TO_UPDATE * 
184 aa062973 bellard
                                       sizeof(unsigned long));
185 aa062973 bellard
    if (!ram_pages_to_update)
186 aa062973 bellard
        goto fail;
187 aa062973 bellard
188 9df217a3 bellard
    init.ram_base = phys_ram_base;
189 9df217a3 bellard
    init.ram_size = phys_ram_size;
190 9df217a3 bellard
    init.ram_dirty = phys_ram_dirty;
191 9df217a3 bellard
    init.phys_to_ram_map = l1_phys_map;
192 9df217a3 bellard
    init.pages_to_flush = pages_to_flush;
193 aa062973 bellard
#if KQEMU_VERSION >= 0x010200
194 aa062973 bellard
    init.ram_pages_to_update = ram_pages_to_update;
195 aa062973 bellard
#endif
196 6e4255f6 bellard
#ifdef _WIN32
197 6e4255f6 bellard
    ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
198 6e4255f6 bellard
                          NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
199 6e4255f6 bellard
#else
200 9df217a3 bellard
    ret = ioctl(kqemu_fd, KQEMU_INIT, &init);
201 6e4255f6 bellard
#endif
202 9df217a3 bellard
    if (ret < 0) {
203 9df217a3 bellard
        fprintf(stderr, "Error %d while initializing QEMU acceleration layer - disabling it for now\n", ret);
204 9df217a3 bellard
    fail:
205 6e4255f6 bellard
        kqemu_closefd(kqemu_fd);
206 6e4255f6 bellard
        kqemu_fd = KQEMU_INVALID_FD;
207 9df217a3 bellard
        return -1;
208 9df217a3 bellard
    }
209 9df217a3 bellard
    kqemu_update_cpuid(env);
210 9df217a3 bellard
    env->kqemu_enabled = 1;
211 9df217a3 bellard
    nb_pages_to_flush = 0;
212 aa062973 bellard
    nb_ram_pages_to_update = 0;
213 9df217a3 bellard
    return 0;
214 9df217a3 bellard
}
215 9df217a3 bellard
216 9df217a3 bellard
void kqemu_flush_page(CPUState *env, target_ulong addr)
217 9df217a3 bellard
{
218 9df217a3 bellard
#ifdef DEBUG
219 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
220 9df217a3 bellard
        fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
221 9df217a3 bellard
    }
222 9df217a3 bellard
#endif
223 9df217a3 bellard
    if (nb_pages_to_flush >= KQEMU_MAX_PAGES_TO_FLUSH)
224 9df217a3 bellard
        nb_pages_to_flush = KQEMU_FLUSH_ALL;
225 9df217a3 bellard
    else
226 9df217a3 bellard
        pages_to_flush[nb_pages_to_flush++] = addr;
227 9df217a3 bellard
}
228 9df217a3 bellard
229 9df217a3 bellard
void kqemu_flush(CPUState *env, int global)
230 9df217a3 bellard
{
231 9df217a3 bellard
#ifdef DEBUG
232 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
233 9df217a3 bellard
        fprintf(logfile, "kqemu_flush:\n");
234 9df217a3 bellard
    }
235 9df217a3 bellard
#endif
236 9df217a3 bellard
    nb_pages_to_flush = KQEMU_FLUSH_ALL;
237 9df217a3 bellard
}
238 9df217a3 bellard
239 aa062973 bellard
void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
240 aa062973 bellard
{
241 aa062973 bellard
#ifdef DEBUG
242 aa062973 bellard
    if (loglevel & CPU_LOG_INT) {
243 aa062973 bellard
        fprintf(logfile, "kqemu_set_notdirty: addr=%08lx\n", ram_addr);
244 aa062973 bellard
    }
245 aa062973 bellard
#endif
246 fc8dc060 bellard
    /* we only track transitions to dirty state */
247 fc8dc060 bellard
    if (phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] != 0xff)
248 fc8dc060 bellard
        return;
249 aa062973 bellard
    if (nb_ram_pages_to_update >= KQEMU_MAX_RAM_PAGES_TO_UPDATE)
250 aa062973 bellard
        nb_ram_pages_to_update = KQEMU_RAM_PAGES_UPDATE_ALL;
251 aa062973 bellard
    else
252 aa062973 bellard
        ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
253 aa062973 bellard
}
254 aa062973 bellard
255 9df217a3 bellard
struct fpstate {
256 9df217a3 bellard
    uint16_t fpuc;
257 9df217a3 bellard
    uint16_t dummy1;
258 9df217a3 bellard
    uint16_t fpus;
259 9df217a3 bellard
    uint16_t dummy2;
260 9df217a3 bellard
    uint16_t fptag;
261 9df217a3 bellard
    uint16_t dummy3;
262 9df217a3 bellard
263 9df217a3 bellard
    uint32_t fpip;
264 9df217a3 bellard
    uint32_t fpcs;
265 9df217a3 bellard
    uint32_t fpoo;
266 9df217a3 bellard
    uint32_t fpos;
267 9df217a3 bellard
    uint8_t fpregs1[8 * 10];
268 9df217a3 bellard
};
269 9df217a3 bellard
270 9df217a3 bellard
struct fpxstate {
271 9df217a3 bellard
    uint16_t fpuc;
272 9df217a3 bellard
    uint16_t fpus;
273 9df217a3 bellard
    uint16_t fptag;
274 9df217a3 bellard
    uint16_t fop;
275 9df217a3 bellard
    uint32_t fpuip;
276 9df217a3 bellard
    uint16_t cs_sel;
277 9df217a3 bellard
    uint16_t dummy0;
278 9df217a3 bellard
    uint32_t fpudp;
279 9df217a3 bellard
    uint16_t ds_sel;
280 9df217a3 bellard
    uint16_t dummy1;
281 9df217a3 bellard
    uint32_t mxcsr;
282 9df217a3 bellard
    uint32_t mxcsr_mask;
283 9df217a3 bellard
    uint8_t fpregs1[8 * 16];
284 c28e951f bellard
    uint8_t xmm_regs[16 * 16];
285 c28e951f bellard
    uint8_t dummy2[96];
286 9df217a3 bellard
};
287 9df217a3 bellard
288 9df217a3 bellard
static struct fpxstate fpx1 __attribute__((aligned(16)));
289 9df217a3 bellard
290 9df217a3 bellard
static void restore_native_fp_frstor(CPUState *env)
291 9df217a3 bellard
{
292 9df217a3 bellard
    int fptag, i, j;
293 9df217a3 bellard
    struct fpstate fp1, *fp = &fp1;
294 9df217a3 bellard
    
295 9df217a3 bellard
    fp->fpuc = env->fpuc;
296 9df217a3 bellard
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
297 9df217a3 bellard
    fptag = 0;
298 9df217a3 bellard
    for (i=7; i>=0; i--) {
299 9df217a3 bellard
        fptag <<= 2;
300 9df217a3 bellard
        if (env->fptags[i]) {
301 9df217a3 bellard
            fptag |= 3;
302 9df217a3 bellard
        } else {
303 9df217a3 bellard
            /* the FPU automatically computes it */
304 9df217a3 bellard
        }
305 9df217a3 bellard
    }
306 9df217a3 bellard
    fp->fptag = fptag;
307 9df217a3 bellard
    j = env->fpstt;
308 9df217a3 bellard
    for(i = 0;i < 8; i++) {
309 9df217a3 bellard
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
310 9df217a3 bellard
        j = (j + 1) & 7;
311 9df217a3 bellard
    }
312 9df217a3 bellard
    asm volatile ("frstor %0" : "=m" (*fp));
313 9df217a3 bellard
}
314 9df217a3 bellard
 
315 9df217a3 bellard
static void save_native_fp_fsave(CPUState *env)
316 9df217a3 bellard
{
317 9df217a3 bellard
    int fptag, i, j;
318 9df217a3 bellard
    uint16_t fpuc;
319 9df217a3 bellard
    struct fpstate fp1, *fp = &fp1;
320 9df217a3 bellard
321 9df217a3 bellard
    asm volatile ("fsave %0" : : "m" (*fp));
322 9df217a3 bellard
    env->fpuc = fp->fpuc;
323 9df217a3 bellard
    env->fpstt = (fp->fpus >> 11) & 7;
324 9df217a3 bellard
    env->fpus = fp->fpus & ~0x3800;
325 9df217a3 bellard
    fptag = fp->fptag;
326 9df217a3 bellard
    for(i = 0;i < 8; i++) {
327 9df217a3 bellard
        env->fptags[i] = ((fptag & 3) == 3);
328 9df217a3 bellard
        fptag >>= 2;
329 9df217a3 bellard
    }
330 9df217a3 bellard
    j = env->fpstt;
331 9df217a3 bellard
    for(i = 0;i < 8; i++) {
332 9df217a3 bellard
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
333 9df217a3 bellard
        j = (j + 1) & 7;
334 9df217a3 bellard
    }
335 9df217a3 bellard
    /* we must restore the default rounding state */
336 9df217a3 bellard
    fpuc = 0x037f | (env->fpuc & (3 << 10));
337 9df217a3 bellard
    asm volatile("fldcw %0" : : "m" (fpuc));
338 9df217a3 bellard
}
339 9df217a3 bellard
340 9df217a3 bellard
static void restore_native_fp_fxrstor(CPUState *env)
341 9df217a3 bellard
{
342 9df217a3 bellard
    struct fpxstate *fp = &fpx1;
343 9df217a3 bellard
    int i, j, fptag;
344 9df217a3 bellard
345 9df217a3 bellard
    fp->fpuc = env->fpuc;
346 9df217a3 bellard
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
347 9df217a3 bellard
    fptag = 0;
348 9df217a3 bellard
    for(i = 0; i < 8; i++)
349 9df217a3 bellard
        fptag |= (env->fptags[i] << i);
350 9df217a3 bellard
    fp->fptag = fptag ^ 0xff;
351 9df217a3 bellard
352 9df217a3 bellard
    j = env->fpstt;
353 9df217a3 bellard
    for(i = 0;i < 8; i++) {
354 9df217a3 bellard
        memcpy(&fp->fpregs1[i * 16], &env->fpregs[j].d, 10);
355 9df217a3 bellard
        j = (j + 1) & 7;
356 9df217a3 bellard
    }
357 9df217a3 bellard
    if (env->cpuid_features & CPUID_SSE) {
358 9df217a3 bellard
        fp->mxcsr = env->mxcsr;
359 9df217a3 bellard
        /* XXX: check if DAZ is not available */
360 9df217a3 bellard
        fp->mxcsr_mask = 0xffff;
361 c28e951f bellard
        memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16);
362 9df217a3 bellard
    }
363 9df217a3 bellard
    asm volatile ("fxrstor %0" : "=m" (*fp));
364 9df217a3 bellard
}
365 9df217a3 bellard
366 9df217a3 bellard
static void save_native_fp_fxsave(CPUState *env)
367 9df217a3 bellard
{
368 9df217a3 bellard
    struct fpxstate *fp = &fpx1;
369 9df217a3 bellard
    int fptag, i, j;
370 9df217a3 bellard
    uint16_t fpuc;
371 9df217a3 bellard
372 9df217a3 bellard
    asm volatile ("fxsave %0" : : "m" (*fp));
373 9df217a3 bellard
    env->fpuc = fp->fpuc;
374 9df217a3 bellard
    env->fpstt = (fp->fpus >> 11) & 7;
375 9df217a3 bellard
    env->fpus = fp->fpus & ~0x3800;
376 9df217a3 bellard
    fptag = fp->fptag ^ 0xff;
377 9df217a3 bellard
    for(i = 0;i < 8; i++) {
378 9df217a3 bellard
        env->fptags[i] = (fptag >> i) & 1;
379 9df217a3 bellard
    }
380 9df217a3 bellard
    j = env->fpstt;
381 9df217a3 bellard
    for(i = 0;i < 8; i++) {
382 9df217a3 bellard
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 16], 10);
383 9df217a3 bellard
        j = (j + 1) & 7;
384 9df217a3 bellard
    }
385 9df217a3 bellard
    if (env->cpuid_features & CPUID_SSE) {
386 9df217a3 bellard
        env->mxcsr = fp->mxcsr;
387 c28e951f bellard
        memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
388 9df217a3 bellard
    }
389 9df217a3 bellard
390 9df217a3 bellard
    /* we must restore the default rounding state */
391 9df217a3 bellard
    asm volatile ("fninit");
392 9df217a3 bellard
    fpuc = 0x037f | (env->fpuc & (3 << 10));
393 9df217a3 bellard
    asm volatile("fldcw %0" : : "m" (fpuc));
394 9df217a3 bellard
}
395 9df217a3 bellard
396 c28e951f bellard
static int do_syscall(CPUState *env,
397 c28e951f bellard
                      struct kqemu_cpu_state *kenv)
398 c28e951f bellard
{
399 c28e951f bellard
    int selector;
400 c28e951f bellard
    
401 c28e951f bellard
    selector = (env->star >> 32) & 0xffff;
402 c28e951f bellard
#ifdef __x86_64__
403 c28e951f bellard
    if (env->hflags & HF_LMA_MASK) {
404 c28e951f bellard
        env->regs[R_ECX] = kenv->next_eip;
405 c28e951f bellard
        env->regs[11] = env->eflags;
406 c28e951f bellard
407 c28e951f bellard
        cpu_x86_set_cpl(env, 0);
408 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
409 c28e951f bellard
                               0, 0xffffffff, 
410 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
411 c28e951f bellard
                               DESC_S_MASK |
412 c28e951f bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
413 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
414 c28e951f bellard
                               0, 0xffffffff,
415 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
416 c28e951f bellard
                               DESC_S_MASK |
417 c28e951f bellard
                               DESC_W_MASK | DESC_A_MASK);
418 c28e951f bellard
        env->eflags &= ~env->fmask;
419 c28e951f bellard
        if (env->hflags & HF_CS64_MASK)
420 c28e951f bellard
            env->eip = env->lstar;
421 c28e951f bellard
        else
422 c28e951f bellard
            env->eip = env->cstar;
423 c28e951f bellard
    } else 
424 c28e951f bellard
#endif
425 c28e951f bellard
    {
426 c28e951f bellard
        env->regs[R_ECX] = (uint32_t)kenv->next_eip;
427 c28e951f bellard
        
428 c28e951f bellard
        cpu_x86_set_cpl(env, 0);
429 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
430 c28e951f bellard
                           0, 0xffffffff, 
431 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
432 c28e951f bellard
                               DESC_S_MASK |
433 c28e951f bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
434 c28e951f bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
435 c28e951f bellard
                               0, 0xffffffff,
436 c28e951f bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
437 c28e951f bellard
                               DESC_S_MASK |
438 c28e951f bellard
                               DESC_W_MASK | DESC_A_MASK);
439 c28e951f bellard
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
440 c28e951f bellard
        env->eip = (uint32_t)env->star;
441 c28e951f bellard
    }
442 c28e951f bellard
    return 2;
443 c28e951f bellard
}
444 c28e951f bellard
445 aa062973 bellard
#ifdef PROFILE
446 aa062973 bellard
447 aa062973 bellard
#define PC_REC_SIZE 1
448 aa062973 bellard
#define PC_REC_HASH_BITS 16
449 aa062973 bellard
#define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
450 aa062973 bellard
451 aa062973 bellard
typedef struct PCRecord {
452 aa062973 bellard
    unsigned long pc;
453 aa062973 bellard
    int64_t count;
454 aa062973 bellard
    struct PCRecord *next;
455 aa062973 bellard
} PCRecord;
456 aa062973 bellard
457 aa062973 bellard
PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
458 aa062973 bellard
int nb_pc_records;
459 aa062973 bellard
460 aa062973 bellard
void kqemu_record_pc(unsigned long pc)
461 aa062973 bellard
{
462 aa062973 bellard
    unsigned long h;
463 aa062973 bellard
    PCRecord **pr, *r;
464 aa062973 bellard
465 aa062973 bellard
    h = pc / PC_REC_SIZE;
466 aa062973 bellard
    h = h ^ (h >> PC_REC_HASH_BITS);
467 aa062973 bellard
    h &= (PC_REC_HASH_SIZE - 1);
468 aa062973 bellard
    pr = &pc_rec_hash[h];
469 aa062973 bellard
    for(;;) {
470 aa062973 bellard
        r = *pr;
471 aa062973 bellard
        if (r == NULL)
472 aa062973 bellard
            break;
473 aa062973 bellard
        if (r->pc == pc) {
474 aa062973 bellard
            r->count++;
475 aa062973 bellard
            return;
476 aa062973 bellard
        }
477 aa062973 bellard
        pr = &r->next;
478 aa062973 bellard
    }
479 aa062973 bellard
    r = malloc(sizeof(PCRecord));
480 aa062973 bellard
    r->count = 1;
481 aa062973 bellard
    r->pc = pc;
482 aa062973 bellard
    r->next = NULL;
483 aa062973 bellard
    *pr = r;
484 aa062973 bellard
    nb_pc_records++;
485 aa062973 bellard
}
486 aa062973 bellard
487 aa062973 bellard
int pc_rec_cmp(const void *p1, const void *p2)
488 aa062973 bellard
{
489 aa062973 bellard
    PCRecord *r1 = *(PCRecord **)p1;
490 aa062973 bellard
    PCRecord *r2 = *(PCRecord **)p2;
491 aa062973 bellard
    if (r1->count < r2->count)
492 aa062973 bellard
        return 1;
493 aa062973 bellard
    else if (r1->count == r2->count)
494 aa062973 bellard
        return 0;
495 aa062973 bellard
    else
496 aa062973 bellard
        return -1;
497 aa062973 bellard
}
498 aa062973 bellard
499 aa062973 bellard
void kqemu_record_dump(void)
500 aa062973 bellard
{
501 aa062973 bellard
    PCRecord **pr, *r;
502 aa062973 bellard
    int i, h;
503 aa062973 bellard
    FILE *f;
504 aa062973 bellard
    int64_t total, sum;
505 aa062973 bellard
506 aa062973 bellard
    pr = malloc(sizeof(PCRecord *) * nb_pc_records);
507 aa062973 bellard
    i = 0;
508 aa062973 bellard
    total = 0;
509 aa062973 bellard
    for(h = 0; h < PC_REC_HASH_SIZE; h++) {
510 aa062973 bellard
        for(r = pc_rec_hash[h]; r != NULL; r = r->next) {
511 aa062973 bellard
            pr[i++] = r;
512 aa062973 bellard
            total += r->count;
513 aa062973 bellard
        }
514 aa062973 bellard
    }
515 aa062973 bellard
    qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
516 aa062973 bellard
    
517 aa062973 bellard
    f = fopen("/tmp/kqemu.stats", "w");
518 aa062973 bellard
    if (!f) {
519 aa062973 bellard
        perror("/tmp/kqemu.stats");
520 aa062973 bellard
        exit(1);
521 aa062973 bellard
    }
522 aa062973 bellard
    fprintf(f, "total: %lld\n", total);
523 aa062973 bellard
    sum = 0;
524 aa062973 bellard
    for(i = 0; i < nb_pc_records; i++) {
525 aa062973 bellard
        r = pr[i];
526 aa062973 bellard
        sum += r->count;
527 aa062973 bellard
        fprintf(f, "%08lx: %lld %0.2f%% %0.2f%%\n", 
528 aa062973 bellard
                r->pc, 
529 aa062973 bellard
                r->count, 
530 aa062973 bellard
                (double)r->count / (double)total * 100.0,
531 aa062973 bellard
                (double)sum / (double)total * 100.0);
532 aa062973 bellard
    }
533 aa062973 bellard
    fclose(f);
534 aa062973 bellard
    free(pr);
535 aa062973 bellard
}
536 aa062973 bellard
#else
537 aa062973 bellard
void kqemu_record_dump(void)
538 aa062973 bellard
{
539 aa062973 bellard
}
540 aa062973 bellard
#endif
541 aa062973 bellard
542 9df217a3 bellard
int kqemu_cpu_exec(CPUState *env)
543 9df217a3 bellard
{
544 9df217a3 bellard
    struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
545 9df217a3 bellard
    int ret;
546 6e4255f6 bellard
#ifdef _WIN32
547 6e4255f6 bellard
    DWORD temp;
548 6e4255f6 bellard
#endif
549 9df217a3 bellard
550 9df217a3 bellard
#ifdef DEBUG
551 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
552 9df217a3 bellard
        fprintf(logfile, "kqemu: cpu_exec: enter\n");
553 9df217a3 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
554 9df217a3 bellard
    }
555 9df217a3 bellard
#endif
556 9df217a3 bellard
    memcpy(kenv->regs, env->regs, sizeof(kenv->regs));
557 9df217a3 bellard
    kenv->eip = env->eip;
558 9df217a3 bellard
    kenv->eflags = env->eflags;
559 9df217a3 bellard
    memcpy(&kenv->segs, &env->segs, sizeof(env->segs));
560 9df217a3 bellard
    memcpy(&kenv->ldt, &env->ldt, sizeof(env->ldt));
561 9df217a3 bellard
    memcpy(&kenv->tr, &env->tr, sizeof(env->tr));
562 9df217a3 bellard
    memcpy(&kenv->gdt, &env->gdt, sizeof(env->gdt));
563 9df217a3 bellard
    memcpy(&kenv->idt, &env->idt, sizeof(env->idt));
564 9df217a3 bellard
    kenv->cr0 = env->cr[0];
565 9df217a3 bellard
    kenv->cr2 = env->cr[2];
566 9df217a3 bellard
    kenv->cr3 = env->cr[3];
567 9df217a3 bellard
    kenv->cr4 = env->cr[4];
568 9df217a3 bellard
    kenv->a20_mask = env->a20_mask;
569 c45b3c0e bellard
#if KQEMU_VERSION >= 0x010100
570 c28e951f bellard
    kenv->efer = env->efer;
571 c28e951f bellard
#endif
572 9df217a3 bellard
    if (env->dr[7] & 0xff) {
573 9df217a3 bellard
        kenv->dr7 = env->dr[7];
574 9df217a3 bellard
        kenv->dr0 = env->dr[0];
575 9df217a3 bellard
        kenv->dr1 = env->dr[1];
576 9df217a3 bellard
        kenv->dr2 = env->dr[2];
577 9df217a3 bellard
        kenv->dr3 = env->dr[3];
578 9df217a3 bellard
    } else {
579 9df217a3 bellard
        kenv->dr7 = 0;
580 9df217a3 bellard
    }
581 9df217a3 bellard
    kenv->dr6 = env->dr[6];
582 9df217a3 bellard
    kenv->cpl = 3;
583 9df217a3 bellard
    kenv->nb_pages_to_flush = nb_pages_to_flush;
584 9df217a3 bellard
    nb_pages_to_flush = 0;
585 aa062973 bellard
#if KQEMU_VERSION >= 0x010200
586 aa062973 bellard
    kenv->user_only = 1;
587 aa062973 bellard
    kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
588 aa062973 bellard
#endif
589 aa062973 bellard
    nb_ram_pages_to_update = 0;
590 9df217a3 bellard
    
591 9df217a3 bellard
    if (!(kenv->cr0 & CR0_TS_MASK)) {
592 9df217a3 bellard
        if (env->cpuid_features & CPUID_FXSR)
593 9df217a3 bellard
            restore_native_fp_fxrstor(env);
594 9df217a3 bellard
        else
595 9df217a3 bellard
            restore_native_fp_frstor(env);
596 9df217a3 bellard
    }
597 9df217a3 bellard
598 6e4255f6 bellard
#ifdef _WIN32
599 6e4255f6 bellard
    DeviceIoControl(kqemu_fd, KQEMU_EXEC,
600 6e4255f6 bellard
                    kenv, sizeof(struct kqemu_cpu_state),
601 6e4255f6 bellard
                    kenv, sizeof(struct kqemu_cpu_state),
602 6e4255f6 bellard
                    &temp, NULL);
603 6e4255f6 bellard
    ret = kenv->retval;
604 6e4255f6 bellard
#else
605 6e4255f6 bellard
#if KQEMU_VERSION >= 0x010100
606 6e4255f6 bellard
    ioctl(kqemu_fd, KQEMU_EXEC, kenv);
607 6e4255f6 bellard
    ret = kenv->retval;
608 6e4255f6 bellard
#else
609 9df217a3 bellard
    ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
610 6e4255f6 bellard
#endif
611 6e4255f6 bellard
#endif
612 9df217a3 bellard
    if (!(kenv->cr0 & CR0_TS_MASK)) {
613 9df217a3 bellard
        if (env->cpuid_features & CPUID_FXSR)
614 9df217a3 bellard
            save_native_fp_fxsave(env);
615 9df217a3 bellard
        else
616 9df217a3 bellard
            save_native_fp_fsave(env);
617 9df217a3 bellard
    }
618 9df217a3 bellard
619 9df217a3 bellard
    memcpy(env->regs, kenv->regs, sizeof(env->regs));
620 9df217a3 bellard
    env->eip = kenv->eip;
621 9df217a3 bellard
    env->eflags = kenv->eflags;
622 9df217a3 bellard
    memcpy(env->segs, kenv->segs, sizeof(env->segs));
623 9df217a3 bellard
#if 0
624 9df217a3 bellard
    /* no need to restore that */
625 9df217a3 bellard
    memcpy(env->ldt, kenv->ldt, sizeof(env->ldt));
626 9df217a3 bellard
    memcpy(env->tr, kenv->tr, sizeof(env->tr));
627 9df217a3 bellard
    memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
628 9df217a3 bellard
    memcpy(env->idt, kenv->idt, sizeof(env->idt));
629 9df217a3 bellard
    env->cr[0] = kenv->cr0;
630 9df217a3 bellard
    env->cr[3] = kenv->cr3;
631 9df217a3 bellard
    env->cr[4] = kenv->cr4;
632 9df217a3 bellard
    env->a20_mask = kenv->a20_mask;
633 9df217a3 bellard
#endif
634 9df217a3 bellard
    env->cr[2] = kenv->cr2;
635 9df217a3 bellard
    env->dr[6] = kenv->dr6;
636 9df217a3 bellard
637 aa062973 bellard
#if KQEMU_VERSION >= 0x010200
638 aa062973 bellard
    if (kenv->nb_ram_pages_to_update > 0) {
639 aa062973 bellard
        cpu_tlb_update_dirty(env);
640 aa062973 bellard
    }
641 aa062973 bellard
#endif
642 aa062973 bellard
643 aa062973 bellard
    /* restore the hidden flags */
644 aa062973 bellard
    {
645 aa062973 bellard
        unsigned int new_hflags;
646 aa062973 bellard
#ifdef TARGET_X86_64
647 aa062973 bellard
        if ((env->hflags & HF_LMA_MASK) && 
648 aa062973 bellard
            (env->segs[R_CS].flags & DESC_L_MASK)) {
649 aa062973 bellard
            /* long mode */
650 aa062973 bellard
            new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
651 aa062973 bellard
        } else
652 aa062973 bellard
#endif
653 aa062973 bellard
        {
654 aa062973 bellard
            /* legacy / compatibility case */
655 aa062973 bellard
            new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
656 aa062973 bellard
                >> (DESC_B_SHIFT - HF_CS32_SHIFT);
657 aa062973 bellard
            new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
658 aa062973 bellard
                >> (DESC_B_SHIFT - HF_SS32_SHIFT);
659 aa062973 bellard
            if (!(env->cr[0] & CR0_PE_MASK) || 
660 aa062973 bellard
                   (env->eflags & VM_MASK) ||
661 aa062973 bellard
                   !(env->hflags & HF_CS32_MASK)) {
662 aa062973 bellard
                /* XXX: try to avoid this test. The problem comes from the
663 aa062973 bellard
                   fact that is real mode or vm86 mode we only modify the
664 aa062973 bellard
                   'base' and 'selector' fields of the segment cache to go
665 aa062973 bellard
                   faster. A solution may be to force addseg to one in
666 aa062973 bellard
                   translate-i386.c. */
667 aa062973 bellard
                new_hflags |= HF_ADDSEG_MASK;
668 aa062973 bellard
            } else {
669 aa062973 bellard
                new_hflags |= ((env->segs[R_DS].base | 
670 aa062973 bellard
                                env->segs[R_ES].base |
671 aa062973 bellard
                                env->segs[R_SS].base) != 0) << 
672 aa062973 bellard
                    HF_ADDSEG_SHIFT;
673 aa062973 bellard
            }
674 aa062973 bellard
        }
675 aa062973 bellard
        env->hflags = (env->hflags & 
676 aa062973 bellard
           ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
677 aa062973 bellard
            new_hflags;
678 aa062973 bellard
    }
679 aa062973 bellard
680 9df217a3 bellard
#ifdef DEBUG
681 9df217a3 bellard
    if (loglevel & CPU_LOG_INT) {
682 9df217a3 bellard
        fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
683 9df217a3 bellard
    }
684 9df217a3 bellard
#endif
685 c28e951f bellard
    if (ret == KQEMU_RET_SYSCALL) {
686 c28e951f bellard
        /* syscall instruction */
687 c28e951f bellard
        return do_syscall(env, kenv);
688 c28e951f bellard
    } else 
689 9df217a3 bellard
    if ((ret & 0xff00) == KQEMU_RET_INT) {
690 9df217a3 bellard
        env->exception_index = ret & 0xff;
691 9df217a3 bellard
        env->error_code = 0;
692 9df217a3 bellard
        env->exception_is_int = 1;
693 9df217a3 bellard
        env->exception_next_eip = kenv->next_eip;
694 9df217a3 bellard
#ifdef DEBUG
695 c28e951f bellard
        if (loglevel & CPU_LOG_INT) {
696 c28e951f bellard
            fprintf(logfile, "kqemu: interrupt v=%02x:\n", 
697 c28e951f bellard
                    env->exception_index);
698 c28e951f bellard
            cpu_dump_state(env, logfile, fprintf, 0);
699 c28e951f bellard
        }
700 9df217a3 bellard
#endif
701 9df217a3 bellard
        return 1;
702 9df217a3 bellard
    } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {
703 9df217a3 bellard
        env->exception_index = ret & 0xff;
704 9df217a3 bellard
        env->error_code = kenv->error_code;
705 9df217a3 bellard
        env->exception_is_int = 0;
706 9df217a3 bellard
        env->exception_next_eip = 0;
707 9df217a3 bellard
#ifdef DEBUG
708 9df217a3 bellard
        if (loglevel & CPU_LOG_INT) {
709 9df217a3 bellard
            fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
710 9df217a3 bellard
                    env->exception_index, env->error_code);
711 9df217a3 bellard
            cpu_dump_state(env, logfile, fprintf, 0);
712 9df217a3 bellard
        }
713 9df217a3 bellard
#endif
714 9df217a3 bellard
        return 1;
715 9df217a3 bellard
    } else if (ret == KQEMU_RET_INTR) {
716 c45b3c0e bellard
#ifdef DEBUG
717 c45b3c0e bellard
        if (loglevel & CPU_LOG_INT) {
718 c45b3c0e bellard
            cpu_dump_state(env, logfile, fprintf, 0);
719 c45b3c0e bellard
        }
720 c45b3c0e bellard
#endif
721 9df217a3 bellard
        return 0;
722 9df217a3 bellard
    } else if (ret == KQEMU_RET_SOFTMMU) { 
723 aa062973 bellard
#ifdef PROFILE
724 aa062973 bellard
        kqemu_record_pc(env->eip + env->segs[R_CS].base);
725 aa062973 bellard
#endif
726 aa062973 bellard
#ifdef DEBUG
727 aa062973 bellard
        if (loglevel & CPU_LOG_INT) {
728 aa062973 bellard
            cpu_dump_state(env, logfile, fprintf, 0);
729 aa062973 bellard
        }
730 aa062973 bellard
#endif
731 9df217a3 bellard
        return 2;
732 9df217a3 bellard
    } else {
733 9df217a3 bellard
        cpu_dump_state(env, stderr, fprintf, 0);
734 9df217a3 bellard
        fprintf(stderr, "Unsupported return value: 0x%x\n", ret);
735 9df217a3 bellard
        exit(1);
736 9df217a3 bellard
    }
737 9df217a3 bellard
    return 0;
738 9df217a3 bellard
}
739 9df217a3 bellard
740 9df217a3 bellard
#endif