| 1 | |
| 2 | |
| 3 | * Resource Director Technology(RDT)
|
| 4 | * - Cache Allocation code.
|
| 5 | *
|
| 6 | * Copyright (C) 2016 Intel Corporation
|
| 7 | *
|
| 8 | * Authors:
|
| 9 | * Fenghua Yu <[email protected]>
|
| 10 | * Tony Luck <[email protected]>
|
| 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 |
|
| 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 |
|
| 121 | lockdep_assert_cpus_held();
|
| 122 |
|
| 123 |
|
| 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 | }
|