Messages in this thread Patch in this message |  | | From | "Fenghua Yu" <> | Subject | [PATCH v4 08/18] x86/intel_rdt: Pick up L3/L2 RDT parameters from CPUID | Date | Fri, 14 Oct 2016 19:12:18 -0700 |
| |
From: Fenghua Yu <fenghua.yu@intel.com>
Define struct rdt_resource to hold all the parameterized values for an RDT resource. Fill in some of those values from CPUID leaf 0x10 (on Haswell we hard code them).
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com> --- arch/x86/include/asm/intel_rdt.h | 62 ++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/intel_rdt.c | 72 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 130 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 3aca86d..8c61d83 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -2,5 +2,67 @@ #define _ASM_X86_INTEL_RDT_H #define IA32_L3_CBM_BASE 0xc90 +#define IA32_L2_CBM_BASE 0xd10 +/** + * struct rdt_resource - attributes of an RDT resource + * @enabled: Is this feature enabled on this machine + * @name: Name to use in "schemata" file + * @max_closid: Maximum number of CLOSIDs supported + * @num_closid: Current number of CLOSIDs available + * @max_cbm: Largest Cache Bit Mask allowed + * @min_cbm_bits: Minimum number of bits to be set in a cache + * bit mask + * @domains: All domains for this resource + * @num_domains: Number of domains active + * @msr_base: Base MSR address for CBMs + * @cdp_capable: Code/Data Prioritization available + * @cdp_enabled: Code/Data Prioritization enabled + * @tmp_cbms: Scratch space when updating schemata + * @cache_level: Which cache level defines scope of this domain + */ +struct rdt_resource { + bool enabled; + char *name; + int max_closid; + int num_closid; + int cbm_len; + int min_cbm_bits; + u32 max_cbm; + struct list_head domains; + int num_domains; + int msr_base; + bool cdp_capable; + bool cdp_enabled; + u32 *tmp_cbms; + int cache_level; +}; + +#define for_each_rdt_resource(r) \ + for (r = rdt_resources_all; r->name; r++) \ + if (r->enabled) + +#define IA32_L3_CBM_BASE 0xc90 +extern struct rdt_resource rdt_resources_all[]; + +enum { + RDT_RESOURCE_L3, + RDT_RESOURCE_L2, +}; + +/* CPUID.(EAX=10H, ECX=ResID=1).EAX */ +union cpuid_0x10_1_eax { + struct { + unsigned int cbm_len:5; + } split; + unsigned int full; +}; + +/* CPUID.(EAX=10H, ECX=ResID=1).EDX */ +union cpuid_0x10_1_edx { + struct { + unsigned int cos_max:16; + } split; + unsigned int full; +}; #endif /* _ASM_X86_INTEL_RDT_H */ diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 9d55942..87f9650 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -31,6 +31,28 @@ #include <asm/intel-family.h> #include <asm/intel_rdt.h> +#define domain_init(name) LIST_HEAD_INIT(rdt_resources_all[name].domains) + +struct rdt_resource rdt_resources_all[] = { + { + .name = "L3", + .domains = domain_init(RDT_RESOURCE_L3), + .msr_base = IA32_L3_CBM_BASE, + .min_cbm_bits = 1, + .cache_level = 3 + }, + { + .name = "L2", + .domains = domain_init(RDT_RESOURCE_L2), + .msr_base = IA32_L2_CBM_BASE, + .min_cbm_bits = 1, + .cache_level = 2 + }, + { + /* NULL terminated */ + } +}; + /* * cache_alloc_hsw_probe() - Have to probe for Intel haswell server CPUs * as they do not have CPUID enumeration support for Cache allocation. @@ -53,6 +75,7 @@ static inline bool cache_alloc_hsw_probe(void) { u32 l, h; u32 max_cbm = BIT_MASK(20) - 1; + struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3]; if (wrmsr_safe(IA32_L3_CBM_BASE, max_cbm, 0)) return false; @@ -60,11 +83,19 @@ static inline bool cache_alloc_hsw_probe(void) if (l != max_cbm) return false; + r->max_closid = 4; + r->num_closid = r->max_closid; + r->cbm_len = 20; + r->max_cbm = max_cbm; + r->min_cbm_bits = 2; + r->enabled = true; + return true; } static inline bool get_rdt_resources(void) { + struct rdt_resource *r; bool ret = false; if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && @@ -74,20 +105,53 @@ static inline bool get_rdt_resources(void) if (!boot_cpu_has(X86_FEATURE_RDT_A)) return false; - if (boot_cpu_has(X86_FEATURE_CAT_L3)) + if (boot_cpu_has(X86_FEATURE_CAT_L3)) { + union cpuid_0x10_1_eax eax; + union cpuid_0x10_1_edx edx; + u32 ebx, ecx; + + r = &rdt_resources_all[RDT_RESOURCE_L3]; + cpuid_count(0x00000010, 1, &eax.full, &ebx, &ecx, &edx.full); + r->max_closid = edx.split.cos_max + 1; + r->num_closid = r->max_closid; + r->cbm_len = eax.split.cbm_len + 1; + r->max_cbm = BIT_MASK(eax.split.cbm_len + 1) - 1; + if (boot_cpu_has(X86_FEATURE_CDP_L3)) + r->cdp_capable = true; + r->enabled = true; + ret = true; + } + if (boot_cpu_has(X86_FEATURE_CAT_L2)) { + union cpuid_0x10_1_eax eax; + union cpuid_0x10_1_edx edx; + u32 ebx, ecx; + + /* CPUID 0x10.2 fields are same format at 0x10.1 */ + r = &rdt_resources_all[RDT_RESOURCE_L2]; + cpuid_count(0x00000010, 2, &eax.full, &ebx, &ecx, &edx.full); + r->max_closid = edx.split.cos_max + 1; + r->num_closid = r->max_closid; + r->cbm_len = eax.split.cbm_len + 1; + r->max_cbm = BIT_MASK(eax.split.cbm_len + 1) - 1; + r->enabled = true; + + ret = true; + } return ret; } static int __init intel_rdt_late_init(void) { + struct rdt_resource *r; + if (!get_rdt_resources()) return -ENODEV; - pr_info("Intel RDT cache allocation detected\n"); - if (boot_cpu_has(X86_FEATURE_CDP_L3)) - pr_info("Intel RDT code data prioritization detected\n"); + for_each_rdt_resource(r) + pr_info("Intel RDT %s allocation %s detected\n", r->name, + r->cdp_capable ? " (with CDP)" : ""); return 0; } -- 2.5.0
|  |