Miscellaneous fixes for ACPI EINJ (error injection) code.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJRsQ4tAAoJEKurIx+X31iBAaIP+wf/lGnTtpR6vwRHbrCV2ZXl EC/qnxiqoy8qKe3wn0yVtmORNsBDWnMEsl6ubyHFIhkOL9zrTTQAQRWWzTYu5MWO 4Vl/Z0zgnBmj66TFVCzDMJLOIsx6o/UHg7uiiCawUEQshWd1jYVZ8bEn+iyj36+y mNL74yJkkR9s5AJIQWr7lAKcgeTR8tXHCBuuW5BoY/ThKKtajDKqg8/q4HytPhwi u18OpTUv01jK9oS2t6wMzf4Hl0jeHt3FySSgQFPBwfcMJxDlPXnbzlO98Out9h12 VEye9Ya1CIcVYfPhRjMFgdIvCEbK1afXkk2SRivjOzRFokwk9XR2VTMm5E+KeGZc bh8JGxZwGqTxZQlWgqAdZusL928LxPPF631+ZmaJUfaJMspf4/25Y2tAFWXuAycr foi1kw/KepE956C0cImS5chRaXPzD1+MJa1lIolD2DUZlTVHRx7rlcPIapWLizyd Ir/TNzYUY14oGcQNZMTNcj3sWIUaGn9iEGB+ZtHynW813Sby4bDtvhe8h6UHzADV mQnvpz/qcKYwEjg8HmtpmGYEioLz/6RxUU1I1VuAyOCIgxFwVHkyWf41+IPBsTqc a4cBF0aLXFn4rcmIVlUGACbrog83XLUNrhXfnmLoFgUcA9ljkmY2ydurcQ1GIhcP 5WAzisHQor+F3GmOFfaD =Pywj -----END PGP SIGNATURE----- Merge tag 'please-pull-einj' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras into x86/ras Pull miscellaneous fixes for ACPI EINJ (error injection) code, from Tony Luck. Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Коммит
d908e1ebbc
|
@ -47,11 +47,16 @@ directory apei/einj. The following files are provided.
|
||||||
|
|
||||||
- param1
|
- param1
|
||||||
This file is used to set the first error parameter value. Effect of
|
This file is used to set the first error parameter value. Effect of
|
||||||
parameter depends on error_type specified.
|
parameter depends on error_type specified. For example, if error
|
||||||
|
type is memory related type, the param1 should be a valid physical
|
||||||
|
memory address.
|
||||||
|
|
||||||
- param2
|
- param2
|
||||||
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. For example, if error
|
||||||
|
type is memory related type, the param2 should be a physical memory
|
||||||
|
address mask. Linux requires page or narrower granularity, say,
|
||||||
|
0xfffffffffffff000.
|
||||||
|
|
||||||
- notrigger
|
- notrigger
|
||||||
The EINJ mechanism is a two step process. First inject the error, then
|
The EINJ mechanism is a two step process. First inject the error, then
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/nmi.h>
|
#include <linux/nmi.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
#include <acpi/acpi.h>
|
#include <acpi/acpi.h>
|
||||||
|
|
||||||
#include "apei-internal.h"
|
#include "apei-internal.h"
|
||||||
|
@ -41,6 +42,10 @@
|
||||||
#define SPIN_UNIT 100 /* 100ns */
|
#define SPIN_UNIT 100 /* 100ns */
|
||||||
/* Firmware should respond within 1 milliseconds */
|
/* Firmware should respond within 1 milliseconds */
|
||||||
#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC)
|
#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC)
|
||||||
|
#define ACPI5_VENDOR_BIT BIT(31)
|
||||||
|
#define MEM_ERROR_MASK (ACPI_EINJ_MEMORY_CORRECTABLE | \
|
||||||
|
ACPI_EINJ_MEMORY_UNCORRECTABLE | \
|
||||||
|
ACPI_EINJ_MEMORY_FATAL)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action.
|
* 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,
|
||||||
* This will cause resource conflict with regular memory. So
|
* This will cause resource conflict with regular memory. So
|
||||||
* remove it from trigger table resources.
|
* remove it from trigger table resources.
|
||||||
*/
|
*/
|
||||||
if ((param_extension || acpi5) && (type & 0x0038) && param2) {
|
if ((param_extension || acpi5) && (type & MEM_ERROR_MASK) && param2) {
|
||||||
struct apei_resources addr_resources;
|
struct apei_resources addr_resources;
|
||||||
apei_resources_init(&addr_resources);
|
apei_resources_init(&addr_resources);
|
||||||
trigger_param_region = einj_get_trigger_parameter_region(
|
trigger_param_region = einj_get_trigger_parameter_region(
|
||||||
|
@ -427,7 +432,7 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
|
||||||
struct set_error_type_with_address *v5param = einj_param;
|
struct set_error_type_with_address *v5param = einj_param;
|
||||||
|
|
||||||
v5param->type = type;
|
v5param->type = type;
|
||||||
if (type & 0x80000000) {
|
if (type & ACPI5_VENDOR_BIT) {
|
||||||
switch (vendor_flags) {
|
switch (vendor_flags) {
|
||||||
case SETWA_FLAGS_APICID:
|
case SETWA_FLAGS_APICID:
|
||||||
v5param->apicid = param1;
|
v5param->apicid = param1;
|
||||||
|
@ -512,7 +517,34 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
|
||||||
static int einj_error_inject(u32 type, u64 param1, u64 param2)
|
static int einj_error_inject(u32 type, u64 param1, u64 param2)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
unsigned long pfn;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need extra sanity checks for memory errors.
|
||||||
|
* Other types leap directly to injection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ensure param1/param2 existed */
|
||||||
|
if (!(param_extension || acpi5))
|
||||||
|
goto inject;
|
||||||
|
|
||||||
|
/* ensure injection is memory related */
|
||||||
|
if (type & ACPI5_VENDOR_BIT) {
|
||||||
|
if (vendor_flags != SETWA_FLAGS_MEM)
|
||||||
|
goto inject;
|
||||||
|
} else if (!(type & MEM_ERROR_MASK))
|
||||||
|
goto inject;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disallow crazy address masks that give BIOS leeway to pick
|
||||||
|
* injection address almost anywhere. Insist on page or
|
||||||
|
* better granularity and that target address is normal RAM.
|
||||||
|
*/
|
||||||
|
pfn = PFN_DOWN(param1 & param2);
|
||||||
|
if (!page_is_ram(pfn) || ((param2 & PAGE_MASK) != PAGE_MASK))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
inject:
|
||||||
mutex_lock(&einj_mutex);
|
mutex_lock(&einj_mutex);
|
||||||
rc = __einj_error_inject(type, param1, param2);
|
rc = __einj_error_inject(type, param1, param2);
|
||||||
mutex_unlock(&einj_mutex);
|
mutex_unlock(&einj_mutex);
|
||||||
|
@ -590,7 +622,7 @@ static int error_type_set(void *data, u64 val)
|
||||||
* Vendor defined types have 0x80000000 bit set, and
|
* Vendor defined types have 0x80000000 bit set, and
|
||||||
* are not enumerated by ACPI_EINJ_GET_ERROR_TYPE
|
* are not enumerated by ACPI_EINJ_GET_ERROR_TYPE
|
||||||
*/
|
*/
|
||||||
vendor = val & 0x80000000;
|
vendor = val & ACPI5_VENDOR_BIT;
|
||||||
tval = val & 0x7fffffff;
|
tval = val & 0x7fffffff;
|
||||||
|
|
||||||
/* Only one error type can be specified */
|
/* Only one error type can be specified */
|
||||||
|
@ -694,6 +726,7 @@ static int __init einj_init(void)
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_release;
|
goto err_release;
|
||||||
|
|
||||||
|
rc = -ENOMEM;
|
||||||
einj_param = einj_get_parameter_address();
|
einj_param = einj_get_parameter_address();
|
||||||
if ((param_extension || acpi5) && einj_param) {
|
if ((param_extension || acpi5) && einj_param) {
|
||||||
fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
|
fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
|
||||||
|
|
|
@ -409,6 +409,7 @@ int __weak page_is_ram(unsigned long pfn)
|
||||||
{
|
{
|
||||||
return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
|
return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(page_is_ram);
|
||||||
|
|
||||||
void __weak arch_remove_reservations(struct resource *avail)
|
void __weak arch_remove_reservations(struct resource *avail)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче