Statistics
| Branch: | Revision:

root / kqemu.c @ 5fafdf24

History | View | Annotate | Download (25.2 kB)

1
/*
2
 *  KQEMU support
3
 *
4
 *  Copyright (c) 2005 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#include "config.h"
21
#ifdef _WIN32
22
#include <windows.h>
23
#include <winioctl.h>
24
#else
25
#include <sys/types.h>
26
#include <sys/mman.h>
27
#include <sys/ioctl.h>
28
#endif
29
#ifdef HOST_SOLARIS
30
#include <sys/ioccom.h>
31
#endif
32
#include <stdlib.h>
33
#include <stdio.h>
34
#include <stdarg.h>
35
#include <string.h>
36
#include <errno.h>
37
#include <unistd.h>
38
#include <inttypes.h>
39

    
40
#include "cpu.h"
41
#include "exec-all.h"
42

    
43
#ifdef USE_KQEMU
44

    
45
#define DEBUG
46
//#define PROFILE
47

    
48
#include <unistd.h>
49
#include <fcntl.h>
50
#include "kqemu.h"
51

    
52
/* compatibility stuff */
53
#ifndef KQEMU_RET_SYSCALL
54
#define KQEMU_RET_SYSCALL   0x0300 /* syscall insn */
55
#endif
56
#ifndef KQEMU_MAX_RAM_PAGES_TO_UPDATE
57
#define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512
58
#define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)
59
#endif
60
#ifndef KQEMU_MAX_MODIFIED_RAM_PAGES
61
#define KQEMU_MAX_MODIFIED_RAM_PAGES 512
62
#endif
63

    
64
#ifdef _WIN32
65
#define KQEMU_DEVICE "\\\\.\\kqemu"
66
#else
67
#define KQEMU_DEVICE "/dev/kqemu"
68
#endif
69

    
70
#ifdef _WIN32
71
#define KQEMU_INVALID_FD INVALID_HANDLE_VALUE
72
HANDLE kqemu_fd = KQEMU_INVALID_FD;
73
#define kqemu_closefd(x) CloseHandle(x)
74
#else
75
#define KQEMU_INVALID_FD -1
76
int kqemu_fd = KQEMU_INVALID_FD;
77
#define kqemu_closefd(x) close(x)
78
#endif
79

    
80
/* 0 = not allowed
81
   1 = user kqemu
82
   2 = kernel kqemu
83
*/
84
int kqemu_allowed = 1;
85
unsigned long *pages_to_flush;
86
unsigned int nb_pages_to_flush;
87
unsigned long *ram_pages_to_update;
88
unsigned int nb_ram_pages_to_update;
89
unsigned long *modified_ram_pages;
90
unsigned int nb_modified_ram_pages;
91
uint8_t *modified_ram_pages_table;
92
extern uint32_t **l1_phys_map;
93

    
94
#define cpuid(index, eax, ebx, ecx, edx) \
95
  asm volatile ("cpuid" \
96
                : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
97
                : "0" (index))
98

    
99
#ifdef __x86_64__
100
static int is_cpuid_supported(void)
101
{
102
    return 1;
103
}
104
#else
105
static int is_cpuid_supported(void)
106
{
107
    int v0, v1;
108
    asm volatile ("pushf\n"
109
                  "popl %0\n"
110
                  "movl %0, %1\n"
111
                  "xorl $0x00200000, %0\n"
112
                  "pushl %0\n"
113
                  "popf\n"
114
                  "pushf\n"
115
                  "popl %0\n"
116
                  : "=a" (v0), "=d" (v1)
117
                  :
118
                  : "cc");
119
    return (v0 != v1);
120
}
121
#endif
122

    
123
static void kqemu_update_cpuid(CPUState *env)
124
{
125
    int critical_features_mask, features, ext_features, ext_features_mask;
126
    uint32_t eax, ebx, ecx, edx;
127

    
128
    /* the following features are kept identical on the host and
129
       target cpus because they are important for user code. Strictly
130
       speaking, only SSE really matters because the OS must support
131
       it if the user code uses it. */
132
    critical_features_mask =
133
        CPUID_CMOV | CPUID_CX8 |
134
        CPUID_FXSR | CPUID_MMX | CPUID_SSE |
135
        CPUID_SSE2 | CPUID_SEP;
136
    ext_features_mask = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR;
137
    if (!is_cpuid_supported()) {
138
        features = 0;
139
        ext_features = 0;
140
    } else {
141
        cpuid(1, eax, ebx, ecx, edx);
142
        features = edx;
143
        ext_features = ecx;
144
    }
145
#ifdef __x86_64__
146
    /* NOTE: on x86_64 CPUs, SYSENTER is not supported in
147
       compatibility mode, so in order to have the best performances
148
       it is better not to use it */
149
    features &= ~CPUID_SEP;
150
#endif
151
    env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
152
        (features & critical_features_mask);
153
    env->cpuid_ext_features = (env->cpuid_ext_features & ~ext_features_mask) |
154
        (ext_features & ext_features_mask);
155
    /* XXX: we could update more of the target CPUID state so that the
156
       non accelerated code sees exactly the same CPU features as the
157
       accelerated code */
158
}
159

    
160
int kqemu_init(CPUState *env)
161
{
162
    struct kqemu_init init;
163
    int ret, version;
164
#ifdef _WIN32
165
    DWORD temp;
166
#endif
167

    
168
    if (!kqemu_allowed)
169
        return -1;
170

    
171
#ifdef _WIN32
172
    kqemu_fd = CreateFile(KQEMU_DEVICE, GENERIC_WRITE | GENERIC_READ,
173
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
174
                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
175
                          NULL);
176
#else
177
    kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
178
#endif
179
    if (kqemu_fd == KQEMU_INVALID_FD) {
180
        fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated: %s\n",
181
                KQEMU_DEVICE, strerror(errno));
182
        return -1;
183
    }
184
    version = 0;
185
#ifdef _WIN32
186
    DeviceIoControl(kqemu_fd, KQEMU_GET_VERSION, NULL, 0,
187
                    &version, sizeof(version), &temp, NULL);
188
#else
189
    ioctl(kqemu_fd, KQEMU_GET_VERSION, &version);
190
#endif
191
    if (version != KQEMU_VERSION) {
192
        fprintf(stderr, "Version mismatch between kqemu module and qemu (%08x %08x) - disabling kqemu use\n",
193
                version, KQEMU_VERSION);
194
        goto fail;
195
    }
196

    
197
    pages_to_flush = qemu_vmalloc(KQEMU_MAX_PAGES_TO_FLUSH *
198
                                  sizeof(unsigned long));
199
    if (!pages_to_flush)
200
        goto fail;
201

    
202
    ram_pages_to_update = qemu_vmalloc(KQEMU_MAX_RAM_PAGES_TO_UPDATE *
203
                                       sizeof(unsigned long));
204
    if (!ram_pages_to_update)
205
        goto fail;
206

    
207
    modified_ram_pages = qemu_vmalloc(KQEMU_MAX_MODIFIED_RAM_PAGES *
208
                                      sizeof(unsigned long));
209
    if (!modified_ram_pages)
210
        goto fail;
211
    modified_ram_pages_table = qemu_mallocz(phys_ram_size >> TARGET_PAGE_BITS);
212
    if (!modified_ram_pages_table)
213
        goto fail;
214

    
215
    init.ram_base = phys_ram_base;
216
    init.ram_size = phys_ram_size;
217
    init.ram_dirty = phys_ram_dirty;
218
    init.phys_to_ram_map = l1_phys_map;
219
    init.pages_to_flush = pages_to_flush;
220
#if KQEMU_VERSION >= 0x010200
221
    init.ram_pages_to_update = ram_pages_to_update;
222
#endif
223
#if KQEMU_VERSION >= 0x010300
224
    init.modified_ram_pages = modified_ram_pages;
225
#endif
226
#ifdef _WIN32
227
    ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
228
                          NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
229
#else
230
    ret = ioctl(kqemu_fd, KQEMU_INIT, &init);
231
#endif
232
    if (ret < 0) {
233
        fprintf(stderr, "Error %d while initializing QEMU acceleration layer - disabling it for now\n", ret);
234
    fail:
235
        kqemu_closefd(kqemu_fd);
236
        kqemu_fd = KQEMU_INVALID_FD;
237
        return -1;
238
    }
