Statistics
| Branch: | Revision:

root / kqemu.c @ 8c5e95d8

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

956 da260249 bellard
   At this point it is not very satisfactory. I leave it for reference
957 da260249 bellard
   as it adds little complexity.
958 da260249 bellard
*/
959 da260249 bellard
960 da260249 bellard
#define QPI_COMM_PAGE_PHYS_ADDR 0xff000000
961 da260249 bellard
962 da260249 bellard
static uint32_t qpi_mem_readb(void *opaque, target_phys_addr_t addr)
963 da260249 bellard
{
964 da260249 bellard
    return 0;
965 da260249 bellard
}
966 da260249 bellard
967 da260249 bellard
static uint32_t qpi_mem_readw(void *opaque, target_phys_addr_t addr)
968 da260249 bellard
{
969 da260249 bellard
    return 0;
970 da260249 bellard
}
971 da260249 bellard
972 da260249 bellard
static void qpi_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
973 da260249 bellard
{
974 da260249 bellard
}
975 da260249 bellard
976 da260249 bellard
static void qpi_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
977 da260249 bellard
{
978 da260249 bellard
}
979 da260249 bellard
980 da260249 bellard
static uint32_t qpi_mem_readl(void *opaque, target_phys_addr_t addr)
981 da260249 bellard
{
982 da260249 bellard
    CPUState *env;
983 da260249 bellard
984 da260249 bellard
    env = cpu_single_env;
985 da260249 bellard
    if (!env)
986 da260249 bellard
        return 0;
987 da260249 bellard
    return env->eflags & (IF_MASK | IOPL_MASK);
988 da260249 bellard
}
989 da260249 bellard
990 da260249 bellard
/* Note: after writing to this address, the guest code must make sure
991 da260249 bellard
   it is exiting the current TB. pushf/popf can be used for that
992 da260249 bellard
   purpose. */
993 da260249 bellard
static void qpi_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
994 da260249 bellard
{
995 da260249 bellard
    CPUState *env;
996 da260249 bellard
997 da260249 bellard
    env = cpu_single_env;
998 da260249 bellard
    if (!env)
999 da260249 bellard
        return;
1000 da260249 bellard
    env->eflags = (env->eflags & ~(IF_MASK | IOPL_MASK)) | 
1001 da260249 bellard
        (val & (IF_MASK | IOPL_MASK));
1002 da260249 bellard
}
1003 da260249 bellard
1004 da260249 bellard
static CPUReadMemoryFunc *qpi_mem_read[3] = {
1005 da260249 bellard
    qpi_mem_readb,
1006 da260249 bellard
    qpi_mem_readw,
1007 da260249 bellard
    qpi_mem_readl,
1008 da260249 bellard
};
1009 da260249 bellard
1010 da260249 bellard
static CPUWriteMemoryFunc *qpi_mem_write[3] = {
1011 da260249 bellard
    qpi_mem_writeb,
1012 da260249 bellard
    qpi_mem_writew,
1013 da260249 bellard
    qpi_mem_writel,
1014 da260249 bellard
};
1015 da260249 bellard
1016 da260249 bellard
static void qpi_init(void)
1017 da260249 bellard
{
1018 da260249 bellard
    kqemu_comm_base = 0xff000000 | 1;
1019 da260249 bellard
    qpi_io_memory = cpu_register_io_memory(0, 
1020 da260249 bellard
                                           qpi_mem_read, 
1021 da260249 bellard
                                           qpi_mem_write, NULL);
1022 da260249 bellard
    cpu_register_physical_memory(kqemu_comm_base & ~0xfff, 
1023 da260249 bellard
                                 0x1000, qpi_io_memory);
1024 da260249 bellard
}
1025 9df217a3 bellard
#endif