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