239
    kqemu_update_cpuid(env);
240
    env->kqemu_enabled = kqemu_allowed;
241
    nb_pages_to_flush = 0;
242
    nb_ram_pages_to_update = 0;
243
    return 0;
244
}
245

    
246
void kqemu_flush_page(CPUState *env, target_ulong addr)
247
{
248
#if defined(DEBUG)
249
    if (loglevel & CPU_LOG_INT) {
250
        fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
251
    }
252
#endif
253
    if (nb_pages_to_flush >= KQEMU_MAX_PAGES_TO_FLUSH)
254
        nb_pages_to_flush = KQEMU_FLUSH_ALL;
255
    else
256
        pages_to_flush[nb_pages_to_flush++] = addr;
257
}
258

    
259
void kqemu_flush(CPUState *env, int global)
260
{
261
#ifdef DEBUG
262
    if (loglevel & CPU_LOG_INT) {
263
        fprintf(logfile, "kqemu_flush:\n");
264
    }
265
#endif
266
    nb_pages_to_flush = KQEMU_FLUSH_ALL;
267
}
268

    
269
void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
270
{
271
#ifdef DEBUG
272
    if (loglevel & CPU_LOG_INT) {
273
        fprintf(logfile, "kqemu_set_notdirty: addr=%08lx\n", ram_addr);
274
    }
275
#endif
276
    /* we only track transitions to dirty state */
277
    if (phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] != 0xff)
278
        return;
279
    if (nb_ram_pages_to_update >= KQEMU_MAX_RAM_PAGES_TO_UPDATE)
280
        nb_ram_pages_to_update = KQEMU_RAM_PAGES_UPDATE_ALL;
281
    else
282
        ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
283
}
284

    
285
static void kqemu_reset_modified_ram_pages(void)
286
{
287
    int i;
288
    unsigned long page_index;
289
   
290
    for(i = 0; i < nb_modified_ram_pages; i++) {
291
        page_index = modified_ram_pages[i] >> TARGET_PAGE_BITS;
292
        modified_ram_pages_table[page_index] = 0;
293
    }
294
    nb_modified_ram_pages = 0;
295
}
296

    
297
void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr)
298
{
299
    unsigned long page_index;
300
    int ret;
301
#ifdef _WIN32
302
    DWORD temp;
303
#endif
304

    
305
    page_index = ram_addr >> TARGET_PAGE_BITS;
306
    if (!modified_ram_pages_table[page_index]) {
307
#if 0
308
        printf("%d: modify_page=%08lx\n", nb_modified_ram_pages, ram_addr);
309
#endif
310
        modified_ram_pages_table[page_index] = 1;
311
        modified_ram_pages[nb_modified_ram_pages++] = ram_addr;
312
        if (nb_modified_ram_pages >= KQEMU_MAX_MODIFIED_RAM_PAGES) {
313
            /* flush */
314
#ifdef _WIN32
315
            ret = DeviceIoControl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES,
316
                                  &nb_modified_ram_pages,
317
                                  sizeof(nb_modified_ram_pages),
318
                                  NULL, 0, &temp, NULL);
319
#else
320
            ret = ioctl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES,
321
                        &nb_modified_ram_pages);
322
#endif
323
            kqemu_reset_modified_ram_pages();
324
        }
325
    }
