Loading drivers/acpi/dispatcher/dsopcode.c +3 −1 Original line number Original line Diff line number Diff line Loading @@ -359,7 +359,9 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) status = acpi_os_validate_address(obj_desc->region.space_id, status = acpi_os_validate_address(obj_desc->region.space_id, obj_desc->region.address, obj_desc->region.address, (acpi_size) obj_desc->region.length); (acpi_size) obj_desc->region.length, acpi_ut_get_node_name(node)); if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) { /* /* * Invalid address/length. We will emit an error message and mark * Invalid address/length. We will emit an error message and mark Loading drivers/acpi/osl.c +174 −2 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,8 @@ #include <asm/uaccess.h> #include <asm/uaccess.h> #include <linux/efi.h> #include <linux/efi.h> #include <linux/ioport.h> #include <linux/list.h> #define _COMPONENT ACPI_OS_SERVICES #define _COMPONENT ACPI_OS_SERVICES ACPI_MODULE_NAME("osl"); ACPI_MODULE_NAME("osl"); Loading Loading @@ -74,6 +76,18 @@ static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; static struct workqueue_struct *kacpid_wq; static struct workqueue_struct *kacpi_notify_wq; static struct workqueue_struct *kacpi_notify_wq; struct acpi_res_list { resource_size_t start; resource_size_t end; acpi_adr_space_type resource_type; /* IO port, System memory, ...*/ char name[5]; /* only can have a length of 4 chars, make use of this one instead of res->name, no need to kalloc then */ struct list_head resource_list; }; static LIST_HEAD(resource_list_head); static DEFINE_SPINLOCK(acpi_res_lock); #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ static char osi_additional_string[OSI_STRING_LENGTH_MAX]; static char osi_additional_string[OSI_STRING_LENGTH_MAX]; Loading Loading @@ -1091,6 +1105,128 @@ static int __init acpi_wake_gpes_always_on_setup(char *str) __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); /* Check of resource interference between native drivers and ACPI * OperationRegions (SystemIO and System Memory only). * IO ports and memory declared in ACPI might be used by the ACPI subsystem * in arbitrary AML code and can interfere with legacy drivers. * acpi_enforce_resources= can be set to: * * - strict (2) * -> further driver trying to access the resources will not load * - lax (default) (1) * -> further driver trying to access the resources will load, but you * get a system message that something might go wrong... * * - no (0) * -> ACPI Operation Region resources will not be registered * */ #define ENFORCE_RESOURCES_STRICT 2 #define ENFORCE_RESOURCES_LAX 1 #define ENFORCE_RESOURCES_NO 0 static unsigned int acpi_enforce_resources = ENFORCE_RESOURCES_LAX; static int __init acpi_enforce_resources_setup(char *str) { if (str == NULL || *str == '\0') return 0; if (!strcmp("strict", str)) acpi_enforce_resources = ENFORCE_RESOURCES_STRICT; else if (!strcmp("lax", str)) acpi_enforce_resources = ENFORCE_RESOURCES_LAX; else if (!strcmp("no", str)) acpi_enforce_resources = ENFORCE_RESOURCES_NO; return 1; } __setup("acpi_enforce_resources=", acpi_enforce_resources_setup); /* Check for resource conflicts between ACPI OperationRegions and native * drivers */ int acpi_check_resource_conflict(struct resource *res) { struct acpi_res_list *res_list_elem; int ioport; int clash = 0; if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) return 0; if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM)) return 0; ioport = res->flags & IORESOURCE_IO; spin_lock(&acpi_res_lock); list_for_each_entry(res_list_elem, &resource_list_head, resource_list) { if (ioport && (res_list_elem->resource_type != ACPI_ADR_SPACE_SYSTEM_IO)) continue; if (!ioport && (res_list_elem->resource_type != ACPI_ADR_SPACE_SYSTEM_MEMORY)) continue; if (res->end < res_list_elem->start || res_list_elem->end < res->start) continue; clash = 1; break; } spin_unlock(&acpi_res_lock); if (clash) { if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) { printk(KERN_INFO "%sACPI: %s resource %s [0x%llx-0x%llx]" " conflicts with ACPI region %s" " [0x%llx-0x%llx]\n", acpi_enforce_resources == ENFORCE_RESOURCES_LAX ? KERN_WARNING : KERN_ERR, ioport ? "I/O" : "Memory", res->name, (long long) res->start, (long long) res->end, res_list_elem->name, (long long) res_list_elem->start, (long long) res_list_elem->end); printk(KERN_INFO "ACPI: Device needs an ACPI driver\n"); } if (acpi_enforce_resources == ENFORCE_RESOURCES_STRICT) return -EBUSY; } return 0; } EXPORT_SYMBOL(acpi_check_resource_conflict); int acpi_check_region(resource_size_t start, resource_size_t n, const char *name) { struct resource res = { .start = start, .end = start + n - 1, .name = name, .flags = IORESOURCE_IO, }; return acpi_check_resource_conflict(&res); } EXPORT_SYMBOL(acpi_check_region); int acpi_check_mem_region(resource_size_t start, resource_size_t n, const char *name) { struct resource res = { .start = start, .end = start + n - 1, .name = name, .flags = IORESOURCE_MEM, }; return acpi_check_resource_conflict(&res); } EXPORT_SYMBOL(acpi_check_mem_region); /* /* * Acquire a spinlock. * Acquire a spinlock. * * Loading Loading @@ -1292,9 +1428,45 @@ acpi_status acpi_os_validate_address ( acpi_os_validate_address ( u8 space_id, u8 space_id, acpi_physical_address address, acpi_physical_address address, acpi_size length) acpi_size length, char *name) { { struct acpi_res_list *res; if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) return AE_OK; switch (space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: case ACPI_ADR_SPACE_SYSTEM_MEMORY: /* Only interference checks against SystemIO and SytemMemory are needed */ res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL); if (!res) return AE_OK; /* ACPI names are fixed to 4 bytes, still better use strlcpy */ strlcpy(res->name, name, 5); res->start = address; res->end = address + length - 1; res->resource_type = space_id; spin_lock(&acpi_res_lock); list_add(&res->resource_list, &resource_list_head); spin_unlock(&acpi_res_lock); pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, " "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO) ? "SystemIO" : "System Memory", (unsigned long long)res->start, (unsigned long long)res->end, res->name); break; case ACPI_ADR_SPACE_PCI_CONFIG: case ACPI_ADR_SPACE_EC: case ACPI_ADR_SPACE_SMBUS: case ACPI_ADR_SPACE_CMOS: case ACPI_ADR_SPACE_PCI_BAR_TARGET: case ACPI_ADR_SPACE_DATA_TABLE: case ACPI_ADR_SPACE_FIXED_HARDWARE: break; } return AE_OK; return AE_OK; } } Loading include/acpi/acpiosxf.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -242,8 +242,8 @@ acpi_status acpi_os_validate_interface(char *interface); acpi_status acpi_osi_invalidate(char* interface); acpi_status acpi_osi_invalidate(char* interface); acpi_status acpi_status acpi_os_validate_address(u8 space_id, acpi_os_validate_address(u8 space_id, acpi_physical_address address, acpi_physical_address address, acpi_size length); acpi_size length, char *name); u64 acpi_os_get_timer(void); u64 acpi_os_get_timer(void); Loading include/linux/acpi.h +25 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ #ifndef _LINUX_ACPI_H #ifndef _LINUX_ACPI_H #define _LINUX_ACPI_H #define _LINUX_ACPI_H #include <linux/ioport.h> /* for struct resource */ #ifdef CONFIG_ACPI #ifdef CONFIG_ACPI Loading Loading @@ -238,6 +239,13 @@ extern int pnpacpi_disabled; #define PXM_INVAL (-1) #define PXM_INVAL (-1) #define NID_INVAL (-1) #define NID_INVAL (-1) int acpi_check_resource_conflict(struct resource *res); int acpi_check_region(resource_size_t start, resource_size_t n, const char *name); int acpi_check_mem_region(resource_size_t start, resource_size_t n, const char *name); #else /* CONFIG_ACPI */ #else /* CONFIG_ACPI */ static inline int acpi_boot_init(void) static inline int acpi_boot_init(void) Loading @@ -250,5 +258,22 @@ static inline int acpi_boot_table_init(void) return 0; return 0; } } static inline int acpi_check_resource_conflict(struct resource *res) { return 0; } static inline int acpi_check_region(resource_size_t start, resource_size_t n, const char *name) { return 0; } static inline int acpi_check_mem_region(resource_size_t start, resource_size_t n, const char *name) { return 0; } #endif /* !CONFIG_ACPI */ #endif /* !CONFIG_ACPI */ #endif /*_LINUX_ACPI_H*/ #endif /*_LINUX_ACPI_H*/ Loading
drivers/acpi/dispatcher/dsopcode.c +3 −1 Original line number Original line Diff line number Diff line Loading @@ -359,7 +359,9 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) status = acpi_os_validate_address(obj_desc->region.space_id, status = acpi_os_validate_address(obj_desc->region.space_id, obj_desc->region.address, obj_desc->region.address, (acpi_size) obj_desc->region.length); (acpi_size) obj_desc->region.length, acpi_ut_get_node_name(node)); if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) { /* /* * Invalid address/length. We will emit an error message and mark * Invalid address/length. We will emit an error message and mark Loading
drivers/acpi/osl.c +174 −2 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,8 @@ #include <asm/uaccess.h> #include <asm/uaccess.h> #include <linux/efi.h> #include <linux/efi.h> #include <linux/ioport.h> #include <linux/list.h> #define _COMPONENT ACPI_OS_SERVICES #define _COMPONENT ACPI_OS_SERVICES ACPI_MODULE_NAME("osl"); ACPI_MODULE_NAME("osl"); Loading Loading @@ -74,6 +76,18 @@ static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; static struct workqueue_struct *kacpid_wq; static struct workqueue_struct *kacpi_notify_wq; static struct workqueue_struct *kacpi_notify_wq; struct acpi_res_list { resource_size_t start; resource_size_t end; acpi_adr_space_type resource_type; /* IO port, System memory, ...*/ char name[5]; /* only can have a length of 4 chars, make use of this one instead of res->name, no need to kalloc then */ struct list_head resource_list; }; static LIST_HEAD(resource_list_head); static DEFINE_SPINLOCK(acpi_res_lock); #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ static char osi_additional_string[OSI_STRING_LENGTH_MAX]; static char osi_additional_string[OSI_STRING_LENGTH_MAX]; Loading Loading @@ -1091,6 +1105,128 @@ static int __init acpi_wake_gpes_always_on_setup(char *str) __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); /* Check of resource interference between native drivers and ACPI * OperationRegions (SystemIO and System Memory only). * IO ports and memory declared in ACPI might be used by the ACPI subsystem * in arbitrary AML code and can interfere with legacy drivers. * acpi_enforce_resources= can be set to: * * - strict (2) * -> further driver trying to access the resources will not load * - lax (default) (1) * -> further driver trying to access the resources will load, but you * get a system message that something might go wrong... * * - no (0) * -> ACPI Operation Region resources will not be registered * */ #define ENFORCE_RESOURCES_STRICT 2 #define ENFORCE_RESOURCES_LAX 1 #define ENFORCE_RESOURCES_NO 0 static unsigned int acpi_enforce_resources = ENFORCE_RESOURCES_LAX; static int __init acpi_enforce_resources_setup(char *str) { if (str == NULL || *str == '\0') return 0; if (!strcmp("strict", str)) acpi_enforce_resources = ENFORCE_RESOURCES_STRICT; else if (!strcmp("lax", str)) acpi_enforce_resources = ENFORCE_RESOURCES_LAX; else if (!strcmp("no", str)) acpi_enforce_resources = ENFORCE_RESOURCES_NO; return 1; } __setup("acpi_enforce_resources=", acpi_enforce_resources_setup); /* Check for resource conflicts between ACPI OperationRegions and native * drivers */ int acpi_check_resource_conflict(struct resource *res) { struct acpi_res_list *res_list_elem; int ioport; int clash = 0; if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) return 0; if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM)) return 0; ioport = res->flags & IORESOURCE_IO; spin_lock(&acpi_res_lock); list_for_each_entry(res_list_elem, &resource_list_head, resource_list) { if (ioport && (res_list_elem->resource_type != ACPI_ADR_SPACE_SYSTEM_IO)) continue; if (!ioport && (res_list_elem->resource_type != ACPI_ADR_SPACE_SYSTEM_MEMORY)) continue; if (res->end < res_list_elem->start || res_list_elem->end < res->start) continue; clash = 1; break; } spin_unlock(&acpi_res_lock); if (clash) { if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) { printk(KERN_INFO "%sACPI: %s resource %s [0x%llx-0x%llx]" " conflicts with ACPI region %s" " [0x%llx-0x%llx]\n", acpi_enforce_resources == ENFORCE_RESOURCES_LAX ? KERN_WARNING : KERN_ERR, ioport ? "I/O" : "Memory", res->name, (long long) res->start, (long long) res->end, res_list_elem->name, (long long) res_list_elem->start, (long long) res_list_elem->end); printk(KERN_INFO "ACPI: Device needs an ACPI driver\n"); } if (acpi_enforce_resources == ENFORCE_RESOURCES_STRICT) return -EBUSY; } return 0; } EXPORT_SYMBOL(acpi_check_resource_conflict); int acpi_check_region(resource_size_t start, resource_size_t n, const char *name) { struct resource res = { .start = start, .end = start + n - 1, .name = name, .flags = IORESOURCE_IO, }; return acpi_check_resource_conflict(&res); } EXPORT_SYMBOL(acpi_check_region); int acpi_check_mem_region(resource_size_t start, resource_size_t n, const char *name) { struct resource res = { .start = start, .end = start + n - 1, .name = name, .flags = IORESOURCE_MEM, }; return acpi_check_resource_conflict(&res); } EXPORT_SYMBOL(acpi_check_mem_region); /* /* * Acquire a spinlock. * Acquire a spinlock. * * Loading Loading @@ -1292,9 +1428,45 @@ acpi_status acpi_os_validate_address ( acpi_os_validate_address ( u8 space_id, u8 space_id, acpi_physical_address address, acpi_physical_address address, acpi_size length) acpi_size length, char *name) { { struct acpi_res_list *res; if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) return AE_OK; switch (space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: case ACPI_ADR_SPACE_SYSTEM_MEMORY: /* Only interference checks against SystemIO and SytemMemory are needed */ res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL); if (!res) return AE_OK; /* ACPI names are fixed to 4 bytes, still better use strlcpy */ strlcpy(res->name, name, 5); res->start = address; res->end = address + length - 1; res->resource_type = space_id; spin_lock(&acpi_res_lock); list_add(&res->resource_list, &resource_list_head); spin_unlock(&acpi_res_lock); pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, " "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO) ? "SystemIO" : "System Memory", (unsigned long long)res->start, (unsigned long long)res->end, res->name); break; case ACPI_ADR_SPACE_PCI_CONFIG: case ACPI_ADR_SPACE_EC: case ACPI_ADR_SPACE_SMBUS: case ACPI_ADR_SPACE_CMOS: case ACPI_ADR_SPACE_PCI_BAR_TARGET: case ACPI_ADR_SPACE_DATA_TABLE: case ACPI_ADR_SPACE_FIXED_HARDWARE: break; } return AE_OK; return AE_OK; } } Loading
include/acpi/acpiosxf.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -242,8 +242,8 @@ acpi_status acpi_os_validate_interface(char *interface); acpi_status acpi_osi_invalidate(char* interface); acpi_status acpi_osi_invalidate(char* interface); acpi_status acpi_status acpi_os_validate_address(u8 space_id, acpi_os_validate_address(u8 space_id, acpi_physical_address address, acpi_physical_address address, acpi_size length); acpi_size length, char *name); u64 acpi_os_get_timer(void); u64 acpi_os_get_timer(void); Loading
include/linux/acpi.h +25 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ #ifndef _LINUX_ACPI_H #ifndef _LINUX_ACPI_H #define _LINUX_ACPI_H #define _LINUX_ACPI_H #include <linux/ioport.h> /* for struct resource */ #ifdef CONFIG_ACPI #ifdef CONFIG_ACPI Loading Loading @@ -238,6 +239,13 @@ extern int pnpacpi_disabled; #define PXM_INVAL (-1) #define PXM_INVAL (-1) #define NID_INVAL (-1) #define NID_INVAL (-1) int acpi_check_resource_conflict(struct resource *res); int acpi_check_region(resource_size_t start, resource_size_t n, const char *name); int acpi_check_mem_region(resource_size_t start, resource_size_t n, const char *name); #else /* CONFIG_ACPI */ #else /* CONFIG_ACPI */ static inline int acpi_boot_init(void) static inline int acpi_boot_init(void) Loading @@ -250,5 +258,22 @@ static inline int acpi_boot_table_init(void) return 0; return 0; } } static inline int acpi_check_resource_conflict(struct resource *res) { return 0; } static inline int acpi_check_region(resource_size_t start, resource_size_t n, const char *name) { return 0; } static inline int acpi_check_mem_region(resource_size_t start, resource_size_t n, const char *name) { return 0; } #endif /* !CONFIG_ACPI */ #endif /* !CONFIG_ACPI */ #endif /*_LINUX_ACPI_H*/ #endif /*_LINUX_ACPI_H*/