1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Resource Director Technology(RDT) 4 * - Cache Allocation code. 5 * 6 * Copyright (C) 2016 Intel Corporation 7 * 8 * Authors: 9 * Fenghua Yu <fenghua.yu@intel.com> 10 * Tony Luck <tony.luck@intel.com> 11 * 12 * More information about RDT be found in the Intel (R) x86 Architecture 13 * Software Developer Manual June 2016, volume 3, section 17.17. 14 */ 15 16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 17 18 #include <linux/cpu.h> 19 #include <linux/math.h> 20 21 #include "internal.h" 22 23 u32 resctrl_arch_preconvert_bw(const struct rdt_resource *r, u32 val) 24 { 25 return roundup(val, (unsigned long)r->membw.bw_gran); 26 } 27 28 int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d, 29 u32 closid, enum resctrl_conf_type t, u32 cfg_val) 30 { 31 struct rdt_hw_ctrl_domain *hw_dom = resctrl_to_arch_ctrl_dom(d); 32 struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r); 33 u32 idx = resctrl_get_config_index(closid, t); 34 struct msr_param msr_param; 35 36 if (!cpumask_test_cpu(smp_processor_id(), &d->hdr.cpu_mask)) 37 return -EINVAL; 38 39 hw_dom->ctrl_val[idx] = cfg_val; 40 41 msr_param.res = r; 42 msr_param.dom = d; 43 msr_param.low = idx; 44 msr_param.high = idx + 1; 45 hw_res->msr_update(&msr_param); 46 47 return 0; 48 } 49 50 int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) 51 { 52 struct resctrl_staged_config *cfg; 53 struct rdt_hw_ctrl_domain *hw_dom; 54 struct msr_param msr_param; 55 struct rdt_ctrl_domain *d; 56 enum resctrl_conf_type t; 57 u32 idx; 58 59 /* Walking r->domains, ensure it can't race with cpuhp */ 60 lockdep_assert_cpus_held(); 61 62 list_for_each_entry_rcu(d, &r->ctrl_domains, hdr.list, lockdep_is_cpus_held()) { 63 hw_dom = resctrl_to_arch_ctrl_dom(d); 64 msr_param.res = NULL; 65 for (t = 0; t < CDP_NUM_TYPES; t++) { 66 cfg = &hw_dom->d_resctrl.staged_config[t]; 67 if (!cfg->have_new_ctrl) 68 continue; 69 70 idx = resctrl_get_config_index(closid, t); 71 if (cfg->new_ctrl == hw_dom->ctrl_val[idx]) 72 continue; 73 hw_dom->ctrl_val[idx] = cfg->new_ctrl; 74 75 if (!msr_param.res) { 76 msr_param.low = idx; 77 msr_param.high = msr_param.low + 1; 78 msr_param.res = r; 79 msr_param.dom = d; 80 } else { 81 msr_param.low = min(msr_param.low, idx); 82 msr_param.high = max(msr_param.high, idx + 1); 83 } 84 } 85 if (msr_param.res) 86 smp_call_function_any(&d->hdr.cpu_mask, rdt_ctrl_update, &msr_param, 1); 87 } 88 89 return 0; 90 } 91 92 u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d, 93 u32 closid, enum resctrl_conf_type type) 94 { 95 struct rdt_hw_ctrl_domain *hw_dom = resctrl_to_arch_ctrl_dom(d); 96 u32 idx = resctrl_get_config_index(closid, type); 97 98 return hw_dom->ctrl_val[idx]; 99 } 100 101 bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r) 102 { 103 return resctrl_to_arch_res(r)->sdciae_enabled; 104 } 105 106 static void resctrl_sdciae_set_one_amd(void *arg) 107 { 108 bool *enable = arg; 109 110 if (*enable) 111 msr_set_bit(MSR_IA32_L3_QOS_EXT_CFG, SDCIAE_ENABLE_BIT); 112 else 113 msr_clear_bit(MSR_IA32_L3_QOS_EXT_CFG, SDCIAE_ENABLE_BIT); 114 } 115 116 static void _resctrl_sdciae_enable(struct rdt_resource *r, bool enable) 117 { 118 struct rdt_ctrl_domain *d; 119 120 /* Walking r->ctrl_domains, ensure it can't race with cpuhp */ 121 lockdep_assert_cpus_held(); 122 123 /* Update MSR_IA32_L3_QOS_EXT_CFG MSR on all the CPUs in all domains */ 124 list_for_each_entry_rcu(d, &r->ctrl_domains, hdr.list, lockdep_is_cpus_held()) 125 on_each_cpu_mask(&d->hdr.cpu_mask, resctrl_sdciae_set_one_amd, &enable, 1); 126 } 127 128 int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable) 129 { 130 struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r); 131 132 if (hw_res->r_resctrl.cache.io_alloc_capable && 133 hw_res->sdciae_enabled != enable) { 134 _resctrl_sdciae_enable(r, enable); 135 hw_res->sdciae_enabled = enable; 136 } 137 138 return 0; 139 } 140