326
}
327

    
328
struct fpstate {
329
    uint16_t fpuc;
330
    uint16_t dummy1;
331
    uint16_t fpus;
332
    uint16_t dummy2;
333
    uint16_t fptag;
334
    uint16_t dummy3;
335

    
336
    uint32_t fpip;
337
    uint32_t fpcs;
338
    uint32_t fpoo;
339
    uint32_t fpos;
340
    uint8_t fpregs1[8 * 10];
341
};
342

    
343
struct fpxstate {
344
    uint16_t fpuc;
345
    uint16_t fpus;
346
    uint16_t fptag;
347
    uint16_t fop;
348
    uint32_t fpuip;
349
    uint16_t cs_sel;
350
    uint16_t dummy0;
351
    uint32_t fpudp;
352
    uint16_t ds_sel;
353
    uint16_t dummy1;
354
    uint32_t mxcsr;
355
    uint32_t mxcsr_mask;
356
    uint8_t fpregs1[8 * 16];
357
    uint8_t xmm_regs[16 * 16];
358
    uint8_t dummy2[96];
359
};
360

    
361
static struct fpxstate fpx1 __attribute__((aligned(16)));
362

    
363
static void restore_native_fp_frstor(CPUState *env)
364
{
365
    int fptag, i, j;
366
    struct fpstate fp1, *fp = &fp1;
367
   
368
    fp->fpuc = env->fpuc;
369
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
370
    fptag = 0;
371
    for (i=7; i>=0; i--) {
372
        fptag <<= 2;
373
        if (env->fptags[i]) {
374
            fptag |= 3;
375
        } else {
376
            /* the FPU automatically computes it */
377
        }
378
    }
379
    fp->fptag = fptag;
380
    j = env->fpstt;
381
    for(i = 0;i < 8; i++) {
382
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
383
        j = (j + 1) & 7;
384
    }
385
    asm volatile ("frstor %0" : "=m" (*fp));
386
}
387

    
388
static void save_native_fp_fsave(CPUState *env)
389
{
390
    int fptag, i, j;
391
    uint16_t fpuc;
392
    struct fpstate fp1, *fp = &fp1;
393

    
394
    asm volatile ("fsave %0" : : "m" (*fp));
395
    env->fpuc = fp->fpuc;
396
    env->fpstt = (fp->fpus >> 11) & 7;
397
    env->fpus = fp->fpus & ~0x3800;
398
    fptag = fp->fptag;
399
    for(i = 0;i < 8; i++) {
400
        env->fptags[i] = ((fptag & 3) == 3);
401
        fptag >>= 2;
402
    }
403
    j = env->fpstt;
404
    for(i = 0;i < 8; i++) {
405
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
406
        j = (j + 1) & 7;
407
    }
408
    /* we must restore the default rounding state */
409
    fpuc = 0x037f | (env->fpuc & (3 << 10));
410
    asm volatile("fldcw %0" : : "m" (fpuc));
411
}
412

    
413
static void restore_native_fp_fxrstor(CPUState *env)
414
{
415
    struct fpxstate *fp = &fpx1;
416
    int i, j, fptag;
417

    
418
    fp->fpuc = env->fpuc;
419
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
420
    fptag = 0;
421
    for(i = 0; i < 8; i++)
422
        fptag |= (env->fptags[i] << i);
423
    fp->fptag = fptag ^ 0xff;
424

    
425
    j = env->fpstt;
426
    for(i = 0;i < 8; i++) {
427
        memcpy(&fp->fpregs1[i * 16], &env->fpregs[j].d, 10);
428
        j = (j + 1) & 7;
429
    }
430
    if (env->cpuid_features & CPUID_SSE) {
431
        fp->mxcsr = env->mxcsr;
432
        /* XXX: check if DAZ is not available */
433
        fp->mxcsr_mask = 0xffff;
434
        memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16);
435
    }
436
    asm volatile ("fxrstor %0" : "=m" (*fp));
437
}
438

    
439
static void save_native_fp_fxsave(CPUState *env)
440
{
441
    struct fpxstate *fp = &fpx1;
442
    int fptag, i, j;
443
    uint16_t fpuc;
444

    
445
    asm volatile ("fxsave %0" : : "m" (*fp));
446
    env->fpuc = fp->fpuc;
447
    env->fpstt = (fp->fpus >> 11) & 7;
448
    env->fpus = fp->fpus & ~0x3800;
449
    fptag = fp->fptag ^ 0xff;
450
    for(i = 0;i < 8; i++) {
451
        env->fptags[i] = (fptag >> i) & 1;
452
    }
453
    j = env->fpstt;
454
    for(i = 0;i < 8; i++) {
455
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 16], 10);
456
        j = (j + 1) & 7;
457
    }
458
    if (env->cpuid_features & CPUID_SSE) {
459
        env->mxcsr = fp->mxcsr;
460
        memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
461
    }
