helper2.c revision d65680efa46fa49e8bf14e67b29b782510ff934c
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/*
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * i386 helpers (without register variable usage)
1ce069685b24d243eb0464f46d4c56b250c64445vboxsync *
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * Copyright (c) 2003 Fabrice Bellard
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync *
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * This library is free software; you can redistribute it and/or
f6b53aa7a361c1f26a3287a95172653219470233vboxsync * modify it under the terms of the GNU Lesser General Public
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * License as published by the Free Software Foundation; either
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * version 2 of the License, or (at your option) any later version.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync *
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * This library is distributed in the hope that it will be useful,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * Lesser General Public License for more details.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync *
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * You should have received a copy of the GNU Lesser General Public
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * License along with this library; if not, write to the Free Software
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/*
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * other than GPL or LGPL is available it will apply instead, Sun elects to use only
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * a choice of LGPL license versions is made available with the language indicating
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * that LGPLv2 or any later version may be used, or where a choice of which version
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync * of the LGPL is applied is otherwise unspecified.
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#include <stdarg.h>
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#include <stdlib.h>
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#include <stdio.h>
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#include <string.h>
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#include <inttypes.h>
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#ifndef VBOX
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#include <signal.h>
9ce5d949e4f1572d445a5c0aecabe9de8b672c99vboxsync#include <assert.h>
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#else
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync# include <VBox/pgm.h> /* PGM_DYNAMIC_RAM_ALLOC */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#endif
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync#include "cpu.h"
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync#include "exec-all.h"
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync//#define DEBUG_MMU
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#ifdef USE_CODE_COPY
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#include <asm/ldt.h>
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync#include <linux/unistd.h>
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#include <linux/version.h>
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsyncint modify_ldt(int func, void *ptr, unsigned long bytecount)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync{
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync return syscall(__NR_modify_ldt, func, ptr, bytecount);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync}
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#define modify_ldt_ldt_s user_desc
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#endif
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#endif /* USE_CODE_COPY */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#ifdef VBOX
4328e87247f4a96449677e199c7e99ef516fc1cevboxsyncCPUX86State *cpu_x86_init(CPUX86State *env)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync{
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#else /* !VBOX */
376b92d26cc4fad78e813cf33afcc0784adc9b19vboxsyncCPUX86State *cpu_x86_init(void)
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync{
c970e7d40b648d5c8f3e2b060692e670d85997d1vboxsync CPUX86State *env;
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync#endif /* !VBOX */
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync static int inited;
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync#ifndef VBOX
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync env = qemu_mallocz(sizeof(CPUX86State));
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync if (!env)
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync return NULL;
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync#endif /* !VBOX */
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync cpu_exec_init(env);
376b92d26cc4fad78e813cf33afcc0784adc9b19vboxsync
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync /* init various static tables */
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync if (!inited) {
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync inited = 1;
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync optimize_flags_init();
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync }
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync#ifdef USE_CODE_COPY
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* testing code for code copy case */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync struct modify_ldt_ldt_s ldt;
0dffbbe0c5f4a9b76066b09d41ca2dca5a4ab3e6vboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ldt.entry_number = 1;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ldt.base_addr = (unsigned long)env;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ldt.seg_32bit = 1;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ldt.contents = MODIFY_LDT_CONTENTS_DATA;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ldt.read_exec_only = 0;
c970e7d40b648d5c8f3e2b060692e670d85997d1vboxsync ldt.limit_in_pages = 1;
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync ldt.seg_not_present = 0;
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync ldt.useable = 1;
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
f409459bdd4c15cdb8d7fb6c6d54338cce9ac814vboxsync#endif
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#ifndef VBOX /* cpuid_features is initialized by caller */
0dffbbe0c5f4a9b76066b09d41ca2dca5a4ab3e6vboxsync {
0dffbbe0c5f4a9b76066b09d41ca2dca5a4ab3e6vboxsync int family, model, stepping;
0dffbbe0c5f4a9b76066b09d41ca2dca5a4ab3e6vboxsync#ifdef TARGET_X86_64
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->cpuid_vendor1 = 0x68747541; /* "Auth" */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->cpuid_vendor2 = 0x69746e65; /* "enti" */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync family = 6;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync model = 2;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync stepping = 3;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#else
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#if 0
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* pentium 75-200 */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync family = 5;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync model = 2;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync stepping = 11;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#else
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* pentium pro */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync family = 6;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync model = 3;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync stepping = 3;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync#endif
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync#endif
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync env->cpuid_level = 2;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync env->cpuid_version = (family << 8) | (model << 4) | stepping;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE |
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync CPUID_TSC | CPUID_MSR | CPUID_MCE |
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync CPUID_CX8 | CPUID_PGE | CPUID_CMOV |
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync CPUID_PAT);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync env->pat = 0x0007040600070406ULL;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync env->cpuid_ext_features = CPUID_EXT_SSE3;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync env->cpuid_features |= CPUID_APIC;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync env->cpuid_xlevel = 0;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync {
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync int c, len, i;
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync len = strlen(model_id);
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync for(i = 0; i < 48; i++) {
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync if (i >= len)
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync c = '\0';
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync else
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync c = model_id[i];
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync }
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync }
6e12ccc60ac657fb87e27b7a2b26e0a63bebe024vboxsync#ifdef TARGET_X86_64
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync /* currently not enabled for std i386 because not fully tested */
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync env->cpuid_xlevel = 0x80000008;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync /* these features are needed for Win64 and aren't fully implemented */
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync /* this feature is needed for Solaris and isn't fully implemented */
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync env->cpuid_features |= CPUID_PSE36;
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync#endif
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync }
9cb702c3a5fd2287c57c7c1e98a61ba9e357b4devboxsync#endif /* VBOX */
657b2c9f6d33f08001e5fa6f6e0572dcf0391013vboxsync cpu_reset(env);
6fe1329154975472e055284198df7fa8e64dee3avboxsync#ifdef USE_KQEMU
6fe1329154975472e055284198df7fa8e64dee3avboxsync kqemu_init(env);
6fe1329154975472e055284198df7fa8e64dee3avboxsync#endif
6fe1329154975472e055284198df7fa8e64dee3avboxsync return env;
6fe1329154975472e055284198df7fa8e64dee3avboxsync}
6fe1329154975472e055284198df7fa8e64dee3avboxsync
6fe1329154975472e055284198df7fa8e64dee3avboxsync/* NOTE: must be called outside the CPU execute loop */
6fe1329154975472e055284198df7fa8e64dee3avboxsyncvoid cpu_reset(CPUX86State *env)
6fe1329154975472e055284198df7fa8e64dee3avboxsync{
6fe1329154975472e055284198df7fa8e64dee3avboxsync int i;
6fe1329154975472e055284198df7fa8e64dee3avboxsync
6fe1329154975472e055284198df7fa8e64dee3avboxsync memset(env, 0, offsetof(CPUX86State, breakpoints));
6fe1329154975472e055284198df7fa8e64dee3avboxsync
6fe1329154975472e055284198df7fa8e64dee3avboxsync tlb_flush(env, 1);
6fe1329154975472e055284198df7fa8e64dee3avboxsync
6fe1329154975472e055284198df7fa8e64dee3avboxsync /* init to reset state */
6fe1329154975472e055284198df7fa8e64dee3avboxsync
6fe1329154975472e055284198df7fa8e64dee3avboxsync#ifdef CONFIG_SOFTMMU
6fe1329154975472e055284198df7fa8e64dee3avboxsync env->hflags |= HF_SOFTMMU_MASK;
6fe1329154975472e055284198df7fa8e64dee3avboxsync#endif
6fe1329154975472e055284198df7fa8e64dee3avboxsync
6fe1329154975472e055284198df7fa8e64dee3avboxsync cpu_x86_update_cr0(env, 0x60000010);
6fe1329154975472e055284198df7fa8e64dee3avboxsync env->a20_mask = 0xffffffff;
6fe1329154975472e055284198df7fa8e64dee3avboxsync env->smbase = 0x30000;
6fe1329154975472e055284198df7fa8e64dee3avboxsync
6fe1329154975472e055284198df7fa8e64dee3avboxsync env->idt.limit = 0xffff;
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync env->gdt.limit = 0xffff;
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync env->ldt.limit = 0xffff;
6fe1329154975472e055284198df7fa8e64dee3avboxsync env->ldt.flags = DESC_P_MASK;
6fe1329154975472e055284198df7fa8e64dee3avboxsync env->tr.limit = 0xffff;
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync env->tr.flags = DESC_P_MASK;
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0);
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync
069b9101fbd3b049610c5511b1cc9534d01ea472vboxsync env->eip = 0xfff0;
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync env->regs[R_EDX] = 0x600; /* indicate P6 processor */
069b9101fbd3b049610c5511b1cc9534d01ea472vboxsync
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync env->eflags = 0x2;
069b9101fbd3b049610c5511b1cc9534d01ea472vboxsync
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync /* FPU init */
069b9101fbd3b049610c5511b1cc9534d01ea472vboxsync for(i = 0;i < 8; i++)
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync env->fptags[i] = 1;
069b9101fbd3b049610c5511b1cc9534d01ea472vboxsync env->fpuc = 0x37f;
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync env->mxcsr = 0x1f80;
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync}
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync#ifndef VBOX
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsyncvoid cpu_x86_close(CPUX86State *env)
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync{
069b9101fbd3b049610c5511b1cc9534d01ea472vboxsync free(env);
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync}
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync#endif
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync/***********************************************************/
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync/* x86 debug */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsyncstatic const char *cc_op_str[] = {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "DYNAMIC",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "EFLAGS",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
ae16af2d7d3c99d359094a7f19f5937efc2e66bdvboxsync "MULB",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "MULW",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "MULL",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "MULQ",
ae017640afff8b6cc50453182a4edf2eb0903a12vboxsync
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "ADDB",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "ADDW",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "ADDL",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "ADDQ",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "ADCB",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "ADCW",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "ADCL",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "ADCQ",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync
8b7ee9f7ebabcdbf40fececa0d6321d97d5143d8vboxsync "SUBB",
8b7ee9f7ebabcdbf40fececa0d6321d97d5143d8vboxsync "SUBW",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "SUBL",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "SUBQ",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync
31a693ce9a8a9ebbecdcea9f24ce7f912aef4cd1vboxsync "SBBB",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "SBBW",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "SBBL",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "SBBQ",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "LOGICB",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "LOGICW",
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "LOGICL",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "LOGICQ",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync
7e837ad8d6aeb3f86520ea7adb61e4eb15f2087evboxsync "INCB",
ae017640afff8b6cc50453182a4edf2eb0903a12vboxsync "INCW",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "INCL",
b986941f0aa5155c7fd37da0aa5876675a7680e4vboxsync "INCQ",
b986941f0aa5155c7fd37da0aa5876675a7680e4vboxsync
b986941f0aa5155c7fd37da0aa5876675a7680e4vboxsync "DECB",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "DECW",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "DECL",
b986941f0aa5155c7fd37da0aa5876675a7680e4vboxsync "DECQ",
b986941f0aa5155c7fd37da0aa5876675a7680e4vboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "SHLB",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "SHLW",
ae16af2d7d3c99d359094a7f19f5937efc2e66bdvboxsync "SHLL",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "SHLQ",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "SARB",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "SARW",
cdf129515a2b03bc9d122091ce7656d6e6934cc7vboxsync "SARL",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "SARQ",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync};
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsyncvoid cpu_dump_state(CPUState *env, FILE *f,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync int flags)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync{
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync int eflags, i, nb;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync char cc_op_name[32];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
29d55b79593710186ceda5a557fdab1727972175vboxsync eflags = env->eflags;
29d55b79593710186ceda5a557fdab1727972175vboxsync#ifdef TARGET_X86_64
29d55b79593710186ceda5a557fdab1727972175vboxsync if (env->hflags & HF_CS64_MASK) {
29d55b79593710186ceda5a557fdab1727972175vboxsync cpu_fprintf(f,
29d55b79593710186ceda5a557fdab1727972175vboxsync "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
29d55b79593710186ceda5a557fdab1727972175vboxsync "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
29d55b79593710186ceda5a557fdab1727972175vboxsync "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
29d55b79593710186ceda5a557fdab1727972175vboxsync "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[R_EAX],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[R_EBX],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[R_ECX],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[R_EDX],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[R_ESI],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[R_EDI],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[R_EBP],
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync env->regs[R_ESP],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[8],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[9],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[10],
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync env->regs[11],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[12],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[13],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[14],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->regs[15],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->eip, eflags,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync eflags & DF_MASK ? 'D' : '-',
42aef05f4b27fb393967e581be04be455064c80avboxsync eflags & CC_O ? 'O' : '-',
42aef05f4b27fb393967e581be04be455064c80avboxsync eflags & CC_S ? 'S' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync eflags & CC_Z ? 'Z' : '-',
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync eflags & CC_A ? 'A' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync eflags & CC_P ? 'P' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync eflags & CC_C ? 'C' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->hflags & HF_CPL_MASK,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync (env->a20_mask >> 20) & 1,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (env->hflags >> HF_SMM_SHIFT) & 1,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (env->hflags >> HF_HALTED_SHIFT) & 1);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync#endif
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->regs[R_EAX],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->regs[R_EBX],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->regs[R_ECX],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->regs[R_EDX],
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync (uint32_t)env->regs[R_ESI],
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync (uint32_t)env->regs[R_EDI],
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync (uint32_t)env->regs[R_EBP],
29d55b79593710186ceda5a557fdab1727972175vboxsync (uint32_t)env->regs[R_ESP],
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync (uint32_t)env->eip, eflags,
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync eflags & DF_MASK ? 'D' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync eflags & CC_O ? 'O' : '-',
3a8aa22ef125135ef67bfc396771bcee15ef02dfvboxsync eflags & CC_S ? 'S' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync eflags & CC_Z ? 'Z' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync eflags & CC_A ? 'A' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync eflags & CC_P ? 'P' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync eflags & CC_C ? 'C' : '-',
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->hflags & HF_CPL_MASK,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (env->a20_mask >> 20) & 1,
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync (env->hflags >> HF_SMM_SHIFT) & 1,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (env->hflags >> HF_HALTED_SHIFT) & 1);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#ifdef TARGET_X86_64
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (env->hflags & HF_LMA_MASK) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync for(i = 0; i < 6; i++) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync SegmentCache *sc = &env->segs[i];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync seg_name[i],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync sc->selector,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync sc->base,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync sc->limit,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync sc->flags);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->ldt.selector,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->ldt.base,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->ldt.limit,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->ldt.flags);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->tr.selector,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->tr.base,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->tr.limit,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->tr.flags);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->gdt.base, env->gdt.limit);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
e48239695d41f806ff02d8a60b97dc20d4822d7avboxsync env->idt.base, env->idt.limit);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->cr[0],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->cr[2],
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync env->cr[3],
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync (uint32_t)env->cr[4]);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#endif
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync for(i = 0; i < 6; i++) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync SegmentCache *sc = &env->segs[i];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync seg_name[i],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync sc->selector,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)sc->base,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync sc->limit,
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync sc->flags);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->ldt.selector,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->ldt.base,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->ldt.limit,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->ldt.flags);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->tr.selector,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->tr.base,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->tr.limit,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->tr.flags);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "GDT= %08x %08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->gdt.base, env->gdt.limit);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "IDT= %08x %08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->idt.base, env->idt.limit);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->cr[0],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->cr[2],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->cr[3],
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->cr[4]);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (flags & X86_DUMP_CCOP) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if ((unsigned)env->cc_op < CC_OP_NB)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync qemu_snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync else
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync qemu_snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#ifdef TARGET_X86_64
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (env->hflags & HF_CS64_MASK) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->cc_src, env->cc_dst,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cc_op_name);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync#endif
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync cc_op_name);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (flags & X86_DUMP_FPU) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync int fptag;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync fptag = 0;
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync for(i = 0; i < 8; i++) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync fptag |= ((!env->fptags[i]) << i);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->fpuc,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->fpstt,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync fptag,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->mxcsr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync for(i=0;i<8;i++) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#if defined(USE_X86LDOUBLE)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync union {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync long double d;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync struct {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync uint64_t lower;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync uint16_t upper;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } l;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } tmp;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync tmp.d = env->fpregs[i].d;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync i, tmp.l.lower, tmp.l.upper);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#else
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "FPR%d=%016" PRIx64,
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync i, env->fpregs[i].mmx.q);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#endif
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if ((i & 1) == 1)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "\n");
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync else
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, " ");
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (env->hflags & HF_CS64_MASK)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync nb = 16;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync else
e48239695d41f806ff02d8a60b97dc20d4822d7avboxsync nb = 8;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync for(i=0;i<nb;i++) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync i,
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync env->xmm_regs[i].XMM_L(3),
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync env->xmm_regs[i].XMM_L(2),
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->xmm_regs[i].XMM_L(1),
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->xmm_regs[i].XMM_L(0));
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if ((i & 1) == 1)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync cpu_fprintf(f, "\n");
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync else
4f3d37f3c8ea851c3d57304fac430764b77a84dcvboxsync cpu_fprintf(f, " ");
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync }
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync }
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync}
89aedeb1d8af54aba6ae46dbbd256281315c1be6vboxsync
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync/***********************************************************/
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync/* x86 mmu */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync/* XXX: add PGE support */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsyncvoid cpu_x86_set_a20(CPUX86State *env, int a20_state)
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync{
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync a20_state = (a20_state != 0);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync if (a20_state != ((env->a20_mask >> 20) & 1)) {
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#if defined(DEBUG_MMU)
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync printf("A20 update: a20=%d\n", a20_state);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#endif
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* if the cpu is currently executing code, we must unlink it and
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync all the potentially executing TB */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* when a20 is changed, all the MMU mappings are invalid, so
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync we must flush everything */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync tlb_flush(env, 1);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->a20_mask = 0xffefffff | (a20_state << 20);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync }
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync}
885f154412c8dc99c44809cf0d5b7f07342a455evboxsync
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsyncvoid cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync{
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync int pe_state;
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#if defined(DEBUG_MMU)
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync printf("CR0 update: CR0=0x%08x\n", new_cr0);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#endif
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
4f3d37f3c8ea851c3d57304fac430764b77a84dcvboxsync (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync tlb_flush(env, 1);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync }
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#ifdef TARGET_X86_64
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync (env->efer & MSR_EFER_LME)) {
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* enter in long mode */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* XXX: generate an exception */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync if (!(env->cr[4] & CR4_PAE_MASK))
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync return;
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->efer |= MSR_EFER_LMA;
8ccde4f32d77b1ad3f02111f28a48ee85abf6779vboxsync env->hflags |= HF_LMA_MASK;
8ccde4f32d77b1ad3f02111f28a48ee85abf6779vboxsync } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync (env->efer & MSR_EFER_LMA)) {
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* exit long mode */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->efer &= ~MSR_EFER_LMA;
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->eip &= 0xffffffff;
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync }
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#endif
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->cr[0] = new_cr0 | CR0_ET_MASK;
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* update PE flag in hidden flags */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync pe_state = (env->cr[0] & CR0_PE_MASK);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* ensure that ADDSEG is always set in real mode */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* update FPU flags */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#ifdef VBOX
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync remR3ChangeCpuMode(env);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#endif
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync}
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync the PDPT */
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsyncvoid cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync{
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync env->cr[3] = new_cr3;
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync if (env->cr[0] & CR0_PG_MASK) {
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#if defined(DEBUG_MMU)
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#endif
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync tlb_flush(env, 0);
8ccde4f32d77b1ad3f02111f28a48ee85abf6779vboxsync }
8ccde4f32d77b1ad3f02111f28a48ee85abf6779vboxsync}
8ccde4f32d77b1ad3f02111f28a48ee85abf6779vboxsync
8ccde4f32d77b1ad3f02111f28a48ee85abf6779vboxsyncvoid cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
8ccde4f32d77b1ad3f02111f28a48ee85abf6779vboxsync{
8ccde4f32d77b1ad3f02111f28a48ee85abf6779vboxsync#if defined(DEBUG_MMU)
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync#endif
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync tlb_flush(env, 1);
0dffbbe0c5f4a9b76066b09d41ca2dca5a4ab3e6vboxsync }
b4bcdbd7ac35c938e6f71a6403fe9f3ebf106a07vboxsync /* SSE handling */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (!(env->cpuid_features & CPUID_SSE))
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync new_cr4 &= ~CR4_OSFXSR_MASK;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (new_cr4 & CR4_OSFXSR_MASK)
885f154412c8dc99c44809cf0d5b7f07342a455evboxsync env->hflags |= HF_OSFXSR_MASK;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync else
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync env->hflags &= ~HF_OSFXSR_MASK;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync env->cr[4] = new_cr4;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync#ifdef VBOX
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync remR3ChangeCpuMode(env);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync#endif
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync}
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync/* XXX: also flush 4MB pages */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsyncvoid cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync{
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync#if defined(DEBUG) && defined(VBOX)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync uint32_t pde;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync /* page directory entry */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pde = remR3PhysReadU32(((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync /* if PSE bit is set, then we use a 4MB page */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync printf("cpu_x86_flush_tlb: 4 MB page!!!!!\n");
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync#endif
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync tlb_flush_page(env, addr);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync}
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync#if defined(CONFIG_USER_ONLY)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsyncint cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync int is_write, int is_user, int is_softmmu)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync{
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync /* user mode only emulation */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync is_write &= 1;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync env->cr[2] = addr;
0dffbbe0c5f4a9b76066b09d41ca2dca5a4ab3e6vboxsync env->error_code = (is_write << PG_ERROR_W_BIT);
0dffbbe0c5f4a9b76066b09d41ca2dca5a4ab3e6vboxsync env->error_code |= PG_ERROR_U_MASK;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync env->exception_index = EXCP0E_PAGE;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync return 1;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync}
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsynctarget_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync{
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync return addr;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync}
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync#else
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync#define PHYS_ADDR_MASK 0xfffff000
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync/* return value:
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync -1 = cannot handle fault
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync 0 = nothing more to do
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync 1 = generate PF fault
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync 2 = soft MMU activation required for this block
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync*/
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsyncint cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync int is_write1, int is_user, int is_softmmu)
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync{
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync uint64_t ptep, pte;
885f154412c8dc99c44809cf0d5b7f07342a455evboxsync uint32_t pdpe_addr, pde_addr, pte_addr;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync int error_code, is_dirty, prot, page_size, ret, is_write;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync unsigned long paddr, page_offset;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync target_ulong vaddr, virt_addr;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync#if defined(DEBUG_MMU)
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync addr, is_write1, is_user, env->eip);
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync#endif
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync is_write = is_write1 & 1;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync if (!(env->cr[0] & CR0_PG_MASK)) {
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync pte = addr;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync virt_addr = addr & TARGET_PAGE_MASK;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync page_size = 4096;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync goto do_mapping;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync }
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync if (env->cr[4] & CR4_PAE_MASK) {
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync uint64_t pde, pdpe;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync /* XXX: we only use 32 bit physical addresses */
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync#ifdef TARGET_X86_64
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync if (env->hflags & HF_LMA_MASK) {
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync uint32_t pml4e_addr;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync uint64_t pml4e;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync int32_t sext;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync /* test virtual address sign extension */
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync sext = (int64_t)addr >> 47;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync if (sext != 0 && sext != -1) {
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync env->error_code = 0;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync env->exception_index = EXCP0D_GPF;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync return 1;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync }
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync env->a20_mask;
0dffbbe0c5f4a9b76066b09d41ca2dca5a4ab3e6vboxsync pml4e = ldq_phys(pml4e_addr);
0dffbbe0c5f4a9b76066b09d41ca2dca5a4ab3e6vboxsync if (!(pml4e & PG_PRESENT_MASK)) {
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync error_code = 0;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync goto do_fault;
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync }
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
a38afdea3cc827dc5964b4ba39a5cae6dbae23bdvboxsync error_code = PG_ERROR_RSVD_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pml4e & PG_ACCESSED_MASK)) {
885f154412c8dc99c44809cf0d5b7f07342a455evboxsync pml4e |= PG_ACCESSED_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync stl_phys_notdirty(pml4e_addr, pml4e);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ptep = pml4e ^ PG_NX_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->a20_mask;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pdpe = ldq_phys(pdpe_addr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pdpe & PG_PRESENT_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync error_code = 0;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync error_code = PG_ERROR_RSVD_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ptep &= pdpe ^ PG_NX_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pdpe & PG_ACCESSED_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pdpe |= PG_ACCESSED_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync stl_phys_notdirty(pdpe_addr, pdpe);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#endif
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* XXX: load them when cr3 is loaded ? */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->a20_mask;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pdpe = ldq_phys(pdpe_addr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pdpe & PG_PRESENT_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync error_code = 0;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->a20_mask;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pde = ldq_phys(pde_addr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pde & PG_PRESENT_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync error_code = 0;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync error_code = PG_ERROR_RSVD_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync ptep &= pde ^ PG_NX_MASK;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (pde & PG_PSE_MASK) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* 2 MB page */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync page_size = 2048 * 1024;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ptep ^= PG_NX_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if ((ptep & PG_NX_MASK) && is_write1 == 2)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault_protect;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (is_user) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(ptep & PG_USER_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault_protect;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (is_write && !(ptep & PG_RW_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault_protect;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync } else {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if ((env->cr[0] & CR0_WP_MASK) &&
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync is_write && !(ptep & PG_RW_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault_protect;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync is_dirty = is_write && !(pde & PG_DIRTY_MASK);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pde |= PG_ACCESSED_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (is_dirty)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pde |= PG_DIRTY_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync stl_phys_notdirty(pde_addr, pde);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* align to page_size */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync virt_addr = addr & ~(page_size - 1);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* 4 KB page */
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (!(pde & PG_ACCESSED_MASK)) {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pde |= PG_ACCESSED_MASK;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync stl_phys_notdirty(pde_addr, pde);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync env->a20_mask;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pte = ldq_phys(pte_addr);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (!(pte & PG_PRESENT_MASK)) {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync error_code = 0;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync goto do_fault;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync error_code = PG_ERROR_RSVD_MASK;
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync goto do_fault;
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync }
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync /* combine pde and pte nx, user and rw protections */
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync ptep &= pte ^ PG_NX_MASK;
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync ptep ^= PG_NX_MASK;
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync if ((ptep & PG_NX_MASK) && is_write1 == 2)
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync goto do_fault_protect;
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync if (is_user) {
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync if (!(ptep & PG_USER_MASK))
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync goto do_fault_protect;
4b9a9888c020ed3508c8ac3a5b47842d6aa3f8d2vboxsync if (is_write && !(ptep & PG_RW_MASK))
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync goto do_fault_protect;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync } else {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if ((env->cr[0] & CR0_WP_MASK) &&
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync is_write && !(ptep & PG_RW_MASK))
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync goto do_fault_protect;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync }
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync is_dirty = is_write && !(pte & PG_DIRTY_MASK);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pte |= PG_ACCESSED_MASK;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync if (is_dirty)
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pte |= PG_DIRTY_MASK;
56349fc0a23f96f82208016f8f59f8377bb284b1vboxsync stl_phys_notdirty(pte_addr, pte);
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync page_size = 4096;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync virt_addr = addr & ~0xfff;
e48239695d41f806ff02d8a60b97dc20d4822d7avboxsync pte = pte & (PHYS_ADDR_MASK | 0xfff);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync uint32_t pde;
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync /* page directory entry */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->a20_mask;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync pde = ldl_phys(pde_addr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pde & PG_PRESENT_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync error_code = 0;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync goto do_fault;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* if PSE bit is set, then we use a 4MB page */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
3933885bc0c2c93436d858a14564c6179ec72872vboxsync page_size = 4096 * 1024;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (is_user) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pde & PG_USER_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault_protect;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (is_write && !(pde & PG_RW_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault_protect;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if ((env->cr[0] & CR0_WP_MASK) &&
3933885bc0c2c93436d858a14564c6179ec72872vboxsync is_write && !(pde & PG_RW_MASK))
3933885bc0c2c93436d858a14564c6179ec72872vboxsync goto do_fault_protect;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync }
3933885bc0c2c93436d858a14564c6179ec72872vboxsync is_dirty = is_write && !(pde & PG_DIRTY_MASK);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pde |= PG_ACCESSED_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (is_dirty)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync pde |= PG_DIRTY_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync stl_phys_notdirty(pde_addr, pde);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
3933885bc0c2c93436d858a14564c6179ec72872vboxsync pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ptep = pte;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync virt_addr = addr & ~(page_size - 1);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else {
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (!(pde & PG_ACCESSED_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pde |= PG_ACCESSED_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync stl_phys_notdirty(pde_addr, pde);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync /* page directory entry */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->a20_mask;
36a04912b64bea8318327fe0723535f1b3f041b0vboxsync pte = ldl_phys(pte_addr);
36a04912b64bea8318327fe0723535f1b3f041b0vboxsync if (!(pte & PG_PRESENT_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync error_code = 0;
36a04912b64bea8318327fe0723535f1b3f041b0vboxsync goto do_fault;
36a04912b64bea8318327fe0723535f1b3f041b0vboxsync }
36a04912b64bea8318327fe0723535f1b3f041b0vboxsync /* combine pde and pte user and rw protections */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ptep = pte & pde;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (is_user) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(ptep & PG_USER_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault_protect;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (is_write && !(ptep & PG_RW_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync goto do_fault_protect;
a72b5355eb89aafe6bfcc8912cf02645d7cccceavboxsync } else {
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if ((env->cr[0] & CR0_WP_MASK) &&
3933885bc0c2c93436d858a14564c6179ec72872vboxsync is_write && !(ptep & PG_RW_MASK))
3933885bc0c2c93436d858a14564c6179ec72872vboxsync goto do_fault_protect;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync is_dirty = is_write && !(pte & PG_DIRTY_MASK);
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pte |= PG_ACCESSED_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (is_dirty)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync pte |= PG_DIRTY_MASK;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync stl_phys_notdirty(pte_addr, pte);
3933885bc0c2c93436d858a14564c6179ec72872vboxsync }
3933885bc0c2c93436d858a14564c6179ec72872vboxsync page_size = 4096;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync virt_addr = addr & ~0xfff;
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync }
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync }
3933885bc0c2c93436d858a14564c6179ec72872vboxsync /* the page can be put in the TLB */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync prot = PAGE_READ;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (!(ptep & PG_NX_MASK))
3933885bc0c2c93436d858a14564c6179ec72872vboxsync prot |= PAGE_EXEC;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (pte & PG_DIRTY_MASK) {
3933885bc0c2c93436d858a14564c6179ec72872vboxsync /* only set write access if already dirty... otherwise wait
3933885bc0c2c93436d858a14564c6179ec72872vboxsync for dirty access */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (is_user) {
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (ptep & PG_RW_MASK)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync prot |= PAGE_WRITE;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync } else {
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (!(env->cr[0] & CR0_WP_MASK) ||
3933885bc0c2c93436d858a14564c6179ec72872vboxsync (ptep & PG_RW_MASK))
3933885bc0c2c93436d858a14564c6179ec72872vboxsync prot |= PAGE_WRITE;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync }
3933885bc0c2c93436d858a14564c6179ec72872vboxsync }
3933885bc0c2c93436d858a14564c6179ec72872vboxsync do_mapping:
3933885bc0c2c93436d858a14564c6179ec72872vboxsync pte = pte & env->a20_mask;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync
060f7ec6ae5c99df18341ef2e1f3e91f4b0c89f1vboxsync /* Even if 4MB pages, we map only one 4KB page in the cache to
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync avoid filling it too fast */
060f7ec6ae5c99df18341ef2e1f3e91f4b0c89f1vboxsync page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync paddr = (pte & TARGET_PAGE_MASK) + page_offset;
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync vaddr = virt_addr + page_offset;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
cc74f15083bf80fbc96723a89faa06c15d0dead8vboxsync return ret;
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync do_fault_protect:
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync error_code = PG_ERROR_P_MASK;
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync do_fault:
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync env->cr[2] = addr;
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync error_code |= (is_write << PG_ERROR_W_BIT);
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync if (is_user)
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync error_code |= PG_ERROR_U_MASK;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (is_write1 == 2 &&
3933885bc0c2c93436d858a14564c6179ec72872vboxsync (env->efer & MSR_EFER_NXE) &&
3933885bc0c2c93436d858a14564c6179ec72872vboxsync (env->cr[4] & CR4_PAE_MASK))
3933885bc0c2c93436d858a14564c6179ec72872vboxsync error_code |= PG_ERROR_I_D_MASK;
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync env->error_code = error_code;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync env->exception_index = EXCP0E_PAGE;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return 1;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync}
3933885bc0c2c93436d858a14564c6179ec72872vboxsync
3933885bc0c2c93436d858a14564c6179ec72872vboxsynctarget_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync{
3933885bc0c2c93436d858a14564c6179ec72872vboxsync uint32_t pde_addr, pte_addr;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync uint32_t pde, pte, paddr, page_offset, page_size;
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (env->cr[4] & CR4_PAE_MASK) {
3933885bc0c2c93436d858a14564c6179ec72872vboxsync uint32_t pdpe_addr, pde_addr, pte_addr;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync uint32_t pdpe;
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync
f80ead6d4496030f4b89cfcbd3a1569c8f39f7cevboxsync /* XXX: we only use 32 bit physical addresses */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync#ifdef TARGET_X86_64
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (env->hflags & HF_LMA_MASK) {
3933885bc0c2c93436d858a14564c6179ec72872vboxsync uint32_t pml4e_addr, pml4e;
aa0553becec2abc2e781f839ba1d399c31c2c07fvboxsync int32_t sext;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync
3933885bc0c2c93436d858a14564c6179ec72872vboxsync /* test virtual address sign extension */
3933885bc0c2c93436d858a14564c6179ec72872vboxsync sext = (int64_t)addr >> 47;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (sext != 0 && sext != -1)
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return -1;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync
3933885bc0c2c93436d858a14564c6179ec72872vboxsync pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
3933885bc0c2c93436d858a14564c6179ec72872vboxsync env->a20_mask;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync pml4e = ldl_phys(pml4e_addr);
3933885bc0c2c93436d858a14564c6179ec72872vboxsync if (!(pml4e & PG_PRESENT_MASK))
3933885bc0c2c93436d858a14564c6179ec72872vboxsync return -1;
3933885bc0c2c93436d858a14564c6179ec72872vboxsync
3933885bc0c2c93436d858a14564c6179ec72872vboxsync pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync env->a20_mask;
70ca8d009d026a301bf7fa08cd18c6494c45fdeevboxsync pdpe = ldl_phys(pdpe_addr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pdpe & PG_PRESENT_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync return -1;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync#endif
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->a20_mask;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pdpe = ldl_phys(pdpe_addr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pdpe & PG_PRESENT_MASK))
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync return -1;
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync }
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync env->a20_mask;
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync pde = ldl_phys(pde_addr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pde & PG_PRESENT_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync return -1;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync if (pde & PG_PSE_MASK) {
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync /* 2 MB page */
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync page_size = 2048 * 1024;
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync } else {
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync /* 4 KB page */
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync env->a20_mask;
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync page_size = 4096;
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync pte = ldl_phys(pte_addr);
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync }
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync } else {
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync if (!(env->cr[0] & CR0_PG_MASK)) {
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync pte = addr;
501181107e73684ab109521ba371063734cd1d76vboxsync page_size = 4096;
501181107e73684ab109521ba371063734cd1d76vboxsync } else {
501181107e73684ab109521ba371063734cd1d76vboxsync /* page directory entry */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pde = ldl_phys(pde_addr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pde & PG_PRESENT_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync return -1;
c970e7d40b648d5c8f3e2b060692e670d85997d1vboxsync if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pte = pde & ~0x003ff000; /* align to 4MB */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync page_size = 4096 * 1024;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync } else {
c970e7d40b648d5c8f3e2b060692e670d85997d1vboxsync /* page directory entry */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync pte = ldl_phys(pte_addr);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync if (!(pte & PG_PRESENT_MASK))
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync return -1;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync page_size = 4096;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync pte = pte & env->a20_mask;
c970e7d40b648d5c8f3e2b060692e670d85997d1vboxsync }
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync paddr = (pte & TARGET_PAGE_MASK) + page_offset;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync return paddr;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync}
501181107e73684ab109521ba371063734cd1d76vboxsync#endif /* !CONFIG_USER_ONLY */
501181107e73684ab109521ba371063734cd1d76vboxsync
501181107e73684ab109521ba371063734cd1d76vboxsync#if defined(USE_CODE_COPY)
501181107e73684ab109521ba371063734cd1d76vboxsyncstruct fpstate {
501181107e73684ab109521ba371063734cd1d76vboxsync uint16_t fpuc;
501181107e73684ab109521ba371063734cd1d76vboxsync uint16_t dummy1;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync uint16_t fpus;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync uint16_t dummy2;
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync uint16_t fptag;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync uint16_t dummy3;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
c970e7d40b648d5c8f3e2b060692e670d85997d1vboxsync uint32_t fpip;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync uint32_t fpcs;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync uint32_t fpoo;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync uint32_t fpos;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync uint8_t fpregs1[8 * 10];
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync};
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
28ae9ced88db55943497a8bb98682bc2be513476vboxsyncvoid restore_native_fp_state(CPUState *env)
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync{
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync int fptag, i, j;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync struct fpstate fp1, *fp = &fp1;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync fp->fpuc = env->fpuc;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync fptag = 0;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync for (i=7; i>=0; i--) {
28ae9ced88db55943497a8bb98682bc2be513476vboxsync fptag <<= 2;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync if (env->fptags[i]) {
28ae9ced88db55943497a8bb98682bc2be513476vboxsync fptag |= 3;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync } else {
28ae9ced88db55943497a8bb98682bc2be513476vboxsync /* the FPU automatically computes it */
28ae9ced88db55943497a8bb98682bc2be513476vboxsync }
28ae9ced88db55943497a8bb98682bc2be513476vboxsync }
28ae9ced88db55943497a8bb98682bc2be513476vboxsync fp->fptag = fptag;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync j = env->fpstt;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync for(i = 0;i < 8; i++) {
28ae9ced88db55943497a8bb98682bc2be513476vboxsync memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
28ae9ced88db55943497a8bb98682bc2be513476vboxsync j = (j + 1) & 7;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync }
28ae9ced88db55943497a8bb98682bc2be513476vboxsync asm volatile ("frstor %0" : "=m" (*fp));
28ae9ced88db55943497a8bb98682bc2be513476vboxsync env->native_fp_regs = 1;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync}
28ae9ced88db55943497a8bb98682bc2be513476vboxsync
28ae9ced88db55943497a8bb98682bc2be513476vboxsyncvoid save_native_fp_state(CPUState *env)
28ae9ced88db55943497a8bb98682bc2be513476vboxsync{
28ae9ced88db55943497a8bb98682bc2be513476vboxsync int fptag, i, j;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync uint16_t fpuc;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync struct fpstate fp1, *fp = &fp1;
28ae9ced88db55943497a8bb98682bc2be513476vboxsync
28ae9ced88db55943497a8bb98682bc2be513476vboxsync asm volatile ("fsave %0" : : "m" (*fp));
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync env->fpuc = fp->fpuc;
03a954338932c2b34361f1d27ae2029828db0958vboxsync env->fpstt = (fp->fpus >> 11) & 7;
03a954338932c2b34361f1d27ae2029828db0958vboxsync env->fpus = fp->fpus & ~0x3800;
03a954338932c2b34361f1d27ae2029828db0958vboxsync fptag = fp->fptag;
03a954338932c2b34361f1d27ae2029828db0958vboxsync for(i = 0;i < 8; i++) {
29d55b79593710186ceda5a557fdab1727972175vboxsync env->fptags[i] = ((fptag & 3) == 3);
03a954338932c2b34361f1d27ae2029828db0958vboxsync fptag >>= 2;
03a954338932c2b34361f1d27ae2029828db0958vboxsync }
03a954338932c2b34361f1d27ae2029828db0958vboxsync j = env->fpstt;
03a954338932c2b34361f1d27ae2029828db0958vboxsync for(i = 0;i < 8; i++) {
03a954338932c2b34361f1d27ae2029828db0958vboxsync memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
03a954338932c2b34361f1d27ae2029828db0958vboxsync j = (j + 1) & 7;
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync }
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* we must restore the default rounding state */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync /* XXX: we do not restore the exception state */
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync fpuc = 0x037f | (env->fpuc & (3 << 10));
5af5f66dd66e8ed177bcb8b429a1c2f3093ab406vboxsync asm volatile("fldcw %0" : : "m" (fpuc));
5af5f66dd66e8ed177bcb8b429a1c2f3093ab406vboxsync env->native_fp_regs = 0;
5af5f66dd66e8ed177bcb8b429a1c2f3093ab406vboxsync}
5af5f66dd66e8ed177bcb8b429a1c2f3093ab406vboxsync#endif
4328e87247f4a96449677e199c7e99ef516fc1cevboxsync