[PATCH 38/42] ACPICA: Events: Enhance acpi_ev_execute_reg_method() to ensure no _REG evaluations can happen during OS early boot stages

2015-12-28 Thread Lv Zheng
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

2015-12-28 Thread Lv Zheng
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