From: Jeremy Fitzhardinge Date: Sun, 25 Jan 2004 02:38:29 +0000 (+0000) Subject: Virtualize CPUID. Rather than just using the host CPU's CPUID, X-Git-Tag: svn/VALGRIND_2_1_1~83 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=daa694d0acaf6fe74362d8a6078cc4894150755f;p=thirdparty%2Fvalgrind.git Virtualize CPUID. Rather than just using the host CPU's CPUID, we now completely virtualize it. The feature flags returned are the intersection of the set the CPU supports, and the set of flags Valgrind supports. This turns out to be a small number of features, like FPU, TSC, MMX, SSE, SSE2, FXSR. All mention of things which are only useful to kernel-mode code are also suppressed. This CPUID doesn't support any extended feature flags, or extended CPUID operations. It returns a vendor string of "ValgrindVCPU". If the host CPU doesn't support CPUID, then we make sure we treat it as an illegal instruction (I'm not sure if we handle the eflags bit toggle test right). This is because the CPUID helper doesn't actually use the cpuid instruction in all cases, so it may succeed where the host CPU wouldn't (other instructions which depend on feature flags will end up generating those instructions, so they'll endup generating a SIGILL if client code uses them on a CPU which doesn't support them). git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2225 --- diff --git a/coregrind/vg_constants.h b/coregrind/vg_constants.h index f588fafdf1..74f3023de9 100644 --- a/coregrind/vg_constants.h +++ b/coregrind/vg_constants.h @@ -94,6 +94,53 @@ /* Assembly code stubs make this request */ #define VG_USERREQ__SIGNAL_RETURNS 0x4001 +/* CPU features */ +#define VG_X86_FEAT_FPU (0*32 + 0) +#define VG_X86_FEAT_VME (0*32 + 1) +#define VG_X86_FEAT_DE (0*32 + 2) +#define VG_X86_FEAT_PSE (0*32 + 3) +#define VG_X86_FEAT_TSC (0*32 + 4) +#define VG_X86_FEAT_MSR (0*32 + 5) +#define VG_X86_FEAT_PAE (0*32 + 6) +#define VG_X86_FEAT_MCE (0*32 + 7) +#define VG_X86_FEAT_CX8 (0*32 + 8) +#define VG_X86_FEAT_APIC (0*32 + 9) +#define VG_X86_FEAT_SEP (0*32 + 11) +#define VG_X86_FEAT_MTRR (0*32 + 12) +#define VG_X86_FEAT_PGE (0*32 + 13) +#define VG_X86_FEAT_MCA (0*32 + 14) +#define VG_X86_FEAT_CMOV (0*32 + 15) +#define VG_X86_FEAT_PAT (0*32 + 16) +#define VG_X86_FEAT_PSE36 (0*32 + 17) +#define VG_X86_FEAT_CLFSH (0*32 + 19) +#define VG_X86_FEAT_DS (0*32 + 21) +#define VG_X86_FEAT_ACPI (0*32 + 22) +#define VG_X86_FEAT_MMX (0*32 + 23) +#define VG_X86_FEAT_FXSR (0*32 + 24) +#define VG_X86_FEAT_SSE (0*32 + 25) +#define VG_X86_FEAT_SSE2 (0*32 + 26) +#define VG_X86_FEAT_SS (0*32 + 27) +#define VG_X86_FEAT_HT (0*32 + 28) +#define VG_X86_FEAT_TM (0*32 + 29) +#define VG_X86_FEAT_PBE (0*32 + 31) + +#define VG_X86_FEAT_EST (1*32 + 7) +#define VG_X86_FEAT_TM2 (1*32 + 8) +#define VG_X86_FEAT_CNXTID (1*32 + 10) + +/* Used internally to mark whether CPUID is even implemented */ +#define VG_X86_FEAT_CPUID (2*32 + 0) + +/* The set of features we're willing to support for the client */ +#define VG_SUPPORTED_FEATURES \ + ((1 << VG_X86_FEAT_FPU) | \ + (1 << VG_X86_FEAT_TSC) | \ + (1 << VG_X86_FEAT_CMOV) | \ + (1 << VG_X86_FEAT_MMX) | \ + (1 << VG_X86_FEAT_FXSR) | \ + (1 << VG_X86_FEAT_SSE) | \ + (1 << VG_X86_FEAT_SSE2)) + /* Various environment variables we pay attention to */ /* The directory we look for all our auxillary files in */ diff --git a/coregrind/vg_helpers.S b/coregrind/vg_helpers.S index f2e8cd0489..5d2c313ab6 100644 --- a/coregrind/vg_helpers.S +++ b/coregrind/vg_helpers.S @@ -193,7 +193,8 @@ out_done: For simulating the cpuid instruction, we will issue a "real" cpuid instruction and then mask out the bits of the features we do not support currently (3dnow mostly). - + We also claim to not support most CPUID operations. + Dirk Mueller http://www.sandpile.org/ia32/cpuid.htm @@ -213,19 +214,39 @@ VG_(helper_CPUID): pushl %edx movl 32(%esp), %eax - cmpl $0x80000001, %eax - je cpuid_no3dnow + /* eax==0 - max valid request+processor vendor */ + cmpl $0, %eax + jne 1f - cpuid - jmp cpuid__99 + movl $1, %eax /* only support request 1 */ + movl valgrind_brand+0, %ebx + movl valgrind_brand+4, %edx + movl valgrind_brand+8, %ecx + jmp 99f -cpuid_no3dnow: - cpuid - - andl $0x3fffffff, %edx + /* eax==1 - CPU features and model ID */ +1: cmpl $1, %eax + jne 2f + + cpuid /* get host CPU's capabilities */ + + movl $0111, %eax + movl $0, %ebx /* clear APIC id, CLFLUSH size, Brand ID */ + movl $0, %ecx /* clear extended feature bits */ + andl $VG_SUPPORTED_FEATURES, %edx /* mask off feature bits we don't support */ + jmp 99f + + /* eax=0x80000000 - extended cpuid functions */ +2: cmpl $0x80000000, %eax + jne 99f -cpuid__99: - movl %edx, 20(%esp) + /* leave eax==0x80000000 - we don't support any other extended operations */ + movl valgrind_brand+0, %ebx /* AMD load the brand string again - */ + movl valgrind_brand+4, %edx /* Intel leaves them "reserved" */ + movl valgrind_brand+8, %ecx + + +99: movl %edx, 20(%esp) movl %ecx, 24(%esp) movl %ebx, 28(%esp) movl %eax, 32(%esp) @@ -235,7 +256,10 @@ cpuid__99: popl %ebx popl %eax ret - +.data +valgrind_brand: + .ascii "ValgrindVCPU" +.text /* Fetch the FPU status register. On entry: diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index 006de0f0eb..fcb3efb543 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -1136,39 +1136,6 @@ extern Bool VG_(is_chained_jumpsite) ( Addr jumpsite ); Exports of vg_to_ucode.c ------------------------------------------------------------------ */ -#define VG_X86_FEAT_FPU (0*32 + 0) -#define VG_X86_FEAT_VME (0*32 + 1) -#define VG_X86_FEAT_DE (0*32 + 2) -#define VG_X86_FEAT_PSE (0*32 + 3) -#define VG_X86_FEAT_TSC (0*32 + 4) -#define VG_X86_FEAT_MSR (0*32 + 5) -#define VG_X86_FEAT_PAE (0*32 + 6) -#define VG_X86_FEAT_MCE (0*32 + 7) -#define VG_X86_FEAT_CX8 (0*32 + 8) -#define VG_X86_FEAT_APIC (0*32 + 9) -#define VG_X86_FEAT_SEP (0*32 + 11) -#define VG_X86_FEAT_MTRR (0*32 + 12) -#define VG_X86_FEAT_PGE (0*32 + 13) -#define VG_X86_FEAT_MCA (0*32 + 14) -#define VG_X86_FEAT_CMOV (0*32 + 15) -#define VG_X86_FEAT_PAT (0*32 + 16) -#define VG_X86_FEAT_PSE36 (0*32 + 17) -#define VG_X86_FEAT_CLFSH (0*32 + 19) -#define VG_X86_FEAT_DS (0*32 + 21) -#define VG_X86_FEAT_ACPI (0*32 + 22) -#define VG_X86_FEAT_MMX (0*32 + 23) -#define VG_X86_FEAT_FXSR (0*32 + 24) -#define VG_X86_FEAT_SSE (0*32 + 25) -#define VG_X86_FEAT_SSE2 (0*32 + 26) -#define VG_X86_FEAT_SS (0*32 + 27) -#define VG_X86_FEAT_HT (0*32 + 28) -#define VG_X86_FEAT_TM (0*32 + 29) -#define VG_X86_FEAT_PBE (0*32 + 31) - -#define VG_X86_FEAT_EST (1*32 + 7) -#define VG_X86_FEAT_TM2 (1*32 + 8) -#define VG_X86_FEAT_CNXTID (1*32 + 10) - Bool VG_(cpu_has_feature)(UInt feat); extern Int VG_(disBB) ( UCodeBlock* cb, Addr eip0 ); diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c index d8441470be..d62459ddf0 100644 --- a/coregrind/vg_to_ucode.c +++ b/coregrind/vg_to_ucode.c @@ -45,7 +45,7 @@ /*--- for now. ---*/ /*------------------------------------------------------------*/ -#define VG_N_FEATURE_WORDS 2 +#define VG_N_FEATURE_WORDS 3 static Int cpuid_level = -2; /* -2 -> not initialized */ static UInt cpu_features[VG_N_FEATURE_WORDS]; @@ -108,6 +108,8 @@ static void get_cpu_features(void) return; } + cpu_features[2] |= (1 << (VG_X86_FEAT_CPUID%32)); + cpuid_level = cpuid_eax(0); if (cpuid_level >= 1) @@ -6503,6 +6505,9 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd ) /* =-=-=-=-=-=-=-=-=- CPUID -=-=-=-=-=-=-=-=-=-=-= */ case 0xA2: /* CPUID */ + if (!VG_(cpu_has_feature)(VG_X86_FEAT_CPUID)) + goto decode_failure; + t1 = newTemp(cb); t2 = newTemp(cb); t3 = newTemp(cb);