462

    
463
    /* we must restore the default rounding state */
464
    asm volatile ("fninit");
465
    fpuc = 0x037f | (env->fpuc & (3 << 10));
466
    asm volatile("fldcw %0" : : "m" (fpuc));
467
}
468

    
469
static int do_syscall(CPUState *env,
470
                      struct kqemu_cpu_state *kenv)
471
{
472
    int selector;
473
   
474
    selector = (env->star >> 32) & 0xffff;
475
#ifdef __x86_64__
476
    if (env->hflags & HF_LMA_MASK) {
477
        int code64;
478

    
479
        env->regs[R_ECX] = kenv->next_eip;
480
        env->regs[11] = env->eflags;
481

    
482
        code64 = env->hflags & HF_CS64_MASK;
483

    
484
        cpu_x86_set_cpl(env, 0);
485
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
486
                               0, 0xffffffff,
487
                               DESC_G_MASK | DESC_P_MASK |
488
                               DESC_S_MASK |
489
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
490
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
491
                               0, 0xffffffff,
492
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
493
                               DESC_S_MASK |
494
                               DESC_W_MASK | DESC_A_MASK);
495
        env->eflags &= ~env->fmask;
496
        if (code64)
497
            env->eip = env->lstar;
498
        else
499
            env->eip = env->cstar;
500
    } else
501
#endif
502
    {
503
        env->regs[R_ECX] = (uint32_t)kenv->next_eip;
504
       
505
        cpu_x86_set_cpl(env, 0);
506
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
507
                           0, 0xffffffff,
508
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
509
                               DESC_S_MASK |
510
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
511
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
512
                               0, 0xffffffff,
513
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
514
                               DESC_S_MASK |
515
                               DESC_W_MASK | DESC_A_MASK);
516
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
517
        env->eip = (uint32_t)env->star;
518
    }
519
    return 2;
