Hi,
My vaio repeatedly crashed by "Data modified on freelist"(*1) or other
memory corruptions. After my long time debug, I found the route cause
is a handling of references of LocalX, like the following:
If ((SMRW (0x0B, 0x16, 0x21, RefOf (Local0)) == Zero))
In the called control method, "RefOf (Local1)" is referred as Arg3, is
stored a value like the following:
Arg3 = \_SB.PCI0.LPCB.EC0.SMD0
In aml_store(), lvalue is reset if lvalue is a LocalX. But since that
was done before resolving the reference, lvalue was not reset if
lvalue is a reference of LocalX.
diff #1 fixes that problem. It resets lvalue after resolving
references.
ok?
diff #2 adds aml_die() if any memory corruption occurs when creating
field in a buffer. This actually happens on my vaio (pro pk 14) if
diff #1 is not applied.
ok?
diff #1
Index: sys/dev/acpi/dsdt.c
===================================================================
RCS file: /var/cvs/openbsd/src/sys/dev/acpi/dsdt.c,v
retrieving revision 1.257
diff -u -p -r1.257 dsdt.c
--- sys/dev/acpi/dsdt.c 17 Dec 2020 17:57:19 -0000 1.257
+++ sys/dev/acpi/dsdt.c 26 Feb 2021 04:12:03 -0000
@@ -2961,11 +2961,11 @@ aml_store(struct aml_scope *scope, struc
aml_rwfield(rhs, 0, rhs->v_field.bitlen, &tmp, ACPI_IOREAD);
rhs = &tmp;
}
+
+ lhs = aml_gettgt(lhs, AMLOP_STORE);
/* Store to LocalX: free value */
if (lhs->stack >= AMLOP_LOCAL0 && lhs->stack <= AMLOP_LOCAL7)
aml_freevalue(lhs);
-
- lhs = aml_gettgt(lhs, AMLOP_STORE);
switch (lhs->type) {
case AML_OBJTYPE_UNINITIALIZED:
aml_copyvalue(lhs, rhs);
diff #2
Index: sys/dev/acpi/dsdt.c
===================================================================
RCS file: /var/cvs/openbsd/src/sys/dev/acpi/dsdt.c,v
retrieving revision 1.257
diff -u -p -r1.257 dsdt.c
--- sys/dev/acpi/dsdt.c 17 Dec 2020 17:57:19 -0000 1.257
+++ sys/dev/acpi/dsdt.c 26 Feb 2021 04:33:21 -0000
@@ -2742,11 +2742,17 @@ aml_rwfield(struct aml_value *fld, int b
} else if (mode == ACPI_IOREAD) {
/* bufferfield:read */
_aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0);
+ if (ref1->length < aml_bytepos(fld->v_field.bitpos) +
+ aml_bytelen(fld->v_field.bitlen))
+ aml_die("bufferfield:read out of range");
aml_bufcpy(&val->v_integer, 0, ref1->v_buffer,
fld->v_field.bitpos, fld->v_field.bitlen);
} else {
/* bufferfield:write */
val = aml_convert(val, AML_OBJTYPE_INTEGER, -1);
+ if (ref1->length < aml_bytepos(fld->v_field.bitpos) +
+ aml_bytelen(fld->v_field.bitlen))
+ aml_die("bufferfield:write out of range");
aml_bufcpy(ref1->v_buffer, fld->v_field.bitpos, &val->v_integer,
0, fld->v_field.bitlen);
aml_delref(&val, "wrbuffld");
*1 example console log
Data modified on freelist: word -35183627074926 of object
0xffff8000024a3060 size 0x10 previous type temp (invalid addr
0xffff8027023e55f0)
uvm_fault(0xffffffff81f63958, 0xffff8027023e55f8, 0, 1) -> e
kernel: page fault trap, code=0
Stopped at malloc+0x482: movq 0x8(%r14),%rcx
Running script...
ddb{0}> malloc(10,91,5) at malloc+0x482
i915_gem_do_execbuffer(ffff8000002ab078,ffff800000ee0c00,ffff8000337a7970,ffff8000020ca000,0)
at i915_gem_do_execbuffer+0xa52
i915_gem_execbuffer2_ioctl(ffff8000002ab078,ffff8000337a7970,ffff800000ee0c00)
at i915_gem_execbuffer2_ioctl+0x144
drmioctl(15700,80406469,ffff8000337a7970,3,ffff8000336a8798) at
drmioctl+0xd8
VOP_IOCTL(fffffd8227abbeb0,80406469,ffff8000337a7970,3,fffffd826bd1dd88,ffff8000336a8798)
at VOP_IOCTL+0x55
vn_ioctl(fffffd82282ee8e8,80406469,ffff8000337a7970,ffff8000336a8798) at
vn_ioctl+0x64
sys_ioctl(ffff8000336a8798,ffff8000337a7a80,ffff8000337a7ae0) at
sys_ioctl+0x3c2
syscall(ffff8000337a7b50) at syscall+0x389
Xsyscall(6,36,0,36,80406469,7f7fffff5c00) at Xsyscall+0x128
end of kernel
end trace frame: 0x7f7fffff5bd0, count: -9