From: John Villalovos <jvillalo@redhat.com> Date: Mon, 18 Aug 2008 13:20:19 -0400 Subject: [cpufreq] acpi: boot crash due to _PSD return-by-ref Message-id: 20080818172018.GA9922@linuxjohn.usersys.redhat.com O-Subject: [RHEL 5.3 PATCH] BZ 428909 ACPI-CPUFREQ possible crash Bugzilla: 428909 RH-Acked-by: Matthew Garrett <mjg@redhat.com> RH-Acked-by: Prarit Bhargava <prarit@redhat.com> RH-Acked-by: Anton Arapov <aarapov@redhat.com> https://bugzilla.redhat.com/show_bug.cgi?id=428909 Background: The acpi-cpufreq module can crash on load/initialization due to named references in the the core ACPI code. This was initially reported and fixed in http://bugzilla.kernel.org/show_bug.cgi?id=9429. Git commit: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=152c300d007c70c4a1847dad39ecdaba22e7d457 Previously the code did not make a copy of the named references and sometimes the item being referenced would be deleted and the named reference was left pointing to something that no longer existed. Matthew Garret has submitted a patch to make acpi-cpufreq be used in RHEL 5.3: https://bugzilla.redhat.com/show_bug.cgi?id=449787 So this issue may affect some platforms out there. Also this same patch fixes https://bugzilla.redhat.com/show_bug.cgi?id=455701 "cpufreq driver get the wrong processor number in domain by ACPI _PSD table" Below is the patch, tested by me on x86_64 against the 2.6.18-104 kernel. Brew is currently down, but I will post brew results after it is back up. John >From 152c300d007c70c4a1847dad39ecdaba22e7d457 Mon Sep 17 00:00:00 2001 Message-Id: <152c300d007c70c4a1847dad39ecdaba22e7d457.1196624815.git.len.brown@intel.com> In-Reply-To: <357dc4c3f13cb5c1e3b40a09cbe6ff1b0df2c7c3.1196624815.git.len.brown@intel.com> References: <357dc4c3f13cb5c1e3b40a09cbe6ff1b0df2c7c3.1196624815.git.len.brown@intel.com> From: Bob Moore <robert.moore@intel.com> Date: Wed, 17 Oct 2007 16:10:18 -0400 Subject: [PATCH 2/2] ACPICA: fix acpi-cpufreq boot crash due to _PSD return-by-reference Organization: Intel Open Source Technology Center Changed resolution of named references in packages Fixed a problem with the Package operator where all named references were created as object references and left otherwise unresolved. According to the ACPI specification, a Package can only contain Data Objects or references to control methods. The implication is that named references to Data Objects (Integer, Buffer, String, Package, BufferField, Field) should be resolved immediately upon package creation. This is the approach taken with this change. References to all other named objects (Methods, Devices, Scopes, etc.) are all now properly created as reference objects. http://bugzilla.kernel.org/show_bug.cgi?id=5328 http://bugzilla.kernel.org/show_bug.cgi?id=9429 Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com> diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 72190ab..c546bc6 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -137,6 +137,71 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } } + + /* Special object resolution for elements of a package */ + + if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == + AML_VAR_PACKAGE_OP)) { + /* + * Attempt to resolve the node to a value before we insert it into + * the package. If this is a reference to a common data type, + * resolve it immediately. According to the ACPI spec, package + * elements can only be "data objects" or method references. + * Attempt to resolve to an Integer, Buffer, String or Package. + * If cannot, return the named reference (for things like Devices, + * Methods, etc.) Buffer Fields and Fields will resolve to simple + * objects (int/buf/str/pkg). + * + * NOTE: References to things like Devices, Methods, Mutexes, etc. + * will remain as named references. This behavior is not described + * in the ACPI spec, but it appears to be an oversight. + */ + obj_desc = (union acpi_operand_object *)op->common.node; + + status = + acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &obj_desc), + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + switch (op->common.node->type) { + /* + * For these types, we need the actual node, not the subobject. + * However, the subobject got an extra reference count above. + */ + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_METHOD: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + obj_desc = + (union acpi_operand_object *)op->common. + node; + break; + + default: + break; + } + + /* + * If above resolved to an operand object, we are done. Otherwise, + * we have a NS node, we must create the package entry as a named + * reference. + */ + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != + ACPI_DESC_TYPE_NAMED) { + goto exit; + } + } } /* Create and init a new internal ACPI object */ @@ -156,6 +221,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } + exit: *obj_desc_ptr = obj_desc; return_ACPI_STATUS(AE_OK); } @@ -358,12 +424,25 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, arg = arg->common.next; for (i = 0; arg; i++) { if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { - - /* Object (package or buffer) is already built */ - - obj_desc->package.elements[i] = - ACPI_CAST_PTR(union acpi_operand_object, - arg->common.node); + if (arg->common.node->type == ACPI_TYPE_METHOD) { + /* + * A method reference "looks" to the parser to be a method + * invocation, so we special case it here + */ + arg->common.aml_opcode = AML_INT_NAMEPATH_OP; + status = + acpi_ds_build_internal_object(walk_state, + arg, + &obj_desc-> + package. + elements[i]); + } else { + /* This package element is already built, just get it */ + + obj_desc->package.elements[i] = + ACPI_CAST_PTR(union acpi_operand_object, + arg->common.node); + } } else { status = acpi_ds_build_internal_object(walk_state, arg, &obj_desc->