Statistics
| Branch: | Revision:

root / kqemu.c @ 50d3eeae

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/modctl.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\n", KQEMU_DEVICE);
181
        return -1;
182
    }
183
    version = 0;
184
#ifdef _WIN32
185
    DeviceIoControl(kqemu_fd, KQEMU_GET_VERSION, NULL, 0,
186
                    &version, sizeof(version), &temp, NULL);
187
#else
188
    ioctl(kqemu_fd, KQEMU_GET_VERSION, &version);
189
#endif
190
    if (version != KQEMU_VERSION) {
191
        fprintf(stderr, "Version mismatch between kqemu module and qemu (%08x %08x) - disabling kqemu use\n",
192
                version, KQEMU_VERSION);
193
        goto fail;
194
    }
195

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
481
        code64 = env->hflags & HF_CS64_MASK;
482

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

    
521
#ifdef CONFIG_PROFILER
522

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

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

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

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

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

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

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

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

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

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

    
627
    kqemu_record_flush();
628
}
629
#endif
630

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

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

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

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

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

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

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

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

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

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

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

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

    
912
#endif