diff mbox

[06/13] ACPI/IPMI: Add reference counting for ACPI operation region handlers

Message ID d9d5acba01eb80580e7696c50db4263ded86a86c.1374566394.git.lv.zheng@intel.com (mailing list archive)
State Deferred, archived
Headers show

Commit Message

Lv Zheng July 23, 2013, 8:09 a.m. UTC
This patch adds reference couting for ACPI operation region handlers to fix
races caused by the ACPICA address space callback invocations.

ACPICA address space callback invocation is not suitable for Linux
CONFIG_MODULE=y execution environment.  This patch tries to protect the
address space callbacks by invoking them under a module safe environment.
The IPMI address space handler is also upgraded in this patch.
The acpi_unregister_region() is designed to meet the following
requirements:
1. It acts as a barrier for operation region callbacks - no callback will
   happen after acpi_unregister_region().
2. acpi_unregister_region() is safe to be called in moudle->exit()
   functions.
Using reference counting rather than module referencing allows
such benefits to be achieved even when acpi_unregister_region() is called
in the environments other than module->exit().
The header file of include/acpi/acpi_bus.h should contain the declarations
that have references to some ACPICA defined types.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Reviewed-by: Huang Ying <ying.huang@intel.com>
---
 drivers/acpi/acpi_ipmi.c |   16 ++--
 drivers/acpi/osl.c       |  224 ++++++++++++++++++++++++++++++++++++++++++++++
 include/acpi/acpi_bus.h  |    5 ++
 3 files changed, 235 insertions(+), 10 deletions(-)

Comments

Rafael Wysocki July 25, 2013, 8:27 p.m. UTC | #1
On Tuesday, July 23, 2013 04:09:43 PM Lv Zheng wrote:
> This patch adds reference couting for ACPI operation region handlers to fix
> races caused by the ACPICA address space callback invocations.
> 
> ACPICA address space callback invocation is not suitable for Linux
> CONFIG_MODULE=y execution environment.  This patch tries to protect the
> address space callbacks by invoking them under a module safe environment.
> The IPMI address space handler is also upgraded in this patch.
> The acpi_unregister_region() is designed to meet the following
> requirements:
> 1. It acts as a barrier for operation region callbacks - no callback will
>    happen after acpi_unregister_region().
> 2. acpi_unregister_region() is safe to be called in moudle->exit()
>    functions.
> Using reference counting rather than module referencing allows
> such benefits to be achieved even when acpi_unregister_region() is called
> in the environments other than module->exit().
> The header file of include/acpi/acpi_bus.h should contain the declarations
> that have references to some ACPICA defined types.
> 
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Reviewed-by: Huang Ying <ying.huang@intel.com>
> ---
>  drivers/acpi/acpi_ipmi.c |   16 ++--
>  drivers/acpi/osl.c       |  224 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/acpi/acpi_bus.h  |    5 ++
>  3 files changed, 235 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c
> index 5f8f495..2a09156 100644
> --- a/drivers/acpi/acpi_ipmi.c
> +++ b/drivers/acpi/acpi_ipmi.c
> @@ -539,20 +539,18 @@ out_ref:
>  static int __init acpi_ipmi_init(void)
>  {
>  	int result = 0;
> -	acpi_status status;
>  
>  	if (acpi_disabled)
>  		return result;
>  
>  	mutex_init(&driver_data.ipmi_lock);
>  
> -	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
> -						    ACPI_ADR_SPACE_IPMI,
> -						    &acpi_ipmi_space_handler,
> -						    NULL, NULL);
> -	if (ACPI_FAILURE(status)) {
> +	result = acpi_register_region(ACPI_ADR_SPACE_IPMI,
> +				      &acpi_ipmi_space_handler,
> +				      NULL, NULL);
> +	if (result) {
>  		pr_warn("Can't register IPMI opregion space handle\n");
> -		return -EINVAL;
> +		return result;
>  	}
>  
>  	result = ipmi_smi_watcher_register(&driver_data.bmc_events);
> @@ -596,9 +594,7 @@ static void __exit acpi_ipmi_exit(void)
>  	}
>  	mutex_unlock(&driver_data.ipmi_lock);
>  
> -	acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
> -					  ACPI_ADR_SPACE_IPMI,
> -					  &acpi_ipmi_space_handler);
> +	acpi_unregister_region(ACPI_ADR_SPACE_IPMI);
>  }
>  
>  module_init(acpi_ipmi_init);
> diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
> index 6ab2c35..8398e51 100644
> --- a/drivers/acpi/osl.c
> +++ b/drivers/acpi/osl.c
> @@ -86,6 +86,42 @@ static struct workqueue_struct *kacpid_wq;
>  static struct workqueue_struct *kacpi_notify_wq;
>  static struct workqueue_struct *kacpi_hotplug_wq;
>  
> +struct acpi_region {
> +	unsigned long flags;
> +#define ACPI_REGION_DEFAULT		0x01
> +#define ACPI_REGION_INSTALLED		0x02
> +#define ACPI_REGION_REGISTERED		0x04
> +#define ACPI_REGION_UNREGISTERING	0x08
> +#define ACPI_REGION_INSTALLING		0x10

What about (1UL << 1), (1UL << 2) etc.?

Also please remove the #defines out of the struct definition.

> +	/*
> +	 * NOTE: Upgrading All Region Handlers
> +	 * This flag is only used during the period where not all of the
> +	 * region handers are upgraded to the new interfaces.
> +	 */
> +#define ACPI_REGION_MANAGED		0x80
> +	acpi_adr_space_handler handler;
> +	acpi_adr_space_setup setup;
> +	void *context;
> +	/* Invoking references */
> +	atomic_t refcnt;

Actually, why don't you use krefs?

> +};
> +
> +static struct acpi_region acpi_regions[ACPI_NUM_PREDEFINED_REGIONS] = {
> +	[ACPI_ADR_SPACE_SYSTEM_MEMORY] = {
> +		.flags = ACPI_REGION_DEFAULT,
> +	},
> +	[ACPI_ADR_SPACE_SYSTEM_IO] = {
> +		.flags = ACPI_REGION_DEFAULT,
> +	},
> +	[ACPI_ADR_SPACE_PCI_CONFIG] = {
> +		.flags = ACPI_REGION_DEFAULT,
> +	},
> +	[ACPI_ADR_SPACE_IPMI] = {
> +		.flags = ACPI_REGION_MANAGED,
> +	},
> +};
> +static DEFINE_MUTEX(acpi_mutex_region);
> +
>  /*
>   * This list of permanent mappings is for memory that may be accessed from
>   * interrupt context, where we can't do the ioremap().
> @@ -1799,3 +1835,191 @@ void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
>  		kfree(hp_work);
>  }
>  EXPORT_SYMBOL_GPL(alloc_acpi_hp_work);
> +
> +static bool acpi_region_managed(struct acpi_region *rgn)
> +{
> +	/*
> +	 * NOTE: Default and Managed
> +	 * We only need to avoid region management on the regions managed
> +	 * by ACPICA (ACPI_REGION_DEFAULT).  Currently, we need additional
> +	 * check as many operation region handlers are not upgraded, so
> +	 * only those known to be safe are managed (ACPI_REGION_MANAGED).
> +	 */
> +	return !(rgn->flags & ACPI_REGION_DEFAULT) &&
> +	       (rgn->flags & ACPI_REGION_MANAGED);
> +}
> +
> +static bool acpi_region_callable(struct acpi_region *rgn)
> +{
> +	return (rgn->flags & ACPI_REGION_REGISTERED) &&
> +	       !(rgn->flags & ACPI_REGION_UNREGISTERING);
> +}
> +
> +static acpi_status
> +acpi_region_default_handler(u32 function,
> +			    acpi_physical_address address,
> +			    u32 bit_width, u64 *value,
> +			    void *handler_context, void *region_context)
> +{
> +	acpi_adr_space_handler handler;
> +	struct acpi_region *rgn = (struct acpi_region *)handler_context;
> +	void *context;
> +	acpi_status status = AE_NOT_EXIST;
> +
> +	mutex_lock(&acpi_mutex_region);
> +	if (!acpi_region_callable(rgn) || !rgn->handler) {
> +		mutex_unlock(&acpi_mutex_region);
> +		return status;
> +	}
> +
> +	atomic_inc(&rgn->refcnt);
> +	handler = rgn->handler;
> +	context = rgn->context;
> +	mutex_unlock(&acpi_mutex_region);
> +
> +	status = handler(function, address, bit_width, value, context,
> +			 region_context);

Why don't we call the handler under the mutex?

What exactly prevents context from becoming NULL before the call above?

> +	atomic_dec(&rgn->refcnt);
> +
> +	return status;
> +}
> +
> +static acpi_status
> +acpi_region_default_setup(acpi_handle handle, u32 function,
> +			  void *handler_context, void **region_context)
> +{
> +	acpi_adr_space_setup setup;
> +	struct acpi_region *rgn = (struct acpi_region *)handler_context;
> +	void *context;
> +	acpi_status status = AE_OK;
> +
> +	mutex_lock(&acpi_mutex_region);
> +	if (!acpi_region_callable(rgn) || !rgn->setup) {
> +		mutex_unlock(&acpi_mutex_region);
> +		return status;
> +	}
> +
> +	atomic_inc(&rgn->refcnt);
> +	setup = rgn->setup;
> +	context = rgn->context;
> +	mutex_unlock(&acpi_mutex_region);
> +
> +	status = setup(handle, function, context, region_context);

Can setup drop rgn->refcnt ?

> +	atomic_dec(&rgn->refcnt);
> +
> +	return status;
> +}
> +
> +static int __acpi_install_region(struct acpi_region *rgn,
> +				 acpi_adr_space_type space_id)
> +{
> +	int res = 0;
> +	acpi_status status;
> +	int installing = 0;
> +
> +	mutex_lock(&acpi_mutex_region);
> +	if (rgn->flags & ACPI_REGION_INSTALLED)
> +		goto out_lock;
> +	if (rgn->flags & ACPI_REGION_INSTALLING) {
> +		res = -EBUSY;
> +		goto out_lock;
> +	}
> +
> +	installing = 1;
> +	rgn->flags |= ACPI_REGION_INSTALLING;
> +	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, space_id,
> +						    acpi_region_default_handler,
> +						    acpi_region_default_setup,
> +						    rgn);
> +	rgn->flags &= ~ACPI_REGION_INSTALLING;
> +	if (ACPI_FAILURE(status))
> +		res = -EINVAL;
> +	else
> +		rgn->flags |= ACPI_REGION_INSTALLED;
> +
> +out_lock:
> +	mutex_unlock(&acpi_mutex_region);
> +	if (installing) {
> +		if (res)
> +			pr_err("Failed to install region %d\n", space_id);
> +		else
> +			pr_info("Region %d installed\n", space_id);
> +	}
> +	return res;
> +}
> +
> +int acpi_register_region(acpi_adr_space_type space_id,
> +			 acpi_adr_space_handler handler,
> +			 acpi_adr_space_setup setup, void *context)
> +{
> +	int res;
> +	struct acpi_region *rgn;
> +
> +	if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)
> +		return -EINVAL;
> +
> +	rgn = &acpi_regions[space_id];
> +	if (!acpi_region_managed(rgn))
> +		return -EINVAL;
> +
> +	res = __acpi_install_region(rgn, space_id);
> +	if (res)
> +		return res;
> +
> +	mutex_lock(&acpi_mutex_region);
> +	if (rgn->flags & ACPI_REGION_REGISTERED) {
> +		mutex_unlock(&acpi_mutex_region);
> +		return -EBUSY;
> +	}
> +
> +	rgn->handler = handler;
> +	rgn->setup = setup;
> +	rgn->context = context;
> +	rgn->flags |= ACPI_REGION_REGISTERED;
> +	atomic_set(&rgn->refcnt, 1);
> +	mutex_unlock(&acpi_mutex_region);
> +
> +	pr_info("Region %d registered\n", space_id);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(acpi_register_region);
> +
> +void acpi_unregister_region(acpi_adr_space_type space_id)
> +{
> +	struct acpi_region *rgn;
> +
> +	if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)
> +		return;
> +
> +	rgn = &acpi_regions[space_id];
> +	if (!acpi_region_managed(rgn))
> +		return;
> +
> +	mutex_lock(&acpi_mutex_region);
> +	if (!(rgn->flags & ACPI_REGION_REGISTERED)) {
> +		mutex_unlock(&acpi_mutex_region);
> +		return;
> +	}
> +	if (rgn->flags & ACPI_REGION_UNREGISTERING) {
> +		mutex_unlock(&acpi_mutex_region);
> +		return;

What about

	if ((rgn->flags & ACPI_REGION_UNREGISTERING)
	    || !(rgn->flags & ACPI_REGION_REGISTERED)) {
		mutex_unlock(&acpi_mutex_region);
		return;
	}

> +	}
> +
> +	rgn->flags |= ACPI_REGION_UNREGISTERING;
> +	rgn->handler = NULL;
> +	rgn->setup = NULL;
> +	rgn->context = NULL;
> +	mutex_unlock(&acpi_mutex_region);
> +
> +	while (atomic_read(&rgn->refcnt) > 1)
> +		schedule_timeout_uninterruptible(usecs_to_jiffies(5));

Wouldn't it be better to use a wait queue here?

> +	atomic_dec(&rgn->refcnt);
> +
> +	mutex_lock(&acpi_mutex_region);
> +	rgn->flags &= ~(ACPI_REGION_REGISTERED | ACPI_REGION_UNREGISTERING);
> +	mutex_unlock(&acpi_mutex_region);
> +
> +	pr_info("Region %d unregistered\n", space_id);
> +}
> +EXPORT_SYMBOL_GPL(acpi_unregister_region);
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index a2c2fbb..15fad0d 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -542,4 +542,9 @@ static inline int unregister_acpi_bus_type(void *bus) { return 0; }
>  
>  #endif				/* CONFIG_ACPI */
>  
> +int acpi_register_region(acpi_adr_space_type space_id,
> +			 acpi_adr_space_handler handler,
> +			 acpi_adr_space_setup setup, void *context);
> +void acpi_unregister_region(acpi_adr_space_type space_id);
> +
>  #endif /*__ACPI_BUS_H__*/

Thanks,
Rafael
Rafael Wysocki July 25, 2013, 9:29 p.m. UTC | #2
On Tuesday, July 23, 2013 04:09:43 PM Lv Zheng wrote:
> This patch adds reference couting for ACPI operation region handlers to fix
> races caused by the ACPICA address space callback invocations.
> 
> ACPICA address space callback invocation is not suitable for Linux
> CONFIG_MODULE=y execution environment.

Actually, can you please explain to me what *exactly* the problem is?