520
}
521

    
522
#ifdef CONFIG_PROFILER
523

    
524
#define PC_REC_SIZE 1
525
#define PC_REC_HASH_BITS 16
526
#define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
527

    
528
typedef struct PCRecord {
529
    unsigned long pc;
530
    int64_t count;
531
    struct PCRecord *next;
532
} PCRecord;
533

    
534
static PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
535
static int nb_pc_records;
536

    
537
static void kqemu_record_pc(unsigned long pc)
538
{
539
    unsigned long h;
540
    PCRecord **pr, *r;
541

    
542
    h = pc / PC_REC_SIZE;
543
    h = h ^ (h >> PC_REC_HASH_BITS);
544
    h &= (PC_REC_HASH_SIZE - 1);
545
    pr = &pc_rec_hash[h];
546
    for(;;) {
547
        r = *pr;
548
        if (r == NULL)
549
            break;
550
        if (r->pc == pc) {
551
            r->count++;
552
            return;
553
        }
554
        pr = &r->next;
555
    }
556
    r = malloc(sizeof(PCRecord));
557
    r->count = 1;
558
    r->pc = pc;
559
    r->next = NULL;
560
    *pr = r;
561
    nb_pc_records++;
562
}
563

    
564
static int pc_rec_cmp(const void *p1, const void *p2)
565
{
566
    PCRecord *r1 = *(PCRecord **)p1;
567
    PCRecord *r2 = *(PCRecord **)p2;
568
    if (r1->count < r2->count)
569
        return 1;
570
    else if (r1->count == r2->count)
571
        return 0;
572
    else
573
        return -1;
574
}
575

    
576
static void kqemu_record_flush(void)
577
{
578
    PCRecord *r, *r_next;
579
    int h;
580

    
581
    for(h = 0; h < PC_REC_HASH_SIZE; h++) {
582
        for(r = pc_rec_hash[h]; r != NULL; r = r_next) {
583
            r_next = r->next;
584
            free(r);
585
        }
586
        pc_rec_hash[h] = NULL;
587
    }
588
    nb_pc_records = 0;
589
}
590

    
591
void kqemu_record_dump(void)
592
{
593
    PCRecord **pr, *r;
594
    int i, h;
595
    FILE *f;
596
    int64_t total, sum;
597

    
598
    pr = malloc(sizeof(PCRecord *) * nb_pc_records);
599
    i = 0;
600
    total = 0;
601
    for(h = 0; h < PC_REC_HASH_SIZE; h++) {
602
        for(r = pc_rec_hash[h]; r != NULL; r = r->next) {
603
            pr[i++] = r;
604
            total += r->count;
605
        }
606
    }
607
    qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
608
   
609
    f = fopen("/tmp/kqemu.stats", "w");
610
    if (!f) {
611
        perror("/tmp/kqemu.stats");
612
        exit(1);
613
    }
614
    fprintf(f, "total: %" PRId64 "\n", total);
615
    sum = 0;
616
    for(i = 0; i < nb_pc_records; i++) {
617
        r = pr[i];
618
        sum += r->count;
619
        fprintf(f, "%08lx: %" PRId64 " %0.2f%% %0.2f%%\n",
620
                r->pc,
621
                r->count,
622
                (double)r->count / (double)total * 100.0,
623
                (double)sum / (double)total * 100.0);
624
    }
625
    fclose(f);
626
    free(pr);
627

    
628
    kqemu_record_flush();
629
}
630
#endif
631

    
632
int kqemu_cpu_exec(CPUState *env)
633
{
634
    struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
635
    int ret, cpl, i;
636
#ifdef CONFIG_PROFILER
637
    int64_t ti;
638
#endif
639

    
640
#ifdef _WIN32
641
    DWORD temp;
642
#endif
643

    
644
#ifdef CONFIG_PROFILER
645
    ti = profile_getclock();
646
#endif
647
#ifdef DEBUG
648
    if (loglevel & CPU_LOG_INT) {
649
        fprintf(logfile, "kqemu: cpu_exec: enter\n");
650
        cpu_dump_state(env, logfile, fprintf, 0);
651
    }
652
#endif
653
    memcpy(kenv->regs, env->regs, sizeof(kenv->regs));
654
    kenv->eip = env->eip;
655
    kenv->eflags = env->eflags;
656
    memcpy(&kenv->segs, &env->segs, sizeof(env->segs));
657
    memcpy(&kenv->ldt, &env->ldt, sizeof(env->ldt));
658
    memcpy(&kenv->tr, &env->tr, sizeof(env->tr));
659
    memcpy(&kenv->gdt, &env->gdt, sizeof(env->gdt));
660
    memcpy(&kenv->idt, &env->idt, sizeof(env->idt));
661
    kenv->cr0 = env->cr[0];
662
    kenv->cr2 = env->cr[2];
663
    kenv->cr3 = env->cr[3];
664
    kenv->cr4 = env->cr[4];
665
    kenv->a20_mask = env->a20_mask;
666
#if KQEMU_VERSION >= 0x010100
667
    kenv->efer = env->efer;
668
#endif
669
#if KQEMU_VERSION >= 0x010300
670
    kenv->tsc_offset = 0;
671
    kenv->star = env->star;
672
    kenv->sysenter_cs = env->sysenter_cs;
673
    kenv->sysenter_esp = env->sysenter_esp;
674
    kenv->sysenter_eip = env->sysenter_eip;
675
#ifdef __x86_64__
676
    kenv->lstar = env->lstar;
677
    kenv->cstar = env->cstar;
678
    kenv->fmask = env->fmask;
679
    kenv->kernelgsbase = env->kernelgsbase;
680
#endif
681
#endif
682
    if (env->dr[7] & 0xff) {
683
        kenv->dr7 = env->dr[7];
684
        kenv->dr0 = env->dr[0];
685
        kenv->dr1 = env->dr[1];
686
        kenv->dr2 = env->dr[2];
687
        kenv->dr3 = env->dr[3];
688
    } else {
689
        kenv->dr7 = 0;
690
    }
691
    kenv->dr6 = env->dr[6];
692
    cpl = (env->hflags & HF_CPL_MASK);
693
    kenv->cpl = cpl;
694
    kenv->nb_pages_to_flush = nb_pages_to_flush;
695
#if KQEMU_VERSION >= 0x010200
696
    kenv->user_only = (env->kqemu_enabled == 1);
697
    kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
698
#endif
699
    nb_ram_pages_to_update = 0;
700
   
701
#if KQEMU_VERSION >= 0x010300
702
    kenv->nb_modified_ram_pages = nb_modified_ram_pages;
703
#endif
704
    kqemu_reset_modified_ram_pages();
705

    
706
    if (env->cpuid_features & CPUID_FXSR)
707
        restore_native_fp_fxrstor(env);
708
    else
709
        restore_native_fp_frstor(env);
710

    
711
#ifdef _WIN32
712
    if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,
713
                        kenv, sizeof(struct kqemu_cpu_state),
714
                        kenv, sizeof(struct kqemu_cpu_state),
715
                        &temp, NULL)) {
716
        ret = kenv->retval;
717
    } else {
718
        ret = -1;
719
    }
