Statistics
| Branch: | Revision:

root / kqemu.c @ f7897430

History | View | Annotate | Download (27.9 kB)

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

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