| 1 | /* | 
|---|
| 2 | *	Routines to identify additional cpu features that are scattered in | 
|---|
| 3 | *	cpuid space. | 
|---|
| 4 | */ | 
|---|
| 5 | #include <linux/cpu.h> | 
|---|
| 6 |  | 
|---|
| 7 | #include <asm/memtype.h> | 
|---|
| 8 | #include <asm/apic.h> | 
|---|
| 9 | #include <asm/processor.h> | 
|---|
| 10 |  | 
|---|
| 11 | #include "cpu.h" | 
|---|
| 12 |  | 
|---|
| 13 | struct cpuid_bit { | 
|---|
| 14 | u16 feature; | 
|---|
| 15 | u8 reg; | 
|---|
| 16 | u8 bit; | 
|---|
| 17 | u32 level; | 
|---|
| 18 | u32 sub_leaf; | 
|---|
| 19 | }; | 
|---|
| 20 |  | 
|---|
| 21 | /* | 
|---|
| 22 | * Please keep the leaf sorted by cpuid_bit.level for faster search. | 
|---|
| 23 | * X86_FEATURE_MBA is supported by both Intel and AMD. But the CPUID | 
|---|
| 24 | * levels are different and there is a separate entry for each. | 
|---|
| 25 | */ | 
|---|
| 26 | static const struct cpuid_bit cpuid_bits[] = { | 
|---|
| 27 | { X86_FEATURE_APERFMPERF,		CPUID_ECX,  0, 0x00000006, 0 }, | 
|---|
| 28 | { X86_FEATURE_EPB,			CPUID_ECX,  3, 0x00000006, 0 }, | 
|---|
| 29 | { X86_FEATURE_INTEL_PPIN,		CPUID_EBX,  0, 0x00000007, 1 }, | 
|---|
| 30 | { X86_FEATURE_MSR_IMM,			CPUID_ECX,  5, 0x00000007, 1 }, | 
|---|
| 31 | { X86_FEATURE_APX,			CPUID_EDX, 21, 0x00000007, 1 }, | 
|---|
| 32 | { X86_FEATURE_RRSBA_CTRL,		CPUID_EDX,  2, 0x00000007, 2 }, | 
|---|
| 33 | { X86_FEATURE_BHI_CTRL,			CPUID_EDX,  4, 0x00000007, 2 }, | 
|---|
| 34 | { X86_FEATURE_CQM_LLC,			CPUID_EDX,  1, 0x0000000f, 0 }, | 
|---|
| 35 | { X86_FEATURE_CQM_OCCUP_LLC,		CPUID_EDX,  0, 0x0000000f, 1 }, | 
|---|
| 36 | { X86_FEATURE_CQM_MBM_TOTAL,		CPUID_EDX,  1, 0x0000000f, 1 }, | 
|---|
| 37 | { X86_FEATURE_CQM_MBM_LOCAL,		CPUID_EDX,  2, 0x0000000f, 1 }, | 
|---|
| 38 | { X86_FEATURE_CAT_L3,			CPUID_EBX,  1, 0x00000010, 0 }, | 
|---|
| 39 | { X86_FEATURE_CAT_L2,			CPUID_EBX,  2, 0x00000010, 0 }, | 
|---|
| 40 | { X86_FEATURE_CDP_L3,			CPUID_ECX,  2, 0x00000010, 1 }, | 
|---|
| 41 | { X86_FEATURE_CDP_L2,			CPUID_ECX,  2, 0x00000010, 2 }, | 
|---|
| 42 | { X86_FEATURE_MBA,			CPUID_EBX,  3, 0x00000010, 0 }, | 
|---|
| 43 | { X86_FEATURE_PER_THREAD_MBA,		CPUID_ECX,  0, 0x00000010, 3 }, | 
|---|
| 44 | { X86_FEATURE_SGX1,			CPUID_EAX,  0, 0x00000012, 0 }, | 
|---|
| 45 | { X86_FEATURE_SGX2,			CPUID_EAX,  1, 0x00000012, 0 }, | 
|---|
| 46 | { X86_FEATURE_SGX_EDECCSSA,		CPUID_EAX, 11, 0x00000012, 0 }, | 
|---|
| 47 | { X86_FEATURE_HW_PSTATE,		CPUID_EDX,  7, 0x80000007, 0 }, | 
|---|
| 48 | { X86_FEATURE_CPB,			.reg: CPUID_EDX,  .bit: 9, .level: 0x80000007, .sub_leaf: 0 }, | 
|---|
| 49 | { X86_FEATURE_PROC_FEEDBACK,		.reg: CPUID_EDX, .bit: 11, .level: 0x80000007, .sub_leaf: 0 }, | 
|---|
| 50 | { X86_FEATURE_AMD_FAST_CPPC,		.reg: CPUID_EDX, .bit: 15, .level: 0x80000007, .sub_leaf: 0 }, | 
|---|
| 51 | { X86_FEATURE_MBA,			.reg: CPUID_EBX,  .bit: 6, .level: 0x80000008, .sub_leaf: 0 }, | 
|---|
| 52 | { X86_FEATURE_COHERENCY_SFW_NO,		.reg: CPUID_EBX, .bit: 31, .level: 0x8000001f, .sub_leaf: 0 }, | 
|---|
| 53 | { X86_FEATURE_SMBA,			.reg: CPUID_EBX,  .bit: 2, .level: 0x80000020, .sub_leaf: 0 }, | 
|---|
| 54 | { X86_FEATURE_BMEC,			.reg: CPUID_EBX,  .bit: 3, .level: 0x80000020, .sub_leaf: 0 }, | 
|---|
| 55 | { X86_FEATURE_ABMC,			.reg: CPUID_EBX,  .bit: 5, .level: 0x80000020, .sub_leaf: 0 }, | 
|---|
| 56 | { X86_FEATURE_TSA_SQ_NO,		.reg: CPUID_ECX,  .bit: 1, .level: 0x80000021, .sub_leaf: 0 }, | 
|---|
| 57 | { X86_FEATURE_TSA_L1_NO,		.reg: CPUID_ECX,  .bit: 2, .level: 0x80000021, .sub_leaf: 0 }, | 
|---|
| 58 | { X86_FEATURE_AMD_WORKLOAD_CLASS,	.reg: CPUID_EAX, .bit: 22, .level: 0x80000021, .sub_leaf: 0 }, | 
|---|
| 59 | { X86_FEATURE_PERFMON_V2,		.reg: CPUID_EAX,  .bit: 0, .level: 0x80000022, .sub_leaf: 0 }, | 
|---|
| 60 | { X86_FEATURE_AMD_LBR_V2,		.reg: CPUID_EAX,  .bit: 1, .level: 0x80000022, .sub_leaf: 0 }, | 
|---|
| 61 | { X86_FEATURE_AMD_LBR_PMC_FREEZE,	.reg: CPUID_EAX,  .bit: 2, .level: 0x80000022, .sub_leaf: 0 }, | 
|---|
| 62 | { X86_FEATURE_AMD_HTR_CORES,		.reg: CPUID_EAX, .bit: 30, .level: 0x80000026, .sub_leaf: 0 }, | 
|---|
| 63 | { .feature: 0, .reg: 0, .bit: 0, .level: 0, .sub_leaf: 0 } | 
|---|
| 64 | }; | 
|---|
| 65 |  | 
|---|
| 66 | void init_scattered_cpuid_features(struct cpuinfo_x86 *c) | 
|---|
| 67 | { | 
|---|
| 68 | u32 max_level; | 
|---|
| 69 | u32 regs[4]; | 
|---|
| 70 | const struct cpuid_bit *cb; | 
|---|
| 71 |  | 
|---|
| 72 | for (cb = cpuid_bits; cb->feature; cb++) { | 
|---|
| 73 |  | 
|---|
| 74 | /* Verify that the level is valid */ | 
|---|
| 75 | max_level = cpuid_eax(op: cb->level & 0xffff0000); | 
|---|
| 76 | if (max_level < cb->level || | 
|---|
| 77 | max_level > (cb->level | 0xffff)) | 
|---|
| 78 | continue; | 
|---|
| 79 |  | 
|---|
| 80 | cpuid_count(op: cb->level, count: cb->sub_leaf, eax: ®s[CPUID_EAX], | 
|---|
| 81 | ebx: ®s[CPUID_EBX], ecx: ®s[CPUID_ECX], | 
|---|
| 82 | edx: ®s[CPUID_EDX]); | 
|---|
| 83 |  | 
|---|
| 84 | if (regs[cb->reg] & (1 << cb->bit)) | 
|---|
| 85 | set_cpu_cap(c, cb->feature); | 
|---|
| 86 | } | 
|---|
| 87 | } | 
|---|
| 88 |  | 
|---|