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