1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * APEI Error Record Serialization Table support
4 *
5 * ERST is a way provided by APEI to save and retrieve hardware error
6 * information to and from a persistent store.
7 *
8 * For more information about ERST, please refer to ACPI Specification
9 * version 4.0, section 17.4.
10 *
11 * Copyright 2010 Intel Corp.
12 * Author: Huang Ying <ying.huang@intel.com>
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/io.h>
20#include <linux/acpi.h>
21#include <linux/uaccess.h>
22#include <linux/cper.h>
23#include <linux/nmi.h>
24#include <linux/hardirq.h>
25#include <linux/pstore.h>
26#include <linux/vmalloc.h>
27#include <linux/mm.h> /* kvfree() */
28#include <acpi/apei.h>
29
30#include "apei-internal.h"
31
32#undef pr_fmt
33#define pr_fmt(fmt) "ERST: " fmt
34
35/* ERST command status */
36#define ERST_STATUS_SUCCESS 0x0
37#define ERST_STATUS_NOT_ENOUGH_SPACE 0x1
38#define ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x2
39#define ERST_STATUS_FAILED 0x3
40#define ERST_STATUS_RECORD_STORE_EMPTY 0x4
41#define ERST_STATUS_RECORD_NOT_FOUND 0x5
42
43#define ERST_TAB_ENTRY(tab) \
44 ((struct acpi_whea_header *)((char *)(tab) + \
45 sizeof(struct acpi_table_erst)))
46
47#define SPIN_UNIT 100 /* 100ns */
48/* Firmware should respond within 1 milliseconds */
49#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC)
50#define FIRMWARE_MAX_STALL 50 /* 50us */
51
52int erst_disable;
53EXPORT_SYMBOL_GPL(erst_disable);
54
55static struct acpi_table_erst *erst_tab;
56
57/* ERST Error Log Address Range attributes */
58#define ERST_RANGE_RESERVED 0x0001
59#define ERST_RANGE_NVRAM 0x0002
60#define ERST_RANGE_SLOW 0x0004
61
62/* ERST Exec max timings */
63#define ERST_EXEC_TIMING_MAX_MASK 0xFFFFFFFF00000000
64#define ERST_EXEC_TIMING_MAX_SHIFT 32
65
66/*
67 * ERST Error Log Address Range, used as buffer for reading/writing
68 * error records.
69 */
70static struct erst_erange {
71 u64 base;
72 u64 size;
73 void __iomem *vaddr;
74 u32 attr;
75 u64 timings;
76} erst_erange;
77
78/*
79 * Prevent ERST interpreter to run simultaneously, because the
80 * corresponding firmware implementation may not work properly when
81 * invoked simultaneously.
82 *
83 * It is used to provide exclusive accessing for ERST Error Log
84 * Address Range too.
85 */
86static DEFINE_RAW_SPINLOCK(erst_lock);
87
88static inline int erst_errno(int command_status)
89{
90 switch (command_status) {
91 case ERST_STATUS_SUCCESS:
92 return 0;
93 case ERST_STATUS_HARDWARE_NOT_AVAILABLE:
94 return -ENODEV;
95 case ERST_STATUS_NOT_ENOUGH_SPACE:
96 return -ENOSPC;
97 case ERST_STATUS_RECORD_STORE_EMPTY:
98 case ERST_STATUS_RECORD_NOT_FOUND:
99 return -ENOENT;
100 default:
101 return -EINVAL;
102 }
103}
104
105static inline u64 erst_get_timeout(void)
106{
107 u64 timeout = FIRMWARE_TIMEOUT;
108
109 if (erst_erange.attr & ERST_RANGE_SLOW) {
110 timeout = ((erst_erange.timings & ERST_EXEC_TIMING_MAX_MASK) >>
111 ERST_EXEC_TIMING_MAX_SHIFT) * NSEC_PER_MSEC;
112 if (timeout < FIRMWARE_TIMEOUT)
113 timeout = FIRMWARE_TIMEOUT;
114 }
115 return timeout;
116}
117
118static int erst_timedout(u64 *t, u64 spin_unit)
119{
120 if ((s64)*t < spin_unit) {
121 pr_warn(FW_WARN "Firmware does not respond in time.\n");
122 return 1;
123 }
124 *t -= spin_unit;
125 ndelay(spin_unit);
126 touch_nmi_watchdog();
127 return 0;
128}
129
130static int erst_exec_load_var1(struct apei_exec_context *ctx,
131 struct acpi_whea_header *entry)
132{
133 return __apei_exec_read_register(entry, val: &ctx->var1);
134}
135
136static int erst_exec_load_var2(struct apei_exec_context *ctx,
137 struct acpi_whea_header *entry)
138{
139 return __apei_exec_read_register(entry, val: &ctx->var2);
140}
141
142static int erst_exec_store_var1(struct apei_exec_context *ctx,
143 struct acpi_whea_header *entry)
144{
145 return __apei_exec_write_register(entry, val: ctx->var1);
146}
147
148static int erst_exec_add(struct apei_exec_context *ctx,
149 struct acpi_whea_header *entry)
150{
151 ctx->var1 += ctx->var2;
152 return 0;
153}
154
155static int erst_exec_subtract(struct apei_exec_context *ctx,
156 struct acpi_whea_header *entry)
157{
158 ctx->var1 -= ctx->var2;
159 return 0;
160}
161
162static int erst_exec_add_value(struct apei_exec_context *ctx,
163 struct acpi_whea_header *entry)
164{
165 int rc;
166 u64 val;
167
168 rc = __apei_exec_read_register(entry, val: &val);
169 if (rc)
170 return rc;
171 val += ctx->value;
172 rc = __apei_exec_write_register(entry, val);
173 return rc;
174}
175
176static int erst_exec_subtract_value(struct apei_exec_context *ctx,
177 struct acpi_whea_header *entry)
178{
179 int rc;
180 u64 val;
181
182 rc = __apei_exec_read_register(entry, val: &val);
183 if (rc)
184 return rc;
185 val -= ctx->value;
186 rc = __apei_exec_write_register(entry, val);
187 return rc;
188}
189
190static int erst_exec_stall(struct apei_exec_context *ctx,
191 struct acpi_whea_header *entry)
192{
193 u64 stall_time;
194
195 if (ctx->value > FIRMWARE_MAX_STALL) {
196 if (!in_nmi())
197 pr_warn(FW_WARN
198 "Too long stall time for stall instruction: 0x%llx.\n",
199 ctx->value);
200 stall_time = FIRMWARE_MAX_STALL;
201 } else
202 stall_time = ctx->value;
203 udelay(stall_time);
204 return 0;
205}
206
207static int erst_exec_stall_while_true(struct apei_exec_context *ctx,
208 struct acpi_whea_header *entry)
209{
210 int rc;
211 u64 val;
212 u64 timeout;
213 u64 stall_time;
214
215 timeout = erst_get_timeout();
216
217 if (ctx->var1 > FIRMWARE_MAX_STALL) {
218 if (!in_nmi())
219 pr_warn(FW_WARN
220 "Too long stall time for stall while true instruction: 0x%llx.\n",
221 ctx->var1);
222 stall_time = FIRMWARE_MAX_STALL;
223 } else
224 stall_time = ctx->var1;
225
226 for (;;) {
227 rc = __apei_exec_read_register(entry, val: &val);
228 if (rc)
229 return rc;
230 if (val != ctx->value)
231 break;
232 if (erst_timedout(t: &timeout, spin_unit: stall_time * NSEC_PER_USEC))
233 return -EIO;
234 }
235 return 0;
236}
237
238static int erst_exec_skip_next_instruction_if_true(
239 struct apei_exec_context *ctx,
240 struct acpi_whea_header *entry)
241{
242 int rc;
243 u64 val;
244
245 rc = __apei_exec_read_register(entry, val: &val);
246 if (rc)
247 return rc;
248 if (val == ctx->value) {
249 ctx->ip += 2;
250 return APEI_EXEC_SET_IP;
251 }
252
253 return 0;
254}
255
256static int erst_exec_goto(struct apei_exec_context *ctx,
257 struct acpi_whea_header *entry)
258{
259 ctx->ip = ctx->value;
260 return APEI_EXEC_SET_IP;
261}
262
263static int erst_exec_set_src_address_base(struct apei_exec_context *ctx,
264 struct acpi_whea_header *entry)
265{
266 return __apei_exec_read_register(entry, val: &ctx->src_base);
267}
268
269static int erst_exec_set_dst_address_base(struct apei_exec_context *ctx,
270 struct acpi_whea_header *entry)
271{
272 return __apei_exec_read_register(entry, val: &ctx->dst_base);
273}
274
275static int erst_exec_move_data(struct apei_exec_context *ctx,
276 struct acpi_whea_header *entry)
277{
278 int rc;
279 u64 offset;
280 void *src, *dst;
281
282 /* ioremap does not work in interrupt context */
283 if (in_interrupt()) {
284 pr_warn("MOVE_DATA can not be used in interrupt context.\n");
285 return -EBUSY;
286 }
287
288 rc = __apei_exec_read_register(entry, val: &offset);
289 if (rc)
290 return rc;
291
292 src = ioremap(offset: ctx->src_base + offset, size: ctx->var2);
293 if (!src)
294 return -ENOMEM;
295 dst = ioremap(offset: ctx->dst_base + offset, size: ctx->var2);
296 if (!dst) {
297 iounmap(addr: src);
298 return -ENOMEM;
299 }
300
301 memmove(dst, src, ctx->var2);
302
303 iounmap(addr: src);
304 iounmap(addr: dst);
305
306 return 0;
307}
308
309static struct apei_exec_ins_type erst_ins_type[] = {
310 [ACPI_ERST_READ_REGISTER] = {
311 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
312 .run = apei_exec_read_register,
313 },
314 [ACPI_ERST_READ_REGISTER_VALUE] = {
315 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
316 .run = apei_exec_read_register_value,
317 },
318 [ACPI_ERST_WRITE_REGISTER] = {
319 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
320 .run = apei_exec_write_register,
321 },
322 [ACPI_ERST_WRITE_REGISTER_VALUE] = {
323 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
324 .run = apei_exec_write_register_value,
325 },
326 [ACPI_ERST_NOOP] = {
327 .flags = 0,
328 .run = apei_exec_noop,
329 },
330 [ACPI_ERST_LOAD_VAR1] = {
331 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
332 .run = erst_exec_load_var1,
333 },
334 [ACPI_ERST_LOAD_VAR2] = {
335 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
336 .run = erst_exec_load_var2,
337 },
338 [ACPI_ERST_STORE_VAR1] = {
339 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
340 .run = erst_exec_store_var1,
341 },
342 [ACPI_ERST_ADD] = {
343 .flags = 0,
344 .run = erst_exec_add,
345 },
346 [ACPI_ERST_SUBTRACT] = {
347 .flags = 0,
348 .run = erst_exec_subtract,
349 },
350 [ACPI_ERST_ADD_VALUE] = {
351 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
352 .run = erst_exec_add_value,
353 },
354 [ACPI_ERST_SUBTRACT_VALUE] = {
355 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
356 .run = erst_exec_subtract_value,
357 },
358 [ACPI_ERST_STALL] = {
359 .flags = 0,
360 .run = erst_exec_stall,
361 },
362 [ACPI_ERST_STALL_WHILE_TRUE] = {
363 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
364 .run = erst_exec_stall_while_true,
365 },
366 [ACPI_ERST_SKIP_NEXT_IF_TRUE] = {
367 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
368 .run = erst_exec_skip_next_instruction_if_true,
369 },
370 [ACPI_ERST_GOTO] = {
371 .flags = 0,
372 .run = erst_exec_goto,
373 },
374 [ACPI_ERST_SET_SRC_ADDRESS_BASE] = {
375 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
376 .run = erst_exec_set_src_address_base,
377 },
378 [ACPI_ERST_SET_DST_ADDRESS_BASE] = {
379 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
380 .run = erst_exec_set_dst_address_base,
381 },
382 [ACPI_ERST_MOVE_DATA] = {
383 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
384 .run = erst_exec_move_data,
385 },
386};
387
388static inline void erst_exec_ctx_init(struct apei_exec_context *ctx)
389{
390 apei_exec_ctx_init(ctx, ins_table: erst_ins_type, ARRAY_SIZE(erst_ins_type),
391 ERST_TAB_ENTRY(erst_tab), entries: erst_tab->entries);
392}
393
394static int erst_get_erange(struct erst_erange *range)
395{
396 struct apei_exec_context ctx;
397 int rc;
398
399 erst_exec_ctx_init(ctx: &ctx);
400 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_GET_ERROR_RANGE);
401 if (rc)
402 return rc;
403 range->base = apei_exec_ctx_get_output(ctx: &ctx);
404 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_GET_ERROR_LENGTH);
405 if (rc)
406 return rc;
407 range->size = apei_exec_ctx_get_output(ctx: &ctx);
408 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_GET_ERROR_ATTRIBUTES);
409 if (rc)
410 return rc;
411 range->attr = apei_exec_ctx_get_output(ctx: &ctx);
412 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_EXECUTE_TIMINGS);
413 if (rc == 0)
414 range->timings = apei_exec_ctx_get_output(ctx: &ctx);
415 else if (rc == -ENOENT)
416 range->timings = 0;
417 else
418 return rc;
419
420 return 0;
421}
422
423static ssize_t __erst_get_record_count(void)
424{
425 struct apei_exec_context ctx;
426 int rc;
427
428 erst_exec_ctx_init(ctx: &ctx);
429 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_GET_RECORD_COUNT);
430 if (rc)
431 return rc;
432 return apei_exec_ctx_get_output(ctx: &ctx);
433}
434
435ssize_t erst_get_record_count(void)
436{
437 ssize_t count;
438 unsigned long flags;
439
440 if (erst_disable)
441 return -ENODEV;
442
443 raw_spin_lock_irqsave(&erst_lock, flags);
444 count = __erst_get_record_count();
445 raw_spin_unlock_irqrestore(&erst_lock, flags);
446
447 return count;
448}
449EXPORT_SYMBOL_GPL(erst_get_record_count);
450
451#define ERST_RECORD_ID_CACHE_SIZE_MIN 16
452#define ERST_RECORD_ID_CACHE_SIZE_MAX 1024
453
454struct erst_record_id_cache {
455 struct mutex lock;
456 u64 *entries;
457 int len;
458 int size;
459 int refcount;
460};
461
462static struct erst_record_id_cache erst_record_id_cache = {
463 .lock = __MUTEX_INITIALIZER(erst_record_id_cache.lock),
464 .refcount = 0,
465};
466
467static int __erst_get_next_record_id(u64 *record_id)
468{
469 struct apei_exec_context ctx;
470 int rc;
471
472 erst_exec_ctx_init(ctx: &ctx);
473 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_GET_RECORD_ID);
474 if (rc)
475 return rc;
476 *record_id = apei_exec_ctx_get_output(ctx: &ctx);
477
478 return 0;
479}
480
481int erst_get_record_id_begin(int *pos)
482{
483 int rc;
484
485 if (erst_disable)
486 return -ENODEV;
487
488 rc = mutex_lock_interruptible(&erst_record_id_cache.lock);
489 if (rc)
490 return rc;
491 erst_record_id_cache.refcount++;
492 mutex_unlock(lock: &erst_record_id_cache.lock);
493
494 *pos = 0;
495
496 return 0;
497}
498EXPORT_SYMBOL_GPL(erst_get_record_id_begin);
499
500/* erst_record_id_cache.lock must be held by caller */
501static int __erst_record_id_cache_add_one(void)
502{
503 u64 id, prev_id, first_id;
504 int i, rc;
505 u64 *entries;
506 unsigned long flags;
507
508 id = prev_id = first_id = APEI_ERST_INVALID_RECORD_ID;
509retry:
510 raw_spin_lock_irqsave(&erst_lock, flags);
511 rc = __erst_get_next_record_id(record_id: &id);
512 raw_spin_unlock_irqrestore(&erst_lock, flags);
513 if (rc == -ENOENT)
514 return 0;
515 if (rc)
516 return rc;
517 if (id == APEI_ERST_INVALID_RECORD_ID)
518 return 0;
519 /* can not skip current ID, or loop back to first ID */
520 if (id == prev_id || id == first_id)
521 return 0;
522 if (first_id == APEI_ERST_INVALID_RECORD_ID)
523 first_id = id;
524 prev_id = id;
525
526 entries = erst_record_id_cache.entries;
527 for (i = 0; i < erst_record_id_cache.len; i++) {
528 if (entries[i] == id)
529 break;
530 }
531 /* record id already in cache, try next */
532 if (i < erst_record_id_cache.len)
533 goto retry;
534 if (erst_record_id_cache.len >= erst_record_id_cache.size) {
535 int new_size;
536 u64 *new_entries;
537
538 new_size = erst_record_id_cache.size * 2;
539 new_size = clamp_val(new_size, ERST_RECORD_ID_CACHE_SIZE_MIN,
540 ERST_RECORD_ID_CACHE_SIZE_MAX);
541 if (new_size <= erst_record_id_cache.size) {
542 if (printk_ratelimit())
543 pr_warn(FW_WARN "too many record IDs!\n");
544 return 0;
545 }
546 new_entries = kvmalloc_array(n: new_size, size: sizeof(entries[0]),
547 GFP_KERNEL);
548 if (!new_entries)
549 return -ENOMEM;
550 memcpy(new_entries, entries,
551 erst_record_id_cache.len * sizeof(entries[0]));
552 kvfree(addr: entries);
553 erst_record_id_cache.entries = entries = new_entries;
554 erst_record_id_cache.size = new_size;
555 }
556 entries[i] = id;
557 erst_record_id_cache.len++;
558
559 return 1;
560}
561
562/*
563 * Get the record ID of an existing error record on the persistent
564 * storage. If there is no error record on the persistent storage, the
565 * returned record_id is APEI_ERST_INVALID_RECORD_ID.
566 */
567int erst_get_record_id_next(int *pos, u64 *record_id)
568{
569 int rc = 0;
570 u64 *entries;
571
572 if (erst_disable)
573 return -ENODEV;
574
575 /* must be enclosed by erst_get_record_id_begin/end */
576 BUG_ON(!erst_record_id_cache.refcount);
577 BUG_ON(*pos < 0 || *pos > erst_record_id_cache.len);
578
579 mutex_lock(&erst_record_id_cache.lock);
580 entries = erst_record_id_cache.entries;
581 for (; *pos < erst_record_id_cache.len; (*pos)++)
582 if (entries[*pos] != APEI_ERST_INVALID_RECORD_ID)
583 break;
584 /* found next record id in cache */
585 if (*pos < erst_record_id_cache.len) {
586 *record_id = entries[*pos];
587 (*pos)++;
588 goto out_unlock;
589 }
590
591 /* Try to add one more record ID to cache */
592 rc = __erst_record_id_cache_add_one();
593 if (rc < 0)
594 goto out_unlock;
595 /* successfully add one new ID */
596 if (rc == 1) {
597 *record_id = erst_record_id_cache.entries[*pos];
598 (*pos)++;
599 rc = 0;
600 } else {
601 *pos = -1;
602 *record_id = APEI_ERST_INVALID_RECORD_ID;
603 }
604out_unlock:
605 mutex_unlock(lock: &erst_record_id_cache.lock);
606
607 return rc;
608}
609EXPORT_SYMBOL_GPL(erst_get_record_id_next);
610
611/* erst_record_id_cache.lock must be held by caller */
612static void __erst_record_id_cache_compact(void)
613{
614 int i, wpos = 0;
615 u64 *entries;
616
617 if (erst_record_id_cache.refcount)
618 return;
619
620 entries = erst_record_id_cache.entries;
621 for (i = 0; i < erst_record_id_cache.len; i++) {
622 if (entries[i] == APEI_ERST_INVALID_RECORD_ID)
623 continue;
624 if (wpos != i)
625 entries[wpos] = entries[i];
626 wpos++;
627 }
628 erst_record_id_cache.len = wpos;
629}
630
631void erst_get_record_id_end(void)
632{
633 /*
634 * erst_disable != 0 should be detected by invoker via the
635 * return value of erst_get_record_id_begin/next, so this
636 * function should not be called for erst_disable != 0.
637 */
638 BUG_ON(erst_disable);
639
640 mutex_lock(&erst_record_id_cache.lock);
641 erst_record_id_cache.refcount--;
642 BUG_ON(erst_record_id_cache.refcount < 0);
643 __erst_record_id_cache_compact();
644 mutex_unlock(lock: &erst_record_id_cache.lock);
645}
646EXPORT_SYMBOL_GPL(erst_get_record_id_end);
647
648static int __erst_write_to_storage(u64 offset)
649{
650 struct apei_exec_context ctx;
651 u64 timeout;
652 u64 val;
653 int rc;
654
655 timeout = erst_get_timeout();
656
657 erst_exec_ctx_init(ctx: &ctx);
658 rc = apei_exec_run_optional(ctx: &ctx, action: ACPI_ERST_BEGIN_WRITE);
659 if (rc)
660 return rc;
661 apei_exec_ctx_set_input(ctx: &ctx, input: offset);
662 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_SET_RECORD_OFFSET);
663 if (rc)
664 return rc;
665 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_EXECUTE_OPERATION);
666 if (rc)
667 return rc;
668 for (;;) {
669 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_CHECK_BUSY_STATUS);
670 if (rc)
671 return rc;
672 val = apei_exec_ctx_get_output(ctx: &ctx);
673 if (!val)
674 break;
675 if (erst_timedout(t: &timeout, SPIN_UNIT))
676 return -EIO;
677 }
678 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_GET_COMMAND_STATUS);
679 if (rc)
680 return rc;
681 val = apei_exec_ctx_get_output(ctx: &ctx);
682 rc = apei_exec_run_optional(ctx: &ctx, action: ACPI_ERST_END);
683 if (rc)
684 return rc;
685
686 return erst_errno(command_status: val);
687}
688
689static int __erst_read_from_storage(u64 record_id, u64 offset)
690{
691 struct apei_exec_context ctx;
692 u64 timeout;
693 u64 val;
694 int rc;
695
696 timeout = erst_get_timeout();
697
698 erst_exec_ctx_init(ctx: &ctx);
699 rc = apei_exec_run_optional(ctx: &ctx, action: ACPI_ERST_BEGIN_READ);
700 if (rc)
701 return rc;
702 apei_exec_ctx_set_input(ctx: &ctx, input: offset);
703 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_SET_RECORD_OFFSET);
704 if (rc)
705 return rc;
706 apei_exec_ctx_set_input(ctx: &ctx, input: record_id);
707 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_SET_RECORD_ID);
708 if (rc)
709 return rc;
710 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_EXECUTE_OPERATION);
711 if (rc)
712 return rc;
713 for (;;) {
714 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_CHECK_BUSY_STATUS);
715 if (rc)
716 return rc;
717 val = apei_exec_ctx_get_output(ctx: &ctx);
718 if (!val)
719 break;
720 if (erst_timedout(t: &timeout, SPIN_UNIT))
721 return -EIO;
722 }
723 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_GET_COMMAND_STATUS);
724 if (rc)
725 return rc;
726 val = apei_exec_ctx_get_output(ctx: &ctx);
727 rc = apei_exec_run_optional(ctx: &ctx, action: ACPI_ERST_END);
728 if (rc)
729 return rc;
730
731 return erst_errno(command_status: val);
732}
733
734static int __erst_clear_from_storage(u64 record_id)
735{
736 struct apei_exec_context ctx;
737 u64 timeout;
738 u64 val;
739 int rc;
740
741 timeout = erst_get_timeout();
742
743 erst_exec_ctx_init(ctx: &ctx);
744 rc = apei_exec_run_optional(ctx: &ctx, action: ACPI_ERST_BEGIN_CLEAR);
745 if (rc)
746 return rc;
747 apei_exec_ctx_set_input(ctx: &ctx, input: record_id);
748 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_SET_RECORD_ID);
749 if (rc)
750 return rc;
751 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_EXECUTE_OPERATION);
752 if (rc)
753 return rc;
754 for (;;) {
755 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_CHECK_BUSY_STATUS);
756 if (rc)
757 return rc;
758 val = apei_exec_ctx_get_output(ctx: &ctx);
759 if (!val)
760 break;
761 if (erst_timedout(t: &timeout, SPIN_UNIT))
762 return -EIO;
763 }
764 rc = apei_exec_run(ctx: &ctx, action: ACPI_ERST_GET_COMMAND_STATUS);
765 if (rc)
766 return rc;
767 val = apei_exec_ctx_get_output(ctx: &ctx);
768 rc = apei_exec_run_optional(ctx: &ctx, action: ACPI_ERST_END);
769 if (rc)
770 return rc;
771
772 return erst_errno(command_status: val);
773}
774
775/* NVRAM ERST Error Log Address Range is not supported yet */
776static void pr_unimpl_nvram(void)
777{
778 if (printk_ratelimit())
779 pr_warn("NVRAM ERST Log Address Range not implemented yet.\n");
780}
781
782static int __erst_write_to_nvram(const struct cper_record_header *record)
783{
784 /* do not print message, because printk is not safe for NMI */
785 return -ENOSYS;
786}
787
788static int __erst_read_to_erange_from_nvram(u64 record_id, u64 *offset)
789{
790 pr_unimpl_nvram();
791 return -ENOSYS;
792}
793
794static int __erst_clear_from_nvram(u64 record_id)
795{
796 pr_unimpl_nvram();
797 return -ENOSYS;
798}
799
800int erst_write(const struct cper_record_header *record)
801{
802 int rc;
803 unsigned long flags;
804 struct cper_record_header *rcd_erange;
805
806 if (erst_disable)
807 return -ENODEV;
808
809 if (memcmp(p: record->signature, CPER_SIG_RECORD, CPER_SIG_SIZE))
810 return -EINVAL;
811
812 if (erst_erange.attr & ERST_RANGE_NVRAM) {
813 if (!raw_spin_trylock_irqsave(&erst_lock, flags))
814 return -EBUSY;
815 rc = __erst_write_to_nvram(record);
816 raw_spin_unlock_irqrestore(&erst_lock, flags);
817 return rc;
818 }
819
820 if (record->record_length > erst_erange.size)
821 return -EINVAL;
822
823 if (!raw_spin_trylock_irqsave(&erst_lock, flags))
824 return -EBUSY;
825 memcpy(erst_erange.vaddr, record, record->record_length);
826 rcd_erange = erst_erange.vaddr;
827 /* signature for serialization system */
828 memcpy(&rcd_erange->persistence_information, "ER", 2);
829
830 rc = __erst_write_to_storage(offset: 0);
831 raw_spin_unlock_irqrestore(&erst_lock, flags);
832
833 return rc;
834}
835EXPORT_SYMBOL_GPL(erst_write);
836
837static int __erst_read_to_erange(u64 record_id, u64 *offset)
838{
839 int rc;
840
841 if (erst_erange.attr & ERST_RANGE_NVRAM)
842 return __erst_read_to_erange_from_nvram(
843 record_id, offset);
844
845 rc = __erst_read_from_storage(record_id, offset: 0);
846 if (rc)
847 return rc;
848 *offset = 0;
849
850 return 0;
851}
852
853static ssize_t __erst_read(u64 record_id, struct cper_record_header *record,
854 size_t buflen)
855{
856 int rc;
857 u64 offset, len = 0;
858 struct cper_record_header *rcd_tmp;
859
860 rc = __erst_read_to_erange(record_id, offset: &offset);
861 if (rc)
862 return rc;
863 rcd_tmp = erst_erange.vaddr + offset;
864 len = rcd_tmp->record_length;
865 if (len <= buflen)
866 memcpy(record, rcd_tmp, len);
867
868 return len;
869}
870
871/*
872 * If return value > buflen, the buffer size is not big enough,
873 * else if return value < 0, something goes wrong,
874 * else everything is OK, and return value is record length
875 */
876ssize_t erst_read(u64 record_id, struct cper_record_header *record,
877 size_t buflen)
878{
879 ssize_t len;
880 unsigned long flags;
881
882 if (erst_disable)
883 return -ENODEV;
884
885 raw_spin_lock_irqsave(&erst_lock, flags);
886 len = __erst_read(record_id, record, buflen);
887 raw_spin_unlock_irqrestore(&erst_lock, flags);
888 return len;
889}
890EXPORT_SYMBOL_GPL(erst_read);
891
892static void erst_clear_cache(u64 record_id)
893{
894 int i;
895 u64 *entries;
896
897 mutex_lock(&erst_record_id_cache.lock);
898
899 entries = erst_record_id_cache.entries;
900 for (i = 0; i < erst_record_id_cache.len; i++) {
901 if (entries[i] == record_id)
902 entries[i] = APEI_ERST_INVALID_RECORD_ID;
903 }
904 __erst_record_id_cache_compact();
905
906 mutex_unlock(lock: &erst_record_id_cache.lock);
907}
908
909ssize_t erst_read_record(u64 record_id, struct cper_record_header *record,
910 size_t buflen, size_t recordlen, const guid_t *creatorid)
911{
912 ssize_t len;
913
914 /*
915 * if creatorid is NULL, read any record for erst-dbg module
916 */
917 if (creatorid == NULL) {
918 len = erst_read(record_id, record, buflen);
919 if (len == -ENOENT)
920 erst_clear_cache(record_id);
921
922 return len;
923 }
924
925 len = erst_read(record_id, record, buflen);
926 /*
927 * if erst_read return value is -ENOENT skip to next record_id,
928 * and clear the record_id cache.
929 */
930 if (len == -ENOENT) {
931 erst_clear_cache(record_id);
932 goto out;
933 }
934
935 if (len < 0)
936 goto out;
937
938 /*
939 * if erst_read return value is less than record head length,
940 * consider it as -EIO, and clear the record_id cache.
941 */
942 if (len < recordlen) {
943 len = -EIO;
944 erst_clear_cache(record_id);
945 goto out;
946 }
947
948 /*
949 * if creatorid is not wanted, consider it as not found,
950 * for skipping to next record_id.
951 */
952 if (!guid_equal(u1: &record->creator_id, u2: creatorid))
953 len = -ENOENT;
954
955out:
956 return len;
957}
958EXPORT_SYMBOL_GPL(erst_read_record);
959
960int erst_clear(u64 record_id)
961{
962 int rc, i;
963 unsigned long flags;
964 u64 *entries;
965
966 if (erst_disable)
967 return -ENODEV;
968
969 rc = mutex_lock_interruptible(&erst_record_id_cache.lock);
970 if (rc)
971 return rc;
972 raw_spin_lock_irqsave(&erst_lock, flags);
973 if (erst_erange.attr & ERST_RANGE_NVRAM)
974 rc = __erst_clear_from_nvram(record_id);
975 else
976 rc = __erst_clear_from_storage(record_id);
977 raw_spin_unlock_irqrestore(&erst_lock, flags);
978 if (rc)
979 goto out;
980 entries = erst_record_id_cache.entries;
981 for (i = 0; i < erst_record_id_cache.len; i++) {
982 if (entries[i] == record_id)
983 entries[i] = APEI_ERST_INVALID_RECORD_ID;
984 }
985 __erst_record_id_cache_compact();
986out:
987 mutex_unlock(lock: &erst_record_id_cache.lock);
988 return rc;
989}
990EXPORT_SYMBOL_GPL(erst_clear);
991
992static int __init setup_erst_disable(char *str)
993{
994 erst_disable = 1;
995 return 1;
996}
997
998__setup("erst_disable", setup_erst_disable);
999
1000static int erst_check_table(struct acpi_table_erst *erst_tab)
1001{
1002 if ((erst_tab->header_length !=
1003 (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header)))
1004 && (erst_tab->header_length != sizeof(struct acpi_table_erst)))
1005 return -EINVAL;
1006 if (erst_tab->header.length < sizeof(struct acpi_table_erst))
1007 return -EINVAL;
1008 if (erst_tab->entries !=
1009 (erst_tab->header.length - sizeof(struct acpi_table_erst)) /
1010 sizeof(struct acpi_erst_entry))
1011 return -EINVAL;
1012
1013 return 0;
1014}
1015
1016static int erst_open_pstore(struct pstore_info *psi);
1017static int erst_close_pstore(struct pstore_info *psi);
1018static ssize_t erst_reader(struct pstore_record *record);
1019static int erst_writer(struct pstore_record *record);
1020static int erst_clearer(struct pstore_record *record);
1021
1022static struct pstore_info erst_info = {
1023 .owner = THIS_MODULE,
1024 .name = "erst",
1025 .flags = PSTORE_FLAGS_DMESG,
1026 .open = erst_open_pstore,
1027 .close = erst_close_pstore,
1028 .read = erst_reader,
1029 .write = erst_writer,
1030 .erase = erst_clearer
1031};
1032
1033#define CPER_CREATOR_PSTORE \
1034 GUID_INIT(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c, \
1035 0x64, 0x90, 0xb8, 0x9d)
1036#define CPER_SECTION_TYPE_DMESG \
1037 GUID_INIT(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54, \
1038 0x94, 0x19, 0xeb, 0x12)
1039#define CPER_SECTION_TYPE_DMESG_Z \
1040 GUID_INIT(0x4f118707, 0x04dd, 0x4055, 0xb5, 0xdd, 0x95, 0x6d, \
1041 0x34, 0xdd, 0xfa, 0xc6)
1042#define CPER_SECTION_TYPE_MCE \
1043 GUID_INIT(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \
1044 0x04, 0x4a, 0x38, 0xfc)
1045
1046struct cper_pstore_record {
1047 struct cper_record_header hdr;
1048 struct cper_section_descriptor sec_hdr;
1049 char data[];
1050} __packed;
1051
1052static int reader_pos;
1053
1054static int erst_open_pstore(struct pstore_info *psi)
1055{
1056 if (erst_disable)
1057 return -ENODEV;
1058
1059 return erst_get_record_id_begin(&reader_pos);
1060}
1061
1062static int erst_close_pstore(struct pstore_info *psi)
1063{
1064 erst_get_record_id_end();
1065
1066 return 0;
1067}
1068
1069static ssize_t erst_reader(struct pstore_record *record)
1070{
1071 int rc;
1072 ssize_t len = 0;
1073 u64 record_id;
1074 struct cper_pstore_record *rcd;
1075 size_t rcd_len = sizeof(*rcd) + erst_info.bufsize;
1076
1077 if (erst_disable)
1078 return -ENODEV;
1079
1080 rcd = kmalloc(size: rcd_len, GFP_KERNEL);
1081 if (!rcd) {
1082 rc = -ENOMEM;
1083 goto out;
1084 }
1085skip:
1086 rc = erst_get_record_id_next(&reader_pos, &record_id);
1087 if (rc)
1088 goto out;
1089
1090 /* no more record */
1091 if (record_id == APEI_ERST_INVALID_RECORD_ID) {
1092 rc = -EINVAL;
1093 goto out;
1094 }
1095
1096 len = erst_read_record(record_id, &rcd->hdr, rcd_len, sizeof(*rcd),
1097 &CPER_CREATOR_PSTORE);
1098 /* The record may be cleared by others, try read next record */
1099 if (len == -ENOENT)
1100 goto skip;
1101 else if (len < 0)
1102 goto out;
1103
1104 record->buf = kmalloc(size: len, GFP_KERNEL);
1105 if (record->buf == NULL) {
1106 rc = -ENOMEM;
1107 goto out;
1108 }
1109 memcpy(record->buf, rcd->data, len - sizeof(*rcd));
1110 record->id = record_id;
1111 record->compressed = false;
1112 record->ecc_notice_size = 0;
1113 if (guid_equal(u1: &rcd->sec_hdr.section_type, u2: &CPER_SECTION_TYPE_DMESG_Z)) {
1114 record->type = PSTORE_TYPE_DMESG;
1115 record->compressed = true;
1116 } else if (guid_equal(u1: &rcd->sec_hdr.section_type, u2: &CPER_SECTION_TYPE_DMESG))
1117 record->type = PSTORE_TYPE_DMESG;
1118 else if (guid_equal(u1: &rcd->sec_hdr.section_type, u2: &CPER_SECTION_TYPE_MCE))
1119 record->type = PSTORE_TYPE_MCE;
1120 else
1121 record->type = PSTORE_TYPE_MAX;
1122
1123 if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP)
1124 record->time.tv_sec = rcd->hdr.timestamp;
1125 else
1126 record->time.tv_sec = 0;
1127 record->time.tv_nsec = 0;
1128
1129out:
1130 kfree(objp: rcd);
1131 return (rc < 0) ? rc : (len - sizeof(*rcd));
1132}
1133
1134static int erst_writer(struct pstore_record *record)
1135{
1136 struct cper_pstore_record *rcd = (struct cper_pstore_record *)
1137 (erst_info.buf - sizeof(*rcd));
1138 int ret;
1139
1140 memset(rcd, 0, sizeof(*rcd));
1141 memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
1142 rcd->hdr.revision = CPER_RECORD_REV;
1143 rcd->hdr.signature_end = CPER_SIG_END;
1144 rcd->hdr.section_count = 1;
1145 rcd->hdr.error_severity = CPER_SEV_FATAL;
1146 /* timestamp valid. platform_id, partition_id are invalid */
1147 rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP;
1148 rcd->hdr.timestamp = ktime_get_real_seconds();
1149 rcd->hdr.record_length = sizeof(*rcd) + record->size;
1150 rcd->hdr.creator_id = CPER_CREATOR_PSTORE;
1151 rcd->hdr.notification_type = CPER_NOTIFY_MCE;
1152 rcd->hdr.record_id = cper_next_record_id();
1153 rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR;
1154
1155 rcd->sec_hdr.section_offset = sizeof(*rcd);
1156 rcd->sec_hdr.section_length = record->size;
1157 rcd->sec_hdr.revision = CPER_SEC_REV;
1158 /* fru_id and fru_text is invalid */
1159 rcd->sec_hdr.validation_bits = 0;
1160 rcd->sec_hdr.flags = CPER_SEC_PRIMARY;
1161 switch (record->type) {
1162 case PSTORE_TYPE_DMESG:
1163 if (record->compressed)
1164 rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG_Z;
1165 else
1166 rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG;
1167 break;
1168 case PSTORE_TYPE_MCE:
1169 rcd->sec_hdr.section_type = CPER_SECTION_TYPE_MCE;
1170 break;
1171 default:
1172 return -EINVAL;
1173 }
1174 rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
1175
1176 ret = erst_write(&rcd->hdr);
1177 record->id = rcd->hdr.record_id;
1178
1179 return ret;
1180}
1181
1182static int erst_clearer(struct pstore_record *record)
1183{
1184 return erst_clear(record->id);
1185}
1186
1187static int __init erst_init(void)
1188{
1189 int rc = 0;
1190 acpi_status status;
1191 struct apei_exec_context ctx;
1192 struct apei_resources erst_resources;
1193 struct resource *r;
1194 char *buf;
1195
1196 if (acpi_disabled)
1197 goto err;
1198
1199 if (erst_disable) {
1200 pr_info(
1201 "Error Record Serialization Table (ERST) support is disabled.\n");
1202 goto err;
1203 }
1204
1205 status = acpi_get_table(ACPI_SIG_ERST, instance: 0,
1206 out_table: (struct acpi_table_header **)&erst_tab);
1207 if (status == AE_NOT_FOUND)
1208 goto err;
1209 else if (ACPI_FAILURE(status)) {
1210 const char *msg = acpi_format_exception(exception: status);
1211 pr_err("Failed to get table, %s\n", msg);
1212 rc = -EINVAL;
1213 goto err;
1214 }
1215
1216 rc = erst_check_table(erst_tab);
1217 if (rc) {
1218 pr_err(FW_BUG "ERST table is invalid.\n");
1219 goto err_put_erst_tab;
1220 }
1221
1222 apei_resources_init(resources: &erst_resources);
1223 erst_exec_ctx_init(ctx: &ctx);
1224 rc = apei_exec_collect_resources(ctx: &ctx, resources: &erst_resources);
1225 if (rc)
1226 goto err_fini;
1227 rc = apei_resources_request(resources: &erst_resources, desc: "APEI ERST");
1228 if (rc)
1229 goto err_fini;
1230 rc = apei_exec_pre_map_gars(ctx: &ctx);
1231 if (rc)
1232 goto err_release;
1233 rc = erst_get_erange(range: &erst_erange);
1234 if (rc) {
1235 if (rc == -ENODEV)
1236 pr_info(
1237 "The corresponding hardware device or firmware implementation "
1238 "is not available.\n");
1239 else
1240 pr_err("Failed to get Error Log Address Range.\n");
1241 goto err_unmap_reg;
1242 }
1243
1244 r = request_mem_region(erst_erange.base, erst_erange.size, "APEI ERST");
1245 if (!r) {
1246 pr_err("Can not request [mem %#010llx-%#010llx] for ERST.\n",
1247 (unsigned long long)erst_erange.base,
1248 (unsigned long long)erst_erange.base + erst_erange.size - 1);
1249 rc = -EIO;
1250 goto err_unmap_reg;
1251 }
1252 rc = -ENOMEM;
1253 erst_erange.vaddr = ioremap_cache(offset: erst_erange.base,
1254 size: erst_erange.size);
1255 if (!erst_erange.vaddr)
1256 goto err_release_erange;
1257
1258 pr_info(
1259 "Error Record Serialization Table (ERST) support is initialized.\n");
1260
1261 buf = kmalloc(size: erst_erange.size, GFP_KERNEL);
1262 if (buf) {
1263 erst_info.buf = buf + sizeof(struct cper_pstore_record);
1264 erst_info.bufsize = erst_erange.size -
1265 sizeof(struct cper_pstore_record);
1266 rc = pstore_register(&erst_info);
1267 if (rc) {
1268 if (rc != -EPERM)
1269 pr_info(
1270 "Could not register with persistent store.\n");
1271 erst_info.buf = NULL;
1272 erst_info.bufsize = 0;
1273 kfree(objp: buf);
1274 }
1275 } else
1276 pr_err(
1277 "Failed to allocate %lld bytes for persistent store error log.\n",
1278 erst_erange.size);
1279
1280 /* Cleanup ERST Resources */
1281 apei_resources_fini(resources: &erst_resources);
1282
1283 return 0;
1284
1285err_release_erange:
1286 release_mem_region(erst_erange.base, erst_erange.size);
1287err_unmap_reg:
1288 apei_exec_post_unmap_gars(ctx: &ctx);
1289err_release:
1290 apei_resources_release(resources: &erst_resources);
1291err_fini:
1292 apei_resources_fini(resources: &erst_resources);
1293err_put_erst_tab:
1294 acpi_put_table(table: (struct acpi_table_header *)erst_tab);
1295err:
1296 erst_disable = 1;
1297 return rc;
1298}
1299
1300device_initcall(erst_init);
1301

source code of linux/drivers/acpi/apei/erst.c