Rafael

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Lv Zheng July 26, 2013, 12:47 a.m. UTC | #3
DQoNCj4gRnJvbTogUmFmYWVsIEouIFd5c29ja2kgW21haWx0bzpyandAc2lzay5wbF0NCj4gU2Vu
dDogRnJpZGF5LCBKdWx5IDI2LCAyMDEzIDQ6MjcgQU0NCj4gDQo+IE9uIFR1ZXNkYXksIEp1bHkg
MjMsIDIwMTMgMDQ6MDk6NDMgUE0gTHYgWmhlbmcgd3JvdGU6DQo+ID4gVGhpcyBwYXRjaCBhZGRz
IHJlZmVyZW5jZSBjb3V0aW5nIGZvciBBQ1BJIG9wZXJhdGlvbiByZWdpb24gaGFuZGxlcnMNCj4g
PiB0byBmaXggcmFjZXMgY2F1c2VkIGJ5IHRoZSBBQ1BJQ0EgYWRkcmVzcyBzcGFjZSBjYWxsYmFj
ayBpbnZvY2F0aW9ucy4NCj4gPg0KPiA+IEFDUElDQSBhZGRyZXNzIHNwYWNlIGNhbGxiYWNrIGlu
dm9jYXRpb24gaXMgbm90IHN1aXRhYmxlIGZvciBMaW51eA0KPiA+IENPTkZJR19NT0RVTEU9eSBl
eGVjdXRpb24gZW52aXJvbm1lbnQuICBUaGlzIHBhdGNoIHRyaWVzIHRvIHByb3RlY3QNCj4gPiB0
aGUgYWRkcmVzcyBzcGFjZSBjYWxsYmFja3MgYnkgaW52b2tpbmcgdGhlbSB1bmRlciBhIG1vZHVs
ZSBzYWZlDQo+IGVudmlyb25tZW50Lg0KPiA+IFRoZSBJUE1JIGFkZHJlc3Mgc3BhY2UgaGFuZGxl
ciBpcyBhbHNvIHVwZ3JhZGVkIGluIHRoaXMgcGF0Y2guDQo+ID4gVGhlIGFjcGlfdW5yZWdpc3Rl
cl9yZWdpb24oKSBpcyBkZXNpZ25lZCB0byBtZWV0IHRoZSBmb2xsb3dpbmcNCj4gPiByZXF1aXJl
bWVudHM6DQo+ID4gMS4gSXQgYWN0cyBhcyBhIGJhcnJpZXIgZm9yIG9wZXJhdGlvbiByZWdpb24g
Y2FsbGJhY2tzIC0gbm8gY2FsbGJhY2sgd2lsbA0KPiA+ICAgIGhhcHBlbiBhZnRlciBhY3BpX3Vu
cmVnaXN0ZXJfcmVnaW9uKCkuDQo+ID4gMi4gYWNwaV91bnJlZ2lzdGVyX3JlZ2lvbigpIGlzIHNh
ZmUgdG8gYmUgY2FsbGVkIGluIG1vdWRsZS0+ZXhpdCgpDQo+ID4gICAgZnVuY3Rpb25zLg0KPiA+
IFVzaW5nIHJlZmVyZW5jZSBjb3VudGluZyByYXRoZXIgdGhhbiBtb2R1bGUgcmVmZXJlbmNpbmcg
YWxsb3dzIHN1Y2gNCj4gPiBiZW5lZml0cyB0byBiZSBhY2hpZXZlZCBldmVuIHdoZW4gYWNwaV91
bnJlZ2lzdGVyX3JlZ2lvbigpIGlzIGNhbGxlZA0KPiA+IGluIHRoZSBlbnZpcm9ubWVudHMgb3Ro
ZXIgdGhhbiBtb2R1bGUtPmV4aXQoKS4NCj4gPiBUaGUgaGVhZGVyIGZpbGUgb2YgaW5jbHVkZS9h
Y3BpL2FjcGlfYnVzLmggc2hvdWxkIGNvbnRhaW4gdGhlDQo+ID4gZGVjbGFyYXRpb25zIHRoYXQg
aGF2ZSByZWZlcmVuY2VzIHRvIHNvbWUgQUNQSUNBIGRlZmluZWQgdHlwZXMuDQo+ID4NCj4gPiBT
aWduZWQtb2ZmLWJ5OiBMdiBaaGVuZyA8bHYuemhlbmdAaW50ZWwuY29tPg0KPiA+IFJldmlld2Vk
LWJ5OiBIdWFuZyBZaW5nIDx5aW5nLmh1YW5nQGludGVsLmNvbT4NCj4gPiAtLS0NCj4gPiAgZHJp
dmVycy9hY3BpL2FjcGlfaXBtaS5jIHwgICAxNiArKy0tDQo+ID4gIGRyaXZlcnMvYWNwaS9vc2wu
YyAgICAgICB8ICAyMjQNCj4gKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrKysrKw0KPiA+ICBpbmNsdWRlL2FjcGkvYWNwaV9idXMuaCAgfCAgICA1ICsrDQo+ID4gIDMg
ZmlsZXMgY2hhbmdlZCwgMjM1IGluc2VydGlvbnMoKyksIDEwIGRlbGV0aW9ucygtKQ0KPiA+DQo+
ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvYWNwaS9hY3BpX2lwbWkuYyBiL2RyaXZlcnMvYWNwaS9h
Y3BpX2lwbWkuYyBpbmRleA0KPiA+IDVmOGY0OTUuLjJhMDkxNTYgMTAwNjQ0DQo+ID4gLS0tIGEv
ZHJpdmVycy9hY3BpL2FjcGlfaXBtaS5jDQo+ID4gKysrIGIvZHJpdmVycy9hY3BpL2FjcGlfaXBt
aS5jDQo+ID4gQEAgLTUzOSwyMCArNTM5LDE4IEBAIG91dF9yZWY6DQo+ID4gIHN0YXRpYyBpbnQg
X19pbml0IGFjcGlfaXBtaV9pbml0KHZvaWQpICB7DQo+ID4gIAlpbnQgcmVzdWx0ID0gMDsNCj4g
PiAtCWFjcGlfc3RhdHVzIHN0YXR1czsNCj4gPg0KPiA+ICAJaWYgKGFjcGlfZGlzYWJsZWQpDQo+
ID4gIAkJcmV0dXJuIHJlc3VsdDsNCj4gPg0KPiA+ICAJbXV0ZXhfaW5pdCgmZHJpdmVyX2RhdGEu
aXBtaV9sb2NrKTsNCj4gPg0KPiA+IC0Jc3RhdHVzID0gYWNwaV9pbnN0YWxsX2FkZHJlc3Nfc3Bh
Y2VfaGFuZGxlcihBQ1BJX1JPT1RfT0JKRUNULA0KPiA+IC0JCQkJCQkgICAgQUNQSV9BRFJfU1BB
Q0VfSVBNSSwNCj4gPiAtCQkJCQkJICAgICZhY3BpX2lwbWlfc3BhY2VfaGFuZGxlciwNCj4gPiAt
CQkJCQkJICAgIE5VTEwsIE5VTEwpOw0KPiA+IC0JaWYgKEFDUElfRkFJTFVSRShzdGF0dXMpKSB7
DQo+ID4gKwlyZXN1bHQgPSBhY3BpX3JlZ2lzdGVyX3JlZ2lvbihBQ1BJX0FEUl9TUEFDRV9JUE1J
LA0KPiA+ICsJCQkJICAgICAgJmFjcGlfaXBtaV9zcGFjZV9oYW5kbGVyLA0KPiA+ICsJCQkJICAg
ICAgTlVMTCwgTlVMTCk7DQo+ID4gKwlpZiAocmVzdWx0KSB7DQo+ID4gIAkJcHJfd2FybigiQ2Fu
J3QgcmVnaXN0ZXIgSVBNSSBvcHJlZ2lvbiBzcGFjZSBoYW5kbGVcbiIpOw0KPiA+IC0JCXJldHVy
biAtRUlOVkFMOw0KPiA+ICsJCXJldHVybiByZXN1bHQ7DQo+ID4gIAl9DQo+ID4NCj4gPiAgCXJl
c3VsdCA9IGlwbWlfc21pX3dhdGNoZXJfcmVnaXN0ZXIoJmRyaXZlcl9kYXRhLmJtY19ldmVudHMp
Ow0KPiA+IEBAIC01OTYsOSArNTk0LDcgQEAgc3RhdGljIHZvaWQgX19leGl0IGFjcGlfaXBtaV9l
eGl0KHZvaWQpDQo+ID4gIAl9DQo+ID4gIAltdXRleF91bmxvY2soJmRyaXZlcl9kYXRhLmlwbWlf
bG9jayk7DQo+ID4NCj4gPiAtCWFjcGlfcmVtb3ZlX2FkZHJlc3Nfc3BhY2VfaGFuZGxlcihBQ1BJ
X1JPT1RfT0JKRUNULA0KPiA+IC0JCQkJCSAgQUNQSV9BRFJfU1BBQ0VfSVBNSSwNCj4gPiAtCQkJ
CQkgICZhY3BpX2lwbWlfc3BhY2VfaGFuZGxlcik7DQo+ID4gKwlhY3BpX3VucmVnaXN0ZXJfcmVn
aW9uKEFDUElfQURSX1NQQUNFX0lQTUkpOw0KPiA+ICB9DQo+ID4NCj4gPiAgbW9kdWxlX2luaXQo
YWNwaV9pcG1pX2luaXQpOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2FjcGkvb3NsLmMgYi9k
cml2ZXJzL2FjcGkvb3NsLmMgaW5kZXgNCj4gPiA2YWIyYzM1Li44Mzk4ZTUxIDEwMDY0NA0KPiA+
IC0tLSBhL2RyaXZlcnMvYWNwaS9vc2wuYw0KPiA+ICsrKyBiL2RyaXZlcnMvYWNwaS9vc2wuYw0K
PiA+IEBAIC04Niw2ICs4Niw0MiBAQCBzdGF0aWMgc3RydWN0IHdvcmtxdWV1ZV9zdHJ1Y3QgKmth
Y3BpZF93cTsgIHN0YXRpYw0KPiA+IHN0cnVjdCB3b3JrcXVldWVfc3RydWN0ICprYWNwaV9ub3Rp
Znlfd3E7ICBzdGF0aWMgc3RydWN0DQo+ID4gd29ya3F1ZXVlX3N0cnVjdCAqa2FjcGlfaG90cGx1
Z193cTsNCj4gPg0KPiA+ICtzdHJ1Y3QgYWNwaV9yZWdpb24gew0KPiA+ICsJdW5zaWduZWQgbG9u
ZyBmbGFnczsNCj4gPiArI2RlZmluZSBBQ1BJX1JFR0lPTl9ERUZBVUxUCQkweDAxDQo+ID4gKyNk
ZWZpbmUgQUNQSV9SRUdJT05fSU5TVEFMTEVECQkweDAyDQo+ID4gKyNkZWZpbmUgQUNQSV9SRUdJ
T05fUkVHSVNURVJFRAkJMHgwNA0KPiA+ICsjZGVmaW5lIEFDUElfUkVHSU9OX1VOUkVHSVNURVJJ
TkcJMHgwOA0KPiA+ICsjZGVmaW5lIEFDUElfUkVHSU9OX0lOU1RBTExJTkcJCTB4MTANCj4gDQo+
IFdoYXQgYWJvdXQgKDFVTCA8PCAxKSwgKDFVTCA8PCAyKSBldGMuPw0KPiANCj4gQWxzbyBwbGVh
c2UgcmVtb3ZlIHRoZSAjZGVmaW5lcyBvdXQgb2YgdGhlIHN0cnVjdCBkZWZpbml0aW9uLg0KDQpP
Sy4NCg0KPiANCj4gPiArCS8qDQo+ID4gKwkgKiBOT1RFOiBVcGdyYWRpbmcgQWxsIFJlZ2lvbiBI
YW5kbGVycw0KPiA+ICsJICogVGhpcyBmbGFnIGlzIG9ubHkgdXNlZCBkdXJpbmcgdGhlIHBlcmlv
ZCB3aGVyZSBub3QgYWxsIG9mIHRoZQ0KPiA+ICsJICogcmVnaW9uIGhhbmRlcnMgYXJlIHVwZ3Jh
ZGVkIHRvIHRoZSBuZXcgaW50ZXJmYWNlcy4NCj4gPiArCSAqLw0KPiA+ICsjZGVmaW5lIEFDUElf
UkVHSU9OX01BTkFHRUQJCTB4ODANCj4gPiArCWFjcGlfYWRyX3NwYWNlX2hhbmRsZXIgaGFuZGxl
cjsNCj4gPiArCWFjcGlfYWRyX3NwYWNlX3NldHVwIHNldHVwOw0KPiA+ICsJdm9pZCAqY29udGV4
dDsNCj4gPiArCS8qIEludm9raW5nIHJlZmVyZW5jZXMgKi8NCj4gPiArCWF0b21pY190IHJlZmNu
dDsNCj4gDQo+IEFjdHVhbGx5LCB3aHkgZG9uJ3QgeW91IHVzZSBrcmVmcz8NCg0KSWYgeW91IHRh
a2UgYSBsb29rIGF0IG90aGVyIHBpZWNlIG9mIG15IGNvZGVzLCB5b3UnbGwgZmluZCB0aGVyZSBh
cmUgdHdvIHJlYXNvbnM6DQoNCjEuIEknbSB1c2luZyB3aGlsZSAoYXRvbWljX3JlYWQoKSA+IDEp
IHRvIGltcGxlbWVudCB0aGUgb2JqZWN0cycgZmx1c2hpbmcgYW5kIHRoZXJlIGlzIG5vIGtyZWYg
QVBJIHRvIGRvIHNvLg0KICBJIGp1c3QgdGhpbmsgaXQgaXMgbm90IHN1aXRhYmxlIGZvciBtZSB0
byBpbnRyb2R1Y2Ugc3VjaCBhbiBBUEkgaW50byBrcmVmLmggYW5kIHN0YXJ0IGFub3RoZXIgYXJn
dW1lbnQgYXJvdW5kIGtyZWYgZGVzaWducyBpbiB0aGlzIGJ1ZyBmaXggcGF0Y2guIDotKQ0KICBJ
J2xsIHN0YXJ0IGEgZGlzY3Vzc2lvbiBhYm91dCBrcmVmIGRlc2lnbiB1c2luZyBhbm90aGVyIHRo
cmVhZC4NCjIuIEknbSB1c2luZyBpcG1pX2Rldnxtc2dfcmVsZWFzZSgpIGFzIGEgcGFpciBvZiBp
cG1pX2Rldnxtc2dfYWxsb2MoKSwgaXQncyBraW5kIG9mIGF0b21pY190IGNvZGluZyBzdHlsZS4N
CiAgSWYgYXRvbWljX3QgaXMgY2hhbmdlZCB0byBzdHJ1Y3Qga3JlZiwgSSB3aWxsIG5lZWQgdG8g
aW1wbGVtZW50IHR3byBBUEksIF9faXBtaV9kZXZfcmVsZWFzZSgpIHRvIHRha2UgYSBzdHJ1Y3Qg
a3JlZiBhcyBwYXJhbWV0ZXIgYW5kIGNhbGwgaXBtaV9kZXZfcmVsZWFzZSBpbnNpZGUgaXQuDQog
IEJ5IG5vdCB1c2luZyBrcmVmLCBJIG5lZWRuJ3Qgd3JpdGUgY29kZXMgdG8gaW1wbGVtZW50IHN1
Y2ggQVBJLg0KDQo+IA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIHN0cnVjdCBhY3BpX3Jl
Z2lvbiBhY3BpX3JlZ2lvbnNbQUNQSV9OVU1fUFJFREVGSU5FRF9SRUdJT05TXQ0KPiA9IHsNCj4g
PiArCVtBQ1BJX0FEUl9TUEFDRV9TWVNURU1fTUVNT1JZXSA9IHsNCj4gPiArCQkuZmxhZ3MgPSBB
Q1BJX1JFR0lPTl9ERUZBVUxULA0KPiA+ICsJfSwNCj4gPiArCVtBQ1BJX0FEUl9TUEFDRV9TWVNU
RU1fSU9dID0gew0KPiA+ICsJCS5mbGFncyA9IEFDUElfUkVHSU9OX0RFRkFVTFQsDQo+ID4gKwl9
LA0KPiA+ICsJW0FDUElfQURSX1NQQUNFX1BDSV9DT05GSUddID0gew0KPiA+ICsJCS5mbGFncyA9
IEFDUElfUkVHSU9OX0RFRkFVTFQsDQo+ID4gKwl9LA0KPiA+ICsJW0FDUElfQURSX1NQQUNFX0lQ
TUldID0gew0KPiA+ICsJCS5mbGFncyA9IEFDUElfUkVHSU9OX01BTkFHRUQsDQo+ID4gKwl9LA0K
PiA+ICt9Ow0KPiA+ICtzdGF0aWMgREVGSU5FX01VVEVYKGFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4g
PiArDQo+ID4gIC8qDQo+ID4gICAqIFRoaXMgbGlzdCBvZiBwZXJtYW5lbnQgbWFwcGluZ3MgaXMg
Zm9yIG1lbW9yeSB0aGF0IG1heSBiZSBhY2Nlc3NlZA0KPiBmcm9tDQo+ID4gICAqIGludGVycnVw
dCBjb250ZXh0LCB3aGVyZSB3ZSBjYW4ndCBkbyB0aGUgaW9yZW1hcCgpLg0KPiA+IEBAIC0xNzk5
LDMgKzE4MzUsMTkxIEBAIHZvaWQgYWxsb2NfYWNwaV9ocF93b3JrKGFjcGlfaGFuZGxlIGhhbmRs
ZSwNCj4gdTMyIHR5cGUsIHZvaWQgKmNvbnRleHQsDQo+ID4gIAkJa2ZyZWUoaHBfd29yayk7DQo+
ID4gIH0NCj4gPiAgRVhQT1JUX1NZTUJPTF9HUEwoYWxsb2NfYWNwaV9ocF93b3JrKTsNCj4gPiAr
DQo+ID4gK3N0YXRpYyBib29sIGFjcGlfcmVnaW9uX21hbmFnZWQoc3RydWN0IGFjcGlfcmVnaW9u
ICpyZ24pIHsNCj4gPiArCS8qDQo+ID4gKwkgKiBOT1RFOiBEZWZhdWx0IGFuZCBNYW5hZ2VkDQo+
ID4gKwkgKiBXZSBvbmx5IG5lZWQgdG8gYXZvaWQgcmVnaW9uIG1hbmFnZW1lbnQgb24gdGhlIHJl
Z2lvbnMgbWFuYWdlZA0KPiA+ICsJICogYnkgQUNQSUNBIChBQ1BJX1JFR0lPTl9ERUZBVUxUKS4g
IEN1cnJlbnRseSwgd2UgbmVlZCBhZGRpdGlvbmFsDQo+ID4gKwkgKiBjaGVjayBhcyBtYW55IG9w
ZXJhdGlvbiByZWdpb24gaGFuZGxlcnMgYXJlIG5vdCB1cGdyYWRlZCwgc28NCj4gPiArCSAqIG9u
bHkgdGhvc2Uga25vd24gdG8gYmUgc2FmZSBhcmUgbWFuYWdlZCAoQUNQSV9SRUdJT05fTUFOQUdF
RCkuDQo+ID4gKwkgKi8NCj4gPiArCXJldHVybiAhKHJnbi0+ZmxhZ3MgJiBBQ1BJX1JFR0lPTl9E
RUZBVUxUKSAmJg0KPiA+ICsJICAgICAgIChyZ24tPmZsYWdzICYgQUNQSV9SRUdJT05fTUFOQUdF
RCk7IH0NCj4gPiArDQo+ID4gK3N0YXRpYyBib29sIGFjcGlfcmVnaW9uX2NhbGxhYmxlKHN0cnVj
dCBhY3BpX3JlZ2lvbiAqcmduKSB7DQo+ID4gKwlyZXR1cm4gKHJnbi0+ZmxhZ3MgJiBBQ1BJX1JF
R0lPTl9SRUdJU1RFUkVEKSAmJg0KPiA+ICsJICAgICAgICEocmduLT5mbGFncyAmIEFDUElfUkVH
SU9OX1VOUkVHSVNURVJJTkcpOyB9DQo+ID4gKw0KPiA+ICtzdGF0aWMgYWNwaV9zdGF0dXMNCj4g
PiArYWNwaV9yZWdpb25fZGVmYXVsdF9oYW5kbGVyKHUzMiBmdW5jdGlvbiwNCj4gPiArCQkJICAg
IGFjcGlfcGh5c2ljYWxfYWRkcmVzcyBhZGRyZXNzLA0KPiA+ICsJCQkgICAgdTMyIGJpdF93aWR0
aCwgdTY0ICp2YWx1ZSwNCj4gPiArCQkJICAgIHZvaWQgKmhhbmRsZXJfY29udGV4dCwgdm9pZCAq
cmVnaW9uX2NvbnRleHQpIHsNCj4gPiArCWFjcGlfYWRyX3NwYWNlX2hhbmRsZXIgaGFuZGxlcjsN
Cj4gPiArCXN0cnVjdCBhY3BpX3JlZ2lvbiAqcmduID0gKHN0cnVjdCBhY3BpX3JlZ2lvbiAqKWhh
bmRsZXJfY29udGV4dDsNCj4gPiArCXZvaWQgKmNvbnRleHQ7DQo+ID4gKwlhY3BpX3N0YXR1cyBz
dGF0dXMgPSBBRV9OT1RfRVhJU1Q7DQo+ID4gKw0KPiA+ICsJbXV0ZXhfbG9jaygmYWNwaV9tdXRl
eF9yZWdpb24pOw0KPiA+ICsJaWYgKCFhY3BpX3JlZ2lvbl9jYWxsYWJsZShyZ24pIHx8ICFyZ24t
PmhhbmRsZXIpIHsNCj4gPiArCQltdXRleF91bmxvY2soJmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4g
PiArCQlyZXR1cm4gc3RhdHVzOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCWF0b21pY19pbmMoJnJn
bi0+cmVmY250KTsNCj4gPiArCWhhbmRsZXIgPSByZ24tPmhhbmRsZXI7DQo+ID4gKwljb250ZXh0
ID0gcmduLT5jb250ZXh0Ow0KPiA+ICsJbXV0ZXhfdW5sb2NrKCZhY3BpX211dGV4X3JlZ2lvbik7
DQo+ID4gKw0KPiA+ICsJc3RhdHVzID0gaGFuZGxlcihmdW5jdGlvbiwgYWRkcmVzcywgYml0X3dp
ZHRoLCB2YWx1ZSwgY29udGV4dCwNCj4gPiArCQkJIHJlZ2lvbl9jb250ZXh0KTsNCj4gDQo+IFdo
eSBkb24ndCB3ZSBjYWxsIHRoZSBoYW5kbGVyIHVuZGVyIHRoZSBtdXRleD8NCj4gDQo+IFdoYXQg
ZXhhY3RseSBwcmV2ZW50cyBjb250ZXh0IGZyb20gYmVjb21pbmcgTlVMTCBiZWZvcmUgdGhlIGNh
bGwgYWJvdmU/DQoNCkl0J3MgYSBraW5kIG9mIHByb2dyYW1taW5nIHN0eWxlIHJlbGF0ZWQgY29u
Y2Vybi4NCklNTywgdXNpbmcgbG9ja3MgYXJvdW5kIGNhbGxiYWNrIGZ1bmN0aW9uIGlzIGEgYnVn
Z3kgcHJvZ3JhbW1pbmcgc3R5bGUgdGhhdCBjb3VsZCBsZWFkIHRvIGRlYWQgbG9ja3MuDQpMZXQg
bWUgZXhwbGFpbiB0aGlzIHVzaW5nIGFuIGV4YW1wbGUuDQoNCk9iamVjdCBBIGV4cG9ydHMgYSBy
ZWdpc3Rlci91bnJlZ2lzdGVyIEFQSSBmb3Igb3RoZXIgb2JqZWN0cy4NCk9iamVjdCBCIGNhbGxz
IEEncyByZWdpc3Rlci91bnJlZ2lzdGVyIEFQSSB0byByZWdpc3Rlci91bnJlZ2lzdGVyIEIncyBj
YWxsYmFjay4NCkl0J3MgbGlrZWx5IHRoYXQgb2JqZWN0IEIgd2lsbCBob2xkIGxvY2tfb2ZfQiBh
cm91bmQgdW5yZWdpc3Rlci9yZWdpc3RlciB3aGVuIG9iamVjdCBCIGlzIGRlc3Ryb3llZC9jcmVh
dGVkLCB0aGUgbG9ja19vZl9CIGlzIGxpa2VseSBhbHNvIHVzZWQgaW5zaWRlIHRoZSBjYWxsYmFj
ay4NClNvIHdoZW4gb2JqZWN0IEEgaG9sZHMgdGhlIGxvY2tfb2ZfQSBhcm91bmQgdGhlIGNhbGxi
YWNrIGludm9jYXRpb24sIGl0IGxlYWRzIHRvIGRlYWQgbG9jayBzaW5jZToNCjEuIHRoZSBsb2Nr
aW5nIG9yZGVyIGZvciB0aGUgcmVnaXN0ZXIvdW5yZWdpc3RlciBzaWRlIHdpbGwgYmU6IGxvY2so
bG9ja19vZl9CKSwgbG9jayhsb2NrX29mX0EpDQoyLiB0aGUgbG9ja2luZyBvcmRlciBmb3IgdGhl
IGNhbGxiYWNrIHNpZGUgd2lsbCBiZTogbG9jayhsb2NrX29mX0EpLCBsb2NrKGxvY2tfb2ZfQikN
ClRoZXkgYXJlIGluIHRoZSByZXZlcnNlZCBvcmRlciENCg0KSU1PLCBMaW51eCBtYXkgbmVlZCB0
byBpbnRyb2R1Y2UgX19jYWxsYmFjaywgX19hcGkgYXMgZGVjZWxlcmF0b3JzIGZvciB0aGUgZnVu
Y3Rpb25zLCBhbmQgdXNlIHNwYXJzZSB0byBlbmZvcmNlIHRoaXMgcnVsZSwgc3BhcnNlIGtub3dz
IGlmIGEgY2FsbGJhY2sgaXMgaW52b2tlZCB1bmRlciBzb21lIGxvY2tzLg0KDQpJbiB0aGUgY2Fz
ZSBvZiBBQ1BJQ0Egc3BhY2VfaGFuZGxlcnMsIGFzIHlvdSBtYXkga25vdywgd2hlbiBhbiBBQ1BJ
IG9wZXJhdGlvbiByZWdpb24gaGFuZGxlciBpcyBpbnZva2VkLCB0aGVyZSB3aWxsIGJlIG5vIGxv
Y2sgaGVsZCBpbnNpZGUgQUNQSUNBIChpbnRlcnByZXRlciBsb2NrIG11c3QgYmUgZnJlZWQgYmVm
b3JlIGV4ZWN1dGluZyBvcGVyYXRpb24gcmVnaW9uIGhhbmRsZXJzKS4NClNvIHRoZSBsaWtlbGlo
b29kIG9mIHRoZSBkZWFkIGxvY2sgaXMgcHJldHR5IG11Y2ggaGlnaCBoZXJlIQ0KDQo+IA0KPiA+
ICsJYXRvbWljX2RlYygmcmduLT5yZWZjbnQpOw0KPiA+ICsNCj4gPiArCXJldHVybiBzdGF0dXM7
DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBhY3BpX3N0YXR1cw0KPiA+ICthY3BpX3JlZ2lv
bl9kZWZhdWx0X3NldHVwKGFjcGlfaGFuZGxlIGhhbmRsZSwgdTMyIGZ1bmN0aW9uLA0KPiA+ICsJ
CQkgIHZvaWQgKmhhbmRsZXJfY29udGV4dCwgdm9pZCAqKnJlZ2lvbl9jb250ZXh0KSB7DQo+ID4g
KwlhY3BpX2Fkcl9zcGFjZV9zZXR1cCBzZXR1cDsNCj4gPiArCXN0cnVjdCBhY3BpX3JlZ2lvbiAq
cmduID0gKHN0cnVjdCBhY3BpX3JlZ2lvbiAqKWhhbmRsZXJfY29udGV4dDsNCj4gPiArCXZvaWQg
KmNvbnRleHQ7DQo+ID4gKwlhY3BpX3N0YXR1cyBzdGF0dXMgPSBBRV9PSzsNCj4gPiArDQo+ID4g
KwltdXRleF9sb2NrKCZhY3BpX211dGV4X3JlZ2lvbik7DQo+ID4gKwlpZiAoIWFjcGlfcmVnaW9u
X2NhbGxhYmxlKHJnbikgfHwgIXJnbi0+c2V0dXApIHsNCj4gPiArCQltdXRleF91bmxvY2soJmFj
cGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiArCQlyZXR1cm4gc3RhdHVzOw0KPiA+ICsJfQ0KPiA+ICsN
Cj4gPiArCWF0b21pY19pbmMoJnJnbi0+cmVmY250KTsNCj4gPiArCXNldHVwID0gcmduLT5zZXR1
cDsNCj4gPiArCWNvbnRleHQgPSByZ24tPmNvbnRleHQ7DQo+ID4gKwltdXRleF91bmxvY2soJmFj
cGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiArDQo+ID4gKwlzdGF0dXMgPSBzZXR1cChoYW5kbGUsIGZ1
bmN0aW9uLCBjb250ZXh0LCByZWdpb25fY29udGV4dCk7DQo+IA0KPiBDYW4gc2V0dXAgZHJvcCBy
Z24tPnJlZmNudCA/DQoNClRoZSByZWFzb24gaXMgc2FtZSBhcyB0aGUgaGFuZGxlciwgYXMgYSBz
ZXR1cCBpcyBhbHNvIGEgY2FsbGJhY2suDQoNCj4gDQo+ID4gKwlhdG9taWNfZGVjKCZyZ24tPnJl
ZmNudCk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHN0YXR1czsNCj4gPiArfQ0KPiA+ICsNCj4gPiAr
c3RhdGljIGludCBfX2FjcGlfaW5zdGFsbF9yZWdpb24oc3RydWN0IGFjcGlfcmVnaW9uICpyZ24s
DQo+ID4gKwkJCQkgYWNwaV9hZHJfc3BhY2VfdHlwZSBzcGFjZV9pZCkNCj4gPiArew0KPiA+ICsJ
aW50IHJlcyA9IDA7DQo+ID4gKwlhY3BpX3N0YXR1cyBzdGF0dXM7DQo+ID4gKwlpbnQgaW5zdGFs
bGluZyA9IDA7DQo+ID4gKw0KPiA+ICsJbXV0ZXhfbG9jaygmYWNwaV9tdXRleF9yZWdpb24pOw0K
PiA+ICsJaWYgKHJnbi0+ZmxhZ3MgJiBBQ1BJX1JFR0lPTl9JTlNUQUxMRUQpDQo+ID4gKwkJZ290
byBvdXRfbG9jazsNCj4gPiArCWlmIChyZ24tPmZsYWdzICYgQUNQSV9SRUdJT05fSU5TVEFMTElO
Rykgew0KPiA+ICsJCXJlcyA9IC1FQlVTWTsNCj4gPiArCQlnb3RvIG91dF9sb2NrOw0KPiA+ICsJ
fQ0KPiA+ICsNCj4gPiArCWluc3RhbGxpbmcgPSAxOw0KPiA+ICsJcmduLT5mbGFncyB8PSBBQ1BJ
X1JFR0lPTl9JTlNUQUxMSU5HOw0KPiA+ICsJc3RhdHVzID0gYWNwaV9pbnN0YWxsX2FkZHJlc3Nf
c3BhY2VfaGFuZGxlcihBQ1BJX1JPT1RfT0JKRUNULA0KPiBzcGFjZV9pZCwNCj4gPiArCQkJCQkJ
ICAgIGFjcGlfcmVnaW9uX2RlZmF1bHRfaGFuZGxlciwNCj4gPiArCQkJCQkJICAgIGFjcGlfcmVn
aW9uX2RlZmF1bHRfc2V0dXAsDQo+ID4gKwkJCQkJCSAgICByZ24pOw0KPiA+ICsJcmduLT5mbGFn
cyAmPSB+QUNQSV9SRUdJT05fSU5TVEFMTElORzsNCj4gPiArCWlmIChBQ1BJX0ZBSUxVUkUoc3Rh
dHVzKSkNCj4gPiArCQlyZXMgPSAtRUlOVkFMOw0KPiA+ICsJZWxzZQ0KPiA+ICsJCXJnbi0+Zmxh
Z3MgfD0gQUNQSV9SRUdJT05fSU5TVEFMTEVEOw0KPiA+ICsNCj4gPiArb3V0X2xvY2s6DQo+ID4g
KwltdXRleF91bmxvY2soJmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiArCWlmIChpbnN0YWxsaW5n
KSB7DQo+ID4gKwkJaWYgKHJlcykNCj4gPiArCQkJcHJfZXJyKCJGYWlsZWQgdG8gaW5zdGFsbCBy
ZWdpb24gJWRcbiIsIHNwYWNlX2lkKTsNCj4gPiArCQllbHNlDQo+ID4gKwkJCXByX2luZm8oIlJl
Z2lvbiAlZCBpbnN0YWxsZWRcbiIsIHNwYWNlX2lkKTsNCj4gPiArCX0NCj4gPiArCXJldHVybiBy
ZXM7DQo+ID4gK30NCj4gPiArDQo+ID4gK2ludCBhY3BpX3JlZ2lzdGVyX3JlZ2lvbihhY3BpX2Fk
cl9zcGFjZV90eXBlIHNwYWNlX2lkLA0KPiA+ICsJCQkgYWNwaV9hZHJfc3BhY2VfaGFuZGxlciBo
YW5kbGVyLA0KPiA+ICsJCQkgYWNwaV9hZHJfc3BhY2Vfc2V0dXAgc2V0dXAsIHZvaWQgKmNvbnRl
eHQpIHsNCj4gPiArCWludCByZXM7DQo+ID4gKwlzdHJ1Y3QgYWNwaV9yZWdpb24gKnJnbjsNCj4g
PiArDQo+ID4gKwlpZiAoc3BhY2VfaWQgPj0gQUNQSV9OVU1fUFJFREVGSU5FRF9SRUdJT05TKQ0K
PiA+ICsJCXJldHVybiAtRUlOVkFMOw0KPiA+ICsNCj4gPiArCXJnbiA9ICZhY3BpX3JlZ2lvbnNb
c3BhY2VfaWRdOw0KPiA+ICsJaWYgKCFhY3BpX3JlZ2lvbl9tYW5hZ2VkKHJnbikpDQo+ID4gKwkJ
cmV0dXJuIC1FSU5WQUw7DQo+ID4gKw0KPiA+ICsJcmVzID0gX19hY3BpX2luc3RhbGxfcmVnaW9u
KHJnbiwgc3BhY2VfaWQpOw0KPiA+ICsJaWYgKHJlcykNCj4gPiArCQlyZXR1cm4gcmVzOw0KPiA+
ICsNCj4gPiArCW11dGV4X2xvY2soJmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiArCWlmIChyZ24t
PmZsYWdzICYgQUNQSV9SRUdJT05fUkVHSVNURVJFRCkgew0KPiA+ICsJCW11dGV4X3VubG9jaygm
YWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ICsJCXJldHVybiAtRUJVU1k7DQo+ID4gKwl9DQo+ID4g
Kw0KPiA+ICsJcmduLT5oYW5kbGVyID0gaGFuZGxlcjsNCj4gPiArCXJnbi0+c2V0dXAgPSBzZXR1
cDsNCj4gPiArCXJnbi0+Y29udGV4dCA9IGNvbnRleHQ7DQo+ID4gKwlyZ24tPmZsYWdzIHw9IEFD
UElfUkVHSU9OX1JFR0lTVEVSRUQ7DQo+ID4gKwlhdG9taWNfc2V0KCZyZ24tPnJlZmNudCwgMSk7
DQo+ID4gKwltdXRleF91bmxvY2soJmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiArDQo+ID4gKwlw
cl9pbmZvKCJSZWdpb24gJWQgcmVnaXN0ZXJlZFxuIiwgc3BhY2VfaWQpOw0KPiA+ICsNCj4gPiAr
CXJldHVybiAwOw0KPiA+ICt9DQo+ID4gK0VYUE9SVF9TWU1CT0xfR1BMKGFjcGlfcmVnaXN0ZXJf
cmVnaW9uKTsNCj4gPiArDQo+ID4gK3ZvaWQgYWNwaV91bnJlZ2lzdGVyX3JlZ2lvbihhY3BpX2Fk
cl9zcGFjZV90eXBlIHNwYWNlX2lkKSB7DQo+ID4gKwlzdHJ1Y3QgYWNwaV9yZWdpb24gKnJnbjsN
Cj4gPiArDQo+ID4gKwlpZiAoc3BhY2VfaWQgPj0gQUNQSV9OVU1fUFJFREVGSU5FRF9SRUdJT05T
KQ0KPiA+ICsJCXJldHVybjsNCj4gPiArDQo+ID4gKwlyZ24gPSAmYWNwaV9yZWdpb25zW3NwYWNl
X2lkXTsNCj4gPiArCWlmICghYWNwaV9yZWdpb25fbWFuYWdlZChyZ24pKQ0KPiA+ICsJCXJldHVy
bjsNCj4gPiArDQo+ID4gKwltdXRleF9sb2NrKCZhY3BpX211dGV4X3JlZ2lvbik7DQo+ID4gKwlp
ZiAoIShyZ24tPmZsYWdzICYgQUNQSV9SRUdJT05fUkVHSVNURVJFRCkpIHsNCj4gPiArCQltdXRl
eF91bmxvY2soJmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiArCQlyZXR1cm47DQo+ID4gKwl9DQo+
ID4gKwlpZiAocmduLT5mbGFncyAmIEFDUElfUkVHSU9OX1VOUkVHSVNURVJJTkcpIHsNCj4gPiAr
CQltdXRleF91bmxvY2soJmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiArCQlyZXR1cm47DQo+IA0K
PiBXaGF0IGFib3V0DQo+IA0KPiAJaWYgKChyZ24tPmZsYWdzICYgQUNQSV9SRUdJT05fVU5SRUdJ
U1RFUklORykNCj4gCSAgICB8fCAhKHJnbi0+ZmxhZ3MgJiBBQ1BJX1JFR0lPTl9SRUdJU1RFUkVE
KSkgew0KPiAJCW11dGV4X3VubG9jaygmYWNwaV9tdXRleF9yZWdpb24pOw0KPiAJCXJldHVybjsN
Cj4gCX0NCj4gDQoNCk9LLg0KDQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmduLT5mbGFncyB8PSBB
Q1BJX1JFR0lPTl9VTlJFR0lTVEVSSU5HOw0KPiA+ICsJcmduLT5oYW5kbGVyID0gTlVMTDsNCj4g
PiArCXJnbi0+c2V0dXAgPSBOVUxMOw0KPiA+ICsJcmduLT5jb250ZXh0ID0gTlVMTDsNCj4gPiAr
CW11dGV4X3VubG9jaygmYWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ICsNCj4gPiArCXdoaWxlIChh
dG9taWNfcmVhZCgmcmduLT5yZWZjbnQpID4gMSkNCj4gPiArCQlzY2hlZHVsZV90aW1lb3V0X3Vu
aW50ZXJydXB0aWJsZSh1c2Vjc190b19qaWZmaWVzKDUpKTsNCj4gDQo+IFdvdWxkbid0IGl0IGJl
IGJldHRlciB0byB1c2UgYSB3YWl0IHF1ZXVlIGhlcmU/DQoNClllcywgSSdsbCB0cnkuDQoNCj4g
DQo+ID4gKwlhdG9taWNfZGVjKCZyZ24tPnJlZmNudCk7DQo+ID4gKw0KPiA+ICsJbXV0ZXhfbG9j
aygmYWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ICsJcmduLT5mbGFncyAmPSB+KEFDUElfUkVHSU9O
X1JFR0lTVEVSRUQgfA0KPiBBQ1BJX1JFR0lPTl9VTlJFR0lTVEVSSU5HKTsNCj4gPiArCW11dGV4
X3VubG9jaygmYWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ICsNCj4gPiArCXByX2luZm8oIlJlZ2lv
biAlZCB1bnJlZ2lzdGVyZWRcbiIsIHNwYWNlX2lkKTsgfQ0KPiA+ICtFWFBPUlRfU1lNQk9MX0dQ
TChhY3BpX3VucmVnaXN0ZXJfcmVnaW9uKTsNCj4gPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9hY3Bp
L2FjcGlfYnVzLmggYi9pbmNsdWRlL2FjcGkvYWNwaV9idXMuaCBpbmRleA0KPiA+IGEyYzJmYmIu
LjE1ZmFkMGQgMTAwNjQ0DQo+ID4gLS0tIGEvaW5jbHVkZS9hY3BpL2FjcGlfYnVzLmgNCj4gPiAr
KysgYi9pbmNsdWRlL2FjcGkvYWNwaV9idXMuaA0KPiA+IEBAIC01NDIsNCArNTQyLDkgQEAgc3Rh
dGljIGlubGluZSBpbnQgdW5yZWdpc3Rlcl9hY3BpX2J1c190eXBlKHZvaWQNCj4gPiAqYnVzKSB7
IHJldHVybiAwOyB9DQo+ID4NCj4gPiAgI2VuZGlmCQkJCS8qIENPTkZJR19BQ1BJICovDQo+ID4N
Cj4gPiAraW50IGFjcGlfcmVnaXN0ZXJfcmVnaW9uKGFjcGlfYWRyX3NwYWNlX3R5cGUgc3BhY2Vf
aWQsDQo+ID4gKwkJCSBhY3BpX2Fkcl9zcGFjZV9oYW5kbGVyIGhhbmRsZXIsDQo+ID4gKwkJCSBh
Y3BpX2Fkcl9zcGFjZV9zZXR1cCBzZXR1cCwgdm9pZCAqY29udGV4dCk7IHZvaWQNCj4gPiArYWNw
aV91bnJlZ2lzdGVyX3JlZ2lvbihhY3BpX2Fkcl9zcGFjZV90eXBlIHNwYWNlX2lkKTsNCj4gPiAr
DQo+ID4gICNlbmRpZiAvKl9fQUNQSV9CVVNfSF9fKi8NCj4gDQo+IFRoYW5rcywNCj4gUmFmYWVs
DQoNClRoYW5rcw0KLUx2DQoNCj4gDQo+IA0KPiAtLQ0KPiBJIHNwZWFrIG9ubHkgZm9yIG15c2Vs
Zi4NCj4gUmFmYWVsIEouIFd5c29ja2ksIEludGVsIE9wZW4gU291cmNlIFRlY2hub2xvZ3kgQ2Vu
dGVyLg0K
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Lv Zheng July 26, 2013, 1:54 a.m. UTC | #4
> From: Rafael J. Wysocki [mailto:rjw@sisk.pl]

> Sent: Friday, July 26, 2013 5:29 AM

> 

> On Tuesday, July 23, 2013 04:09:43 PM Lv Zheng wrote:

> > This patch adds reference couting for ACPI operation region handlers to fix

> > races caused by the ACPICA address space callback invocations.

> >

> > ACPICA address space callback invocation is not suitable for Linux

> > CONFIG_MODULE=y execution environment.

> 

> Actually, can you please explain to me what *exactly* the problem is?


OK.  I'll add race explanations in the next revision.

The problem is there is no "lock" held inside ACPICA for invoking operation region handlers.
Thus races happens between the acpi_remove/install_address_space_handler and the handler/setup callbacks.

This is correct per ACPI specification.
As if there is interpreter locks held for invoking operation region handlers, the timeout implemented inside the operation region handlers will make all locking facilities (Acquire or Sleep,...) timed out.
Please refer to ACPI specification "5.5.2 Control Method Execution":
Interpretation of a Control Method is not preemptive, but it can block. When a control method does block, OSPM can initiate or continue the execution of a different control method. A control method can only assume that access to global objects is exclusive for any period the control method does not block.

So it is pretty much likely that ACPI IO transfers are locked inside the operation region callback implementations.
Using locking facility to protect the callback invocation will risk dead locks.

Thanks
-Lv

> Rafael
Lv Zheng July 26, 2013, 8:09 a.m. UTC | #5
PiBGcm9tOiBsaW51eC1hY3BpLW93bmVyQHZnZXIua2VybmVsLm9yZw0KPiBbbWFpbHRvOmxpbnV4
LWFjcGktb3duZXJAdmdlci5rZXJuZWwub3JnXSBPbiBCZWhhbGYgT2YgWmhlbmcsIEx2DQo+IFNl
bnQ6IEZyaWRheSwgSnVseSAyNiwgMjAxMyA4OjQ4IEFNDQo+IA0KPiANCj4gDQo+ID4gRnJvbTog
UmFmYWVsIEouIFd5c29ja2kgW21haWx0bzpyandAc2lzay5wbF0NCj4gPiBTZW50OiBGcmlkYXks
IEp1bHkgMjYsIDIwMTMgNDoyNyBBTQ0KPiA+DQo+ID4gT24gVHVlc2RheSwgSnVseSAyMywgMjAx
MyAwNDowOTo0MyBQTSBMdiBaaGVuZyB3cm90ZToNCj4gPiA+IFRoaXMgcGF0Y2ggYWRkcyByZWZl
cmVuY2UgY291dGluZyBmb3IgQUNQSSBvcGVyYXRpb24gcmVnaW9uIGhhbmRsZXJzDQo+ID4gPiB0
byBmaXggcmFjZXMgY2F1c2VkIGJ5IHRoZSBBQ1BJQ0EgYWRkcmVzcyBzcGFjZSBjYWxsYmFjayBp
bnZvY2F0aW9ucy4NCj4gPiA+DQo+ID4gPiBBQ1BJQ0EgYWRkcmVzcyBzcGFjZSBjYWxsYmFjayBp
bnZvY2F0aW9uIGlzIG5vdCBzdWl0YWJsZSBmb3IgTGludXgNCj4gPiA+IENPTkZJR19NT0RVTEU9
eSBleGVjdXRpb24gZW52aXJvbm1lbnQuICBUaGlzIHBhdGNoIHRyaWVzIHRvIHByb3RlY3QNCj4g
PiA+IHRoZSBhZGRyZXNzIHNwYWNlIGNhbGxiYWNrcyBieSBpbnZva2luZyB0aGVtIHVuZGVyIGEg
bW9kdWxlIHNhZmUNCj4gPiBlbnZpcm9ubWVudC4NCj4gPiA+IFRoZSBJUE1JIGFkZHJlc3Mgc3Bh
Y2UgaGFuZGxlciBpcyBhbHNvIHVwZ3JhZGVkIGluIHRoaXMgcGF0Y2guDQo+ID4gPiBUaGUgYWNw
aV91bnJlZ2lzdGVyX3JlZ2lvbigpIGlzIGRlc2lnbmVkIHRvIG1lZXQgdGhlIGZvbGxvd2luZw0K
PiA+ID4gcmVxdWlyZW1lbnRzOg0KPiA+ID4gMS4gSXQgYWN0cyBhcyBhIGJhcnJpZXIgZm9yIG9w
ZXJhdGlvbiByZWdpb24gY2FsbGJhY2tzIC0gbm8gY2FsbGJhY2sgd2lsbA0KPiA+ID4gICAgaGFw
cGVuIGFmdGVyIGFjcGlfdW5yZWdpc3Rlcl9yZWdpb24oKS4NCj4gPiA+IDIuIGFjcGlfdW5yZWdp
c3Rlcl9yZWdpb24oKSBpcyBzYWZlIHRvIGJlIGNhbGxlZCBpbiBtb3VkbGUtPmV4aXQoKQ0KPiA+
ID4gICAgZnVuY3Rpb25zLg0KPiA+ID4gVXNpbmcgcmVmZXJlbmNlIGNvdW50aW5nIHJhdGhlciB0
aGFuIG1vZHVsZSByZWZlcmVuY2luZyBhbGxvd3Mgc3VjaA0KPiA+ID4gYmVuZWZpdHMgdG8gYmUg
YWNoaWV2ZWQgZXZlbiB3aGVuIGFjcGlfdW5yZWdpc3Rlcl9yZWdpb24oKSBpcyBjYWxsZWQNCj4g
PiA+IGluIHRoZSBlbnZpcm9ubWVudHMgb3RoZXIgdGhhbiBtb2R1bGUtPmV4aXQoKS4NCj4gPiA+
IFRoZSBoZWFkZXIgZmlsZSBvZiBpbmNsdWRlL2FjcGkvYWNwaV9idXMuaCBzaG91bGQgY29udGFp
biB0aGUNCj4gPiA+IGRlY2xhcmF0aW9ucyB0aGF0IGhhdmUgcmVmZXJlbmNlcyB0byBzb21lIEFD
UElDQSBkZWZpbmVkIHR5cGVzLg0KPiA+ID4NCj4gPiA+IFNpZ25lZC1vZmYtYnk6IEx2IFpoZW5n
IDxsdi56aGVuZ0BpbnRlbC5jb20+DQo+ID4gPiBSZXZpZXdlZC1ieTogSHVhbmcgWWluZyA8eWlu
Zy5odWFuZ0BpbnRlbC5jb20+DQo+ID4gPiAtLS0NCj4gPiA+ICBkcml2ZXJzL2FjcGkvYWNwaV9p
cG1pLmMgfCAgIDE2ICsrLS0NCj4gPiA+ICBkcml2ZXJzL2FjcGkvb3NsLmMgICAgICAgfCAgMjI0
DQo+ID4gKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKw0KPiA+
ID4gIGluY2x1ZGUvYWNwaS9hY3BpX2J1cy5oICB8ICAgIDUgKysNCj4gPiA+ICAzIGZpbGVzIGNo
YW5nZWQsIDIzNSBpbnNlcnRpb25zKCspLCAxMCBkZWxldGlvbnMoLSkNCj4gPiA+DQo+ID4gPiBk
aWZmIC0tZ2l0IGEvZHJpdmVycy9hY3BpL2FjcGlfaXBtaS5jIGIvZHJpdmVycy9hY3BpL2FjcGlf
aXBtaS5jDQo+ID4gPiBpbmRleA0KPiA+ID4gNWY4ZjQ5NS4uMmEwOTE1NiAxMDA2NDQNCj4gPiA+
IC0tLSBhL2RyaXZlcnMvYWNwaS9hY3BpX2lwbWkuYw0KPiA+ID4gKysrIGIvZHJpdmVycy9hY3Bp
L2FjcGlfaXBtaS5jDQo+ID4gPiBAQCAtNTM5LDIwICs1MzksMTggQEAgb3V0X3JlZjoNCj4gPiA+
ICBzdGF0aWMgaW50IF9faW5pdCBhY3BpX2lwbWlfaW5pdCh2b2lkKSAgew0KPiA+ID4gIAlpbnQg
cmVzdWx0ID0gMDsNCj4gPiA+IC0JYWNwaV9zdGF0dXMgc3RhdHVzOw0KPiA+ID4NCj4gPiA+ICAJ
aWYgKGFjcGlfZGlzYWJsZWQpDQo+ID4gPiAgCQlyZXR1cm4gcmVzdWx0Ow0KPiA+ID4NCj4gPiA+
ICAJbXV0ZXhfaW5pdCgmZHJpdmVyX2RhdGEuaXBtaV9sb2NrKTsNCj4gPiA+DQo+ID4gPiAtCXN0
YXR1cyA9IGFjcGlfaW5zdGFsbF9hZGRyZXNzX3NwYWNlX2hhbmRsZXIoQUNQSV9ST09UX09CSkVD
VCwNCj4gPiA+IC0JCQkJCQkgICAgQUNQSV9BRFJfU1BBQ0VfSVBNSSwNCj4gPiA+IC0JCQkJCQkg
ICAgJmFjcGlfaXBtaV9zcGFjZV9oYW5kbGVyLA0KPiA+ID4gLQkJCQkJCSAgICBOVUxMLCBOVUxM
KTsNCj4gPiA+IC0JaWYgKEFDUElfRkFJTFVSRShzdGF0dXMpKSB7DQo+ID4gPiArCXJlc3VsdCA9
IGFjcGlfcmVnaXN0ZXJfcmVnaW9uKEFDUElfQURSX1NQQUNFX0lQTUksDQo+ID4gPiArCQkJCSAg
ICAgICZhY3BpX2lwbWlfc3BhY2VfaGFuZGxlciwNCj4gPiA+ICsJCQkJICAgICAgTlVMTCwgTlVM
TCk7DQo+ID4gPiArCWlmIChyZXN1bHQpIHsNCj4gPiA+ICAJCXByX3dhcm4oIkNhbid0IHJlZ2lz
dGVyIElQTUkgb3ByZWdpb24gc3BhY2UgaGFuZGxlXG4iKTsNCj4gPiA+IC0JCXJldHVybiAtRUlO
VkFMOw0KPiA+ID4gKwkJcmV0dXJuIHJlc3VsdDsNCj4gPiA+ICAJfQ0KPiA+ID4NCj4gPiA+ICAJ
cmVzdWx0ID0gaXBtaV9zbWlfd2F0Y2hlcl9yZWdpc3RlcigmZHJpdmVyX2RhdGEuYm1jX2V2ZW50
cyk7DQo+ID4gPiBAQCAtNTk2LDkgKzU5NCw3IEBAIHN0YXRpYyB2b2lkIF9fZXhpdCBhY3BpX2lw
bWlfZXhpdCh2b2lkKQ0KPiA+ID4gIAl9DQo+ID4gPiAgCW11dGV4X3VubG9jaygmZHJpdmVyX2Rh
dGEuaXBtaV9sb2NrKTsNCj4gPiA+DQo+ID4gPiAtCWFjcGlfcmVtb3ZlX2FkZHJlc3Nfc3BhY2Vf
aGFuZGxlcihBQ1BJX1JPT1RfT0JKRUNULA0KPiA+ID4gLQkJCQkJICBBQ1BJX0FEUl9TUEFDRV9J
UE1JLA0KPiA+ID4gLQkJCQkJICAmYWNwaV9pcG1pX3NwYWNlX2hhbmRsZXIpOw0KPiA+ID4gKwlh
Y3BpX3VucmVnaXN0ZXJfcmVnaW9uKEFDUElfQURSX1NQQUNFX0lQTUkpOw0KPiA+ID4gIH0NCj4g
PiA+DQo+ID4gPiAgbW9kdWxlX2luaXQoYWNwaV9pcG1pX2luaXQpOw0KPiA+ID4gZGlmZiAtLWdp
dCBhL2RyaXZlcnMvYWNwaS9vc2wuYyBiL2RyaXZlcnMvYWNwaS9vc2wuYyBpbmRleA0KPiA+ID4g
NmFiMmMzNS4uODM5OGU1MSAxMDA2NDQNCj4gPiA+IC0tLSBhL2RyaXZlcnMvYWNwaS9vc2wuYw0K
PiA+ID4gKysrIGIvZHJpdmVycy9hY3BpL29zbC5jDQo+ID4gPiBAQCAtODYsNiArODYsNDIgQEAg
c3RhdGljIHN0cnVjdCB3b3JrcXVldWVfc3RydWN0ICprYWNwaWRfd3E7DQo+ID4gPiBzdGF0aWMg
c3RydWN0IHdvcmtxdWV1ZV9zdHJ1Y3QgKmthY3BpX25vdGlmeV93cTsgIHN0YXRpYyBzdHJ1Y3QN
Cj4gPiA+IHdvcmtxdWV1ZV9zdHJ1Y3QgKmthY3BpX2hvdHBsdWdfd3E7DQo+ID4gPg0KPiA+ID4g
K3N0cnVjdCBhY3BpX3JlZ2lvbiB7DQo+ID4gPiArCXVuc2lnbmVkIGxvbmcgZmxhZ3M7DQo+ID4g
PiArI2RlZmluZSBBQ1BJX1JFR0lPTl9ERUZBVUxUCQkweDAxDQo+ID4gPiArI2RlZmluZSBBQ1BJ
X1JFR0lPTl9JTlNUQUxMRUQJCTB4MDINCj4gPiA+ICsjZGVmaW5lIEFDUElfUkVHSU9OX1JFR0lT
VEVSRUQJCTB4MDQNCj4gPiA+ICsjZGVmaW5lIEFDUElfUkVHSU9OX1VOUkVHSVNURVJJTkcJMHgw
OA0KPiA+ID4gKyNkZWZpbmUgQUNQSV9SRUdJT05fSU5TVEFMTElORwkJMHgxMA0KPiA+DQo+ID4g
V2hhdCBhYm91dCAoMVVMIDw8IDEpLCAoMVVMIDw8IDIpIGV0Yy4/DQo+ID4NCj4gPiBBbHNvIHBs
ZWFzZSByZW1vdmUgdGhlICNkZWZpbmVzIG91dCBvZiB0aGUgc3RydWN0IGRlZmluaXRpb24uDQo+
IA0KPiBPSy4NCj4gDQo+ID4NCj4gPiA+ICsJLyoNCj4gPiA+ICsJICogTk9URTogVXBncmFkaW5n
IEFsbCBSZWdpb24gSGFuZGxlcnMNCj4gPiA+ICsJICogVGhpcyBmbGFnIGlzIG9ubHkgdXNlZCBk
dXJpbmcgdGhlIHBlcmlvZCB3aGVyZSBub3QgYWxsIG9mIHRoZQ0KPiA+ID4gKwkgKiByZWdpb24g
aGFuZGVycyBhcmUgdXBncmFkZWQgdG8gdGhlIG5ldyBpbnRlcmZhY2VzLg0KPiA+ID4gKwkgKi8N
Cj4gPiA+ICsjZGVmaW5lIEFDUElfUkVHSU9OX01BTkFHRUQJCTB4ODANCj4gPiA+ICsJYWNwaV9h
ZHJfc3BhY2VfaGFuZGxlciBoYW5kbGVyOw0KPiA+ID4gKwlhY3BpX2Fkcl9zcGFjZV9zZXR1cCBz
ZXR1cDsNCj4gPiA+ICsJdm9pZCAqY29udGV4dDsNCj4gPiA+ICsJLyogSW52b2tpbmcgcmVmZXJl
bmNlcyAqLw0KPiA+ID4gKwlhdG9taWNfdCByZWZjbnQ7DQo+ID4NCj4gPiBBY3R1YWxseSwgd2h5
IGRvbid0IHlvdSB1c2Uga3JlZnM/DQo+IA0KPiBJZiB5b3UgdGFrZSBhIGxvb2sgYXQgb3RoZXIg
cGllY2Ugb2YgbXkgY29kZXMsIHlvdSdsbCBmaW5kIHRoZXJlIGFyZSB0d28gcmVhc29uczoNCj4g
DQo+IDEuIEknbSB1c2luZyB3aGlsZSAoYXRvbWljX3JlYWQoKSA+IDEpIHRvIGltcGxlbWVudCB0
aGUgb2JqZWN0cycgZmx1c2hpbmcgYW5kDQo+IHRoZXJlIGlzIG5vIGtyZWYgQVBJIHRvIGRvIHNv
Lg0KPiAgIEkganVzdCB0aGluayBpdCBpcyBub3Qgc3VpdGFibGUgZm9yIG1lIHRvIGludHJvZHVj
ZSBzdWNoIGFuIEFQSSBpbnRvIGtyZWYuaCBhbmQNCj4gc3RhcnQgYW5vdGhlciBhcmd1bWVudCBh
cm91bmQga3JlZiBkZXNpZ25zIGluIHRoaXMgYnVnIGZpeCBwYXRjaC4gOi0pDQo+ICAgSSdsbCBz
dGFydCBhIGRpc2N1c3Npb24gYWJvdXQga3JlZiBkZXNpZ24gdXNpbmcgYW5vdGhlciB0aHJlYWQu
DQo+IDIuIEknbSB1c2luZyBpcG1pX2Rldnxtc2dfcmVsZWFzZSgpIGFzIGEgcGFpciBvZiBpcG1p
X2Rldnxtc2dfYWxsb2MoKSwgaXQncyBraW5kDQo+IG9mIGF0b21pY190IGNvZGluZyBzdHlsZS4N
Cj4gICBJZiBhdG9taWNfdCBpcyBjaGFuZ2VkIHRvIHN0cnVjdCBrcmVmLCBJIHdpbGwgbmVlZCB0
byBpbXBsZW1lbnQgdHdvIEFQSSwNCj4gX19pcG1pX2Rldl9yZWxlYXNlKCkgdG8gdGFrZSBhIHN0
cnVjdCBrcmVmIGFzIHBhcmFtZXRlciBhbmQgY2FsbA0KPiBpcG1pX2Rldl9yZWxlYXNlIGluc2lk
ZSBpdC4NCj4gICBCeSBub3QgdXNpbmcga3JlZiwgSSBuZWVkbid0IHdyaXRlIGNvZGVzIHRvIGlt
cGxlbWVudCBzdWNoIEFQSS4NCj4gDQo+ID4NCj4gPiA+ICt9Ow0KPiA+ID4gKw0KPiA+ID4gK3N0
YXRpYyBzdHJ1Y3QgYWNwaV9yZWdpb24NCj4gYWNwaV9yZWdpb25zW0FDUElfTlVNX1BSRURFRklO
RURfUkVHSU9OU10NCj4gPiA9IHsNCj4gPiA+ICsJW0FDUElfQURSX1NQQUNFX1NZU1RFTV9NRU1P
UlldID0gew0KPiA+ID4gKwkJLmZsYWdzID0gQUNQSV9SRUdJT05fREVGQVVMVCwNCj4gPiA+ICsJ
fSwNCj4gPiA+ICsJW0FDUElfQURSX1NQQUNFX1NZU1RFTV9JT10gPSB7DQo+ID4gPiArCQkuZmxh
Z3MgPSBBQ1BJX1JFR0lPTl9ERUZBVUxULA0KPiA+ID4gKwl9LA0KPiA+ID4gKwlbQUNQSV9BRFJf
U1BBQ0VfUENJX0NPTkZJR10gPSB7DQo+ID4gPiArCQkuZmxhZ3MgPSBBQ1BJX1JFR0lPTl9ERUZB
VUxULA0KPiA+ID4gKwl9LA0KPiA+ID4gKwlbQUNQSV9BRFJfU1BBQ0VfSVBNSV0gPSB7DQo+ID4g
PiArCQkuZmxhZ3MgPSBBQ1BJX1JFR0lPTl9NQU5BR0VELA0KPiA+ID4gKwl9LA0KPiA+ID4gK307
DQo+ID4gPiArc3RhdGljIERFRklORV9NVVRFWChhY3BpX211dGV4X3JlZ2lvbik7DQo+ID4gPiAr
DQo+ID4gPiAgLyoNCj4gPiA+ICAgKiBUaGlzIGxpc3Qgb2YgcGVybWFuZW50IG1hcHBpbmdzIGlz
IGZvciBtZW1vcnkgdGhhdCBtYXkgYmUNCj4gPiA+IGFjY2Vzc2VkDQo+ID4gZnJvbQ0KPiA+ID4g
ICAqIGludGVycnVwdCBjb250ZXh0LCB3aGVyZSB3ZSBjYW4ndCBkbyB0aGUgaW9yZW1hcCgpLg0K
PiA+ID4gQEAgLTE3OTksMyArMTgzNSwxOTEgQEAgdm9pZCBhbGxvY19hY3BpX2hwX3dvcmsoYWNw
aV9oYW5kbGUgaGFuZGxlLA0KPiA+IHUzMiB0eXBlLCB2b2lkICpjb250ZXh0LA0KPiA+ID4gIAkJ
a2ZyZWUoaHBfd29yayk7DQo+ID4gPiAgfQ0KPiA+ID4gIEVYUE9SVF9TWU1CT0xfR1BMKGFsbG9j
X2FjcGlfaHBfd29yayk7DQo+ID4gPiArDQo+ID4gPiArc3RhdGljIGJvb2wgYWNwaV9yZWdpb25f
bWFuYWdlZChzdHJ1Y3QgYWNwaV9yZWdpb24gKnJnbikgew0KPiA+ID4gKwkvKg0KPiA+ID4gKwkg
KiBOT1RFOiBEZWZhdWx0IGFuZCBNYW5hZ2VkDQo+ID4gPiArCSAqIFdlIG9ubHkgbmVlZCB0byBh
dm9pZCByZWdpb24gbWFuYWdlbWVudCBvbiB0aGUgcmVnaW9ucw0KPiBtYW5hZ2VkDQo+ID4gPiAr
CSAqIGJ5IEFDUElDQSAoQUNQSV9SRUdJT05fREVGQVVMVCkuICBDdXJyZW50bHksIHdlIG5lZWQN
Cj4gYWRkaXRpb25hbA0KPiA+ID4gKwkgKiBjaGVjayBhcyBtYW55IG9wZXJhdGlvbiByZWdpb24g
aGFuZGxlcnMgYXJlIG5vdCB1cGdyYWRlZCwgc28NCj4gPiA+ICsJICogb25seSB0aG9zZSBrbm93
biB0byBiZSBzYWZlIGFyZSBtYW5hZ2VkDQo+IChBQ1BJX1JFR0lPTl9NQU5BR0VEKS4NCj4gPiA+
ICsJICovDQo+ID4gPiArCXJldHVybiAhKHJnbi0+ZmxhZ3MgJiBBQ1BJX1JFR0lPTl9ERUZBVUxU
KSAmJg0KPiA+ID4gKwkgICAgICAgKHJnbi0+ZmxhZ3MgJiBBQ1BJX1JFR0lPTl9NQU5BR0VEKTsg
fQ0KPiA+ID4gKw0KPiA+ID4gK3N0YXRpYyBib29sIGFjcGlfcmVnaW9uX2NhbGxhYmxlKHN0cnVj
dCBhY3BpX3JlZ2lvbiAqcmduKSB7DQo+ID4gPiArCXJldHVybiAocmduLT5mbGFncyAmIEFDUElf
UkVHSU9OX1JFR0lTVEVSRUQpICYmDQo+ID4gPiArCSAgICAgICAhKHJnbi0+ZmxhZ3MgJiBBQ1BJ
X1JFR0lPTl9VTlJFR0lTVEVSSU5HKTsgfQ0KPiA+ID4gKw0KPiA+ID4gK3N0YXRpYyBhY3BpX3N0
YXR1cw0KPiA+ID4gK2FjcGlfcmVnaW9uX2RlZmF1bHRfaGFuZGxlcih1MzIgZnVuY3Rpb24sDQo+
ID4gPiArCQkJICAgIGFjcGlfcGh5c2ljYWxfYWRkcmVzcyBhZGRyZXNzLA0KPiA+ID4gKwkJCSAg
ICB1MzIgYml0X3dpZHRoLCB1NjQgKnZhbHVlLA0KPiA+ID4gKwkJCSAgICB2b2lkICpoYW5kbGVy
X2NvbnRleHQsIHZvaWQgKnJlZ2lvbl9jb250ZXh0KSB7DQo+ID4gPiArCWFjcGlfYWRyX3NwYWNl
X2hhbmRsZXIgaGFuZGxlcjsNCj4gPiA+ICsJc3RydWN0IGFjcGlfcmVnaW9uICpyZ24gPSAoc3Ry
dWN0IGFjcGlfcmVnaW9uICopaGFuZGxlcl9jb250ZXh0Ow0KPiA+ID4gKwl2b2lkICpjb250ZXh0
Ow0KPiA+ID4gKwlhY3BpX3N0YXR1cyBzdGF0dXMgPSBBRV9OT1RfRVhJU1Q7DQo+ID4gPiArDQo+
ID4gPiArCW11dGV4X2xvY2soJmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiA+ICsJaWYgKCFhY3Bp
X3JlZ2lvbl9jYWxsYWJsZShyZ24pIHx8ICFyZ24tPmhhbmRsZXIpIHsNCj4gPiA+ICsJCW11dGV4
X3VubG9jaygmYWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ID4gKwkJcmV0dXJuIHN0YXR1czsNCj4g
PiA+ICsJfQ0KPiA+ID4gKw0KPiA+ID4gKwlhdG9taWNfaW5jKCZyZ24tPnJlZmNudCk7DQo+ID4g
PiArCWhhbmRsZXIgPSByZ24tPmhhbmRsZXI7DQo+ID4gPiArCWNvbnRleHQgPSByZ24tPmNvbnRl
eHQ7DQo+ID4gPiArCW11dGV4X3VubG9jaygmYWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ID4gKw0K
PiA+ID4gKwlzdGF0dXMgPSBoYW5kbGVyKGZ1bmN0aW9uLCBhZGRyZXNzLCBiaXRfd2lkdGgsIHZh
bHVlLCBjb250ZXh0LA0KPiA+ID4gKwkJCSByZWdpb25fY29udGV4dCk7DQo+ID4NCj4gPiBXaHkg
ZG9uJ3Qgd2UgY2FsbCB0aGUgaGFuZGxlciB1bmRlciB0aGUgbXV0ZXg/DQoNCkkgdGhpbmsgbXkg
cmVwbHkgaXMgYWdhaW5zdCB0aGlzIHF1ZXN0aW9uLCBsZXQgbWUgcmVtb3ZlIGl0IHVwLg0KDQo+
IEl0J3MgYSBraW5kIG9mIHByb2dyYW1taW5nIHN0eWxlIHJlbGF0ZWQgY29uY2Vybi4NCj4gSU1P
LCB1c2luZyBsb2NrcyBhcm91bmQgY2FsbGJhY2sgZnVuY3Rpb24gaXMgYSBidWdneSBwcm9ncmFt
bWluZyBzdHlsZSB0aGF0DQo+IGNvdWxkIGxlYWQgdG8gZGVhZCBsb2Nrcy4NCj4gTGV0IG1lIGV4
cGxhaW4gdGhpcyB1c2luZyBhbiBleGFtcGxlLg0KPiANCj4gT2JqZWN0IEEgZXhwb3J0cyBhIHJl
Z2lzdGVyL3VucmVnaXN0ZXIgQVBJIGZvciBvdGhlciBvYmplY3RzLg0KPiBPYmplY3QgQiBjYWxs
cyBBJ3MgcmVnaXN0ZXIvdW5yZWdpc3RlciBBUEkgdG8gcmVnaXN0ZXIvdW5yZWdpc3RlciBCJ3Mg
Y2FsbGJhY2suDQoNClNvcnJ5IEkgaGF2ZSB0byB1c2Ugb2JqZWN0IHJhdGhlciB0aGFuIG1vZHVs
ZSBoZXJlIGFzIHRoZXJlIG1pZ2h0IGJlIHNldmVyYWwgb2JqZWN0cyBpbnNpZGUgYSBtb2R1bGUg
dGhhdCBoYXZlIHRoZSBzYW1lIHNpdHVhdGlvbiBuZWVkIHRvIGJlIGhhbmRsZWQuDQoNCj4gSXQn
cyBsaWtlbHkgdGhhdCBvYmplY3QgQiB3aWxsIGhvbGQgbG9ja19vZl9CIGFyb3VuZCB1bnJlZ2lz
dGVyL3JlZ2lzdGVyIHdoZW4NCj4gb2JqZWN0IEIgaXMgZGVzdHJveWVkL2NyZWF0ZWQsIHRoZSBs
b2NrX29mX0IgaXMgbGlrZWx5IGFsc28gdXNlZCBpbnNpZGUgdGhlDQo+IGNhbGxiYWNrLg0KPiBT
byB3aGVuIG9iamVjdCBBIGhvbGRzIHRoZSBsb2NrX29mX0EgYXJvdW5kIHRoZSBjYWxsYmFjayBp
bnZvY2F0aW9uLCBpdCBsZWFkcyB0bw0KPiBkZWFkIGxvY2sgc2luY2U6DQo+IDEuIHRoZSBsb2Nr
aW5nIG9yZGVyIGZvciB0aGUgcmVnaXN0ZXIvdW5yZWdpc3RlciBzaWRlIHdpbGwgYmU6IGxvY2so
bG9ja19vZl9CKSwNCj4gbG9jayhsb2NrX29mX0EpIDIuIHRoZSBsb2NraW5nIG9yZGVyIGZvciB0
aGUgY2FsbGJhY2sgc2lkZSB3aWxsIGJlOiBsb2NrKGxvY2tfb2ZfQSksDQo+IGxvY2sobG9ja19v
Zl9CKSBUaGV5IGFyZSBpbiB0aGUgcmV2ZXJzZWQgb3JkZXIhDQoNCkkgdGhpbmsgdGhpcyBleGFt
cGxlIGlzIG5vdCBxdWl0ZSBjb3JyZWN0Lg0KVGhlcmUgaXMgYW5vdGhlciBhc3BlY3QgaW4gdW5y
ZWdpc3RlciBpbXBsZW1lbnRhdGlvbiB3aGljaCBpcyB0aGUgaW50ZW50IG9mIHRoaXMgcGF0Y2g6
DQpObyBjYWxsYmFjayBydW5uaW5nL2ltaXRhdGVkIGFmdGVyICJ1bnJlZ2lzdGVyIiwgd2UgY2Fu
IGNhbGwgdGhpcyBhICJmbHVzaCIgcmVxdWlyZW1lbnQuDQpJbnNpZGUgb2YgdGhlIGNhbGxiYWNr
LCBsb2NrX29mX0Igc2hvdWxkIG5vdCBiZSBoZWxkIGlmICJmbHVzaCIgaXMgcmVxdWlyZWQuDQoN
Cj4gDQo+IElNTywgTGludXggbWF5IG5lZWQgdG8gaW50cm9kdWNlIF9fY2FsbGJhY2ssIF9fYXBp
IGFzIGRlY2VsZXJhdG9ycyBmb3IgdGhlDQo+IGZ1bmN0aW9ucywgYW5kIHVzZSBzcGFyc2UgdG8g
ZW5mb3JjZSB0aGlzIHJ1bGUsIHNwYXJzZSBrbm93cyBpZiBhIGNhbGxiYWNrIGlzDQo+IGludm9r
ZWQgdW5kZXIgc29tZSBsb2Nrcy4NCj4gDQo+IEluIHRoZSBjYXNlIG9mIEFDUElDQSBzcGFjZV9o
YW5kbGVycywgYXMgeW91IG1heSBrbm93LCB3aGVuIGFuIEFDUEkNCj4gb3BlcmF0aW9uIHJlZ2lv
biBoYW5kbGVyIGlzIGludm9rZWQsIHRoZXJlIHdpbGwgYmUgbm8gbG9jayBoZWxkIGluc2lkZSBB
Q1BJQ0ENCj4gKGludGVycHJldGVyIGxvY2sgbXVzdCBiZSBmcmVlZCBiZWZvcmUgZXhlY3V0aW5n
IG9wZXJhdGlvbiByZWdpb24gaGFuZGxlcnMpLg0KPiBTbyB0aGUgbGlrZWxpaG9vZCBvZiB0aGUg
ZGVhZCBsb2NrIGlzIHByZXR0eSBtdWNoIGhpZ2ggaGVyZSENCg0KSSBuZWVkIHRvIG1lbnRpb24g
YW5vdGhlciByZXF1aXJlbWVudCBvZiB0aGUgb3BlcmF0aW9uIHJlZ2lvbiBoYW5kbGVyLg0KSXQg
aXMgcmVxdWlyZWQgdGhhdCBtdWx0aXBsZSBvcGVyYXRpb24gcmVnaW9uIGhhbmRsZXJzIGFyZSBl
eGVjdXRlZCBhdCB0aGUgc2FtZSB0aW1lLCBvciB0aGUgSU8gb3BlcmF0aW9ucyBpbnZva2VkIGJ5
IHRoZSBCSU9TIEFTTCBjb2RlcyB3aWxsIGJlIHNlcmlhbGl6ZWQuDQpJTU8sIElPIG9wZXJhdGlv
bnMgaW52b2tlZCBieSB0aGUgQklPUyBBU0wgbmVlZCB0byBiZSBwYXJhbGxlbGl6ZWQuDQpUaHVz
IG11dGV4IGlzIG5vdCB1c2VmdWwgdG8gaW1wbGVtZW50IGEgcHJvdGVjdGlvbiBoZXJlLg0KDQpT
byB0aGUgbXV0ZXggaXMgdW5sb2NrZWQgYmVmb3JlIGV4ZWN1dGluZyB0aGUgaGFuZGxlciwgSU1P
LCByZWZlcmVuY2UgY291bnRpbmcgaXMgdXNlZnVsIGhlcmUgdG8gbWVldCB0aGlzIHJlcXVpcmVt
ZW50Lg0KDQo+ID4NCj4gPiBXaGF0IGV4YWN0bHkgcHJldmVudHMgY29udGV4dCBmcm9tIGJlY29t
aW5nIE5VTEwgYmVmb3JlIHRoZSBjYWxsIGFib3ZlPw0KDQpJIHRoaW5rIG15IGFuc3dlcnMgZGlk
IG5vdCBhbnN3ZXIgdGhpcyBxdWVzdGlvbiBkaXJlY3RseS4NCg0KU29ycnkgdGhhdCBJJ20gbm90
IGNsZWFyIHdoYXQgeW91IHdhbnQgdG8gYXNrIGhlcmUuICBMZXQgbWUganVzdCB0cnkgdG8gYmUg
cHJhY3RpY2FsLg0KDQpUaGUgY29kZSBpcyBoZXJlOg0KPg0KPiA+ID4gKwltdXRleF9sb2NrKCZh
Y3BpX211dGV4X3JlZ2lvbik7DQo+ID4gPiArCWlmICghYWNwaV9yZWdpb25fY2FsbGFibGUocmdu
KSB8fCAhcmduLT5oYW5kbGVyKSB7DQoNCj4gPiA+ICsJaGFuZGxlciA9IHJnbi0+aGFuZGxlcjsN
Cj4gPiA+ICsJY29udGV4dCA9IHJnbi0+Y29udGV4dDsNCj4gPiA+ICsJbXV0ZXhfdW5sb2NrKCZh
Y3BpX211dGV4X3JlZ2lvbik7DQoNClRoZSBoYW5kbGVyIGlzIGVuc3VyZWQgbm90IHRvIGJlIE5V
TEwgd2l0aGluIHRoZSBtdXRleCBsb2NrLg0KDQpUaGFua3MgZm9yIGNvbW1lbnRpbmcuDQoNCkJl
c3QgcmVnYXJkcw0KLUx2DQoNCj4gPg0KPiA+ID4gKwlhdG9taWNfZGVjKCZyZ24tPnJlZmNudCk7
DQo+ID4gPiArDQo+ID4gPiArCXJldHVybiBzdGF0dXM7DQo+ID4gPiArfQ0KPiA+ID4gKw0KPiA+
ID4gK3N0YXRpYyBhY3BpX3N0YXR1cw0KPiA+ID4gK2FjcGlfcmVnaW9uX2RlZmF1bHRfc2V0dXAo
YWNwaV9oYW5kbGUgaGFuZGxlLCB1MzIgZnVuY3Rpb24sDQo+ID4gPiArCQkJICB2b2lkICpoYW5k
bGVyX2NvbnRleHQsIHZvaWQgKipyZWdpb25fY29udGV4dCkgew0KPiA+ID4gKwlhY3BpX2Fkcl9z
cGFjZV9zZXR1cCBzZXR1cDsNCj4gPiA+ICsJc3RydWN0IGFjcGlfcmVnaW9uICpyZ24gPSAoc3Ry
dWN0IGFjcGlfcmVnaW9uICopaGFuZGxlcl9jb250ZXh0Ow0KPiA+ID4gKwl2b2lkICpjb250ZXh0
Ow0KPiA+ID4gKwlhY3BpX3N0YXR1cyBzdGF0dXMgPSBBRV9PSzsNCj4gPiA+ICsNCj4gPiA+ICsJ
bXV0ZXhfbG9jaygmYWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ID4gKwlpZiAoIWFjcGlfcmVnaW9u
X2NhbGxhYmxlKHJnbikgfHwgIXJnbi0+c2V0dXApIHsNCj4gPiA+ICsJCW11dGV4X3VubG9jaygm
YWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ID4gKwkJcmV0dXJuIHN0YXR1czsNCj4gPiA+ICsJfQ0K
PiA+ID4gKw0KPiA+ID4gKwlhdG9taWNfaW5jKCZyZ24tPnJlZmNudCk7DQo+ID4gPiArCXNldHVw
ID0gcmduLT5zZXR1cDsNCj4gPiA+ICsJY29udGV4dCA9IHJnbi0+Y29udGV4dDsNCj4gPiA+ICsJ
bXV0ZXhfdW5sb2NrKCZhY3BpX211dGV4X3JlZ2lvbik7DQo+ID4gPiArDQo+ID4gPiArCXN0YXR1
cyA9IHNldHVwKGhhbmRsZSwgZnVuY3Rpb24sIGNvbnRleHQsIHJlZ2lvbl9jb250ZXh0KTsNCj4g
Pg0KPiA+IENhbiBzZXR1cCBkcm9wIHJnbi0+cmVmY250ID8NCj4gDQo+IFRoZSByZWFzb24gaXMg
c2FtZSBhcyB0aGUgaGFuZGxlciwgYXMgYSBzZXR1cCBpcyBhbHNvIGEgY2FsbGJhY2suDQo+IA0K
PiA+DQo+ID4gPiArCWF0b21pY19kZWMoJnJnbi0+cmVmY250KTsNCj4gPiA+ICsNCj4gPiA+ICsJ
cmV0dXJuIHN0YXR1czsNCj4gPiA+ICt9DQo+ID4gPiArDQo+ID4gPiArc3RhdGljIGludCBfX2Fj
cGlfaW5zdGFsbF9yZWdpb24oc3RydWN0IGFjcGlfcmVnaW9uICpyZ24sDQo+ID4gPiArCQkJCSBh
Y3BpX2Fkcl9zcGFjZV90eXBlIHNwYWNlX2lkKQ0KPiA+ID4gK3sNCj4gPiA+ICsJaW50IHJlcyA9
IDA7DQo+ID4gPiArCWFjcGlfc3RhdHVzIHN0YXR1czsNCj4gPiA+ICsJaW50IGluc3RhbGxpbmcg
PSAwOw0KPiA+ID4gKw0KPiA+ID4gKwltdXRleF9sb2NrKCZhY3BpX211dGV4X3JlZ2lvbik7DQo+
ID4gPiArCWlmIChyZ24tPmZsYWdzICYgQUNQSV9SRUdJT05fSU5TVEFMTEVEKQ0KPiA+ID4gKwkJ
Z290byBvdXRfbG9jazsNCj4gPiA+ICsJaWYgKHJnbi0+ZmxhZ3MgJiBBQ1BJX1JFR0lPTl9JTlNU
QUxMSU5HKSB7DQo+ID4gPiArCQlyZXMgPSAtRUJVU1k7DQo+ID4gPiArCQlnb3RvIG91dF9sb2Nr
Ow0KPiA+ID4gKwl9DQo+ID4gPiArDQo+ID4gPiArCWluc3RhbGxpbmcgPSAxOw0KPiA+ID4gKwly
Z24tPmZsYWdzIHw9IEFDUElfUkVHSU9OX0lOU1RBTExJTkc7DQo+ID4gPiArCXN0YXR1cyA9IGFj
cGlfaW5zdGFsbF9hZGRyZXNzX3NwYWNlX2hhbmRsZXIoQUNQSV9ST09UX09CSkVDVCwNCj4gPiBz
cGFjZV9pZCwNCj4gPiA+ICsJCQkJCQkgICAgYWNwaV9yZWdpb25fZGVmYXVsdF9oYW5kbGVyLA0K
PiA+ID4gKwkJCQkJCSAgICBhY3BpX3JlZ2lvbl9kZWZhdWx0X3NldHVwLA0KPiA+ID4gKwkJCQkJ
CSAgICByZ24pOw0KPiA+ID4gKwlyZ24tPmZsYWdzICY9IH5BQ1BJX1JFR0lPTl9JTlNUQUxMSU5H
Ow0KPiA+ID4gKwlpZiAoQUNQSV9GQUlMVVJFKHN0YXR1cykpDQo+ID4gPiArCQlyZXMgPSAtRUlO
VkFMOw0KPiA+ID4gKwllbHNlDQo+ID4gPiArCQlyZ24tPmZsYWdzIHw9IEFDUElfUkVHSU9OX0lO
U1RBTExFRDsNCj4gPiA+ICsNCj4gPiA+ICtvdXRfbG9jazoNCj4gPiA+ICsJbXV0ZXhfdW5sb2Nr
KCZhY3BpX211dGV4X3JlZ2lvbik7DQo+ID4gPiArCWlmIChpbnN0YWxsaW5nKSB7DQo+ID4gPiAr
CQlpZiAocmVzKQ0KPiA+ID4gKwkJCXByX2VycigiRmFpbGVkIHRvIGluc3RhbGwgcmVnaW9uICVk
XG4iLCBzcGFjZV9pZCk7DQo+ID4gPiArCQllbHNlDQo+ID4gPiArCQkJcHJfaW5mbygiUmVnaW9u
ICVkIGluc3RhbGxlZFxuIiwgc3BhY2VfaWQpOw0KPiA+ID4gKwl9DQo+ID4gPiArCXJldHVybiBy
ZXM7DQo+ID4gPiArfQ0KPiA+ID4gKw0KPiA+ID4gK2ludCBhY3BpX3JlZ2lzdGVyX3JlZ2lvbihh
Y3BpX2Fkcl9zcGFjZV90eXBlIHNwYWNlX2lkLA0KPiA+ID4gKwkJCSBhY3BpX2Fkcl9zcGFjZV9o
YW5kbGVyIGhhbmRsZXIsDQo+ID4gPiArCQkJIGFjcGlfYWRyX3NwYWNlX3NldHVwIHNldHVwLCB2
b2lkICpjb250ZXh0KSB7DQo+ID4gPiArCWludCByZXM7DQo+ID4gPiArCXN0cnVjdCBhY3BpX3Jl
Z2lvbiAqcmduOw0KPiA+ID4gKw0KPiA+ID4gKwlpZiAoc3BhY2VfaWQgPj0gQUNQSV9OVU1fUFJF
REVGSU5FRF9SRUdJT05TKQ0KPiA+ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gPiArDQo+ID4g
PiArCXJnbiA9ICZhY3BpX3JlZ2lvbnNbc3BhY2VfaWRdOw0KPiA+ID4gKwlpZiAoIWFjcGlfcmVn
aW9uX21hbmFnZWQocmduKSkNCj4gPiA+ICsJCXJldHVybiAtRUlOVkFMOw0KPiA+ID4gKw0KPiA+
ID4gKwlyZXMgPSBfX2FjcGlfaW5zdGFsbF9yZWdpb24ocmduLCBzcGFjZV9pZCk7DQo+ID4gPiAr
CWlmIChyZXMpDQo+ID4gPiArCQlyZXR1cm4gcmVzOw0KPiA+ID4gKw0KPiA+ID4gKwltdXRleF9s
b2NrKCZhY3BpX211dGV4X3JlZ2lvbik7DQo+ID4gPiArCWlmIChyZ24tPmZsYWdzICYgQUNQSV9S
RUdJT05fUkVHSVNURVJFRCkgew0KPiA+ID4gKwkJbXV0ZXhfdW5sb2NrKCZhY3BpX211dGV4X3Jl
Z2lvbik7DQo+ID4gPiArCQlyZXR1cm4gLUVCVVNZOw0KPiA+ID4gKwl9DQo+ID4gPiArDQo+ID4g
PiArCXJnbi0+aGFuZGxlciA9IGhhbmRsZXI7DQo+ID4gPiArCXJnbi0+c2V0dXAgPSBzZXR1cDsN
Cj4gPiA+ICsJcmduLT5jb250ZXh0ID0gY29udGV4dDsNCj4gPiA+ICsJcmduLT5mbGFncyB8PSBB
Q1BJX1JFR0lPTl9SRUdJU1RFUkVEOw0KPiA+ID4gKwlhdG9taWNfc2V0KCZyZ24tPnJlZmNudCwg
MSk7DQo+ID4gPiArCW11dGV4X3VubG9jaygmYWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ID4gKw0K
PiA+ID4gKwlwcl9pbmZvKCJSZWdpb24gJWQgcmVnaXN0ZXJlZFxuIiwgc3BhY2VfaWQpOw0KPiA+
ID4gKw0KPiA+ID4gKwlyZXR1cm4gMDsNCj4gPiA+ICt9DQo+ID4gPiArRVhQT1JUX1NZTUJPTF9H
UEwoYWNwaV9yZWdpc3Rlcl9yZWdpb24pOw0KPiA+ID4gKw0KPiA+ID4gK3ZvaWQgYWNwaV91bnJl
Z2lzdGVyX3JlZ2lvbihhY3BpX2Fkcl9zcGFjZV90eXBlIHNwYWNlX2lkKSB7DQo+ID4gPiArCXN0
cnVjdCBhY3BpX3JlZ2lvbiAqcmduOw0KPiA+ID4gKw0KPiA+ID4gKwlpZiAoc3BhY2VfaWQgPj0g
QUNQSV9OVU1fUFJFREVGSU5FRF9SRUdJT05TKQ0KPiA+ID4gKwkJcmV0dXJuOw0KPiA+ID4gKw0K
PiA+ID4gKwlyZ24gPSAmYWNwaV9yZWdpb25zW3NwYWNlX2lkXTsNCj4gPiA+ICsJaWYgKCFhY3Bp
X3JlZ2lvbl9tYW5hZ2VkKHJnbikpDQo+ID4gPiArCQlyZXR1cm47DQo+ID4gPiArDQo+ID4gPiAr
CW11dGV4X2xvY2soJmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiA+ICsJaWYgKCEocmduLT5mbGFn
cyAmIEFDUElfUkVHSU9OX1JFR0lTVEVSRUQpKSB7DQo+ID4gPiArCQltdXRleF91bmxvY2soJmFj
cGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiA+ICsJCXJldHVybjsNCj4gPiA+ICsJfQ0KPiA+ID4gKwlp
ZiAocmduLT5mbGFncyAmIEFDUElfUkVHSU9OX1VOUkVHSVNURVJJTkcpIHsNCj4gPiA+ICsJCW11
dGV4X3VubG9jaygmYWNwaV9tdXRleF9yZWdpb24pOw0KPiA+ID4gKwkJcmV0dXJuOw0KPiA+DQo+
ID4gV2hhdCBhYm91dA0KPiA+DQo+ID4gCWlmICgocmduLT5mbGFncyAmIEFDUElfUkVHSU9OX1VO
UkVHSVNURVJJTkcpDQo+ID4gCSAgICB8fCAhKHJnbi0+ZmxhZ3MgJiBBQ1BJX1JFR0lPTl9SRUdJ
U1RFUkVEKSkgew0KPiA+IAkJbXV0ZXhfdW5sb2NrKCZhY3BpX211dGV4X3JlZ2lvbik7DQo+ID4g
CQlyZXR1cm47DQo+ID4gCX0NCj4gPg0KPiANCj4gT0suDQo+IA0KPiA+ID4gKwl9DQo+ID4gPiAr
DQo+ID4gPiArCXJnbi0+ZmxhZ3MgfD0gQUNQSV9SRUdJT05fVU5SRUdJU1RFUklORzsNCj4gPiA+
ICsJcmduLT5oYW5kbGVyID0gTlVMTDsNCj4gPiA+ICsJcmduLT5zZXR1cCA9IE5VTEw7DQo+ID4g
PiArCXJnbi0+Y29udGV4dCA9IE5VTEw7DQo+ID4gPiArCW11dGV4X3VubG9jaygmYWNwaV9tdXRl
eF9yZWdpb24pOw0KPiA+ID4gKw0KPiA+ID4gKwl3aGlsZSAoYXRvbWljX3JlYWQoJnJnbi0+cmVm
Y250KSA+IDEpDQo+ID4gPiArCQlzY2hlZHVsZV90aW1lb3V0X3VuaW50ZXJydXB0aWJsZSh1c2Vj
c190b19qaWZmaWVzKDUpKTsNCj4gPg0KPiA+IFdvdWxkbid0IGl0IGJlIGJldHRlciB0byB1c2Ug
YSB3YWl0IHF1ZXVlIGhlcmU/DQo+IA0KPiBZZXMsIEknbGwgdHJ5Lg0KPiANCj4gPg0KPiA+ID4g
KwlhdG9taWNfZGVjKCZyZ24tPnJlZmNudCk7DQo+ID4gPiArDQo+ID4gPiArCW11dGV4X2xvY2so
JmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiA+ICsJcmduLT5mbGFncyAmPSB+KEFDUElfUkVHSU9O
X1JFR0lTVEVSRUQgfA0KPiA+IEFDUElfUkVHSU9OX1VOUkVHSVNURVJJTkcpOw0KPiA+ID4gKwlt
dXRleF91bmxvY2soJmFjcGlfbXV0ZXhfcmVnaW9uKTsNCj4gPiA+ICsNCj4gPiA+ICsJcHJfaW5m
bygiUmVnaW9uICVkIHVucmVnaXN0ZXJlZFxuIiwgc3BhY2VfaWQpOyB9DQo+ID4gPiArRVhQT1JU
X1NZTUJPTF9HUEwoYWNwaV91bnJlZ2lzdGVyX3JlZ2lvbik7DQo+ID4gPiBkaWZmIC0tZ2l0IGEv
aW5jbHVkZS9hY3BpL2FjcGlfYnVzLmggYi9pbmNsdWRlL2FjcGkvYWNwaV9idXMuaCBpbmRleA0K
PiA+ID4gYTJjMmZiYi4uMTVmYWQwZCAxMDA2NDQNCj4gPiA+IC0tLSBhL2luY2x1ZGUvYWNwaS9h
Y3BpX2J1cy5oDQo+ID4gPiArKysgYi9pbmNsdWRlL2FjcGkvYWNwaV9idXMuaA0KPiA+ID4gQEAg
LTU0Miw0ICs1NDIsOSBAQCBzdGF0aWMgaW5saW5lIGludCB1bnJlZ2lzdGVyX2FjcGlfYnVzX3R5
cGUodm9pZA0KPiA+ID4gKmJ1cykgeyByZXR1cm4gMDsgfQ0KPiA+ID4NCj4gPiA+ICAjZW5kaWYJ
CQkJLyogQ09ORklHX0FDUEkgKi8NCj4gPiA+DQo+ID4gPiAraW50IGFjcGlfcmVnaXN0ZXJfcmVn
aW9uKGFjcGlfYWRyX3NwYWNlX3R5cGUgc3BhY2VfaWQsDQo+ID4gPiArCQkJIGFjcGlfYWRyX3Nw
YWNlX2hhbmRsZXIgaGFuZGxlciwNCj4gPiA+ICsJCQkgYWNwaV9hZHJfc3BhY2Vfc2V0dXAgc2V0
dXAsIHZvaWQgKmNvbnRleHQpOyB2b2lkDQo+ID4gPiArYWNwaV91bnJlZ2lzdGVyX3JlZ2lvbihh
Y3BpX2Fkcl9zcGFjZV90eXBlIHNwYWNlX2lkKTsNCj4gPiA+ICsNCj4gPiA+ICAjZW5kaWYgLypf
X0FDUElfQlVTX0hfXyovDQo+ID4NCj4gPiBUaGFua3MsDQo+ID4gUmFmYWVsDQo+IA0KPiBUaGFu
a3MNCj4gLUx2DQo+IA0KPiA+DQo+ID4NCj4gPiAtLQ0KPiA+IEkgc3BlYWsgb25seSBmb3IgbXlz
ZWxmLg0KPiA+IFJhZmFlbCBKLiBXeXNvY2tpLCBJbnRlbCBPcGVuIFNvdXJjZSBUZWNobm9sb2d5
IENlbnRlci4NCj4gTiAgICAgciAgeSAgIGIgWCAgx6d2IF4gKd66ey5uICsgICAgeyBpIGIge2F5
IB3Kh9qZICxqICAgZiAgIGggICB6IB4gdw0KPiBqOit2ICAgdyBqIG0gICAgICAgICB6WisgICAg
IN2iaiIgICEgaQ0K
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Lv Zheng July 26, 2013, 8:15 a.m. UTC | #6
PiBGcm9tOiBsaW51eC1hY3BpLW93bmVyQHZnZXIua2VybmVsLm9yZw0KPiBbbWFpbHRvOmxpbnV4
LWFjcGktb3duZXJAdmdlci5rZXJuZWwub3JnXSBPbiBCZWhhbGYgT2YgWmhlbmcsIEx2DQo+IFNl
bnQ6IEZyaWRheSwgSnVseSAyNiwgMjAxMyA5OjU0IEFNDQo+IFRvOiBSYWZhZWwgSi4gV3lzb2Nr
aQ0KPiBDYzogV3lzb2NraSwgUmFmYWVsIEo7IEJyb3duLCBMZW47IGxpbnV4LWtlcm5lbEB2Z2Vy
Lmtlcm5lbC5vcmc7DQo+IGxpbnV4LWFjcGlAdmdlci5rZXJuZWwub3JnDQo+IFN1YmplY3Q6IFJF
OiBbUEFUQ0ggMDYvMTNdIEFDUEkvSVBNSTogQWRkIHJlZmVyZW5jZSBjb3VudGluZyBmb3IgQUNQ
SQ0KPiBvcGVyYXRpb24gcmVnaW9uIGhhbmRsZXJzDQo+IA0KPiA+IEZyb206IFJhZmFlbCBKLiBX
eXNvY2tpIFttYWlsdG86cmp3QHNpc2sucGxdDQo+ID4gU2VudDogRnJpZGF5LCBKdWx5IDI2LCAy
MDEzIDU6MjkgQU0NCj4gPg0KPiA+IE9uIFR1ZXNkYXksIEp1bHkgMjMsIDIwMTMgMDQ6MDk6NDMg
UE0gTHYgWmhlbmcgd3JvdGU6DQo+ID4gPiBUaGlzIHBhdGNoIGFkZHMgcmVmZXJlbmNlIGNvdXRp
bmcgZm9yIEFDUEkgb3BlcmF0aW9uIHJlZ2lvbiBoYW5kbGVycw0KPiA+ID4gdG8gZml4IHJhY2Vz
IGNhdXNlZCBieSB0aGUgQUNQSUNBIGFkZHJlc3Mgc3BhY2UgY2FsbGJhY2sgaW52b2NhdGlvbnMu
DQo+ID4gPg0KPiA+ID4gQUNQSUNBIGFkZHJlc3Mgc3BhY2UgY2FsbGJhY2sgaW52b2NhdGlvbiBp
cyBub3Qgc3VpdGFibGUgZm9yIExpbnV4DQo+ID4gPiBDT05GSUdfTU9EVUxFPXkgZXhlY3V0aW9u
IGVudmlyb25tZW50Lg0KPiA+DQo+ID4gQWN0dWFsbHksIGNhbiB5b3UgcGxlYXNlIGV4cGxhaW4g
dG8gbWUgd2hhdCAqZXhhY3RseSogdGhlIHByb2JsZW0gaXM/DQo+IA0KPiBPSy4gIEknbGwgYWRk
IHJhY2UgZXhwbGFuYXRpb25zIGluIHRoZSBuZXh0IHJldmlzaW9uLg0KPiANCj4gVGhlIHByb2Js
ZW0gaXMgdGhlcmUgaXMgbm8gImxvY2siIGhlbGQgaW5zaWRlIEFDUElDQSBmb3IgaW52b2tpbmcg
b3BlcmF0aW9uDQo+IHJlZ2lvbiBoYW5kbGVycy4NCj4gVGh1cyByYWNlcyBoYXBwZW5zIGJldHdl
ZW4gdGhlIGFjcGlfcmVtb3ZlL2luc3RhbGxfYWRkcmVzc19zcGFjZV9oYW5kbGVyDQo+IGFuZCB0
aGUgaGFuZGxlci9zZXR1cCBjYWxsYmFja3MuDQoNClRoaXMgc2VlbXMgbm90IGEgZ29vZCBleHBs
YW5hdGlvbiBvZiB0aGUgaW50ZW50IG9mIHRoaXMgcGF0Y2guDQpJIHRoaW5rIHRoZSBpbnRlbnQg
aXMgaGVyZSBpbiB0aGUgcGF0Y2ggZGVzY3JpcHRpb246DQoNCjEuIEl0IGFjdHMgYXMgYSBiYXJy
aWVyIGZvciBvcGVyYXRpb24gcmVnaW9uIGNhbGxiYWNrcyAtIG5vIGNhbGxiYWNrIHdpbGwNCiAg
IGhhcHBlbiBhZnRlciBhY3BpX3VucmVnaXN0ZXJfcmVnaW9uKCkuDQoyLiBhY3BpX3VucmVnaXN0
ZXJfcmVnaW9uKCkgaXMgc2FmZSB0byBiZSBjYWxsZWQgaW4gbW91ZGxlLT5leGl0KCkNCiAgIGZ1
bmN0aW9ucy4NCg0KSG1tLCBtYXliZSBJIG5lZWQgdG8gcmUtb3JkZXIgdGhlIHBhdGNoIGRlc2Ny
aXB0aW9uIGZvciB0aGlzIHBhdGNoLg0KDQpUaGFua3MgZm9yIGNvbW1lbnRpbmcuDQoNCkJlc3Qg
cmVnYXJkcw0KLUx2DQoNCj4gDQo+IFRoaXMgaXMgY29ycmVjdCBwZXIgQUNQSSBzcGVjaWZpY2F0
aW9uLg0KPiBBcyBpZiB0aGVyZSBpcyBpbnRlcnByZXRlciBsb2NrcyBoZWxkIGZvciBpbnZva2lu
ZyBvcGVyYXRpb24gcmVnaW9uIGhhbmRsZXJzLCB0aGUNCj4gdGltZW91dCBpbXBsZW1lbnRlZCBp
bnNpZGUgdGhlIG9wZXJhdGlvbiByZWdpb24gaGFuZGxlcnMgd2lsbCBtYWtlIGFsbCBsb2NraW5n
DQo+IGZhY2lsaXRpZXMgKEFjcXVpcmUgb3IgU2xlZXAsLi4uKSB0aW1lZCBvdXQuDQo+IFBsZWFz
ZSByZWZlciB0byBBQ1BJIHNwZWNpZmljYXRpb24gIjUuNS4yIENvbnRyb2wgTWV0aG9kIEV4ZWN1
dGlvbiI6DQo+IEludGVycHJldGF0aW9uIG9mIGEgQ29udHJvbCBNZXRob2QgaXMgbm90IHByZWVt
cHRpdmUsIGJ1dCBpdCBjYW4gYmxvY2suIFdoZW4gYQ0KPiBjb250cm9sIG1ldGhvZCBkb2VzIGJs
b2NrLCBPU1BNIGNhbiBpbml0aWF0ZSBvciBjb250aW51ZSB0aGUgZXhlY3V0aW9uIG9mIGENCj4g
ZGlmZmVyZW50IGNvbnRyb2wgbWV0aG9kLiBBIGNvbnRyb2wgbWV0aG9kIGNhbiBvbmx5IGFzc3Vt
ZSB0aGF0IGFjY2VzcyB0bw0KPiBnbG9iYWwgb2JqZWN0cyBpcyBleGNsdXNpdmUgZm9yIGFueSBw
ZXJpb2QgdGhlIGNvbnRyb2wgbWV0aG9kIGRvZXMgbm90IGJsb2NrLg0KPiANCj4gU28gaXQgaXMg
cHJldHR5IG11Y2ggbGlrZWx5IHRoYXQgQUNQSSBJTyB0cmFuc2ZlcnMgYXJlIGxvY2tlZCBpbnNp
ZGUgdGhlIG9wZXJhdGlvbg0KPiByZWdpb24gY2FsbGJhY2sgaW1wbGVtZW50YXRpb25zLg0KPiBV
c2luZyBsb2NraW5nIGZhY2lsaXR5IHRvIHByb3RlY3QgdGhlIGNhbGxiYWNrIGludm9jYXRpb24g
d2lsbCByaXNrIGRlYWQgbG9ja3MuDQo+IA0KPiBUaGFua3MNCj4gLUx2DQo+IA0KPiA+IFJhZmFl
bA0K
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael Wysocki July 26, 2013, 2 p.m. UTC | #7
On Friday, July 26, 2013 12:47:44 AM Zheng, Lv wrote:
> 
> > From: Rafael J. Wysocki [mailto:rjw@sisk.pl]
> > Sent: Friday, July 26, 2013 4:27 AM
> > 
> > On Tuesday, July 23, 2013 04:09:43 PM Lv Zheng wrote:
> > > This patch adds reference couting for ACPI operation region handlers
> > > to fix races caused by the ACPICA address space callback invocations.
> > >
> > > ACPICA address space callback invocation is not suitable for Linux
> > > CONFIG_MODULE=y execution environment.  This patch tries to protect
> > > the address space callbacks by invoking them under a module safe
> > environment.
> > > The IPMI address space handler is also upgraded in this patch.
> > > The acpi_unregister_region() is designed to meet the following
> > > requirements:
> > > 1. It acts as a barrier for operation region callbacks - no callback will
> > >    happen after acpi_unregister_region().
> > > 2. acpi_unregister_region() is safe to be called in moudle->exit()
> > >    functions.
> > > Using reference counting rather than module referencing allows such
> > > benefits to be achieved even when acpi_unregister_region() is called
> > > in the environments other than module->exit().
> > > The header file of include/acpi/acpi_bus.h should contain the
> > > declarations that have references to some ACPICA defined types.
> > >
> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > > Reviewed-by: Huang Ying <ying.huang@intel.com>
> > > ---
> > >  drivers/acpi/acpi_ipmi.c |   16 ++--
> > >  drivers/acpi/osl.c       |  224
> > ++++++++++++++++++++++++++++++++++++++++++++++
> > >  include/acpi/acpi_bus.h  |    5 ++
> > >  3 files changed, 235 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index
> > > 5f8f495..2a09156 100644
> > > --- a/drivers/acpi/acpi_ipmi.c
> > > +++ b/drivers/acpi/acpi_ipmi.c
> > > @@ -539,20 +539,18 @@ out_ref:
> > >  static int __init acpi_ipmi_init(void)  {
> > >  	int result = 0;
> > > -	acpi_status status;
> > >
> > >  	if (acpi_disabled)
> > >  		return result;
> > >
> > >  	mutex_init(&driver_data.ipmi_lock);
> > >
> > > -	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
> > > -						    ACPI_ADR_SPACE_IPMI,
> > > -						    &acpi_ipmi_space_handler,
> > > -						    NULL, NULL);
> > > -	if (ACPI_FAILURE(status)) {
> > > +	result = acpi_register_region(ACPI_ADR_SPACE_IPMI,
> > > +				      &acpi_ipmi_space_handler,
> > > +				      NULL, NULL);
> > > +	if (result) {
> > >  		pr_warn("Can't register IPMI opregion space handle\n");
> > > -		return -EINVAL;
> > > +		return result;
> > >  	}
> > >
> > >  	result = ipmi_smi_watcher_register(&driver_data.bmc_events);
> > > @@ -596,9 +594,7 @@ static void __exit acpi_ipmi_exit(void)
> > >  	}
> > >  	mutex_unlock(&driver_data.ipmi_lock);
> > >
> > > -	acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
> > > -					  ACPI_ADR_SPACE_IPMI,
> > > -					  &acpi_ipmi_space_handler);
> > > +	acpi_unregister_region(ACPI_ADR_SPACE_IPMI);
> > >  }
> > >
> > >  module_init(acpi_ipmi_init);
> > > diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index
> > > 6ab2c35..8398e51 100644
> > > --- a/drivers/acpi/osl.c
> > > +++ b/drivers/acpi/osl.c
> > > @@ -86,6 +86,42 @@ static struct workqueue_struct *kacpid_wq;  static
> > > struct workqueue_struct *kacpi_notify_wq;  static struct
> > > workqueue_struct *kacpi_hotplug_wq;
> > >
> > > +struct acpi_region {
> > > +	unsigned long flags;
> > > +#define ACPI_REGION_DEFAULT		0x01
> > > +#define ACPI_REGION_INSTALLED		0x02
> > > +#define ACPI_REGION_REGISTERED		0x04
> > > +#define ACPI_REGION_UNREGISTERING	0x08
> > > +#define ACPI_REGION_INSTALLING		0x10
> > 
> > What about (1UL << 1), (1UL << 2) etc.?
> > 
> > Also please remove the #defines out of the struct definition.
> 
> OK.
> 
> > 
> > > +	/*
> > > +	 * NOTE: Upgrading All Region Handlers
> > > +	 * This flag is only used during the period where not all of the
> > > +	 * region handers are upgraded to the new interfaces.
> > > +	 */
> > > +#define ACPI_REGION_MANAGED		0x80
> > > +	acpi_adr_space_handler handler;
> > > +	acpi_adr_space_setup setup;
> > > +	void *context;
> > > +	/* Invoking references */
> > > +	atomic_t refcnt;
> > 
> > Actually, why don't you use krefs?
> 
> If you take a look at other piece of my codes, you'll find there are two reasons:
> 
> 1. I'm using while (atomic_read() > 1) to implement the objects' flushing and there is no kref API to do so.

No, there's not any, but you can read kref.refcount directly, can't you?

Moreover, it is not entirely clear to me that doing the while (atomic_read() > 1)
is actually correct.

>   I just think it is not suitable for me to introduce such an API into kref.h and start another argument around kref designs in this bug fix patch. :-)
>   I'll start a discussion about kref design using another thread.

