1 /* 2 * Page Deallocation Table (PDT) support 3 * 4 * The Page Deallocation Table (PDT) is maintained by firmware and holds a 5 * list of memory addresses in which memory errors were detected. 6 * The list contains both single-bit (correctable) and double-bit 7 * (uncorrectable) errors. 8 * 9 * Copyright 2017 by Helge Deller <deller@gmx.de> 10 * 11 * possible future enhancements: 12 * - add userspace interface via procfs or sysfs to clear PDT 13 */ 14 15 #include <linux/memblock.h> 16 #include <linux/seq_file.h> 17 #include <linux/kthread.h> 18 19 #include <asm/pdc.h> 20 #include <asm/pdcpat.h> 21 #include <asm/sections.h> 22 #include <asm/pgtable.h> 23 24 enum pdt_access_type { 25 PDT_NONE, 26 PDT_PDC, 27 PDT_PAT_NEW, 28 PDT_PAT_CELL 29 }; 30 31 static enum pdt_access_type pdt_type; 32 33 /* PDT poll interval: 1 minute if errors, 5 minutes if everything OK. */ 34 #define PDT_POLL_INTERVAL_DEFAULT (5*60*HZ) 35 #define PDT_POLL_INTERVAL_SHORT (1*60*HZ) 36 static unsigned long pdt_poll_interval = PDT_POLL_INTERVAL_DEFAULT; 37 38 /* global PDT status information */ 39 static struct pdc_mem_retinfo pdt_status; 40 41 #define MAX_PDT_TABLE_SIZE PAGE_SIZE 42 #define MAX_PDT_ENTRIES (MAX_PDT_TABLE_SIZE / sizeof(unsigned long)) 43 static unsigned long pdt_entry[MAX_PDT_ENTRIES] __page_aligned_bss; 44 45 /* 46 * Constants for the pdt_entry format: 47 * A pdt_entry holds the physical address in bits 0-57, bits 58-61 are 48 * reserved, bit 62 is the perm bit and bit 63 is the error_type bit. 49 * The perm bit indicates whether the error have been verified as a permanent 50 * error (value of 1) or has not been verified, and may be transient (value 51 * of 0). The error_type bit indicates whether the error is a single bit error 52 * (value of 1) or a multiple bit error. 53 * On non-PAT machines phys_addr is encoded in bits 0-59 and error_type in bit 54 * 63. Those machines don't provide the perm bit. 55 */ 56 57 #define PDT_ADDR_PHYS_MASK (pdt_type != PDT_PDC ? ~0x3f : ~0x0f) 58 #define PDT_ADDR_PERM_ERR (pdt_type != PDT_PDC ? 2UL : 0UL) 59 #define PDT_ADDR_SINGLE_ERR 1UL 60 61 /* report PDT entries via /proc/meminfo */ 62 void arch_report_meminfo(struct seq_file *m) 63 { 64 if (pdt_type == PDT_NONE) 65 return; 66 67 seq_printf(m, "PDT_max_entries: %7lu\n", 68 pdt_status.pdt_size); 69 seq_printf(m, "PDT_cur_entries: %7lu\n", 70 pdt_status.pdt_entries); 71 } 72 73 static int get_info_pat_new(void) 74 { 75 struct pdc_pat_mem_retinfo pat_rinfo; 76 int ret; 77 78 /* newer PAT machines like C8000 report info for all cells */ 79 if (is_pdc_pat()) 80 ret = pdc_pat_mem_pdt_info(&pat_rinfo); 81 else 82 return PDC_BAD_PROC; 83 84 pdt_status.pdt_size = pat_rinfo.max_pdt_entries; 85 pdt_status.pdt_entries = pat_rinfo.current_pdt_entries; 86 pdt_status.pdt_status = 0; 87 pdt_status.first_dbe_loc = pat_rinfo.first_dbe_loc; 88 pdt_status.good_mem = pat_rinfo.good_mem; 89 90 return ret; 91 } 92 93 static int get_info_pat_cell(void) 94 { 95 struct pdc_pat_mem_cell_pdt_retinfo cell_rinfo; 96 int ret; 97 98 /* older PAT machines like rp5470 report cell info only */ 99 if (is_pdc_pat()) 100 ret = pdc_pat_mem_pdt_cell_info(&cell_rinfo, parisc_cell_num); 101 else 102 return PDC_BAD_PROC; 103 104 pdt_status.pdt_size = cell_rinfo.max_pdt_entries; 105 pdt_status.pdt_entries = cell_rinfo.current_pdt_entries; 106 pdt_status.pdt_status = 0; 107 pdt_status.first_dbe_loc = cell_rinfo.first_dbe_loc; 108 pdt_status.good_mem = cell_rinfo.good_mem; 109 110 return ret; 111 } 112 113 static void report_mem_err(unsigned long pde) 114 { 115 struct pdc_pat_mem_phys_mem_location loc; 116 unsigned long addr; 117 char dimm_txt[32]; 118 119 addr = pde & PDT_ADDR_PHYS_MASK; 120 121 /* show DIMM slot description on PAT machines */ 122 if (is_pdc_pat()) { 123 pdc_pat_mem_get_dimm_phys_location(&loc, addr); 124 sprintf(dimm_txt, "DIMM slot %02x, ", loc.dimm_slot); 125 } else 126 dimm_txt[0] = 0; 127 128 pr_warn("PDT: BAD MEMORY at 0x%08lx, %s%s%s-bit error.\n", 129 addr, dimm_txt, 130 pde & PDT_ADDR_PERM_ERR ? "permanent ":"", 131 pde & PDT_ADDR_SINGLE_ERR ? "single":"multi"); 132 } 133 134 135 /* 136 * pdc_pdt_init() 137 * 138 * Initialize kernel PDT structures, read initial PDT table from firmware, 139 * report all current PDT entries and mark bad memory with memblock_reserve() 140 * to avoid that the kernel will use broken memory areas. 141 * 142 */ 143 void __init pdc_pdt_init(void) 144 { 145 int ret, i; 146 unsigned long entries; 147 struct pdc_mem_read_pdt pdt_read_ret; 148 149 pdt_type = PDT_PAT_NEW; 150 ret = get_info_pat_new(); 151 152 if (ret != PDC_OK) { 153 pdt_type = PDT_PAT_CELL; 154 ret = get_info_pat_cell(); 155 } 156 157 if (ret != PDC_OK) { 158 pdt_type = PDT_PDC; 159 /* non-PAT machines provide the standard PDC call */ 160 ret = pdc_mem_pdt_info(&pdt_status); 161 } 162 163 if (ret != PDC_OK) { 164 pdt_type = PDT_NONE; 165 pr_info("PDT: Firmware does not provide any page deallocation" 166 " information.\n"); 167 return; 168 } 169 170 entries = pdt_status.pdt_entries; 171 if (WARN_ON(entries > MAX_PDT_ENTRIES)) 172 entries = pdt_status.pdt_entries = MAX_PDT_ENTRIES; 173 174 pr_info("PDT: type %s, size %lu, entries %lu, status %lu, dbe_loc 0x%lx," 175 " good_mem %lu MB\n", 176 pdt_type == PDT_PDC ? __stringify(PDT_PDC) : 177 pdt_type == PDT_PAT_CELL ? __stringify(PDT_PAT_CELL) 178 : __stringify(PDT_PAT_NEW), 179 pdt_status.pdt_size, pdt_status.pdt_entries, 180 pdt_status.pdt_status, pdt_status.first_dbe_loc, 181 pdt_status.good_mem / 1024 / 1024); 182 183 if (entries == 0) { 184 pr_info("PDT: Firmware reports all memory OK.\n"); 185 return; 186 } 187 188 if (pdt_status.first_dbe_loc && 189 pdt_status.first_dbe_loc <= __pa((unsigned long)&_end)) 190 pr_crit("CRITICAL: Bad memory inside kernel image memory area!\n"); 191 192 pr_warn("PDT: Firmware reports %lu entries of faulty memory:\n", 193 entries); 194 195 if (pdt_type == PDT_PDC) 196 ret = pdc_mem_pdt_read_entries(&pdt_read_ret, pdt_entry); 197 else { 198 #ifdef CONFIG_64BIT 199 struct pdc_pat_mem_read_pd_retinfo pat_pret; 200 201 if (pdt_type == PDT_PAT_CELL) 202 ret = pdc_pat_mem_read_cell_pdt(&pat_pret, pdt_entry, 203 MAX_PDT_ENTRIES); 204 else 205 ret = pdc_pat_mem_read_pd_pdt(&pat_pret, pdt_entry, 206 MAX_PDT_TABLE_SIZE, 0); 207 #else 208 ret = PDC_BAD_PROC; 209 #endif 210 } 211 212 if (ret != PDC_OK) { 213 pdt_type = PDT_NONE; 214 pr_warn("PDT: Get PDT entries failed with %d\n", ret); 215 return; 216 } 217 218 for (i = 0; i < pdt_status.pdt_entries; i++) { 219 report_mem_err(pdt_entry[i]); 220 221 /* mark memory page bad */ 222 memblock_reserve(pdt_entry[i] & PAGE_MASK, PAGE_SIZE); 223 } 224 } 225 226 227 /* 228 * This is the PDT kernel thread main loop. 229 */ 230 231 static int pdt_mainloop(void *unused) 232 { 233 struct pdc_mem_read_pdt pdt_read_ret; 234 struct pdc_pat_mem_read_pd_retinfo pat_pret __maybe_unused; 235 unsigned long old_num_entries; 236 unsigned long *bad_mem_ptr; 237 int num, ret; 238 239 for (;;) { 240 set_current_state(TASK_INTERRUPTIBLE); 241 242 old_num_entries = pdt_status.pdt_entries; 243 244 schedule_timeout(pdt_poll_interval); 245 if (kthread_should_stop()) 246 break; 247 248 /* Do we have new PDT entries? */ 249 switch (pdt_type) { 250 case PDT_PAT_NEW: 251 ret = get_info_pat_new(); 252 break; 253 case PDT_PAT_CELL: 254 ret = get_info_pat_cell(); 255 break; 256 default: 257 ret = pdc_mem_pdt_info(&pdt_status); 258 break; 259 } 260 261 if (ret != PDC_OK) { 262 pr_warn("PDT: unexpected failure %d\n", ret); 263 return -EINVAL; 264 } 265 266 /* if no new PDT entries, just wait again */ 267 num = pdt_status.pdt_entries - old_num_entries; 268 if (num <= 0) 269 continue; 270 271 /* decrease poll interval in case we found memory errors */ 272 if (pdt_status.pdt_entries && 273 pdt_poll_interval == PDT_POLL_INTERVAL_DEFAULT) 274 pdt_poll_interval = PDT_POLL_INTERVAL_SHORT; 275 276 /* limit entries to get */ 277 if (num > MAX_PDT_ENTRIES) { 278 num = MAX_PDT_ENTRIES; 279 pdt_status.pdt_entries = old_num_entries + num; 280 } 281 282 /* get new entries */ 283 switch (pdt_type) { 284 #ifdef CONFIG_64BIT 285 case PDT_PAT_CELL: 286 if (pdt_status.pdt_entries > MAX_PDT_ENTRIES) { 287 pr_crit("PDT: too many entries.\n"); 288 return -ENOMEM; 289 } 290 ret = pdc_pat_mem_read_cell_pdt(&pat_pret, pdt_entry, 291 MAX_PDT_ENTRIES); 292 bad_mem_ptr = &pdt_entry[old_num_entries]; 293 break; 294 case PDT_PAT_NEW: 295 ret = pdc_pat_mem_read_pd_pdt(&pat_pret, 296 pdt_entry, 297 num * sizeof(unsigned long), 298 old_num_entries * sizeof(unsigned long)); 299 bad_mem_ptr = &pdt_entry[0]; 300 break; 301 #endif 302 default: 303 ret = pdc_mem_pdt_read_entries(&pdt_read_ret, 304 pdt_entry); 305 bad_mem_ptr = &pdt_entry[old_num_entries]; 306 break; 307 } 308 309 /* report and mark memory broken */ 310 while (num--) { 311 unsigned long pde = *bad_mem_ptr++; 312 313 report_mem_err(pde); 314 315 #ifdef CONFIG_MEMORY_FAILURE 316 if ((pde & PDT_ADDR_PERM_ERR) || 317 ((pde & PDT_ADDR_SINGLE_ERR) == 0)) 318 memory_failure(pde >> PAGE_SHIFT, 0, 0); 319 else 320 soft_offline_page( 321 pfn_to_page(pde >> PAGE_SHIFT), 0); 322 #else 323 pr_crit("PDT: memory error at 0x%lx ignored.\n" 324 "Rebuild kernel with CONFIG_MEMORY_FAILURE=y " 325 "for real handling.\n", 326 pde & PDT_ADDR_PHYS_MASK); 327 #endif 328 329 } 330 } 331 332 return 0; 333 } 334 335 336 static int __init pdt_initcall(void) 337 { 338 struct task_struct *kpdtd_task; 339 340 if (pdt_type == PDT_NONE) 341 return -ENODEV; 342 343 kpdtd_task = kthread_create(pdt_mainloop, NULL, "kpdtd"); 344 if (IS_ERR(kpdtd_task)) 345 return PTR_ERR(kpdtd_task); 346 347 wake_up_process(kpdtd_task); 348 349 return 0; 350 } 351 352 late_initcall(pdt_initcall); 353