root/drivers/acpi/apei/einj.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. einj_exec_ctx_init
  2. __einj_get_available_error_type
  3. einj_get_available_error_type
  4. einj_timedout
  5. check_vendor_extension
  6. einj_get_parameter_address
  7. einj_check_trigger_header
  8. einj_get_trigger_parameter_region
  9. __einj_error_trigger
  10. __einj_error_inject
  11. einj_error_inject
  12. available_error_type_show
  13. error_type_get
  14. error_type_set
  15. error_inject_set
  16. einj_check_table
  17. einj_init
  18. einj_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * APEI Error INJection support
   4  *
   5  * EINJ provides a hardware error injection mechanism, this is useful
   6  * for debugging and testing of other APEI and RAS features.
   7  *
   8  * For more information about EINJ, please refer to ACPI Specification
   9  * version 4.0, section 17.5.
  10  *
  11  * Copyright 2009-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/io.h>
  19 #include <linux/debugfs.h>
  20 #include <linux/seq_file.h>
  21 #include <linux/nmi.h>
  22 #include <linux/delay.h>
  23 #include <linux/mm.h>
  24 #include <asm/unaligned.h>
  25 
  26 #include "apei-internal.h"
  27 
  28 #undef pr_fmt
  29 #define pr_fmt(fmt) "EINJ: " fmt
  30 
  31 #define SPIN_UNIT               100                     /* 100ns */
  32 /* Firmware should respond within 1 milliseconds */
  33 #define FIRMWARE_TIMEOUT        (1 * NSEC_PER_MSEC)
  34 #define ACPI5_VENDOR_BIT        BIT(31)
  35 #define MEM_ERROR_MASK          (ACPI_EINJ_MEMORY_CORRECTABLE | \
  36                                 ACPI_EINJ_MEMORY_UNCORRECTABLE | \
  37                                 ACPI_EINJ_MEMORY_FATAL)
  38 
  39 /*
  40  * ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action.
  41  */
  42 static int acpi5;
  43 
  44 struct set_error_type_with_address {
  45         u32     type;
  46         u32     vendor_extension;
  47         u32     flags;
  48         u32     apicid;
  49         u64     memory_address;
  50         u64     memory_address_range;
  51         u32     pcie_sbdf;
  52 };
  53 enum {
  54         SETWA_FLAGS_APICID = 1,
  55         SETWA_FLAGS_MEM = 2,
  56         SETWA_FLAGS_PCIE_SBDF = 4,
  57 };
  58 
  59 /*
  60  * Vendor extensions for platform specific operations
  61  */
  62 struct vendor_error_type_extension {
  63         u32     length;
  64         u32     pcie_sbdf;
  65         u16     vendor_id;
  66         u16     device_id;
  67         u8      rev_id;
  68         u8      reserved[3];
  69 };
  70 
  71 static u32 notrigger;
  72 
  73 static u32 vendor_flags;
  74 static struct debugfs_blob_wrapper vendor_blob;
  75 static char vendor_dev[64];
  76 
  77 /*
  78  * Some BIOSes allow parameters to the SET_ERROR_TYPE entries in the
  79  * EINJ table through an unpublished extension. Use with caution as
  80  * most will ignore the parameter and make their own choice of address
  81  * for error injection.  This extension is used only if
  82  * param_extension module parameter is specified.
  83  */
  84 struct einj_parameter {
  85         u64 type;
  86         u64 reserved1;
  87         u64 reserved2;
  88         u64 param1;
  89         u64 param2;
  90 };
  91 
  92 #define EINJ_OP_BUSY                    0x1
  93 #define EINJ_STATUS_SUCCESS             0x0
  94 #define EINJ_STATUS_FAIL                0x1
  95 #define EINJ_STATUS_INVAL               0x2
  96 
  97 #define EINJ_TAB_ENTRY(tab)                                             \
  98         ((struct acpi_whea_header *)((char *)(tab) +                    \
  99                                     sizeof(struct acpi_table_einj)))
 100 
 101 static bool param_extension;
 102 module_param(param_extension, bool, 0);
 103 
 104 static struct acpi_table_einj *einj_tab;
 105 
 106 static struct apei_resources einj_resources;
 107 
 108 static struct apei_exec_ins_type einj_ins_type[] = {
 109         [ACPI_EINJ_READ_REGISTER] = {
 110                 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
 111                 .run   = apei_exec_read_register,
 112         },
 113         [ACPI_EINJ_READ_REGISTER_VALUE] = {
 114                 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
 115                 .run   = apei_exec_read_register_value,
 116         },
 117         [ACPI_EINJ_WRITE_REGISTER] = {
 118                 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
 119                 .run   = apei_exec_write_register,
 120         },
 121         [ACPI_EINJ_WRITE_REGISTER_VALUE] = {
 122                 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
 123                 .run   = apei_exec_write_register_value,
 124         },
 125         [ACPI_EINJ_NOOP] = {
 126                 .flags = 0,
 127                 .run   = apei_exec_noop,
 128         },
 129 };
 130 
 131 /*
 132  * Prevent EINJ interpreter to run simultaneously, because the
 133  * corresponding firmware implementation may not work properly when
 134  * invoked simultaneously.
 135  */
 136 static DEFINE_MUTEX(einj_mutex);
 137 
 138 static void *einj_param;
 139 
 140 static void einj_exec_ctx_init(struct apei_exec_context *ctx)
 141 {
 142         apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type),
 143                            EINJ_TAB_ENTRY(einj_tab), einj_tab->entries);
 144 }
 145 
 146 static int __einj_get_available_error_type(u32 *type)
 147 {
 148         struct apei_exec_context ctx;
 149         int rc;
 150 
 151         einj_exec_ctx_init(&ctx);
 152         rc = apei_exec_run(&ctx, ACPI_EINJ_GET_ERROR_TYPE);
 153         if (rc)
 154                 return rc;
 155         *type = apei_exec_ctx_get_output(&ctx);
 156 
 157         return 0;
 158 }
 159 
 160 /* Get error injection capabilities of the platform */
 161 static int einj_get_available_error_type(u32 *type)
 162 {
 163         int rc;
 164 
 165         mutex_lock(&einj_mutex);
 166         rc = __einj_get_available_error_type(type);
 167         mutex_unlock(&einj_mutex);
 168 
 169         return rc;
 170 }
 171 
 172 static int einj_timedout(u64 *t)
 173 {
 174         if ((s64)*t < SPIN_UNIT) {
 175                 pr_warning(FW_WARN "Firmware does not respond in time\n");
 176                 return 1;
 177         }
 178         *t -= SPIN_UNIT;
 179         ndelay(SPIN_UNIT);
 180         touch_nmi_watchdog();
 181         return 0;
 182 }
 183 
 184 static void check_vendor_extension(u64 paddr,
 185                                    struct set_error_type_with_address *v5param)
 186 {
 187         int     offset = v5param->vendor_extension;
 188         struct  vendor_error_type_extension *v;
 189         u32     sbdf;
 190 
 191         if (!offset)
 192                 return;
 193         v = acpi_os_map_iomem(paddr + offset, sizeof(*v));
 194         if (!v)
 195                 return;
 196         sbdf = v->pcie_sbdf;
 197         sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n",
 198                 sbdf >> 24, (sbdf >> 16) & 0xff,
 199                 (sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7,
 200                  v->vendor_id, v->device_id, v->rev_id);
 201         acpi_os_unmap_iomem(v, sizeof(*v));
 202 }
 203 
 204 static void *einj_get_parameter_address(void)
 205 {
 206         int i;
 207         u64 pa_v4 = 0, pa_v5 = 0;
 208         struct acpi_whea_header *entry;
 209 
 210         entry = EINJ_TAB_ENTRY(einj_tab);
 211         for (i = 0; i < einj_tab->entries; i++) {
 212                 if (entry->action == ACPI_EINJ_SET_ERROR_TYPE &&
 213                     entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
 214                     entry->register_region.space_id ==
 215                     ACPI_ADR_SPACE_SYSTEM_MEMORY)
 216                         pa_v4 = get_unaligned(&entry->register_region.address);
 217                 if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS &&
 218                     entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
 219                     entry->register_region.space_id ==
 220                     ACPI_ADR_SPACE_SYSTEM_MEMORY)
 221                         pa_v5 = get_unaligned(&entry->register_region.address);
 222                 entry++;
 223         }
 224         if (pa_v5) {
 225                 struct set_error_type_with_address *v5param;
 226 
 227                 v5param = acpi_os_map_iomem(pa_v5, sizeof(*v5param));
 228                 if (v5param) {
 229                         acpi5 = 1;
 230                         check_vendor_extension(pa_v5, v5param);
 231                         return v5param;
 232                 }
 233         }
 234         if (param_extension && pa_v4) {
 235                 struct einj_parameter *v4param;
 236 
 237                 v4param = acpi_os_map_iomem(pa_v4, sizeof(*v4param));
 238                 if (!v4param)
 239                         return NULL;
 240                 if (v4param->reserved1 || v4param->reserved2) {
 241                         acpi_os_unmap_iomem(v4param, sizeof(*v4param));
 242                         return NULL;
 243                 }
 244                 return v4param;
 245         }
 246 
 247         return NULL;
 248 }
 249 
 250 /* do sanity check to trigger table */
 251 static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
 252 {
 253         if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger))
 254                 return -EINVAL;
 255         if (trigger_tab->table_size > PAGE_SIZE ||
 256             trigger_tab->table_size < trigger_tab->header_size)
 257                 return -EINVAL;
 258         if (trigger_tab->entry_count !=
 259             (trigger_tab->table_size - trigger_tab->header_size) /
 260             sizeof(struct acpi_einj_entry))
 261                 return -EINVAL;
 262 
 263         return 0;
 264 }
 265 
 266 static struct acpi_generic_address *einj_get_trigger_parameter_region(
 267         struct acpi_einj_trigger *trigger_tab, u64 param1, u64 param2)
 268 {
 269         int i;
 270         struct acpi_whea_header *entry;
 271 
 272         entry = (struct acpi_whea_header *)
 273                 ((char *)trigger_tab + sizeof(struct acpi_einj_trigger));
 274         for (i = 0; i < trigger_tab->entry_count; i++) {
 275                 if (entry->action == ACPI_EINJ_TRIGGER_ERROR &&
 276                 entry->instruction <= ACPI_EINJ_WRITE_REGISTER_VALUE &&
 277                 entry->register_region.space_id ==
 278                         ACPI_ADR_SPACE_SYSTEM_MEMORY &&
 279                 (entry->register_region.address & param2) == (param1 & param2))
 280                         return &entry->register_region;
 281                 entry++;
 282         }
 283 
 284         return NULL;
 285 }
 286 /* Execute instructions in trigger error action table */
 287 static int __einj_error_trigger(u64 trigger_paddr, u32 type,
 288                                 u64 param1, u64 param2)
 289 {
 290         struct acpi_einj_trigger *trigger_tab = NULL;
 291         struct apei_exec_context trigger_ctx;
 292         struct apei_resources trigger_resources;
 293         struct acpi_whea_header *trigger_entry;
 294         struct resource *r;
 295         u32 table_size;
 296         int rc = -EIO;
 297         struct acpi_generic_address *trigger_param_region = NULL;
 298 
 299         r = request_mem_region(trigger_paddr, sizeof(*trigger_tab),
 300                                "APEI EINJ Trigger Table");
 301         if (!r) {
 302                 pr_err("Can not request [mem %#010llx-%#010llx] for Trigger table\n",
 303                        (unsigned long long)trigger_paddr,
 304                        (unsigned long long)trigger_paddr +
 305                             sizeof(*trigger_tab) - 1);
 306                 goto out;
 307         }
 308         trigger_tab = ioremap_cache(trigger_paddr, sizeof(*trigger_tab));
 309         if (!trigger_tab) {
 310                 pr_err("Failed to map trigger table!\n");
 311                 goto out_rel_header;
 312         }
 313         rc = einj_check_trigger_header(trigger_tab);
 314         if (rc) {
 315                 pr_warning(FW_BUG "Invalid trigger error action table.\n");
 316                 goto out_rel_header;
 317         }
 318 
 319         /* No action structures in the TRIGGER_ERROR table, nothing to do */
 320         if (!trigger_tab->entry_count)
 321                 goto out_rel_header;
 322 
 323         rc = -EIO;
 324         table_size = trigger_tab->table_size;
 325         r = request_mem_region(trigger_paddr + sizeof(*trigger_tab),
 326                                table_size - sizeof(*trigger_tab),
 327                                "APEI EINJ Trigger Table");
 328         if (!r) {
 329                 pr_err("Can not request [mem %#010llx-%#010llx] for Trigger Table Entry\n",
 330                        (unsigned long long)trigger_paddr + sizeof(*trigger_tab),
 331                        (unsigned long long)trigger_paddr + table_size - 1);
 332                 goto out_rel_header;
 333         }
 334         iounmap(trigger_tab);
 335         trigger_tab = ioremap_cache(trigger_paddr, table_size);
 336         if (!trigger_tab) {
 337                 pr_err("Failed to map trigger table!\n");
 338                 goto out_rel_entry;
 339         }
 340         trigger_entry = (struct acpi_whea_header *)
 341                 ((char *)trigger_tab + sizeof(struct acpi_einj_trigger));
 342         apei_resources_init(&trigger_resources);
 343         apei_exec_ctx_init(&trigger_ctx, einj_ins_type,
 344                            ARRAY_SIZE(einj_ins_type),
 345                            trigger_entry, trigger_tab->entry_count);
 346         rc = apei_exec_collect_resources(&trigger_ctx, &trigger_resources);
 347         if (rc)
 348                 goto out_fini;
 349         rc = apei_resources_sub(&trigger_resources, &einj_resources);
 350         if (rc)
 351                 goto out_fini;
 352         /*
 353          * Some firmware will access target address specified in
 354          * param1 to trigger the error when injecting memory error.
 355          * This will cause resource conflict with regular memory.  So
 356          * remove it from trigger table resources.
 357          */
 358         if ((param_extension || acpi5) && (type & MEM_ERROR_MASK) && param2) {
 359                 struct apei_resources addr_resources;
 360                 apei_resources_init(&addr_resources);
 361                 trigger_param_region = einj_get_trigger_parameter_region(
 362                         trigger_tab, param1, param2);
 363                 if (trigger_param_region) {
 364                         rc = apei_resources_add(&addr_resources,
 365                                 trigger_param_region->address,
 366                                 trigger_param_region->bit_width/8, true);
 367                         if (rc)
 368                                 goto out_fini;
 369                         rc = apei_resources_sub(&trigger_resources,
 370                                         &addr_resources);
 371                 }
 372                 apei_resources_fini(&addr_resources);
 373                 if (rc)
 374                         goto out_fini;
 375         }
 376         rc = apei_resources_request(&trigger_resources, "APEI EINJ Trigger");
 377         if (rc)
 378                 goto out_fini;
 379         rc = apei_exec_pre_map_gars(&trigger_ctx);
 380         if (rc)
 381                 goto out_release;
 382 
 383         rc = apei_exec_run(&trigger_ctx, ACPI_EINJ_TRIGGER_ERROR);
 384 
 385         apei_exec_post_unmap_gars(&trigger_ctx);
 386 out_release:
 387         apei_resources_release(&trigger_resources);
 388 out_fini:
 389         apei_resources_fini(&trigger_resources);
 390 out_rel_entry:
 391         release_mem_region(trigger_paddr + sizeof(*trigger_tab),
 392                            table_size - sizeof(*trigger_tab));
 393 out_rel_header:
 394         release_mem_region(trigger_paddr, sizeof(*trigger_tab));
 395 out:
 396         if (trigger_tab)
 397                 iounmap(trigger_tab);
 398 
 399         return rc;
 400 }
 401 
 402 static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
 403                                u64 param3, u64 param4)
 404 {
 405         struct apei_exec_context ctx;
 406         u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT;
 407         int rc;
 408 
 409         einj_exec_ctx_init(&ctx);
 410 
 411         rc = apei_exec_run_optional(&ctx, ACPI_EINJ_BEGIN_OPERATION);
 412         if (rc)
 413                 return rc;
 414         apei_exec_ctx_set_input(&ctx, type);
 415         if (acpi5) {
 416                 struct set_error_type_with_address *v5param = einj_param;
 417 
 418                 v5param->type = type;
 419                 if (type & ACPI5_VENDOR_BIT) {
 420                         switch (vendor_flags) {
 421                         case SETWA_FLAGS_APICID:
 422                                 v5param->apicid = param1;
 423                                 break;
 424                         case SETWA_FLAGS_MEM:
 425                                 v5param->memory_address = param1;
 426                                 v5param->memory_address_range = param2;
 427                                 break;
 428                         case SETWA_FLAGS_PCIE_SBDF:
 429                                 v5param->pcie_sbdf = param1;
 430                                 break;
 431                         }
 432                         v5param->flags = vendor_flags;
 433                 } else if (flags) {
 434                                 v5param->flags = flags;
 435                                 v5param->memory_address = param1;
 436                                 v5param->memory_address_range = param2;
 437                                 v5param->apicid = param3;
 438                                 v5param->pcie_sbdf = param4;
 439                 } else {
 440                         switch (type) {
 441                         case ACPI_EINJ_PROCESSOR_CORRECTABLE:
 442                         case ACPI_EINJ_PROCESSOR_UNCORRECTABLE:
 443                         case ACPI_EINJ_PROCESSOR_FATAL:
 444                                 v5param->apicid = param1;
 445                                 v5param->flags = SETWA_FLAGS_APICID;
 446                                 break;
 447                         case ACPI_EINJ_MEMORY_CORRECTABLE:
 448                         case ACPI_EINJ_MEMORY_UNCORRECTABLE:
 449                         case ACPI_EINJ_MEMORY_FATAL:
 450                                 v5param->memory_address = param1;
 451                                 v5param->memory_address_range = param2;
 452                                 v5param->flags = SETWA_FLAGS_MEM;
 453                                 break;
 454                         case ACPI_EINJ_PCIX_CORRECTABLE:
 455                         case ACPI_EINJ_PCIX_UNCORRECTABLE:
 456                         case ACPI_EINJ_PCIX_FATAL:
 457                                 v5param->pcie_sbdf = param1;
 458                                 v5param->flags = SETWA_FLAGS_PCIE_SBDF;
 459                                 break;
 460                         }
 461                 }
 462         } else {
 463                 rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE);
 464                 if (rc)
 465                         return rc;
 466                 if (einj_param) {
 467                         struct einj_parameter *v4param = einj_param;
 468                         v4param->param1 = param1;
 469                         v4param->param2 = param2;
 470                 }
 471         }
 472         rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION);
 473         if (rc)
 474                 return rc;
 475         for (;;) {
 476                 rc = apei_exec_run(&ctx, ACPI_EINJ_CHECK_BUSY_STATUS);
 477                 if (rc)
 478                         return rc;
 479                 val = apei_exec_ctx_get_output(&ctx);
 480                 if (!(val & EINJ_OP_BUSY))
 481                         break;
 482                 if (einj_timedout(&timeout))
 483                         return -EIO;
 484         }
 485         rc = apei_exec_run(&ctx, ACPI_EINJ_GET_COMMAND_STATUS);
 486         if (rc)
 487                 return rc;
 488         val = apei_exec_ctx_get_output(&ctx);
 489         if (val != EINJ_STATUS_SUCCESS)
 490                 return -EBUSY;
 491 
 492         rc = apei_exec_run(&ctx, ACPI_EINJ_GET_TRIGGER_TABLE);
 493         if (rc)
 494                 return rc;
 495         trigger_paddr = apei_exec_ctx_get_output(&ctx);
 496         if (notrigger == 0) {
 497                 rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
 498                 if (rc)
 499                         return rc;
 500         }
 501         rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
 502 
 503         return rc;
 504 }
 505 
 506 /* Inject the specified hardware error */
 507 static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
 508                              u64 param3, u64 param4)
 509 {
 510         int rc;
 511         u64 base_addr, size;
 512 
 513         /* If user manually set "flags", make sure it is legal */
 514         if (flags && (flags &
 515                 ~(SETWA_FLAGS_APICID|SETWA_FLAGS_MEM|SETWA_FLAGS_PCIE_SBDF)))
 516                 return -EINVAL;
 517 
 518         /*
 519          * We need extra sanity checks for memory errors.
 520          * Other types leap directly to injection.
 521          */
 522 
 523         /* ensure param1/param2 existed */
 524         if (!(param_extension || acpi5))
 525                 goto inject;
 526 
 527         /* ensure injection is memory related */
 528         if (type & ACPI5_VENDOR_BIT) {
 529                 if (vendor_flags != SETWA_FLAGS_MEM)
 530                         goto inject;
 531         } else if (!(type & MEM_ERROR_MASK) && !(flags & SETWA_FLAGS_MEM))
 532                 goto inject;
 533 
 534         /*
 535          * Disallow crazy address masks that give BIOS leeway to pick
 536          * injection address almost anywhere. Insist on page or
 537          * better granularity and that target address is normal RAM or
 538          * NVDIMM.
 539          */
 540         base_addr = param1 & param2;
 541         size = ~param2 + 1;
 542 
 543         if (((param2 & PAGE_MASK) != PAGE_MASK) ||
 544             ((region_intersects(base_addr, size, IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)
 545                                 != REGION_INTERSECTS) &&
 546              (region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY)
 547                                 != REGION_INTERSECTS)))
 548                 return -EINVAL;
 549 
 550 inject:
 551         mutex_lock(&einj_mutex);
 552         rc = __einj_error_inject(type, flags, param1, param2, param3, param4);
 553         mutex_unlock(&einj_mutex);
 554 
 555         return rc;
 556 }
 557 
 558 static u32 error_type;
 559 static u32 error_flags;
 560 static u64 error_param1;
 561 static u64 error_param2;
 562 static u64 error_param3;
 563 static u64 error_param4;
 564 static struct dentry *einj_debug_dir;
 565 
 566 static int available_error_type_show(struct seq_file *m, void *v)
 567 {
 568         int rc;
 569         u32 available_error_type = 0;
 570 
 571         rc = einj_get_available_error_type(&available_error_type);
 572         if (rc)
 573                 return rc;
 574         if (available_error_type & 0x0001)
 575                 seq_printf(m, "0x00000001\tProcessor Correctable\n");
 576         if (available_error_type & 0x0002)
 577                 seq_printf(m, "0x00000002\tProcessor Uncorrectable non-fatal\n");
 578         if (available_error_type & 0x0004)
 579                 seq_printf(m, "0x00000004\tProcessor Uncorrectable fatal\n");
 580         if (available_error_type & 0x0008)
 581                 seq_printf(m, "0x00000008\tMemory Correctable\n");
 582         if (available_error_type & 0x0010)
 583                 seq_printf(m, "0x00000010\tMemory Uncorrectable non-fatal\n");
 584         if (available_error_type & 0x0020)
 585                 seq_printf(m, "0x00000020\tMemory Uncorrectable fatal\n");
 586         if (available_error_type & 0x0040)
 587                 seq_printf(m, "0x00000040\tPCI Express Correctable\n");
 588         if (available_error_type & 0x0080)
 589                 seq_printf(m, "0x00000080\tPCI Express Uncorrectable non-fatal\n");
 590         if (available_error_type & 0x0100)
 591                 seq_printf(m, "0x00000100\tPCI Express Uncorrectable fatal\n");
 592         if (available_error_type & 0x0200)
 593                 seq_printf(m, "0x00000200\tPlatform Correctable\n");
 594         if (available_error_type & 0x0400)
 595                 seq_printf(m, "0x00000400\tPlatform Uncorrectable non-fatal\n");
 596         if (available_error_type & 0x0800)
 597                 seq_printf(m, "0x00000800\tPlatform Uncorrectable fatal\n");
 598 
 599         return 0;
 600 }
 601 
 602 DEFINE_SHOW_ATTRIBUTE(available_error_type);
 603 
 604 static int error_type_get(void *data, u64 *val)
 605 {
 606         *val = error_type;
 607 
 608         return 0;
 609 }
 610 
 611 static int error_type_set(void *data, u64 val)
 612 {
 613         int rc;
 614         u32 available_error_type = 0;
 615         u32 tval, vendor;
 616 
 617         /*
 618          * Vendor defined types have 0x80000000 bit set, and
 619          * are not enumerated by ACPI_EINJ_GET_ERROR_TYPE
 620          */
 621         vendor = val & ACPI5_VENDOR_BIT;
 622         tval = val & 0x7fffffff;
 623 
 624         /* Only one error type can be specified */
 625         if (tval & (tval - 1))
 626                 return -EINVAL;
 627         if (!vendor) {
 628                 rc = einj_get_available_error_type(&available_error_type);
 629                 if (rc)
 630                         return rc;
 631                 if (!(val & available_error_type))
 632                         return -EINVAL;
 633         }
 634         error_type = val;
 635 
 636         return 0;
 637 }
 638 
 639 DEFINE_DEBUGFS_ATTRIBUTE(error_type_fops, error_type_get, error_type_set,
 640                          "0x%llx\n");
 641 
 642 static int error_inject_set(void *data, u64 val)
 643 {
 644         if (!error_type)
 645                 return -EINVAL;
 646 
 647         return einj_error_inject(error_type, error_flags, error_param1, error_param2,
 648                 error_param3, error_param4);
 649 }
 650 
 651 DEFINE_DEBUGFS_ATTRIBUTE(error_inject_fops, NULL, error_inject_set, "%llu\n");
 652 
 653 static int einj_check_table(struct acpi_table_einj *einj_tab)
 654 {
 655         if ((einj_tab->header_length !=
 656              (sizeof(struct acpi_table_einj) - sizeof(einj_tab->header)))
 657             && (einj_tab->header_length != sizeof(struct acpi_table_einj)))
 658                 return -EINVAL;
 659         if (einj_tab->header.length < sizeof(struct acpi_table_einj))
 660                 return -EINVAL;
 661         if (einj_tab->entries !=
 662             (einj_tab->header.length - sizeof(struct acpi_table_einj)) /
 663             sizeof(struct acpi_einj_entry))
 664                 return -EINVAL;
 665 
 666         return 0;
 667 }
 668 
 669 static int __init einj_init(void)
 670 {
 671         int rc;
 672         acpi_status status;
 673         struct apei_exec_context ctx;
 674 
 675         if (acpi_disabled) {
 676                 pr_warn("ACPI disabled.\n");
 677                 return -ENODEV;
 678         }
 679 
 680         status = acpi_get_table(ACPI_SIG_EINJ, 0,
 681                                 (struct acpi_table_header **)&einj_tab);
 682         if (status == AE_NOT_FOUND) {
 683                 pr_warn("EINJ table not found.\n");
 684                 return -ENODEV;
 685         }
 686         else if (ACPI_FAILURE(status)) {
 687                 pr_err("Failed to get EINJ table: %s\n",
 688                                 acpi_format_exception(status));
 689                 return -EINVAL;
 690         }
 691 
 692         rc = einj_check_table(einj_tab);
 693         if (rc) {
 694                 pr_warn(FW_BUG "Invalid EINJ table.\n");
 695                 return -EINVAL;
 696         }
 697 
 698         rc = -ENOMEM;
 699         einj_debug_dir = debugfs_create_dir("einj", apei_get_debugfs_dir());
 700 
 701         debugfs_create_file("available_error_type", S_IRUSR, einj_debug_dir,
 702                             NULL, &available_error_type_fops);
 703         debugfs_create_file_unsafe("error_type", 0600, einj_debug_dir,
 704                                    NULL, &error_type_fops);
 705         debugfs_create_file_unsafe("error_inject", 0200, einj_debug_dir,
 706                                    NULL, &error_inject_fops);
 707 
 708         apei_resources_init(&einj_resources);
 709         einj_exec_ctx_init(&ctx);
 710         rc = apei_exec_collect_resources(&ctx, &einj_resources);
 711         if (rc) {
 712                 pr_err("Error collecting EINJ resources.\n");
 713                 goto err_fini;
 714         }
 715 
 716         rc = apei_resources_request(&einj_resources, "APEI EINJ");
 717         if (rc) {
 718                 pr_err("Error requesting memory/port resources.\n");
 719                 goto err_fini;
 720         }
 721 
 722         rc = apei_exec_pre_map_gars(&ctx);
 723         if (rc) {
 724                 pr_err("Error pre-mapping GARs.\n");
 725                 goto err_release;
 726         }
 727 
 728         rc = -ENOMEM;
 729         einj_param = einj_get_parameter_address();
 730         if ((param_extension || acpi5) && einj_param) {
 731                 debugfs_create_x32("flags", S_IRUSR | S_IWUSR, einj_debug_dir,
 732                                    &error_flags);
 733                 debugfs_create_x64("param1", S_IRUSR | S_IWUSR, einj_debug_dir,
 734                                    &error_param1);
 735                 debugfs_create_x64("param2", S_IRUSR | S_IWUSR, einj_debug_dir,
 736                                    &error_param2);
 737                 debugfs_create_x64("param3", S_IRUSR | S_IWUSR, einj_debug_dir,
 738                                    &error_param3);
 739                 debugfs_create_x64("param4", S_IRUSR | S_IWUSR, einj_debug_dir,
 740                                    &error_param4);
 741                 debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
 742                                    einj_debug_dir, &notrigger);
 743         }
 744 
 745         if (vendor_dev[0]) {
 746                 vendor_blob.data = vendor_dev;
 747                 vendor_blob.size = strlen(vendor_dev);
 748                 debugfs_create_blob("vendor", S_IRUSR, einj_debug_dir,
 749                                     &vendor_blob);
 750                 debugfs_create_x32("vendor_flags", S_IRUSR | S_IWUSR,
 751                                    einj_debug_dir, &vendor_flags);
 752         }
 753 
 754         pr_info("Error INJection is initialized.\n");
 755 
 756         return 0;
 757 
 758 err_release:
 759         apei_resources_release(&einj_resources);
 760 err_fini:
 761         apei_resources_fini(&einj_resources);
 762         debugfs_remove_recursive(einj_debug_dir);
 763 
 764         return rc;
 765 }
 766 
 767 static void __exit einj_exit(void)
 768 {
 769         struct apei_exec_context ctx;
 770 
 771         if (einj_param) {
 772                 acpi_size size = (acpi5) ?
 773                         sizeof(struct set_error_type_with_address) :
 774                         sizeof(struct einj_parameter);
 775 
 776                 acpi_os_unmap_iomem(einj_param, size);
 777         }
 778         einj_exec_ctx_init(&ctx);
 779         apei_exec_post_unmap_gars(&ctx);
 780         apei_resources_release(&einj_resources);
 781         apei_resources_fini(&einj_resources);
 782         debugfs_remove_recursive(einj_debug_dir);
 783 }
 784 
 785 module_init(einj_init);
 786 module_exit(einj_exit);
 787 
 788 MODULE_AUTHOR("Huang Ying");
 789 MODULE_DESCRIPTION("APEI Error INJection support");
 790 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */