Merge branch 'kvm-ppc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus...
[sfrench/cifs-2.6.git] / arch / parisc / kernel / pdt.c
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);