720
#else
721
#if KQEMU_VERSION >= 0x010100
722
    ioctl(kqemu_fd, KQEMU_EXEC, kenv);
723
    ret = kenv->retval;
724
#else
725
    ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
726
#endif
727
#endif
728
    if (env->cpuid_features & CPUID_FXSR)
729
        save_native_fp_fxsave(env);
730
    else
731
        save_native_fp_fsave(env);
732

    
733
    memcpy(env->regs, kenv->regs, sizeof(env->regs));
734
    env->eip = kenv->eip;
735
    env->eflags = kenv->eflags;
736
    memcpy(env->segs, kenv->segs, sizeof(env->segs));
737
    cpu_x86_set_cpl(env, kenv->cpl);
738
    memcpy(&env->ldt, &kenv->ldt, sizeof(env->ldt));
739
#if 0
740
    /* no need to restore that */
741
    memcpy(env->tr, kenv->tr, sizeof(env->tr));
742
    memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
743
    memcpy(env->idt, kenv->idt, sizeof(env->idt));
744
    env->a20_mask = kenv->a20_mask;
745
#endif
746
    env->cr[0] = kenv->cr0;
747
    env->cr[4] = kenv->cr4;
748
    env->cr[3] = kenv->cr3;
749
    env->cr[2] = kenv->cr2;
750
    env->dr[6] = kenv->dr6;
751
#if KQEMU_VERSION >= 0x010300
752
#ifdef __x86_64__
753
    env->kernelgsbase = kenv->kernelgsbase;
754
#endif
755
#endif
756

    
757
    /* flush pages as indicated by kqemu */
758
    if (kenv->nb_pages_to_flush >= KQEMU_FLUSH_ALL) {
759
        tlb_flush(env, 1);
760
    } else {
761
        for(i = 0; i < kenv->nb_pages_to_flush; i++) {
762
            tlb_flush_page(env, pages_to_flush[i]);
763
        }
764
    }
765
    nb_pages_to_flush = 0;
766

    
767
#ifdef CONFIG_PROFILER
768
    kqemu_time += profile_getclock() - ti;
769
    kqemu_exec_count++;
770
#endif
771

    
772
#if KQEMU_VERSION >= 0x010200
773
    if (kenv->nb_ram_pages_to_update > 0) {
774
        cpu_tlb_update_dirty(env);
775
    }
776
#endif
777

    
778
#if KQEMU_VERSION >= 0x010300
779
    if (kenv->nb_modified_ram_pages > 0) {
780
        for(i = 0; i < kenv->nb_modified_ram_pages; i++) {
781
            unsigned long addr;
782
            addr = modified_ram_pages[i];
783
            tb_invalidate_phys_page_range(addr, addr + TARGET_PAGE_SIZE, 0);
784
        }
785
    }
786
#endif
787

    
788
    /* restore the hidden flags */