You don't need to do that at all.

> 2. I'm using ipmi_dev|msg_release() as a pair of ipmi_dev|msg_alloc(), it's kind of atomic_t coding style.
>   If atomic_t is changed to struct kref, I will need to implement two API, __ipmi_dev_release() to take a struct kref as parameter and call ipmi_dev_release inside it.
>   By not using kref, I needn't write codes to implement such API.

I'm not following you, sorry.

Please just use krefs for reference counting, the same way as you use
struct list_head for implementing lists.  This is the way everyone does
that in the kernel and that's for a reason.

Unless you do your reference counting under a lock, in which case using
atomic_t isn't necessary at all and you can use a non-atomic counter.

> > > +};
> > > +
> > > +static struct acpi_region acpi_regions[ACPI_NUM_PREDEFINED_REGIONS]
> > = {
> > > +	[ACPI_ADR_SPACE_SYSTEM_MEMORY] = {
> > > +		.flags = ACPI_REGION_DEFAULT,
> > > +	},
> > > +	[ACPI_ADR_SPACE_SYSTEM_IO] = {
> > > +		.flags = ACPI_REGION_DEFAULT,
> > > +	},
> > > +	[ACPI_ADR_SPACE_PCI_CONFIG] = {
> > > +		.flags = ACPI_REGION_DEFAULT,
> > > +	},
> > > +	[ACPI_ADR_SPACE_IPMI] = {
> > > +		.flags = ACPI_REGION_MANAGED,
> > > +	},
> > > +};
> > > +static DEFINE_MUTEX(acpi_mutex_region);
> > > +
> > >  /*
> > >   * This list of permanent mappings is for memory that may be accessed
> > from
> > >   * interrupt context, where we can't do the ioremap().
> > > @@ -1799,3 +1835,191 @@ void alloc_acpi_hp_work(acpi_handle handle,
> > u32 type, void *context,
> > >  		kfree(hp_work);
> > >  }
> > >  EXPORT_SYMBOL_GPL(alloc_acpi_hp_work);
> > > +
> > > +static bool acpi_region_managed(struct acpi_region *rgn) {
> > > +	/*
> > > +	 * NOTE: Default and Managed
> > > +	 * We only need to avoid region management on the regions managed
> > > +	 * by ACPICA (ACPI_REGION_DEFAULT).  Currently, we need additional
> > > +	 * check as many operation region handlers are not upgraded, so
> > > +	 * only those known to be safe are managed (ACPI_REGION_MANAGED).
> > > +	 */
> > > +	return !(rgn->flags & ACPI_REGION_DEFAULT) &&
> > > +	       (rgn->flags & ACPI_REGION_MANAGED); }
> > > +
> > > +static bool acpi_region_callable(struct acpi_region *rgn) {
> > > +	return (rgn->flags & ACPI_REGION_REGISTERED) &&
> > > +	       !(rgn->flags & ACPI_REGION_UNREGISTERING); }
> > > +
> > > +static acpi_status
> > > +acpi_region_default_handler(u32 function,
> > > +			    acpi_physical_address address,
> > > +			    u32 bit_width, u64 *value,
> > > +			    void *handler_context, void *region_context) {
> > > +	acpi_adr_space_handler handler;
> > > +	struct acpi_region *rgn = (struct acpi_region *)handler_context;
> > > +	void *context;
> > > +	acpi_status status = AE_NOT_EXIST;
> > > +
> > > +	mutex_lock(&acpi_mutex_region);
> > > +	if (!acpi_region_callable(rgn) || !rgn->handler) {
> > > +		mutex_unlock(&acpi_mutex_region);
> > > +		return status;
> > > +	}
> > > +
> > > +	atomic_inc(&rgn->refcnt);
> > > +	handler = rgn->handler;
> > > +	context = rgn->context;
> > > +	mutex_unlock(&acpi_mutex_region);
> > > +
> > > +	status = handler(function, address, bit_width, value, context,
> > > +			 region_context);
> > 
> > Why don't we call the handler under the mutex?
> > 
> > What exactly prevents context from becoming NULL before the call above?
> 
> It's a kind of programming style related concern.
> IMO, using locks around callback function is a buggy programming style that could lead to dead locks.
> Let me explain this using an example.
> 
> Object A exports a register/unregister API for other objects.
> Object B calls A's register/unregister API to register/unregister B's callback.
> It's likely that object B will hold lock_of_B around unregister/register when object B is destroyed/created, the lock_of_B is likely also used inside the callback.

Why is it likely to be used inside the callback?  Clearly, if a callback is
executed under a lock, that lock can't be acquired by that callback.

> So when object A holds the lock_of_A around the callback invocation, it leads to dead lock since:
> 1. the locking order for the register/unregister side will be: lock(lock_of_B), lock(lock_of_A)
> 2. the locking order for the callback side will be: lock(lock_of_A), lock(lock_of_B)
> They are in the reversed order!
> 
> IMO, Linux may need to introduce __callback, __api as decelerators for the functions, and use sparse to enforce this rule, sparse knows if a callback is invoked under some locks.

Oh, dear.  Yes, sparse knows such things, and so what?

> In the case of ACPICA space_handlers, as you may know, when an ACPI operation region handler is invoked, there will be no lock held inside ACPICA (interpreter lock must be freed before executing operation region handlers).
> So the likelihood of the dead lock is pretty much high here!

Sorry, what are you talking about?

Please let me rephrase my question: What *practical* problems would it lead to
if we executed this particular callback under this particular mutex?

Not *theoretical* in the general theory of everything, *practical* in this
particular piece of code.

And we are talking about a *global* mutex here, not something object-specific.

> > > +	atomic_dec(&rgn->refcnt);
> > > +
> > > +	return status;
> > > +}
> > > +
> > > +static acpi_status
> > > +acpi_region_default_setup(acpi_handle handle, u32 function,
> > > +			  void *handler_context, void **region_context) {
> > > +	acpi_adr_space_setup setup;
> > > +	struct acpi_region *rgn = (struct acpi_region *)handler_context;
> > > +	void *context;
> > > +	acpi_status status = AE_OK;
> > > +
> > > +	mutex_lock(&acpi_mutex_region);
> > > +	if (!acpi_region_callable(rgn) || !rgn->setup) {
> > > +		mutex_unlock(&acpi_mutex_region);
> > > +		return status;
> > > +	}
> > > +
> > > +	atomic_inc(&rgn->refcnt);
> > > +	setup = rgn->setup;
> > > +	context = rgn->context;
> > > +	mutex_unlock(&acpi_mutex_region);
> > > +
> > > +	status = setup(handle, function, context, region_context);
> > 
> > Can setup drop rgn->refcnt ?
> 
> The reason is same as the handler, as a setup is also a callback.

Let me rephrase: Is it legitimate for setup to modify rgn->refcnt?
If so, then why?

> > 
> > > +	atomic_dec(&rgn->refcnt);
> > > +
> > > +	return status;
> > > +}
> > > +
> > > +static int __acpi_install_region(struct acpi_region *rgn,
> > > +				 acpi_adr_space_type space_id)
> > > +{
> > > +	int res = 0;
> > > +	acpi_status status;
> > > +	int installing = 0;
> > > +
> > > +	mutex_lock(&acpi_mutex_region);
> > > +	if (rgn->flags & ACPI_REGION_INSTALLED)
> > > +		goto out_lock;
> > > +	if (rgn->flags & ACPI_REGION_INSTALLING) {
> > > +		res = -EBUSY;
> > > +		goto out_lock;
> > > +	}
> > > +
> > > +	installing = 1;
> > > +	rgn->flags |= ACPI_REGION_INSTALLING;
> > > +	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
> > space_id,
> > > +						    acpi_region_default_handler,
> > > +						    acpi_region_default_setup,
> > > +						    rgn);
> > > +	rgn->flags &= ~ACPI_REGION_INSTALLING;
> > > +	if (ACPI_FAILURE(status))
> > > +		res = -EINVAL;
> > > +	else
> > > +		rgn->flags |= ACPI_REGION_INSTALLED;
> > > +
> > > +out_lock:
> > > +	mutex_unlock(&acpi_mutex_region);
> > > +	if (installing) {
> > > +		if (res)
> > > +			pr_err("Failed to install region %d\n", space_id);
> > > +		else
> > > +			pr_info("Region %d installed\n", space_id);
> > > +	}
> > > +	return res;
> > > +}
> > > +
> > > +int acpi_register_region(acpi_adr_space_type space_id,
> > > +			 acpi_adr_space_handler handler,
> > > +			 acpi_adr_space_setup setup, void *context) {
> > > +	int res;
> > > +	struct acpi_region *rgn;
> > > +
> > > +	if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)
> > > +		return -EINVAL;
> > > +
> > > +	rgn = &acpi_regions[space_id];
> > > +	if (!acpi_region_managed(rgn))
> > > +		return -EINVAL;
> > > +
> > > +	res = __acpi_install_region(rgn, space_id);
> > > +	if (res)
> > > +		return res;
> > > +
> > > +	mutex_lock(&acpi_mutex_region);
> > > +	if (rgn->flags & ACPI_REGION_REGISTERED) {
> > > +		mutex_unlock(&acpi_mutex_region);
> > > +		return -EBUSY;
> > > +	}
> > > +
> > > +	rgn->handler = handler;
> > > +	rgn->setup = setup;
> > > +	rgn->context = context;
> > > +	rgn->flags |= ACPI_REGION_REGISTERED;
> > > +	atomic_set(&rgn->refcnt, 1);
> > > +	mutex_unlock(&acpi_mutex_region);
> > > +
> > > +	pr_info("Region %d registered\n", space_id);
> > > +
> > > +	return 0;
> > > +}
> > > +EXPORT_SYMBOL_GPL(acpi_register_region);
> > > +
> > > +void acpi_unregister_region(acpi_adr_space_type space_id) {
> > > +	struct acpi_region *rgn;
> > > +
> > > +	if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)
> > > +		return;
> > > +
> > > +	rgn = &acpi_regions[space_id];
> > > +	if (!acpi_region_managed(rgn))
> > > +		return;
> > > +
> > > +	mutex_lock(&acpi_mutex_region);
> > > +	if (!(rgn->flags & ACPI_REGION_REGISTERED)) {
> > > +		mutex_unlock(&acpi_mutex_region);
> > > +		return;
> > > +	}
> > > +	if (rgn->flags & ACPI_REGION_UNREGISTERING) {
> > > +		mutex_unlock(&acpi_mutex_region);
> > > +		return;
> > 
> > What about
> > 
> > 	if ((rgn->flags & ACPI_REGION_UNREGISTERING)
> > 	    || !(rgn->flags & ACPI_REGION_REGISTERED)) {
> > 		mutex_unlock(&acpi_mutex_region);
> > 		return;
> > 	}
> > 
> 
> OK.
> 
> > > +	}
> > > +
> > > +	rgn->flags |= ACPI_REGION_UNREGISTERING;
> > > +	rgn->handler = NULL;
> > > +	rgn->setup = NULL;
> > > +	rgn->context = NULL;
> > > +	mutex_unlock(&acpi_mutex_region);
> > > +
> > > +	while (atomic_read(&rgn->refcnt) > 1)
> > > +		schedule_timeout_uninterruptible(usecs_to_jiffies(5));
> > 
> > Wouldn't it be better to use a wait queue here?
> 
> Yes, I'll try.

