Statistics
| Branch: | Revision:

root / kqemu.c @ 3fb94d56

History | View | Annotate | Download (27.8 kB)

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

927 da260249 bellard
   At this point it is not very satisfactory. I leave it for reference
928 da260249 bellard
   as it adds little complexity.
929 da260249 bellard
*/
930 da260249 bellard
931 da260249 bellard
#define QPI_COMM_PAGE_PHYS_ADDR 0xff000000
932 da260249 bellard
933 da260249 bellard
static uint32_t qpi_mem_readb(void *opaque, target_phys_addr_t addr)
934 da260249 bellard
{
935 da260249 bellard
    return 0;
936 da260249 bellard
}
937 da260249 bellard
938 da260249 bellard
static uint32_t qpi_mem_readw(void *opaque, target_phys_addr_t addr)
939 da260249 bellard
{
940 da260249 bellard
    return 0;
941 da260249 bellard
}
942 da260249 bellard
943 da260249 bellard
static void qpi_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
944 da260249 bellard
{
945 da260249 bellard
}
946 da260249 bellard
947 da260249 bellard
static void qpi_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
948 da260249 bellard
{
949 da260249 bellard
}
950 da260249 bellard
951 da260249 bellard
static uint32_t qpi_mem_readl(void *opaque, target_phys_addr_t addr)
952 da260249 bellard
{
953 da260249 bellard
    CPUState *env;
954 da260249 bellard
955 da260249 bellard
    env = cpu_single_env;
956 da260249 bellard
    if (!env)
957 da260249 bellard
        return 0;
958 da260249 bellard
    return env->eflags & (IF_MASK | IOPL_MASK);
959 da260249 bellard
}
960 da260249 bellard
961 da260249 bellard
/* Note: after writing to this address, the guest code must make sure
962 da260249 bellard
   it is exiting the current TB. pushf/popf can be used for that
963 da260249 bellard
   purpose. */
964 da260249 bellard
static void qpi_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
965 da260249 bellard
{
966 da260249 bellard
    CPUState *env;
967 da260249 bellard
968 da260249 bellard
    env = cpu_single_env;
969 da260249 bellard
    if (!env)
970 da260249 bellard
        return;
971 da260249 bellard
    env->eflags = (env->eflags & ~(IF_MASK | IOPL_MASK)) | 
972 da260249 bellard
        (val & (IF_MASK | IOPL_MASK));
973 da260249 bellard
}
974 da260249 bellard
975 da260249 bellard
static CPUReadMemoryFunc *qpi_mem_read[3] = {
976 da260249 bellard
    qpi_mem_readb,
977 da260249 bellard
    qpi_mem_readw,
978 da260249 bellard
    qpi_mem_readl,
979 da260249 bellard
};
980 da260249 bellard
981 da260249 bellard
static CPUWriteMemoryFunc *qpi_mem_write[3] = {
982 da260249 bellard
    qpi_mem_writeb,
983 da260249 bellard
    qpi_mem_writew,
984 da260249 bellard
    qpi_mem_writel,
985 da260249 bellard
};
986 da260249 bellard
987 da260249 bellard
static void qpi_init(void)
988 da260249 bellard
{
989 da260249 bellard
    kqemu_comm_base = 0xff000000 | 1;
990 da260249 bellard
    qpi_io_memory = cpu_register_io_memory(0, 
991 da260249 bellard
                                           qpi_mem_read, 
992 da260249 bellard
                                           qpi_mem_write, NULL);
993 da260249 bellard
    cpu_register_physical_memory(kqemu_comm_base & ~0xfff, 
994 da260249 bellard
                                 0x1000, qpi_io_memory);
995 da260249 bellard
}
996 9df217a3 bellard
#endif