[PATCH 38/42] ACPICA: Events: Enhance acpi_ev_execute_reg_method() to ensure no _REG evaluations can happen during OS early boot stages
ACPICA commit 31178590dde82368fdb0f6b0e466b6c0add96c57 We can ensure no early _REG evaluations by ensuring the following rules in acpi_ev_execute_reg_method(): 1. If an address space handler is installed during early stage, _REG(CONNECT) evaluations are blocked. This is achieved using acpi_gbl_reg_methods_enabled which is renamed from acpi_gbl_reg_methods_executed. 2. If _REG(CONNECT) has never been evalauted for the region object, _REG(DISCONNECT) evaluations are blocked. This is achieved by a new region object flag: AOPOBJ_REG_CONNECTED. Note that, after applying this patch, we can ensure _REG(DISCONNECT) is always paired to _REG(CONNECT). Lv Zheng Link: https://github.com/acpica/acpica/commit/31178590 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore --- drivers/acpi/acpica/acglobal.h |2 +- drivers/acpi/acpica/acobject.h |7 --- drivers/acpi/acpica/evregion.c | 25 ++--- drivers/acpi/acpica/evxfregn.c | 33 - drivers/acpi/acpica/excreate.c |3 ++- drivers/acpi/acpica/utinit.c |1 - drivers/acpi/acpica/utxfinit.c |1 + 7 files changed, 30 insertions(+), 42 deletions(-) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index ef0abf4..73462ca 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -165,7 +165,7 @@ ACPI_GLOBAL(u8, acpi_gbl_next_owner_id_offset); /* Initialization sequencing */ -ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed); +ACPI_INIT_GLOBAL(u8, acpi_gbl_reg_methods_enabled, FALSE); /* Misc */ diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 0bd02c4..2b154cf 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -93,9 +93,10 @@ #define AOPOBJ_AML_CONSTANT 0x01 /* Integer is an AML constant */ #define AOPOBJ_STATIC_POINTER 0x02 /* Data is part of an ACPI table, don't delete */ #define AOPOBJ_DATA_VALID 0x04 /* Object is initialized and data is valid */ -#define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized, _REG was run */ -#define AOPOBJ_SETUP_COMPLETE 0x10 /* Region setup is complete */ -#define AOPOBJ_INVALID 0x20 /* Host OS won't allow a Region address */ +#define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized */ +#define AOPOBJ_REG_CONNECTED0x10 /* _REG was run */ +#define AOPOBJ_SETUP_COMPLETE 0x20 /* Region setup is complete */ +#define AOPOBJ_INVALID 0x40 /* Host OS won't allow a Region address */ /** * diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 432b810..cf6e878 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -104,8 +104,6 @@ acpi_status acpi_ev_initialize_op_regions(void) } } - acpi_gbl_reg_methods_executed = TRUE; - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -601,7 +599,18 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) return_ACPI_STATUS(AE_NOT_EXIST); } - if (region_obj2->extra.method_REG == NULL) { + if (region_obj2->extra.method_REG == NULL || + region_obj->region.handler == NULL || + !acpi_gbl_reg_methods_enabled) { + return_ACPI_STATUS(AE_OK); + } + + /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */ + + if ((function == ACPI_REG_CONNECT && +region_obj->common.flags & AOPOBJ_REG_CONNECTED) || + (function == ACPI_REG_DISCONNECT && +!(region_obj->common.flags & AOPOBJ_REG_CONNECTED))) { return_ACPI_STATUS(AE_OK); } @@ -650,6 +659,16 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) status = acpi_ns_evaluate(info); acpi_ut_remove_reference(args[1]); + if (ACPI_FAILURE(status)) { + goto cleanup2; + } + + if (function == ACPI_REG_CONNECT) { + region_obj->common.flags |= AOPOBJ_REG_CONNECTED; + } else { + region_obj->common.flags &= ~AOPOBJ_REG_CONNECTED; + } + cleanup2: acpi_ut_remove_reference(args[0]); diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 3c90508..29f9f39 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -112,39 +112,6 @@ acpi_install_address_space_handler(acpi_handle device, goto unlock_and_exit; } - /* -* For the default space_IDs, (the IDs for which there are default region handlers -* installed) Only execute the _REG methods if the global initialization _REG -* methods have already been
[PATCH 38/42] ACPICA: Events: Enhance acpi_ev_execute_reg_method() to ensure no _REG evaluations can happen during OS early boot stages
ACPICA commit 31178590dde82368fdb0f6b0e466b6c0add96c57 We can ensure no early _REG evaluations by ensuring the following rules in acpi_ev_execute_reg_method(): 1. If an address space handler is installed during early stage, _REG(CONNECT) evaluations are blocked. This is achieved using acpi_gbl_reg_methods_enabled which is renamed from acpi_gbl_reg_methods_executed. 2. If _REG(CONNECT) has never been evalauted for the region object, _REG(DISCONNECT) evaluations are blocked. This is achieved by a new region object flag: AOPOBJ_REG_CONNECTED. Note that, after applying this patch, we can ensure _REG(DISCONNECT) is always paired to _REG(CONNECT). Lv Zheng Link: https://github.com/acpica/acpica/commit/31178590 Signed-off-by: Lv ZhengSigned-off-by: Bob Moore --- drivers/acpi/acpica/acglobal.h |2 +- drivers/acpi/acpica/acobject.h |7 --- drivers/acpi/acpica/evregion.c | 25 ++--- drivers/acpi/acpica/evxfregn.c | 33 - drivers/acpi/acpica/excreate.c |3 ++- drivers/acpi/acpica/utinit.c |1 - drivers/acpi/acpica/utxfinit.c |1 + 7 files changed, 30 insertions(+), 42 deletions(-) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index ef0abf4..73462ca 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -165,7 +165,7 @@ ACPI_GLOBAL(u8, acpi_gbl_next_owner_id_offset); /* Initialization sequencing */ -ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed); +ACPI_INIT_GLOBAL(u8, acpi_gbl_reg_methods_enabled, FALSE); /* Misc */ diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 0bd02c4..2b154cf 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -93,9 +93,10 @@ #define AOPOBJ_AML_CONSTANT 0x01 /* Integer is an AML constant */ #define AOPOBJ_STATIC_POINTER 0x02 /* Data is part of an ACPI table, don't delete */ #define AOPOBJ_DATA_VALID 0x04 /* Object is initialized and data is valid */ -#define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized, _REG was run */ -#define AOPOBJ_SETUP_COMPLETE 0x10 /* Region setup is complete */ -#define AOPOBJ_INVALID 0x20 /* Host OS won't allow a Region address */ +#define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized */ +#define AOPOBJ_REG_CONNECTED0x10 /* _REG was run */ +#define AOPOBJ_SETUP_COMPLETE 0x20 /* Region setup is complete */ +#define AOPOBJ_INVALID 0x40 /* Host OS won't allow a Region address */ /** * diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 432b810..cf6e878 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -104,8 +104,6 @@ acpi_status acpi_ev_initialize_op_regions(void) } } - acpi_gbl_reg_methods_executed = TRUE; - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); } @@ -601,7 +599,18 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) return_ACPI_STATUS(AE_NOT_EXIST); } - if (region_obj2->extra.method_REG == NULL) { + if (region_obj2->extra.method_REG == NULL || + region_obj->region.handler == NULL || + !acpi_gbl_reg_methods_enabled) { + return_ACPI_STATUS(AE_OK); + } + + /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */ + + if ((function == ACPI_REG_CONNECT && +region_obj->common.flags & AOPOBJ_REG_CONNECTED) || + (function == ACPI_REG_DISCONNECT && +!(region_obj->common.flags & AOPOBJ_REG_CONNECTED))) { return_ACPI_STATUS(AE_OK); } @@ -650,6 +659,16 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) status = acpi_ns_evaluate(info); acpi_ut_remove_reference(args[1]); + if (ACPI_FAILURE(status)) { + goto cleanup2; + } + + if (function == ACPI_REG_CONNECT) { + region_obj->common.flags |= AOPOBJ_REG_CONNECTED; + } else { + region_obj->common.flags &= ~AOPOBJ_REG_CONNECTED; + } + cleanup2: acpi_ut_remove_reference(args[0]); diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 3c90508..29f9f39 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -112,39 +112,6 @@ acpi_install_address_space_handler(acpi_handle device, goto unlock_and_exit; } - /* -* For the default space_IDs, (the IDs for which there are default region handlers -* installed) Only execute the _REG methods if the global initialization