By the way, we do we need to do that?

> > > +	atomic_dec(&rgn->refcnt);
> > > +
> > > +	mutex_lock(&acpi_mutex_region);
> > > +	rgn->flags &= ~(ACPI_REGION_REGISTERED |
> > ACPI_REGION_UNREGISTERING);
> > > +	mutex_unlock(&acpi_mutex_region);
> > > +
> > > +	pr_info("Region %d unregistered\n", space_id); }
> > > +EXPORT_SYMBOL_GPL(acpi_unregister_region);
> > > diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index
> > > a2c2fbb..15fad0d 100644
> > > --- a/include/acpi/acpi_bus.h
> > > +++ b/include/acpi/acpi_bus.h
> > > @@ -542,4 +542,9 @@ static inline int unregister_acpi_bus_type(void
> > > *bus) { return 0; }
> > >
> > >  #endif				/* CONFIG_ACPI */
> > >
> > > +int acpi_register_region(acpi_adr_space_type space_id,
> > > +			 acpi_adr_space_handler handler,
> > > +			 acpi_adr_space_setup setup, void *context); void
> > > +acpi_unregister_region(acpi_adr_space_type space_id);
> > > +
> > >  #endif /*__ACPI_BUS_H__*/

Thanks,
Rafael
Rafael Wysocki July 26, 2013, 2:49 p.m. UTC | #8
On Friday, July 26, 2013 01:54:00 AM Zheng, Lv wrote:
> > From: Rafael J. Wysocki [mailto:rjw@sisk.pl]
> > Sent: Friday, July 26, 2013 5:29 AM
> > 
> > On Tuesday, July 23, 2013 04:09:43 PM Lv Zheng wrote:
> > > This patch adds reference couting for ACPI operation region handlers to fix
> > > races caused by the ACPICA address space callback invocations.
> > >
> > > ACPICA address space callback invocation is not suitable for Linux
> > > CONFIG_MODULE=y execution environment.
> > 
> > Actually, can you please explain to me what *exactly* the problem is?
> 
> OK.  I'll add race explanations in the next revision.
> 
> The problem is there is no "lock" held inside ACPICA for invoking operation
> region handlers.
> Thus races happens between the acpi_remove/install_address_space_handler and
> the handler/setup callbacks.