789
    {
790
        unsigned int new_hflags;
791
#ifdef TARGET_X86_64
792
        if ((env->hflags & HF_LMA_MASK) &&
793
            (env->segs[R_CS].flags & DESC_L_MASK)) {
794
            /* long mode */
795
            new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
796
        } else
797
#endif
798
        {
799
            /* legacy / compatibility case */
800
            new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
801
                >> (DESC_B_SHIFT - HF_CS32_SHIFT);
802
            new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
803
                >> (DESC_B_SHIFT - HF_SS32_SHIFT);
804
            if (!(env->cr[0] & CR0_PE_MASK) ||
805
                   (env->eflags & VM_MASK) ||
806
                   !(env->hflags & HF_CS32_MASK)) {
807
                /* XXX: try to avoid this test. The problem comes from the
808
                   fact that is real mode or vm86 mode we only modify the
809
                   'base' and 'selector' fields of the segment cache to go
810
                   faster. A solution may be to force addseg to one in
811
                   translate-i386.c. */
812
                new_hflags |= HF_ADDSEG_MASK;
813
            } else {
814
                new_hflags |= ((env->segs[R_DS].base |
815
                                env->segs[R_ES].base |
816
                                env->segs[R_SS].base) != 0) <<
817
                    HF_ADDSEG_SHIFT;
818
            }
819
        }
820
        env->hflags = (env->hflags &
821
           ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
822
            new_hflags;
823
    }
824
    /* update FPU flags */
825
    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
826
        ((env->cr[0] << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
827
    if (env->cr[4] & CR4_OSFXSR_MASK)
828
        env->hflags |= HF_OSFXSR_MASK;
829
    else
830
        env->hflags &= ~HF_OSFXSR_MASK;
831
       
832
#ifdef DEBUG
833
    if (loglevel & CPU_LOG_INT) {
834
        fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
835
    }
836
#endif
837
    if (ret == KQEMU_RET_SYSCALL) {
838
        /* syscall instruction */
839
        return do_syscall(env, kenv);
840
    } else
841
    if ((ret & 0xff00) == KQEMU_RET_INT) {
842
        env->exception_index = ret & 0xff;
843
        env->error_code = 0;
844
        env->exception_is_int = 1;
845
        env->exception_next_eip = kenv->next_eip;
846
#ifdef CONFIG_PROFILER
847
        kqemu_ret_int_count++;
848
#endif
849
#ifdef DEBUG
850
        if (loglevel & CPU_LOG_INT) {
851
            fprintf(logfile, "kqemu: interrupt v=%02x:\n",
852
                    env->exception_index);
853
            cpu_dump_state(env, logfile, fprintf, 0);
854
        }
855
#endif
856
        return 1;
857
    } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {
858
        env->exception_index = ret & 0xff;
859
        env->error_code = kenv->error_code;
860
        env->exception_is_int = 0;
861
        env->exception_next_eip = 0;
862
#ifdef CONFIG_PROFILER
863
        kqemu_ret_excp_count++;
864
#endif
865
#ifdef DEBUG
866
        if (loglevel & CPU_LOG_INT) {
867
            fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
868
                    env->exception_index, env->error_code);
869
            cpu_dump_state(env, logfile, fprintf, 0);
870
        }
871
#endif
872
        return 1;
873
    } else if (ret == KQEMU_RET_INTR) {
874
#ifdef CONFIG_PROFILER
875
        kqemu_ret_intr_count++;
876
#endif
877
#ifdef DEBUG
878
        if (loglevel & CPU_LOG_INT) {
879
            cpu_dump_state(env, logfile, fprintf, 0);
880
        }
881
#endif
882
        return 0;
883
    } else if (ret == KQEMU_RET_SOFTMMU) {
884
#ifdef CONFIG_PROFILER
885
        {
886
            unsigned long pc = env->eip + env->segs[R_CS].base;
887
            kqemu_record_pc(pc);
888
        }
889
#endif
890
#ifdef DEBUG
891
        if (loglevel & CPU_LOG_INT) {
892
            cpu_dump_state(env, logfile, fprintf, 0);
893
        }
894
#endif
895
        return 2;
896
    } else {
897
        cpu_dump_state(env, stderr, fprintf, 0);
898
        fprintf(stderr, "Unsupported return value: 0x%x\n", ret);
899
        exit(1);
900
    }
901
    return 0;
902
}
903

    
904
void kqemu_cpu_interrupt(CPUState *env)
905
{
906
#if defined(_WIN32) && KQEMU_VERSION >= 0x010101
907
    /* cancelling the I/O request causes KQEMU to finish executing the
908
       current block and successfully returning. */
909
    CancelIo(kqemu_fd);
910
#endif
911
}
912

    
913
#endif