1// SPDX-License-Identifier: GPL-2.0 2#include "amd64_edac.h" 3 4static ssize_t amd64_inject_section_show(struct device *dev, 5 struct device_attribute *mattr, 6 char *buf) 7{ 8 struct mem_ctl_info *mci = to_mci(dev); 9 struct amd64_pvt *pvt = mci->pvt_info; 10 return sprintf(buf, "0x%x\n", pvt->injection.section); 11} 12 13/* 14 * store error injection section value which refers to one of 4 16-byte sections 15 * within a 64-byte cacheline 16 * 17 * range: 0..3 18 */ 19static ssize_t amd64_inject_section_store(struct device *dev, 20 struct device_attribute *mattr, 21 const char *data, size_t count) 22{ 23 struct mem_ctl_info *mci = to_mci(dev); 24 struct amd64_pvt *pvt = mci->pvt_info; 25 unsigned long value; 26 int ret; 27 28 ret = kstrtoul(data, 10, &value); 29 if (ret < 0) 30 return ret; 31 32 if (value > 3) { 33 amd64_warn("%s: invalid section 0x%lx\n", __func__, value); 34 return -EINVAL; 35 } 36 37 pvt->injection.section = (u32) value; 38 return count; 39} 40 41static ssize_t amd64_inject_word_show(struct device *dev, 42 struct device_attribute *mattr, 43 char *buf) 44{ 45 struct mem_ctl_info *mci = to_mci(dev); 46 struct amd64_pvt *pvt = mci->pvt_info; 47 return sprintf(buf, "0x%x\n", pvt->injection.word); 48} 49 50/* 51 * store error injection word value which refers to one of 9 16-bit word of the 52 * 16-byte (128-bit + ECC bits) section 53 * 54 * range: 0..8 55 */ 56static ssize_t amd64_inject_word_store(struct device *dev, 57 struct device_attribute *mattr, 58 const char *data, size_t count) 59{ 60 struct mem_ctl_info *mci = to_mci(dev); 61 struct amd64_pvt *pvt = mci->pvt_info; 62 unsigned long value; 63 int ret; 64 65 ret = kstrtoul(data, 10, &value); 66 if (ret < 0) 67 return ret; 68 69 if (value > 8) { 70 amd64_warn("%s: invalid word 0x%lx\n", __func__, value); 71 return -EINVAL; 72 } 73 74 pvt->injection.word = (u32) value; 75 return count; 76} 77 78static ssize_t amd64_inject_ecc_vector_show(struct device *dev, 79 struct device_attribute *mattr, 80 char *buf) 81{ 82 struct mem_ctl_info *mci = to_mci(dev); 83 struct amd64_pvt *pvt = mci->pvt_info; 84 return sprintf(buf, "0x%x\n", pvt->injection.bit_map); 85} 86 87/* 88 * store 16 bit error injection vector which enables injecting errors to the 89 * corresponding bit within the error injection word above. When used during a 90 * DRAM ECC read, it holds the contents of the of the DRAM ECC bits. 91 */ 92static ssize_t amd64_inject_ecc_vector_store(struct device *dev, 93 struct device_attribute *mattr, 94 const char *data, size_t count) 95{ 96 struct mem_ctl_info *mci = to_mci(dev); 97 struct amd64_pvt *pvt = mci->pvt_info; 98 unsigned long value; 99 int ret; 100 101 ret = kstrtoul(data, 16, &value); 102 if (ret < 0) 103 return ret; 104 105 if (value & 0xFFFF0000) { 106 amd64_warn("%s: invalid EccVector: 0x%lx\n", __func__, value); 107 return -EINVAL; 108 } 109 110 pvt->injection.bit_map = (u32) value; 111 return count; 112} 113 114/* 115 * Do a DRAM ECC read. Assemble staged values in the pvt area, format into 116 * fields needed by the injection registers and read the NB Array Data Port. 117 */ 118static ssize_t amd64_inject_read_store(struct device *dev, 119 struct device_attribute *mattr, 120 const char *data, size_t count) 121{ 122 struct mem_ctl_info *mci = to_mci(dev); 123 struct amd64_pvt *pvt = mci->pvt_info; 124 unsigned long value; 125 u32 section, word_bits; 126 int ret; 127 128 ret = kstrtoul(data, 10, &value); 129 if (ret < 0) 130 return ret; 131 132 /* Form value to choose 16-byte section of cacheline */ 133 section = F10_NB_ARRAY_DRAM | SET_NB_ARRAY_ADDR(pvt->injection.section); 134 135 amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section); 136 137 word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection); 138 139 /* Issue 'word' and 'bit' along with the READ request */ 140 amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits); 141 142 edac_dbg(0, "section=0x%x word_bits=0x%x\n", section, word_bits); 143 144 return count; 145} 146 147/* 148 * Do a DRAM ECC write. Assemble staged values in the pvt area and format into 149 * fields needed by the injection registers. 150 */ 151static ssize_t amd64_inject_write_store(struct device *dev, 152 struct device_attribute *mattr, 153 const char *data, size_t count) 154{ 155 struct mem_ctl_info *mci = to_mci(dev); 156 struct amd64_pvt *pvt = mci->pvt_info; 157 u32 section, word_bits, tmp; 158 unsigned long value; 159 int ret; 160 161 ret = kstrtoul(data, 10, &value); 162 if (ret < 0) 163 return ret; 164 165 /* Form value to choose 16-byte section of cacheline */ 166 section = F10_NB_ARRAY_DRAM | SET_NB_ARRAY_ADDR(pvt->injection.section); 167 168 amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section); 169 170 word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection); 171 172 pr_notice_once("Don't forget to decrease MCE polling interval in\n" 173 "/sys/bus/machinecheck/devices/machinecheck<CPUNUM>/check_interval\n" 174 "so that you can get the error report faster.\n"); 175 176 on_each_cpu(disable_caches, NULL, 1); 177 178 /* Issue 'word' and 'bit' along with the READ request */ 179 amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits); 180 181 retry: 182 /* wait until injection happens */ 183 amd64_read_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, &tmp); 184 if (tmp & F10_NB_ARR_ECC_WR_REQ) { 185 cpu_relax(); 186 goto retry; 187 } 188 189 on_each_cpu(enable_caches, NULL, 1); 190 191 edac_dbg(0, "section=0x%x word_bits=0x%x\n", section, word_bits); 192 193 return count; 194} 195 196/* 197 * update NUM_INJ_ATTRS in case you add new members 198 */ 199 200static DEVICE_ATTR(inject_section, S_IRUGO | S_IWUSR, 201 amd64_inject_section_show, amd64_inject_section_store); 202static DEVICE_ATTR(inject_word, S_IRUGO | S_IWUSR, 203 amd64_inject_word_show, amd64_inject_word_store); 204static DEVICE_ATTR(inject_ecc_vector, S_IRUGO | S_IWUSR, 205 amd64_inject_ecc_vector_show, amd64_inject_ecc_vector_store); 206static DEVICE_ATTR(inject_write, S_IWUSR, 207 NULL, amd64_inject_write_store); 208static DEVICE_ATTR(inject_read, S_IWUSR, 209 NULL, amd64_inject_read_store); 210 211static struct attribute *amd64_edac_inj_attrs[] = { 212 &dev_attr_inject_section.attr, 213 &dev_attr_inject_word.attr, 214 &dev_attr_inject_ecc_vector.attr, 215 &dev_attr_inject_write.attr, 216 &dev_attr_inject_read.attr, 217 NULL 218}; 219 220static umode_t amd64_edac_inj_is_visible(struct kobject *kobj, 221 struct attribute *attr, int idx) 222{ 223 struct device *dev = kobj_to_dev(kobj); 224 struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev); 225 struct amd64_pvt *pvt = mci->pvt_info; 226 227 if (pvt->fam < 0x10) 228 return 0; 229 return attr->mode; 230} 231 232const struct attribute_group amd64_edac_inj_group = { 233 .attrs = amd64_edac_inj_attrs, 234 .is_visible = amd64_edac_inj_is_visible, 235}; 236