I see.  Now you're trying to introduce something that would prevent those
races from happening, right?

> This is correct per ACPI specification.
> As if there is interpreter locks held for invoking operation region handlers,
> the timeout implemented inside the operation region handlers will make all
> locking facilities (Acquire or Sleep,...) timed out.
> Please refer to ACPI specification "5.5.2 Control Method Execution":
> Interpretation of a Control Method is not preemptive, but it can block. When
> a control method does block, OSPM can initiate or continue the execution of
> a different control method. A control method can only assume that access to
> global objects is exclusive for any period the control method does not block.
> 
> So it is pretty much likely that ACPI IO transfers are locked inside the
> operation region callback implementations.
> Using locking facility to protect the callback invocation will risk dead locks.

No.  If you use a single global lock around all invocations of operation region
handlers, it won't deadlock, but it will *serialize* things.  This means that
there won't be two handlers executing in parallel.  That may or may not be bad
depending on what those handlers actually do.

Your concern seems to be that if one address space handler is buggy and it
blocks indefinitely, executing it under such a lock would affect the other
address space handlers and in my opinion this is a valid concern.

So the idea seems to be to add wrappers around acpi_install_address_space_handler()
and acpi_remove_address_space_handler (but I don't see where the latter is called
after the change?), such that they will know when it is safe to unregister the
handler.  That is simple enough.

However, I'm not sure it is needed in the context of IPMI.  Your address space
handler's context is NULL, so even it if is executed after
acpi_remove_address_space_handler() has been called for it (or in parallel),
it doesn't depend on anything passed by the caller, so I don't see why the
issue can't be addressed by a proper synchronization between
acpi_ipmi_exit() and acpi_ipmi_space_handler().

Clearly, acpi_ipmi_exit() should wait for all already running instances of
acpi_ipmi_space_handler() to complete and all acpi_ipmi_space_handler()
instances started after acpi_ipmi_exit() has been called must return
immediately.

I would imagine an algorithm like this:

acpi_ipmi_exit()
 1. Take "address space handler lock".
 2. Set "unregistering address space handler" flag.
 3. Check if "count of currently running handlers" is 0.  If so,
    call acpi_remove_address_space_handler(), drop the lock (possibly clear the
    flag) and return.
 4. Otherwise drop the lock and go to sleep in "address space handler wait queue".
 5. When woken up, take "address space handler lock" and go to 3.

acpi_ipmi_space_handler()
 1. Take "address space handler lock".
 2. Check "unregistering address space handler" flag.  If set, drop the lock
    and return.
 3. Increment "count of currently running handlers".
 4. Drop the lock.
 5. Do your work.
 6. Take "address space handler lock".
 7. Decrement "count of currently running handlers" and if 0, signal the
    tasks waiting on it to wake up.
 8. Drop the lock.

Thanks,
Rafael
Lv Zheng July 29, 2013, 1:43 a.m. UTC | #9
> On Friday, July 26, 2013 10:01 PM Rafael J. Wysocki wrote:

> > On Friday, July 26, 2013 12:47:44 AM Zheng, Lv wrote:

> >

> > > On Friday, July 26, 2013 4:27 AM Rafael J. Wysocki wrote:

> > >

> > > On Tuesday, July 23, 2013 04:09:43 PM Lv Zheng wrote:

> > > > This patch adds reference couting for ACPI operation region handlers

> > > > to fix races caused by the ACPICA address space callback invocations.

> > > >

> > > > ACPICA address space callback invocation is not suitable for Linux

> > > > CONFIG_MODULE=y execution environment.  This patch tries to protect

> > > > the address space callbacks by invoking them under a module safe

> > > environment.

> > > > The IPMI address space handler is also upgraded in this patch.

> > > > The acpi_unregister_region() is designed to meet the following

> > > > requirements:

> > > > 1. It acts as a barrier for operation region callbacks - no callback will

> > > >    happen after acpi_unregister_region().

> > > > 2. acpi_unregister_region() is safe to be called in moudle->exit()

> > > >    functions.

> > > > Using reference counting rather than module referencing allows such

> > > > benefits to be achieved even when acpi_unregister_region() is called

> > > > in the environments other than module->exit().

> > > > The header file of include/acpi/acpi_bus.h should contain the

> > > > declarations that have references to some ACPICA defined types.

> > > >

> > > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>

> > > > Reviewed-by: Huang Ying <ying.huang@intel.com>

> > > > ---

> > > >  drivers/acpi/acpi_ipmi.c |   16 ++--

> > > >  drivers/acpi/osl.c       |  224

> > > ++++++++++++++++++++++++++++++++++++++++++++++

> > > >  include/acpi/acpi_bus.h  |    5 ++

> > > >  3 files changed, 235 insertions(+), 10 deletions(-)

> > > >

> > > > diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index

> > > > 5f8f495..2a09156 100644

> > > > --- a/drivers/acpi/acpi_ipmi.c

> > > > +++ b/drivers/acpi/acpi_ipmi.c

> > > > @@ -539,20 +539,18 @@ out_ref:

> > > >  static int __init acpi_ipmi_init(void)  {

> > > >  	int result = 0;

> > > > -	acpi_status status;

> > > >

> > > >  	if (acpi_disabled)

> > > >  		return result;

> > > >

> > > >  	mutex_init(&driver_data.ipmi_lock);

> > > >

> > > > -	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,

> > > > -						    ACPI_ADR_SPACE_IPMI,

> > > > -						    &acpi_ipmi_space_handler,

> > > > -						    NULL, NULL);

> > > > -	if (ACPI_FAILURE(status)) {

> > > > +	result = acpi_register_region(ACPI_ADR_SPACE_IPMI,

> > > > +				      &acpi_ipmi_space_handler,

> > > > +				      NULL, NULL);

> > > > +	if (result) {

> > > >  		pr_warn("Can't register IPMI opregion space handle\n");

> > > > -		return -EINVAL;

> > > > +		return result;

> > > >  	}

> > > >

> > > >  	result = ipmi_smi_watcher_register(&driver_data.bmc_events);

> > > > @@ -596,9 +594,7 @@ static void __exit acpi_ipmi_exit(void)

> > > >  	}

> > > >  	mutex_unlock(&driver_data.ipmi_lock);

> > > >

> > > > -	acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,

> > > > -					  ACPI_ADR_SPACE_IPMI,

> > > > -					  &acpi_ipmi_space_handler);

> > > > +	acpi_unregister_region(ACPI_ADR_SPACE_IPMI);

> > > >  }

> > > >

> > > >  module_init(acpi_ipmi_init);

> > > > diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index

> > > > 6ab2c35..8398e51 100644

> > > > --- a/drivers/acpi/osl.c

> > > > +++ b/drivers/acpi/osl.c

> > > > @@ -86,6 +86,42 @@ static struct workqueue_struct *kacpid_wq;

> static

> > > > struct workqueue_struct *kacpi_notify_wq;  static struct

> > > > workqueue_struct *kacpi_hotplug_wq;

> > > >

> > > > +struct acpi_region {

> > > > +	unsigned long flags;

> > > > +#define ACPI_REGION_DEFAULT		0x01

> > > > +#define ACPI_REGION_INSTALLED		0x02

> > > > +#define ACPI_REGION_REGISTERED		0x04

> > > > +#define ACPI_REGION_UNREGISTERING	0x08

> > > > +#define ACPI_REGION_INSTALLING		0x10

> > >

> > > What about (1UL << 1), (1UL << 2) etc.?

> > >

> > > Also please remove the #defines out of the struct definition.

> >

> > OK.

> >

> > >

> > > > +	/*

> > > > +	 * NOTE: Upgrading All Region Handlers

> > > > +	 * This flag is only used during the period where not all of the

> > > > +	 * region handers are upgraded to the new interfaces.

> > > > +	 */

> > > > +#define ACPI_REGION_MANAGED		0x80

> > > > +	acpi_adr_space_handler handler;

> > > > +	acpi_adr_space_setup setup;

> > > > +	void *context;

> > > > +	/* Invoking references */

> > > > +	atomic_t refcnt;

> > >

> > > Actually, why don't you use krefs?

> >

> > If you take a look at other piece of my codes, you'll find there are two

> reasons:

> >

> > 1. I'm using while (atomic_read() > 1) to implement the objects' flushing and

> there is no kref API to do so.

> 

> No, there's not any, but you can read kref.refcount directly, can't you?

> 

> Moreover, it is not entirely clear to me that doing the while (atomic_read() > 1)

> is actually correct.

> 

> >   I just think it is not suitable for me to introduce such an API into kref.h and

> start another argument around kref designs in this bug fix patch. :-)

> >   I'll start a discussion about kref design using another thread.

> 

> You don't need to do that at all.

> 

> > 2. I'm using ipmi_dev|msg_release() as a pair of ipmi_dev|msg_alloc(), it's

> kind of atomic_t coding style.

> >   If atomic_t is changed to struct kref, I will need to implement two API,

> __ipmi_dev_release() to take a struct kref as parameter and call

> ipmi_dev_release inside it.

> >   By not using kref, I needn't write codes to implement such API.

> 

> I'm not following you, sorry.

> 

> Please just use krefs for reference counting, the same way as you use

> struct list_head for implementing lists.  This is the way everyone does

> that in the kernel and that's for a reason.

> 

> Unless you do your reference counting under a lock, in which case using

> atomic_t isn't necessary at all and you can use a non-atomic counter.


I'll follow your suggestion of kref.
You can find my concern 2 related stuff in the next revision.
It's trivial.

> 

> > > > +};

> > > > +

> > > > +static struct acpi_region

> acpi_regions[ACPI_NUM_PREDEFINED_REGIONS]

> > > = {

> > > > +	[ACPI_ADR_SPACE_SYSTEM_MEMORY] = {

> > > > +		.flags = ACPI_REGION_DEFAULT,

> > > > +	},

> > > > +	[ACPI_ADR_SPACE_SYSTEM_IO] = {

> > > > +		.flags = ACPI_REGION_DEFAULT,

> > > > +	},

> > > > +	[ACPI_ADR_SPACE_PCI_CONFIG] = {

> > > > +		.flags = ACPI_REGION_DEFAULT,

> > > > +	},

> > > > +	[ACPI_ADR_SPACE_IPMI] = {

> > > > +		.flags = ACPI_REGION_MANAGED,

> > > > +	},

> > > > +};

> > > > +static DEFINE_MUTEX(acpi_mutex_region);

> > > > +

> > > >  /*

> > > >   * This list of permanent mappings is for memory that may be accessed

> > > from

> > > >   * interrupt context, where we can't do the ioremap().

> > > > @@ -1799,3 +1835,191 @@ void alloc_acpi_hp_work(acpi_handle

> handle,

> > > u32 type, void *context,

> > > >  		kfree(hp_work);

> > > >  }

> > > >  EXPORT_SYMBOL_GPL(alloc_acpi_hp_work);

> > > > +

> > > > +static bool acpi_region_managed(struct acpi_region *rgn) {

> > > > +	/*

> > > > +	 * NOTE: Default and Managed

> > > > +	 * We only need to avoid region management on the regions

> managed

> > > > +	 * by ACPICA (ACPI_REGION_DEFAULT).  Currently, we need

> additional

> > > > +	 * check as many operation region handlers are not upgraded, so

> > > > +	 * only those known to be safe are managed

> (ACPI_REGION_MANAGED).

> > > > +	 */

> > > > +	return !(rgn->flags & ACPI_REGION_DEFAULT) &&

> > > > +	       (rgn->flags & ACPI_REGION_MANAGED); }

> > > > +

> > > > +static bool acpi_region_callable(struct acpi_region *rgn) {

> > > > +	return (rgn->flags & ACPI_REGION_REGISTERED) &&

> > > > +	       !(rgn->flags & ACPI_REGION_UNREGISTERING); }

> > > > +

> > > > +static acpi_status

> > > > +acpi_region_default_handler(u32 function,

> > > > +			    acpi_physical_address address,

> > > > +			    u32 bit_width, u64 *value,

> > > > +			    void *handler_context, void *region_context) {

> > > > +	acpi_adr_space_handler handler;

> > > > +	struct acpi_region *rgn = (struct acpi_region *)handler_context;

> > > > +	void *context;

> > > > +	acpi_status status = AE_NOT_EXIST;

> > > > +

> > > > +	mutex_lock(&acpi_mutex_region);

> > > > +	if (!acpi_region_callable(rgn) || !rgn->handler) {

> > > > +		mutex_unlock(&acpi_mutex_region);

> > > > +		return status;

> > > > +	}

> > > > +

> > > > +	atomic_inc(&rgn->refcnt);

> > > > +	handler = rgn->handler;

> > > > +	context = rgn->context;

> > > > +	mutex_unlock(&acpi_mutex_region);

> > > > +

> > > > +	status = handler(function, address, bit_width, value, context,

> > > > +			 region_context);

> > >

> > > Why don't we call the handler under the mutex?

> > >

> > > What exactly prevents context from becoming NULL before the call above?

> >

> > It's a kind of programming style related concern.

> > IMO, using locks around callback function is a buggy programming style that

> could lead to dead locks.

> > Let me explain this using an example.

> >

> > Object A exports a register/unregister API for other objects.

> > Object B calls A's register/unregister API to register/unregister B's callback.

> > It's likely that object B will hold lock_of_B around unregister/register when

> object B is destroyed/created, the lock_of_B is likely also used inside the

> callback.

> 

> Why is it likely to be used inside the callback?  Clearly, if a callback is

> executed under a lock, that lock can't be acquired by that callback.


I think this is not related to the real purpose of why we must not hold a lock in this situation.
So let's ignore this paragraph.

> 

> > So when object A holds the lock_of_A around the callback invocation, it leads

> to dead lock since:

> > 1. the locking order for the register/unregister side will be: lock(lock_of_B),

> lock(lock_of_A)

> > 2. the locking order for the callback side will be: lock(lock_of_A),

> lock(lock_of_B)

> > They are in the reversed order!

> >

> > IMO, Linux may need to introduce __callback, __api as decelerators for the

> functions, and use sparse to enforce this rule, sparse knows if a callback is

> invoked under some locks.

> 

> Oh, dear.  Yes, sparse knows such things, and so what?


I was thinking sparse can give us warnings on __api marked function invocation where __acquire count is not 0, this might be mandatory for high quality codes.
And sparse can also give us warnings on __callback marked function invocations where __acquire count is not 0, this should be optional.
But since it is not related to our topic, let's ignore this paragraph.

> 

> > In the case of ACPICA space_handlers, as you may know, when an ACPI

> operation region handler is invoked, there will be no lock held inside ACPICA

> (interpreter lock must be freed before executing operation region handlers).

> > So the likelihood of the dead lock is pretty much high here!

> 

> Sorry, what are you talking about?

> 

> Please let me rephrase my question: What *practical* problems would it lead

> to

> if we executed this particular callback under this particular mutex?

> 

> Not *theoretical* in the general theory of everything, *practical* in this

> particular piece of code.

> 

> And we are talking about a *global* mutex here, not something object-specific.


I think you have additional replies on this in another email.
Let me reply you there.

> 

> > > > +	atomic_dec(&rgn->refcnt);

> > > > +

> > > > +	return status;

> > > > +}

> > > > +

> > > > +static acpi_status

> > > > +acpi_region_default_setup(acpi_handle handle, u32 function,

> > > > +			  void *handler_context, void **region_context) {

> > > > +	acpi_adr_space_setup setup;

> > > > +	struct acpi_region *rgn = (struct acpi_region *)handler_context;

> > > > +	void *context;

> > > > +	acpi_status status = AE_OK;

> > > > +

> > > > +	mutex_lock(&acpi_mutex_region);

> > > > +	if (!acpi_region_callable(rgn) || !rgn->setup) {

> > > > +		mutex_unlock(&acpi_mutex_region);

> > > > +		return status;

> > > > +	}

> > > > +

> > > > +	atomic_inc(&rgn->refcnt);

> > > > +	setup = rgn->setup;

> > > > +	context = rgn->context;

> > > > +	mutex_unlock(&acpi_mutex_region);

> > > > +

> > > > +	status = setup(handle, function, context, region_context);

> > >

> > > Can setup drop rgn->refcnt ?

> >

> > The reason is same as the handler, as a setup is also a callback.

> 

> Let me rephrase: Is it legitimate for setup to modify rgn->refcnt?

> If so, then why?


Yes, the race is same as the handler.
When ACPICA is accessing the text segment of the setup function implementation, the module owns the setup function can also be unloaded as there is no lock hold before invoking setup - note that ExitInter also happens to setup invocations.

> 

> > >

> > > > +	atomic_dec(&rgn->refcnt);

> > > > +

> > > > +	return status;

> > > > +}

> > > > +

> > > > +static int __acpi_install_region(struct acpi_region *rgn,

> > > > +				 acpi_adr_space_type space_id)

