Merge branch 'apei' into release
Conflicts: drivers/acpi/apei/apei-base.c This was a conflict between15afae6046
(CPI, APEI: Fix incorrect APEI register bit width check and usage) and653f4b538f
(ACPICA: Expand OSL memory read/write interfaces to 64 bits) The former changed a parameter in the call to acpi_os_read_memory64() and the later replaced all calls to acpi_os_read_memory64() with calls to acpi_os_read_memory(). Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
commit
73f0533049
5 changed files with 64 additions and 26 deletions
|
@ -53,6 +53,14 @@ directory apei/einj. The following files are provided.
|
||||||
This file is used to set the second error parameter value. Effect of
|
This file is used to set the second error parameter value. Effect of
|
||||||
parameter depends on error_type specified.
|
parameter depends on error_type specified.
|
||||||
|
|
||||||
|
- notrigger
|
||||||
|
The EINJ mechanism is a two step process. First inject the error, then
|
||||||
|
perform some actions to trigger it. Setting "notrigger" to 1 skips the
|
||||||
|
trigger phase, which *may* allow the user to cause the error in some other
|
||||||
|
context by a simple access to the cpu, memory location, or device that is
|
||||||
|
the target of the error injection. Whether this actually works depends
|
||||||
|
on what operations the BIOS actually includes in the trigger phase.
|
||||||
|
|
||||||
BIOS versions based in the ACPI 4.0 specification have limited options
|
BIOS versions based in the ACPI 4.0 specification have limited options
|
||||||
to control where the errors are injected. Your BIOS may support an
|
to control where the errors are injected. Your BIOS may support an
|
||||||
extension (enabled with the param_extension=1 module parameter, or
|
extension (enabled with the param_extension=1 module parameter, or
|
||||||
|
|
|
@ -558,33 +558,48 @@ void apei_resources_release(struct apei_resources *resources)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(apei_resources_release);
|
EXPORT_SYMBOL_GPL(apei_resources_release);
|
||||||
|
|
||||||
static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
|
static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
|
||||||
|
u32 *access_bit_width)
|
||||||
{
|
{
|
||||||
u32 width, space_id;
|
u32 bit_width, bit_offset, access_size_code, space_id;
|
||||||
|
|
||||||
width = reg->bit_width;
|
bit_width = reg->bit_width;
|
||||||
|
bit_offset = reg->bit_offset;
|
||||||
|
access_size_code = reg->access_width;
|
||||||
space_id = reg->space_id;
|
space_id = reg->space_id;
|
||||||
/* Handle possible alignment issues */
|
/* Handle possible alignment issues */
|
||||||
memcpy(paddr, ®->address, sizeof(*paddr));
|
memcpy(paddr, ®->address, sizeof(*paddr));
|
||||||
if (!*paddr) {
|
if (!*paddr) {
|
||||||
pr_warning(FW_BUG APEI_PFX
|
pr_warning(FW_BUG APEI_PFX
|
||||||
"Invalid physical address in GAR [0x%llx/%u/%u]\n",
|
"Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n",
|
||||||
*paddr, width, space_id);
|
*paddr, bit_width, bit_offset, access_size_code,
|
||||||
|
space_id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) {
|
if (access_size_code < 1 || access_size_code > 4) {
|
||||||
pr_warning(FW_BUG APEI_PFX
|
pr_warning(FW_BUG APEI_PFX
|
||||||
"Invalid bit width in GAR [0x%llx/%u/%u]\n",
|
"Invalid access size code in GAR [0x%llx/%u/%u/%u/%u]\n",
|
||||||
*paddr, width, space_id);
|
*paddr, bit_width, bit_offset, access_size_code,
|
||||||
|
space_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
*access_bit_width = 1UL << (access_size_code + 2);
|
||||||
|
|
||||||
|
if ((bit_width + bit_offset) > *access_bit_width) {
|
||||||
|
pr_warning(FW_BUG APEI_PFX
|
||||||
|
"Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n",
|
||||||
|
*paddr, bit_width, bit_offset, access_size_code,
|
||||||
|
space_id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
|
if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
|
||||||
space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
|
space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||||
pr_warning(FW_BUG APEI_PFX
|
pr_warning(FW_BUG APEI_PFX
|
||||||
"Invalid address space type in GAR [0x%llx/%u/%u]\n",
|
"Invalid address space type in GAR [0x%llx/%u/%u/%u/%u]\n",
|
||||||
*paddr, width, space_id);
|
*paddr, bit_width, bit_offset, access_size_code,
|
||||||
|
space_id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,23 +610,25 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
|
||||||
int apei_read(u64 *val, struct acpi_generic_address *reg)
|
int apei_read(u64 *val, struct acpi_generic_address *reg)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
u32 access_bit_width;
|
||||||
u64 address;
|
u64 address;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
|
|
||||||
rc = apei_check_gar(reg, &address);
|
rc = apei_check_gar(reg, &address, &access_bit_width);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
*val = 0;
|
*val = 0;
|
||||||
switch(reg->space_id) {
|
switch(reg->space_id) {
|
||||||
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
||||||
status = acpi_os_read_memory((acpi_physical_address)
|
status = acpi_os_read_memory((acpi_physical_address) address,
|
||||||
address, val, reg->bit_width);
|
val, access_bit_width);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
break;
|
break;
|
||||||
case ACPI_ADR_SPACE_SYSTEM_IO:
|
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||||
status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
|
status = acpi_os_read_port(address, (u32 *)val,
|
||||||
|
access_bit_width);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
break;
|
break;
|
||||||
|
@ -627,22 +644,23 @@ EXPORT_SYMBOL_GPL(apei_read);
|
||||||
int apei_write(u64 val, struct acpi_generic_address *reg)
|
int apei_write(u64 val, struct acpi_generic_address *reg)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
u32 access_bit_width;
|
||||||
u64 address;
|
u64 address;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
|
|
||||||
rc = apei_check_gar(reg, &address);
|
rc = apei_check_gar(reg, &address, &access_bit_width);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
switch (reg->space_id) {
|
switch (reg->space_id) {
|
||||||
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
||||||
status = acpi_os_write_memory((acpi_physical_address)
|
status = acpi_os_write_memory((acpi_physical_address) address,
|
||||||
address, val, reg->bit_width);
|
val, access_bit_width);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
break;
|
break;
|
||||||
case ACPI_ADR_SPACE_SYSTEM_IO:
|
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||||
status = acpi_os_write_port(address, val, reg->bit_width);
|
status = acpi_os_write_port(address, val, access_bit_width);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
break;
|
break;
|
||||||
|
@ -661,23 +679,24 @@ static int collect_res_callback(struct apei_exec_context *ctx,
|
||||||
struct apei_resources *resources = data;
|
struct apei_resources *resources = data;
|
||||||
struct acpi_generic_address *reg = &entry->register_region;
|
struct acpi_generic_address *reg = &entry->register_region;
|
||||||
u8 ins = entry->instruction;
|
u8 ins = entry->instruction;
|
||||||
|
u32 access_bit_width;
|
||||||
u64 paddr;
|
u64 paddr;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER))
|
if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rc = apei_check_gar(reg, &paddr);
|
rc = apei_check_gar(reg, &paddr, &access_bit_width);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
switch (reg->space_id) {
|
switch (reg->space_id) {
|
||||||
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
||||||
return apei_res_add(&resources->iomem, paddr,
|
return apei_res_add(&resources->iomem, paddr,
|
||||||
reg->bit_width / 8);
|
access_bit_width / 8);
|
||||||
case ACPI_ADR_SPACE_SYSTEM_IO:
|
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||||
return apei_res_add(&resources->ioport, paddr,
|
return apei_res_add(&resources->ioport, paddr,
|
||||||
reg->bit_width / 8);
|
access_bit_width / 8);
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,6 +362,7 @@ void apei_estatus_print(const char *pfx,
|
||||||
gedata_len = gdata->error_data_length;
|
gedata_len = gdata->error_data_length;
|
||||||
apei_estatus_print_section(pfx, gdata, sec_no);
|
apei_estatus_print_section(pfx, gdata, sec_no);
|
||||||
data_len -= gedata_len + sizeof(*gdata);
|
data_len -= gedata_len + sizeof(*gdata);
|
||||||
|
gdata = (void *)(gdata + 1) + gedata_len;
|
||||||
sec_no++;
|
sec_no++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,6 +397,7 @@ int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
|
||||||
if (gedata_len > data_len - sizeof(*gdata))
|
if (gedata_len > data_len - sizeof(*gdata))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
data_len -= gedata_len + sizeof(*gdata);
|
data_len -= gedata_len + sizeof(*gdata);
|
||||||
|
gdata = (void *)(gdata + 1) + gedata_len;
|
||||||
}
|
}
|
||||||
if (data_len)
|
if (data_len)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -74,6 +74,8 @@ struct vendor_error_type_extension {
|
||||||
u8 reserved[3];
|
u8 reserved[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static u32 notrigger;
|
||||||
|
|
||||||
static u32 vendor_flags;
|
static u32 vendor_flags;
|
||||||
static struct debugfs_blob_wrapper vendor_blob;
|
static struct debugfs_blob_wrapper vendor_blob;
|
||||||
static char vendor_dev[64];
|
static char vendor_dev[64];
|
||||||
|
@ -238,7 +240,7 @@ static void *einj_get_parameter_address(void)
|
||||||
return v5param;
|
return v5param;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (paddrv4) {
|
if (param_extension && paddrv4) {
|
||||||
struct einj_parameter *v4param;
|
struct einj_parameter *v4param;
|
||||||
|
|
||||||
v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param));
|
v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param));
|
||||||
|
@ -496,9 +498,11 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
trigger_paddr = apei_exec_ctx_get_output(&ctx);
|
trigger_paddr = apei_exec_ctx_get_output(&ctx);
|
||||||
rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
|
if (notrigger == 0) {
|
||||||
if (rc)
|
rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
|
||||||
return rc;
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
|
rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -700,6 +704,11 @@ static int __init einj_init(void)
|
||||||
einj_debug_dir, &error_param2);
|
einj_debug_dir, &error_param2);
|
||||||
if (!fentry)
|
if (!fentry)
|
||||||
goto err_unmap;
|
goto err_unmap;
|
||||||
|
|
||||||
|
fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
|
||||||
|
einj_debug_dir, ¬rigger);
|
||||||
|
if (!fentry)
|
||||||
|
goto err_unmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vendor_dev[0]) {
|
if (vendor_dev[0]) {
|
||||||
|
|
|
@ -917,7 +917,7 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
|
||||||
{
|
{
|
||||||
if ((erst_tab->header_length !=
|
if ((erst_tab->header_length !=
|
||||||
(sizeof(struct acpi_table_erst) - sizeof(erst_tab->header)))
|
(sizeof(struct acpi_table_erst) - sizeof(erst_tab->header)))
|
||||||
&& (erst_tab->header_length != sizeof(struct acpi_table_einj)))
|
&& (erst_tab->header_length != sizeof(struct acpi_table_erst)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (erst_tab->header.length < sizeof(struct acpi_table_erst))
|
if (erst_tab->header.length < sizeof(struct acpi_table_erst))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
Loading…
Reference in a new issue