Statistics
| Branch: | Revision:

root / kqemu.c @ 109819e0

History | View | Annotate | Download (27.8 kB)

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

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