Browse Source

cpuid: Now we support extended feature testing.

For now, we'll just have this and later on I'll make it support
writing it also using cpuid_write_info.

Signed-off-by: Ahmed Samy <f.fallen45@gmail.com>
Ahmed Samy 12 years ago
parent
commit
6977745243
2 changed files with 126 additions and 23 deletions
  1. 52 21
      ccan/cpuid/cpuid.c
  2. 74 2
      ccan/cpuid/cpuid.h

+ 52 - 21
ccan/cpuid/cpuid.c

@@ -151,49 +151,80 @@ bool cpuid_test_feature(cpuid_t feature)
 	return (feature <= cpuid_highest_ext_func_supported());
 }
 
-bool cpuid_has_ecxfeature(int feature)
-{
-	static uint32_t _ecx;
-	if (_ecx == 0) {
 #if defined(__GNUC__) || defined(__clang__)
+static uint32_t fetch_ecx(uint32_t what)
+{
+	static uint32_t ecx;
+	if (ecx == 0) {
 		asm volatile(
 			"cpuid\n\t"
-			: "=c" (_ecx)
-			: "a" (CPUID_PROCINFO_AND_FEATUREBITS)
+			: "=c" (ecx)
+			: "a" (what)
 		);
-#elif defined _MSC_VER
+	}
+
+	return ecx;
+}
+
+static uint32_t fetch_edx(uint32_t what)
+{
+	static uint32_t edx;
+	if (edx == 0) {
+		asm volatile(
+			"cpuid\n\t"
+			: "=d" (edx)
+			: "a" (what)
+		);
+	}
+
+	return edx;
+}
+#elif defined(_MSC_VER)
+static uint32_t fetch_ecx(uint32_t what)
+{
+	static uint32_t _ecx;
+	if (_ecx == 0) {
 		__asm {
-			mov eax, CPUID_PROCINFO_AND_FEATUREBITS
+			mov eax, what
 			cpuid
 			mov _ecx, ecx
 		};
-#endif
 	}
 
-	return (_ecx & feature) == feature;
+	return _ecx;
 }
 
-bool cpuid_has_edxfeature(int feature)
+static uint32_t fetch_edx(uint32_t what)
 {
 	static uint32_t _edx;
 	if (_edx == 0) {
-#if defined(__GNUC__) || defined(__clang__)
-		asm volatile(
-			"cpuid\n\t"
-			: "=d" (_edx)
-			: "a" (CPUID_PROCINFO_AND_FEATUREBITS)
-		);
-#elif defined _MSC_VER
 		__asm {
-			mov eax, CPUID_PROCINFO_AND_FEATUREBITS
+			mov eax, what
 			cpuid
 			mov _edx, edx
 		};
-#endif
 	}
 
-	return (_edx & feature) == feature;
+	return _edx;
 }
+#endif
+
+#define DEFINE_FEATURE_FUNC(NAME, REGISTER, TYPE) \
+	bool cpuid_has_##NAME(int feature) \
+	{ \
+		static uint32_t REGISTER; \
+		if (REGISTER == 0) \
+			REGISTER = fetch_##REGISTER(TYPE); \
+		return (REGISTER & feature) == feature; \
+	}
+
+DEFINE_FEATURE_FUNC(ecxfeature, ecx, CPUID_PROCINFO_AND_FEATUREBITS)
+DEFINE_FEATURE_FUNC(edxfeature, edx, CPUID_PROCINFO_AND_FEATUREBITS)
+
+DEFINE_FEATURE_FUNC(ecxfeature_ext, ecx, CPUID_EXTENDED_PROC_INFO_FEATURE_BITS)
+DEFINE_FEATURE_FUNC(edxfeature_ext, edx, CPUID_EXTENDED_PROC_INFO_FEATURE_BITS)
+
+#undef DEFINE_FEATURE_FUNC
 
 static const char *const cpuids[] = {
 	"Nooooooooone",

+ 74 - 2
ccan/cpuid/cpuid.h

@@ -158,6 +158,60 @@ enum {
 					| CPUID_FEAT_EDX_TM1 | CPUID_FEAT_EDX_IA64 | CPUID_FEAT_EDX_PBE
 };
 
+enum {
+	CPUID_EXTFEAT_ECX_LAHF_LM 		= 1 << 0,
+	CPUID_EXTFEAT_ECX_CMP_LEGACY 		= 1 << 1,
+	CPUID_EXTFEAT_ECX_SVM 			= 1 << 2,
+	CPUID_EXTFEAT_ECX_EXTAPIC 		= 1 << 3,
+	CPUID_EXTFEAT_ECX_CR8_LEGACY 		= 1 << 4,
+	CPUID_EXTFEAT_ECX_ABM 			= 1 << 5,
+	CPUID_EXTFEAT_ECX_SSE4A 		= 1 << 6,
+	CPUID_EXTFEAT_ECX_MISALIGNSSE 		= 1 << 7,
+	CPUID_EXTFEAT_ECX_3DNOWPREFETCH 	= 1 << 8,
+	CPUID_EXTFEAT_ECX_OSVW 			= 1 << 9,
+	CPUID_EXTFEAT_ECX_IBS 			= 1 << 10,
+	CPUID_EXTFEAT_ECX_XOP			= 1 << 11,
+	CPUID_EXTFEAT_ECX_SKINIT 		= 1 << 12,
+	CPUID_EXTFEAT_ECX_WDT 			= 1 << 13,
+	CPUID_EXTFEAT_ECX_LWP 			= 1 << 15,
+	CPUID_EXTFEAT_ECX_FMA4 			= 1 << 16,
+	CPUID_EXTFEAT_ECX_TCE 			= 1 << 17,
+	CPUID_EXTFEAT_ECX_NODEIDE_MSR 		= 1 << 19,
+	CPUID_EXTFEAT_ECX_TBM 			= 1 << 21,
+	CPUID_EXTFEAT_ECX_TOPOEXT 		= 1 << 22,
+	CPUID_EXTFEAT_ECX_PERFXTR_CORE 		= 1 << 23,
+	CPUID_EXTFEAT_ECX_PERFCTR_NB 		= 1 << 24,
+
+	CPUID_EXTFEAT_EDX_FPU 			= 1 << 0,
+	CPUID_EXTFEAT_EDX_VME 			= 1 << 1,
+	CPUID_EXTFEAT_EDX_DE 			= 1 << 2,
+	CPUID_EXTFEAT_EDX_PSE 			= 1 << 3,
+	CPUID_EXTFEAT_EDX_TSC 			= 1 << 4,
+	CPUID_EXTFEAT_EDX_MSR 			= 1 << 5,
+	CPUID_EXTFEAT_EDX_PAE 			= 1 << 6,
+	CPUID_EXTFEAT_EDX_MCE 			= 1 << 7,
+	CPUID_EXTFEAT_EDX_CX8 			= 1 << 8,
+	CPUID_EXTFEAT_EDX_APIC 			= 1 << 9,
+	CPUID_EXTFEAT_EDX_SYSCALL 		= 1 << 11,
+	CPUID_EXTFEAT_EDX_MTRR 			= 1 << 12,
+	CPUID_EXTFEAT_EDX_PGE 			= 1 << 13,
+	CPUID_EXTFEAT_EDX_MCA 			= 1 << 14,
+	CPUID_EXTFEAT_EDX_CMOV 			= 1 << 15,
+	CPUID_EXTFEAT_EDX_PAT 			= 1 << 16,
+	CPUID_EXTFEAT_EDX_PSE36 		= 1 << 17,
+	CPUID_EXTFEAT_EDX_MP 			= 1 << 19,
+	CPUID_EXTFEAT_EDX_NX 			= 1 << 20,
+	CPUID_EXTFEAT_EDX_MMXEXT 		= 1 << 22,
+	CPUID_EXTFEAT_EDX_MMX 			= 1 << 23,
+	CPUID_EXTFEAT_EDX_FXSR 			= 1 << 24,
+	CPUID_EXTFEAT_EDX_FXSR_OPT 		= 1 << 25,
+	CPUID_EXTFEAT_EDX_PDPE1GB 		= 1 << 26,
+	CPUID_EXTFEAT_EDX_RDTSCP		= 1 << 27,
+	CPUID_EXTFEAT_EDX_LM 			= 1 << 29,
+	CPUID_EXTFEAT_EDX_3DNOWEXT 		= 1 << 30,
+	CPUID_EXTFEAT_EDX_3DNOW 		= 1 << 31
+};
+
 typedef enum cputype {
 	CT_NONE,
 	CT_AMDK5,
@@ -322,14 +376,32 @@ bool cpuid_test_feature(cpuid_t feature);
  * cpuid_has_feature - Test if @feature is supported
  *
  * Test if the CPU supports MMX/SSE* etc.
- * Use cpuid_has_ecxfeature() for *_ECX* features and
- * cpuid_has_edxfeature() for *_EDX* features.
+ * This is split into two parts:
+ * 	cpuid_has_ecxfeature and
+ * 	cpuid_has_edxfeature.
+ * See the enum for more information.
+ *
  *
  * Returns true if the feature is available, false otherwise.
  */
 bool cpuid_has_ecxfeature(int feature);
 bool cpuid_has_edxfeature(int feature);
 
+/**
+ * cpuid_has_extfeature - Test if @extfeature is supported
+ * @extfeature: the extended feature to test.
+ *
+ * This is split into two parts:
+ * 	cpuid_has_ecxfeature_ext and
+ * 	cpuid_has_edxfeature_ext.
+ * See the enum for more information.
+ *
+ * Test if the CPU supports this feature.
+ * Returns true on success, false otherwise.
+ */
+bool cpuid_has_ecxfeature_ext(int extfeature);
+bool cpuid_has_edxfeature_ext(int extfeature);
+
 #else
 #include <ccan/build_assert/build_assert.h>