Statistics
| Branch: | Revision:

root / kqemu.c @ 72249e34

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

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