> > > > +{

> > > > +	int res = 0;

> > > > +	acpi_status status;

> > > > +	int installing = 0;

> > > > +

> > > > +	mutex_lock(&acpi_mutex_region);

> > > > +	if (rgn->flags & ACPI_REGION_INSTALLED)

> > > > +		goto out_lock;

> > > > +	if (rgn->flags & ACPI_REGION_INSTALLING) {

> > > > +		res = -EBUSY;

> > > > +		goto out_lock;

> > > > +	}

> > > > +

> > > > +	installing = 1;

> > > > +	rgn->flags |= ACPI_REGION_INSTALLING;

> > > > +	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,

> > > space_id,

> > > > +						    acpi_region_default_handler,

> > > > +						    acpi_region_default_setup,

> > > > +						    rgn);

> > > > +	rgn->flags &= ~ACPI_REGION_INSTALLING;

> > > > +	if (ACPI_FAILURE(status))

> > > > +		res = -EINVAL;

> > > > +	else

> > > > +		rgn->flags |= ACPI_REGION_INSTALLED;

> > > > +

> > > > +out_lock:

> > > > +	mutex_unlock(&acpi_mutex_region);

> > > > +	if (installing) {

> > > > +		if (res)

> > > > +			pr_err("Failed to install region %d\n", space_id);

> > > > +		else

> > > > +			pr_info("Region %d installed\n", space_id);

> > > > +	}

> > > > +	return res;

> > > > +}

> > > > +

> > > > +int acpi_register_region(acpi_adr_space_type space_id,

> > > > +			 acpi_adr_space_handler handler,

> > > > +			 acpi_adr_space_setup setup, void *context) {

> > > > +	int res;

> > > > +	struct acpi_region *rgn;

> > > > +

> > > > +	if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)

> > > > +		return -EINVAL;

> > > > +

> > > > +	rgn = &acpi_regions[space_id];

> > > > +	if (!acpi_region_managed(rgn))

> > > > +		return -EINVAL;

> > > > +

> > > > +	res = __acpi_install_region(rgn, space_id);

> > > > +	if (res)

> > > > +		return res;

> > > > +

> > > > +	mutex_lock(&acpi_mutex_region);

> > > > +	if (rgn->flags & ACPI_REGION_REGISTERED) {

> > > > +		mutex_unlock(&acpi_mutex_region);

> > > > +		return -EBUSY;

> > > > +	}

> > > > +

> > > > +	rgn->handler = handler;

> > > > +	rgn->setup = setup;

> > > > +	rgn->context = context;

> > > > +	rgn->flags |= ACPI_REGION_REGISTERED;

> > > > +	atomic_set(&rgn->refcnt, 1);

> > > > +	mutex_unlock(&acpi_mutex_region);

> > > > +

> > > > +	pr_info("Region %d registered\n", space_id);

> > > > +

> > > > +	return 0;

> > > > +}

> > > > +EXPORT_SYMBOL_GPL(acpi_register_region);

> > > > +

> > > > +void acpi_unregister_region(acpi_adr_space_type space_id) {

> > > > +	struct acpi_region *rgn;

> > > > +

> > > > +	if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)

> > > > +		return;

> > > > +

> > > > +	rgn = &acpi_regions[space_id];

> > > > +	if (!acpi_region_managed(rgn))

> > > > +		return;

> > > > +

> > > > +	mutex_lock(&acpi_mutex_region);

> > > > +	if (!(rgn->flags & ACPI_REGION_REGISTERED)) {

> > > > +		mutex_unlock(&acpi_mutex_region);

> > > > +		return;

> > > > +	}

> > > > +	if (rgn->flags & ACPI_REGION_UNREGISTERING) {

> > > > +		mutex_unlock(&acpi_mutex_region);

> > > > +		return;

> > >

> > > What about

> > >

> > > 	if ((rgn->flags & ACPI_REGION_UNREGISTERING)

> > > 	    || !(rgn->flags & ACPI_REGION_REGISTERED)) {

> > > 		mutex_unlock(&acpi_mutex_region);

> > > 		return;

> > > 	}

> > >

> >

> > OK.

> >

> > > > +	}

> > > > +

> > > > +	rgn->flags |= ACPI_REGION_UNREGISTERING;

> > > > +	rgn->handler = NULL;

> > > > +	rgn->setup = NULL;

> > > > +	rgn->context = NULL;

> > > > +	mutex_unlock(&acpi_mutex_region);

> > > > +

> > > > +	while (atomic_read(&rgn->refcnt) > 1)

> > > > +		schedule_timeout_uninterruptible(usecs_to_jiffies(5));

> > >

> > > Wouldn't it be better to use a wait queue here?

> >

> > Yes, I'll try.

> 

> By the way, we do we need to do that?


I think you have additional replies on this in another email.
Let me reply you there.

Thanks for commenting.

Best regards
-Lv

> 

> > > > +	atomic_dec(&rgn->refcnt);

> > > > +

> > > > +	mutex_lock(&acpi_mutex_region);

> > > > +	rgn->flags &= ~(ACPI_REGION_REGISTERED |

> > > ACPI_REGION_UNREGISTERING);

> > > > +	mutex_unlock(&acpi_mutex_region);

> > > > +

> > > > +	pr_info("Region %d unregistered\n", space_id); }

> > > > +EXPORT_SYMBOL_GPL(acpi_unregister_region);

> > > > diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index

> > > > a2c2fbb..15fad0d 100644

> > > > --- a/include/acpi/acpi_bus.h

> > > > +++ b/include/acpi/acpi_bus.h

> > > > @@ -542,4 +542,9 @@ static inline int unregister_acpi_bus_type(void

> > > > *bus) { return 0; }

> > > >

> > > >  #endif				/* CONFIG_ACPI */

> > > >

> > > > +int acpi_register_region(acpi_adr_space_type space_id,

> > > > +			 acpi_adr_space_handler handler,

> > > > +			 acpi_adr_space_setup setup, void *context); void

> > > > +acpi_unregister_region(acpi_adr_space_type space_id);

> > > > +

> > > >  #endif /*__ACPI_BUS_H__*/

> 

> Thanks,

> Rafael

> 

> 

> --

> I speak only for myself.

> Rafael J. Wysocki, Intel Open Source Technology Center.
Lv Zheng July 29, 2013, 1:56 a.m. UTC | #10
> On Friday, July 26, 2013 10:49 PM Rafael J. Wysocki wrote:

> > On Friday, July 26, 2013 01:54:00 AM Zheng, Lv wrote:

> > > On Friday, July 26, 2013 5:29 AM Rafael J. Wysocki wrote:

> > > On Tuesday, July 23, 2013 04:09:43 PM Lv Zheng wrote:

> > > > This patch adds reference couting for ACPI operation region

> > > > handlers to fix races caused by the ACPICA address space callback

> invocations.

> > > >

> > > > ACPICA address space callback invocation is not suitable for Linux

> > > > CONFIG_MODULE=y execution environment.

> > >

> > > Actually, can you please explain to me what *exactly* the problem is?

> >

> > OK.  I'll add race explanations in the next revision.

> >

> > The problem is there is no "lock" held inside ACPICA for invoking

> > operation region handlers.

> > Thus races happens between the

> > acpi_remove/install_address_space_handler and the handler/setup

> callbacks.

> 

> I see.  Now you're trying to introduce something that would prevent those

> races from happening, right?


Yes. Let me explain this later in this email.

> 

> > This is correct per ACPI specification.

> > As if there is interpreter locks held for invoking operation region

> > handlers, the timeout implemented inside the operation region handlers

> > will make all locking facilities (Acquire or Sleep,...) timed out.

> > Please refer to ACPI specification "5.5.2 Control Method Execution":

> > Interpretation of a Control Method is not preemptive, but it can

> > block. When a control method does block, OSPM can initiate or continue

> > the execution of a different control method. A control method can only

> > assume that access to global objects is exclusive for any period the control

> method does not block.

> >

> > So it is pretty much likely that ACPI IO transfers are locked inside

> > the operation region callback implementations.

> > Using locking facility to protect the callback invocation will risk dead locks.

> 

> No.  If you use a single global lock around all invocations of operation region

> handlers, it won't deadlock, but it will *serialize* things.  This means that

> there won't be two handlers executing in parallel.  That may or may not be

> bad depending on what those handlers actually do.

> 

> Your concern seems to be that if one address space handler is buggy and it

> blocks indefinitely, executing it under such a lock would affect the other address

> space handlers and in my opinion this is a valid concern.


It can be expressed in more detailed ways:

The interpreter runs control methods in the following style according to the ACPI spec.
CM1_Enter -> EnterInter -> CM1_Running -> OpRegion1 -> ExitInter -> EnterInter                            -> CM1_running -> ExitInter -> CM1_Exit
CM2_Enter -> EnterInter ->                                       -> CM2_Running -> OpRegion1 -> ExitInter -> EnterInter               -> CM2_running -> ExitInter -> CM2_Exit

EnterInter: Enter interpreter lock
ExitInter: Leave interpreter lock

Let me introduce two situations:

1. If we hold global "mutex" before "EnterInter", then no second control method can be run "NotSerialized".
If the CM1 just have some codes waiting for a hardware flag and CM2 can access other hardware IOs to trigger this flag, then nothing can happen any longer.
This is a practical bug as what we have already seen in "NotSerialized" marked ACPI control methods behave in the interpreter mode executed in serialized way - kernel parameter "acpi_serialize".

2. If we hold global "mutex" after "EnterInter" and Before OpRegion1
If we do things this way, then all IO accesses are serialized, if we have something in an IPMI operation region failed due to timeout, then any other system IOs that should happen in parallel will just happen after 5 seconds.  This is not an acceptable experience.

> 

> So the idea seems to be to add wrappers around

> acpi_install_address_space_handler()

> and acpi_remove_address_space_handler (but I don't see where the latter is

> called after the change?), such that they will know when it is safe to unregister

> the handler.  That is simple enough.


An obvious bug, it should be put between the while (atomic_read() > 1) block and the final atomic_dec().

> However, I'm not sure it is needed in the context of IPMI.


I think I do this just because I need a quick fix to test IPMI bug-fix series.
The issue is highly related to ACPI interpreter design, and codes should be implemented inside ACPICA.
And there is not only ACPI_ROOT_OBJECT based address space handlers, but also non-ACPI_ROOT_OBJECT based address space handlers, this patch can't protect the latter ones.

> Your address space

> handler's context is NULL, so even it if is executed after

> acpi_remove_address_space_handler() has been called for it (or in parallel), it

> doesn't depend on anything passed by the caller, so I don't see why the issue

> can't be addressed by a proper synchronization between

> acpi_ipmi_exit() and acpi_ipmi_space_handler().

> 

> Clearly, acpi_ipmi_exit() should wait for all already running instances of

> acpi_ipmi_space_handler() to complete and all acpi_ipmi_space_handler()

> instances started after acpi_ipmi_exit() has been called must return

> immediately.

> 

> I would imagine an algorithm like this:

> 

> acpi_ipmi_exit()

>  1. Take "address space handler lock".

>  2. Set "unregistering address space handler" flag.

>  3. Check if "count of currently running handlers" is 0.  If so,

>     call acpi_remove_address_space_handler(), drop the lock (possibly clear

> the

>     flag) and return.

>  4. Otherwise drop the lock and go to sleep in "address space handler wait

> queue".

>  5. When woken up, take "address space handler lock" and go to 3.

> 

> acpi_ipmi_space_handler()

>  1. Take "address space handler lock".

>  2. Check "unregistering address space handler" flag.  If set, drop the lock

>     and return.

>  3. Increment "count of currently running handlers".

>  4. Drop the lock.

>  5. Do your work.

>  6. Take "address space handler lock".

>  7. Decrement "count of currently running handlers" and if 0, signal the

>     tasks waiting on it to wake up.

>  8. Drop the lock.


Yes, it can also work, but the fix will go inside IPMI.
And I agree that the codes should not appear in the IPMI context since the issue is highly ACPI interpreter related.
What if we just stop doing any further work on this patch and just mark it as RFC or a test patch for information purpose.
It is only useful for the testers.

Thanks and best regards
-Lv

> 

> Thanks,

> Rafael

> 

> 

> --

> I speak only for myself.

> Rafael J. Wysocki, Intel Open Source Technology Center.
diff mbox

Patch

diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c
index 5f8f495..2a09156 100644
--- a/drivers/acpi/acpi_ipmi.c
+++ b/drivers/acpi/acpi_ipmi.c
@@ -539,20 +539,18 @@  out_ref:
 static int __init acpi_ipmi_init(void)
 {
 	int result = 0;
-	acpi_status status;
 
 	if (acpi_disabled)
 		return result;
 
 	mutex_init(&driver_data.ipmi_lock);
 
-	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
-						    ACPI_ADR_SPACE_IPMI,
-						    &acpi_ipmi_space_handler,
-						    NULL, NULL);
-	if (ACPI_FAILURE(status)) {
+	result = acpi_register_region(ACPI_ADR_SPACE_IPMI,
+				      &acpi_ipmi_space_handler,
+				      NULL, NULL);
+	if (result) {
 		pr_warn("Can't register IPMI opregion space handle\n");
-		return -EINVAL;
+		return result;
 	}
 
 	result = ipmi_smi_watcher_register(&driver_data.bmc_events);
@@ -596,9 +594,7 @@  static void __exit acpi_ipmi_exit(void)
 	}
 	mutex_unlock(&driver_data.ipmi_lock);
 
-	acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
-					  ACPI_ADR_SPACE_IPMI,
-					  &acpi_ipmi_space_handler);
+	acpi_unregister_region(ACPI_ADR_SPACE_IPMI);
 }
 
 module_init(acpi_ipmi_init);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 6ab2c35..8398e51 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -86,6 +86,42 @@  static struct workqueue_struct *kacpid_wq;
 static struct workqueue_struct *kacpi_notify_wq;
 static struct workqueue_struct *kacpi_hotplug_wq;
 
+struct acpi_region {
+	unsigned long flags;
+#define ACPI_REGION_DEFAULT		0x01
+#define ACPI_REGION_INSTALLED		0x02
+#define ACPI_REGION_REGISTERED		0x04
+#define ACPI_REGION_UNREGISTERING	0x08
+#define ACPI_REGION_INSTALLING		0x10
+	/*
+	 * NOTE: Upgrading All Region Handlers
+	 * This flag is only used during the period where not all of the
+	 * region handers are upgraded to the new interfaces.
+	 */
+#define ACPI_REGION_MANAGED		0x80
+	acpi_adr_space_handler handler;
+	acpi_adr_space_setup setup;
+	void *context;
+	/* Invoking references */
+	atomic_t refcnt;
+};
+
+static struct acpi_region acpi_regions[ACPI_NUM_PREDEFINED_REGIONS] = {
+	[ACPI_ADR_SPACE_SYSTEM_MEMORY] = {
+		.flags = ACPI_REGION_DEFAULT,
+	},
+	[ACPI_ADR_SPACE_SYSTEM_IO] = {
+		.flags = ACPI_REGION_DEFAULT,
+	},
+	[ACPI_ADR_SPACE_PCI_CONFIG] = {
+		.flags = ACPI_REGION_DEFAULT,
+	},
+	[ACPI_ADR_SPACE_IPMI] = {
+		.flags = ACPI_REGION_MANAGED,
+	},
+};
+static DEFINE_MUTEX(acpi_mutex_region);
+
 /*
  * This list of permanent mappings is for memory that may be accessed from
  * interrupt context, where we can't do the ioremap().
@@ -1799,3 +1835,191 @@  void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
 		kfree(hp_work);
 }
 EXPORT_SYMBOL_GPL(alloc_acpi_hp_work);
+
+static bool acpi_region_managed(struct acpi_region *rgn)
+{
+	/*
+	 * NOTE: Default and Managed
+	 * We only need to avoid region management on the regions managed
+	 * by ACPICA (ACPI_REGION_DEFAULT).  Currently, we need additional
+	 * check as many operation region handlers are not upgraded, so
+	 * only those known to be safe are managed (ACPI_REGION_MANAGED).
+	 */
+	return !(rgn->flags & ACPI_REGION_DEFAULT) &&
+	       (rgn->flags & ACPI_REGION_MANAGED);
+}
+
+static bool acpi_region_callable(struct acpi_region *rgn)
+{
+	return (rgn->flags & ACPI_REGION_REGISTERED) &&
+	       !(rgn->flags & ACPI_REGION_UNREGISTERING);
+}
+
+static acpi_status
+acpi_region_default_handler(u32 function,
+			    acpi_physical_address address,
+			    u32 bit_width, u64 *value,
+			    void *handler_context, void *region_context)
+{
+	acpi_adr_space_handler handler;
+	struct acpi_region *rgn = (struct acpi_region *)handler_context;
+	void *context;
+	acpi_status status = AE_NOT_EXIST;
+
+	mutex_lock(&acpi_mutex_region);
+	if (!acpi_region_callable(rgn) || !rgn->handler) {
+		mutex_unlock(&acpi_mutex_region);
+		return status;
+	}
+
+	atomic_inc(&rgn->refcnt);
+	handler = rgn->handler;
+	context = rgn->context;
+	mutex_unlock(&acpi_mutex_region);
+
+	status = handler(function, address, bit_width, value, context,
+			 region_context);
+	atomic_dec(&rgn->refcnt);
+
+	return status;
+}
+
+static acpi_status
+acpi_region_default_setup(acpi_handle handle, u32 function,
+			  void *handler_context, void **region_context)
+{
+	acpi_adr_space_setup setup;
+	struct acpi_region *rgn = (struct acpi_region *)handler_context;
+	void *context;
+	acpi_status status = AE_OK;
+
+	mutex_lock(&acpi_mutex_region);
+	if (!acpi_region_callable(rgn) || !rgn->setup) {
+		mutex_unlock(&acpi_mutex_region);
+		return status;
+	}
+
+	atomic_inc(&rgn->refcnt);
+	setup = rgn->setup;
+	context = rgn->context;
+	mutex_unlock(&acpi_mutex_region);
+
+	status = setup(handle, function, context, region_context);
+	atomic_dec(&rgn->refcnt);
+
+	return status;
+}
+
+static int __acpi_install_region(struct acpi_region *rgn,
+				 acpi_adr_space_type space_id)
+{
+	int res = 0;
+	acpi_status status;
+	int installing = 0;
+
+	mutex_lock(&acpi_mutex_region);
+	if (rgn->flags & ACPI_REGION_INSTALLED)
+		goto out_lock;
+	if (rgn->flags & ACPI_REGION_INSTALLING) {
+		res = -EBUSY;
+		goto out_lock;
+	}
+
+	installing = 1;
+	rgn->flags |= ACPI_REGION_INSTALLING;
+	status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, space_id,
+						    acpi_region_default_handler,
+						    acpi_region_default_setup,
+						    rgn);
+	rgn->flags &= ~ACPI_REGION_INSTALLING;
+	if (ACPI_FAILURE(status))
+		res = -EINVAL;
+	else
+		rgn->flags |= ACPI_REGION_INSTALLED;
+
+out_lock:
+	mutex_unlock(&acpi_mutex_region);
+	if (installing) {
+		if (res)
+			pr_err("Failed to install region %d\n", space_id);
+		else
+			pr_info("Region %d installed\n", space_id);
+	}
+	return res;
+}
+
+int acpi_register_region(acpi_adr_space_type space_id,
+			 acpi_adr_space_handler handler,
+			 acpi_adr_space_setup setup, void *context)
+{
+	int res;
+	struct acpi_region *rgn;
+
+	if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)
+		return -EINVAL;
+
+	rgn = &acpi_regions[space_id];
+	if (!acpi_region_managed(rgn))
+		return -EINVAL;
+
+	res = __acpi_install_region(rgn, space_id);
+	if (res)
+		return res;
+
+	mutex_lock(&acpi_mutex_region);
+	if (rgn->flags & ACPI_REGION_REGISTERED) {
+		mutex_unlock(&acpi_mutex_region);
+		return -EBUSY;
+	}
+
+	rgn->handler = handler;
+	rgn->setup = setup;
+	rgn->context = context;
+	rgn->flags |= ACPI_REGION_REGISTERED;
+	atomic_set(&rgn->refcnt, 1);
+	mutex_unlock(&acpi_mutex_region);
+
+	pr_info("Region %d registered\n", space_id);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_register_region);
+
+void acpi_unregister_region(acpi_adr_space_type space_id)
+{
+	struct acpi_region *rgn;
+
+	if (space_id >= ACPI_NUM_PREDEFINED_REGIONS)
+		return;
+
+	rgn = &acpi_regions[space_id];
+	if (!acpi_region_managed(rgn))
+		return;
+
+	mutex_lock(&acpi_mutex_region);
+	if (!(rgn->flags & ACPI_REGION_REGISTERED)) {
+		mutex_unlock(&acpi_mutex_region);
+		return;
+	}
+	if (rgn->flags & ACPI_REGION_UNREGISTERING) {
+		mutex_unlock(&acpi_mutex_region);
+		return;
+	}
+
+	rgn->flags |= ACPI_REGION_UNREGISTERING;
+	rgn->handler = NULL;
+	rgn->setup = NULL;
+	rgn->context = NULL;
+	mutex_unlock(&acpi_mutex_region);
+
+	while (atomic_read(&rgn->refcnt) > 1)
+		schedule_timeout_uninterruptible(usecs_to_jiffies(5));
+	atomic_dec(&rgn->refcnt);
+
+	mutex_lock(&acpi_mutex_region);
+	rgn->flags &= ~(ACPI_REGION_REGISTERED | ACPI_REGION_UNREGISTERING);
+	mutex_unlock(&acpi_mutex_region);
+
+	pr_info("Region %d unregistered\n", space_id);
+}
+EXPORT_SYMBOL_GPL(acpi_unregister_region);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index a2c2fbb..15fad0d 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -542,4 +542,9 @@  static inline int unregister_acpi_bus_type(void *bus) { return 0; }
 
 #endif				/* CONFIG_ACPI */
 
+int acpi_register_region(acpi_adr_space_type space_id,
+			 acpi_adr_space_handler handler,
+			 acpi_adr_space_setup setup, void *context);
+void acpi_unregister_region(acpi_adr_space_type space_id);
+
 #endif /*__ACPI_BUS_H__*/