From: Fenghua Yu <fenghua...@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...@intel.com> Signed-off-by: Tony Luck <tony.l...@intel.com> --- arch/x86/include/asm/intel_rdt.h | 67 ++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/intel_rdt.c | 54 +++++++++++++++++++++++++++++--- 2 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 arch/x86/include/asm/intel_rdt.h diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h new file mode 100644 index 0000000..251ac2a --- /dev/null +++ b/arch/x86/include/asm/intel_rdt.h @@ -0,0 +1,67 @@ +#ifndef _ASM_X86_INTEL_RDT_H +#define _ASM_X86_INTEL_RDT_H + +/** + * 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, +}; + +/* Maximum CLOSID allowed across all enabled resoources */ +extern int rdt_max_closid; + +/* 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 bc7f10b..b9b1e9e 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -28,6 +28,24 @@ #include <linux/err.h> #include <asm/intel_rdt_common.h> #include <asm/intel-family.h> +#include <asm/intel_rdt.h> + +int rdt_max_closid; + +#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 + }, + { + /* NULL terminated */ + } +}; /* * cache_alloc_hsw_probe() - Have to probe for Intel haswell server CPUs @@ -41,6 +59,7 @@ static inline bool cache_alloc_hsw_probe(void) { u32 l, h_old, h_new, h_tmp; + struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3]; if (rdmsr_safe(MSR_IA32_PQR_ASSOC, &l, &h_old)) return false; @@ -58,11 +77,19 @@ static inline bool cache_alloc_hsw_probe(void) wrmsr(MSR_IA32_PQR_ASSOC, l, h_old); + r->max_closid = 4; + r->num_closid = r->max_closid; + r->cbm_len = 20; + r->max_cbm = BIT_MASK(20) - 1; + r->min_cbm_bits = 2; + r->enabled = true; + return true; } static inline bool get_rdt_resources(struct cpuinfo_x86 *c) { + struct rdt_resource *r; bool ret = false; if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 6 && @@ -71,8 +98,23 @@ static inline bool get_rdt_resources(struct cpuinfo_x86 *c) if (!cpu_has(c, X86_FEATURE_RDT_A)) return false; - if (cpu_has(c, X86_FEATURE_CAT_L3)) + if (cpu_has(c, 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 (cpu_has(c, X86_FEATURE_CDP_L3)) + r->cdp_capable = true; + r->enabled = true; + ret = true; + } return ret; } @@ -80,13 +122,17 @@ static inline bool get_rdt_resources(struct cpuinfo_x86 *c) static int __init intel_rdt_late_init(void) { struct cpuinfo_x86 *c = &boot_cpu_data; + struct rdt_resource *r; if (!get_rdt_resources(c)) return -ENODEV; - pr_info("Intel cache allocation detected\n"); - if (cpu_has(c, X86_FEATURE_CDP_L3)) - pr_info("Intel code data prioritization detected\n"); + for_each_rdt_resource(r) + rdt_max_closid = max(rdt_max_closid, r->max_closid); + + for_each_rdt_resource(r) + pr_info("Intel %s allocation %s detected\n", r->name, + r->cdp_capable ? " (with CDP)" : ""); return 0; } -- 2.5.0