aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/apei/einj.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/apei/einj.c')
-rw-r--r--drivers/acpi/apei/einj.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 2cc8e034a3c0..fb57d03e698b 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -32,6 +32,7 @@
32#include <linux/seq_file.h> 32#include <linux/seq_file.h>
33#include <linux/nmi.h> 33#include <linux/nmi.h>
34#include <linux/delay.h> 34#include <linux/delay.h>
35#include <linux/mm.h>
35#include <acpi/acpi.h> 36#include <acpi/acpi.h>
36 37
37#include "apei-internal.h" 38#include "apei-internal.h"
@@ -41,6 +42,10 @@
41#define SPIN_UNIT 100 /* 100ns */ 42#define SPIN_UNIT 100 /* 100ns */
42/* Firmware should respond within 1 milliseconds */ 43/* Firmware should respond within 1 milliseconds */
43#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) 44#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC)
45#define ACPI5_VENDOR_BIT BIT(31)
46#define MEM_ERROR_MASK (ACPI_EINJ_MEMORY_CORRECTABLE | \
47 ACPI_EINJ_MEMORY_UNCORRECTABLE | \
48 ACPI_EINJ_MEMORY_FATAL)
44 49
45/* 50/*
46 * ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action. 51 * ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action.
@@ -367,7 +372,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
367 * This will cause resource conflict with regular memory. So 372 * This will cause resource conflict with regular memory. So
368 * remove it from trigger table resources. 373 * remove it from trigger table resources.
369 */ 374 */
370 if ((param_extension || acpi5) && (type & 0x0038) && param2) { 375 if ((param_extension || acpi5) && (type & MEM_ERROR_MASK) && param2) {
371 struct apei_resources addr_resources; 376 struct apei_resources addr_resources;
372 apei_resources_init(&addr_resources); 377 apei_resources_init(&addr_resources);
373 trigger_param_region = einj_get_trigger_parameter_region( 378 trigger_param_region = einj_get_trigger_parameter_region(
@@ -427,7 +432,7 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
427 struct set_error_type_with_address *v5param = einj_param; 432 struct set_error_type_with_address *v5param = einj_param;
428 433
429 v5param->type = type; 434 v5param->type = type;
430 if (type & 0x80000000) { 435 if (type & ACPI5_VENDOR_BIT) {
431 switch (vendor_flags) { 436 switch (vendor_flags) {
432 case SETWA_FLAGS_APICID: 437 case SETWA_FLAGS_APICID:
433 v5param->apicid = param1; 438 v5param->apicid = param1;
@@ -512,7 +517,34 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
512static int einj_error_inject(u32 type, u64 param1, u64 param2) 517static int einj_error_inject(u32 type, u64 param1, u64 param2)
513{ 518{
514 int rc; 519 int rc;
520 unsigned long pfn;
515 521
522 /*
523 * We need extra sanity checks for memory errors.
524 * Other types leap directly to injection.
525 */
526
527 /* ensure param1/param2 existed */
528 if (!(param_extension || acpi5))
529 goto inject;
530
531 /* ensure injection is memory related */
532 if (type & ACPI5_VENDOR_BIT) {
533 if (vendor_flags != SETWA_FLAGS_MEM)
534 goto inject;
535 } else if (!(type & MEM_ERROR_MASK))
536 goto inject;
537
538 /*
539 * Disallow crazy address masks that give BIOS leeway to pick
540 * injection address almost anywhere. Insist on page or
541 * better granularity and that target address is normal RAM.
542 */
543 pfn = PFN_DOWN(param1 & param2);
544 if (!page_is_ram(pfn) || ((param2 & PAGE_MASK) != PAGE_MASK))
545 return -EINVAL;
546
547inject:
516 mutex_lock(&einj_mutex); 548 mutex_lock(&einj_mutex);
517 rc = __einj_error_inject(type, param1, param2); 549 rc = __einj_error_inject(type, param1, param2);
518 mutex_unlock(&einj_mutex); 550 mutex_unlock(&einj_mutex);
@@ -590,7 +622,7 @@ static int error_type_set(void *data, u64 val)
590 * Vendor defined types have 0x80000000 bit set, and 622 * Vendor defined types have 0x80000000 bit set, and
591 * are not enumerated by ACPI_EINJ_GET_ERROR_TYPE 623 * are not enumerated by ACPI_EINJ_GET_ERROR_TYPE
592 */ 624 */
593 vendor = val & 0x80000000; 625 vendor = val & ACPI5_VENDOR_BIT;
594 tval = val & 0x7fffffff; 626 tval = val & 0x7fffffff;
595 627
596 /* Only one error type can be specified */ 628 /* Only one error type can be specified */