|
15 | 15 | * Software Developer Manual June 2016, volume 3, section 17.17.
|
16 | 16 | */
|
17 | 17 |
|
| 18 | +#define pr_fmt(fmt) "resctrl: " fmt |
| 19 | + |
18 | 20 | #include <linux/cpu.h>
|
19 | 21 | #include <linux/module.h>
|
20 | 22 | #include <linux/sizes.h>
|
@@ -1110,13 +1112,77 @@ void arch_mon_domain_online(struct rdt_resource *r, struct rdt_mon_domain *d)
|
1110 | 1112 | msr_clear_bit(MSR_RMID_SNC_CONFIG, 0);
|
1111 | 1113 | }
|
1112 | 1114 |
|
| 1115 | +/* CPU models that support MSR_RMID_SNC_CONFIG */ |
| 1116 | +static const struct x86_cpu_id snc_cpu_ids[] __initconst = { |
| 1117 | + X86_MATCH_VFM(INTEL_ICELAKE_X, 0), |
| 1118 | + X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, 0), |
| 1119 | + X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X, 0), |
| 1120 | + X86_MATCH_VFM(INTEL_GRANITERAPIDS_X, 0), |
| 1121 | + X86_MATCH_VFM(INTEL_ATOM_CRESTMONT_X, 0), |
| 1122 | + {} |
| 1123 | +}; |
| 1124 | + |
| 1125 | +/* |
| 1126 | + * There isn't a simple hardware bit that indicates whether a CPU is running |
| 1127 | + * in Sub-NUMA Cluster (SNC) mode. Infer the state by comparing the |
| 1128 | + * number of CPUs sharing the L3 cache with CPU0 to the number of CPUs in |
| 1129 | + * the same NUMA node as CPU0. |
| 1130 | + * It is not possible to accurately determine SNC state if the system is |
| 1131 | + * booted with a maxcpus=N parameter. That distorts the ratio of SNC nodes |
| 1132 | + * to L3 caches. It will be OK if system is booted with hyperthreading |
| 1133 | + * disabled (since this doesn't affect the ratio). |
| 1134 | + */ |
| 1135 | +static __init int snc_get_config(void) |
| 1136 | +{ |
| 1137 | + struct cacheinfo *ci = get_cpu_cacheinfo_level(0, RESCTRL_L3_CACHE); |
| 1138 | + const cpumask_t *node0_cpumask; |
| 1139 | + int cpus_per_node, cpus_per_l3; |
| 1140 | + int ret; |
| 1141 | + |
| 1142 | + if (!x86_match_cpu(snc_cpu_ids) || !ci) |
| 1143 | + return 1; |
| 1144 | + |
| 1145 | + cpus_read_lock(); |
| 1146 | + if (num_online_cpus() != num_present_cpus()) |
| 1147 | + pr_warn("Some CPUs offline, SNC detection may be incorrect\n"); |
| 1148 | + cpus_read_unlock(); |
| 1149 | + |
| 1150 | + node0_cpumask = cpumask_of_node(cpu_to_node(0)); |
| 1151 | + |
| 1152 | + cpus_per_node = cpumask_weight(node0_cpumask); |
| 1153 | + cpus_per_l3 = cpumask_weight(&ci->shared_cpu_map); |
| 1154 | + |
| 1155 | + if (!cpus_per_node || !cpus_per_l3) |
| 1156 | + return 1; |
| 1157 | + |
| 1158 | + ret = cpus_per_l3 / cpus_per_node; |
| 1159 | + |
| 1160 | + /* sanity check: Only valid results are 1, 2, 3, 4 */ |
| 1161 | + switch (ret) { |
| 1162 | + case 1: |
| 1163 | + break; |
| 1164 | + case 2 ... 4: |
| 1165 | + pr_info("Sub-NUMA Cluster mode detected with %d nodes per L3 cache\n", ret); |
| 1166 | + rdt_resources_all[RDT_RESOURCE_L3].r_resctrl.mon_scope = RESCTRL_L3_NODE; |
| 1167 | + break; |
| 1168 | + default: |
| 1169 | + pr_warn("Ignore improbable SNC node count %d\n", ret); |
| 1170 | + ret = 1; |
| 1171 | + break; |
| 1172 | + } |
| 1173 | + |
| 1174 | + return ret; |
| 1175 | +} |
| 1176 | + |
1113 | 1177 | int __init rdt_get_mon_l3_config(struct rdt_resource *r)
|
1114 | 1178 | {
|
1115 | 1179 | unsigned int mbm_offset = boot_cpu_data.x86_cache_mbm_width_offset;
|
1116 | 1180 | struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
|
1117 | 1181 | unsigned int threshold;
|
1118 | 1182 | int ret;
|
1119 | 1183 |
|
| 1184 | + snc_nodes_per_l3_cache = snc_get_config(); |
| 1185 | + |
1120 | 1186 | resctrl_rmid_realloc_limit = boot_cpu_data.x86_cache_size * 1024;
|
1121 | 1187 | hw_res->mon_scale = boot_cpu_data.x86_cache_occ_scale / snc_nodes_per_l3_cache;
|
1122 | 1188 | r->num_rmid = (boot_cpu_data.x86_cache_max_rmid + 1) / snc_nodes_per_l3_cache;
|
|
0 commit comments