Re: Somewhat important ACPI diff
Maybe a bit late, but this diff appears to have fixed my acpitz bug.[1] Since it was somewhat irregular I wanted to test it for a little longer. Thank you so much for fixing this. [1] http://marc.info/?l=openbsd-bugsm=136539785515806w=2 On 05/20/13 18:57, Mark Kettenis wrote: As diagnosed by some other people (armani@, jcs@?) a while ago, our code to deal with IndexField() operators in our AML interpreter is quite broken. It works for fields that are less than a byte in size, but anything else is pretty much completely busted. I wouldn't be surprised if this is the cause of many ACPI-related problems. One that comes to mind are the ridiculous temperatures reported by acpitz(4) that have been plaguing us since basically forever. I don't have a lot of machines that have AML with IndexField() operators. I've verified that those return the correct values, but this defenitely could use further testing on a wide variety of i386/amd64 hardware please. Index: dsdt.c === RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v retrieving revision 1.200 diff -u -p -r1.200 dsdt.c --- dsdt.c 10 Apr 2013 01:35:55 - 1.200 +++ dsdt.c 20 May 2013 16:55:27 - @@ -2221,8 +2221,9 @@ aml_evalhid(struct aml_node *node, struc return (0); } -void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); void aml_rwgas(struct aml_value *, int, int, struct aml_value *, int, int); +void aml_rwindexfield(struct aml_value *, struct aml_value *val, int); +void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); /* Get PCI address for opregion objects */ int @@ -2341,6 +2342,81 @@ aml_rwgas(struct aml_value *rgn, int bpo aml_freevalue(tmp); } + +void +aml_rwindexfield(struct aml_value *fld, struct aml_value *val, int mode) +{ + struct aml_value tmp, *ref1, *ref2; + void *tbit, *vbit; + int vpos, bpos, blen; + int indexval; + int sz, len; + + ref2 = fld-v_field.ref2; + ref1 = fld-v_field.ref1; + bpos = fld-v_field.bitpos; + blen = fld-v_field.bitlen; + + memset(tmp, 0, sizeof(tmp)); + tmp.refcnt = 99; + + /* Get field access size */ + switch (AML_FIELD_ACCESS(fld-v_field.flags)) { + case AML_FIELD_WORDACC: + sz = 2; + break; + case AML_FIELD_DWORDACC: + sz = 4; + break; + case AML_FIELD_QWORDACC: + sz = 8; + break; + default: + sz = 1; + break; + } + + if (blen aml_intlen) { + if (mode == ACPI_IOREAD) { + /* Read from a large field: create buffer */ + _aml_setvalue(val, AML_OBJTYPE_BUFFER, + (blen + 7) 3, 0); + } + vbit = val-v_buffer; + } else { + if (mode == ACPI_IOREAD) { + /* Read from a short field: initialize integer */ + _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); + } + vbit = val-v_integer; + } + tbit = tmp.v_integer; + vpos = 0; + + indexval = (bpos 3) ~(sz - 1); + bpos = bpos - (indexval 3); + + while (blen 0) { + len = min(blen, (sz 3) - bpos); + + /* Write index register */ + _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, indexval, 0); + aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); + indexval += sz; + + /* Read/write data register */ + _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, 0, 0); + if (mode == ACPI_IOWRITE) + aml_bufcpy(tbit, 0, vbit, vpos, len); + aml_rwfield(ref1, bpos, len, tmp, mode); + if (mode == ACPI_IOREAD) + aml_bufcpy(vbit, vpos, tbit, 0, len); + vpos += len; + blen -= len; + bpos = 0; + } +} + void aml_rwfield(struct aml_value *fld, int bpos, int blen, struct aml_value *val, int mode) @@ -2356,10 +2432,7 @@ aml_rwfield(struct aml_value *fld, int b memset(tmp, 0, sizeof(tmp)); aml_addref(tmp, fld.write); if (fld-v_field.type == AMLOP_INDEXFIELD) { - _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, fld-v_field.ref3, 0); - aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); - aml_rwfield(ref1, fld-v_field.bitpos, fld-v_field.bitlen, - val, mode); + aml_rwindexfield(fld, val, mode); } else if (fld-v_field.type == AMLOP_BANKFIELD) { _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, fld-v_field.ref3, 0); aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); @@ -2414,10 +2487,6 @@ aml_createfield(struct aml_value *field, opcode == AMLOP_BANKFIELD) ?
Re: Somewhat important ACPI diff
2013/5/20 Mark Kettenis mark.kette...@xs4all.nl As diagnosed by some other people (armani@, jcs@?) a while ago, our code to deal with IndexField() operators in our AML interpreter is quite broken. It works for fields that are less than a byte in size, but anything else is pretty much completely busted. I wouldn't be surprised if this is the cause of many ACPI-related problems. One that comes to mind are the ridiculous temperatures reported by acpitz(4) that have been plaguing us since basically forever. I don't have a lot of machines that have AML with IndexField() operators. I've verified that those return the correct values, but this defenitely could use further testing on a wide variety of i386/amd64 hardware please. Index: dsdt.c === RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v retrieving revision 1.200 diff -u -p -r1.200 dsdt.c --- dsdt.c 10 Apr 2013 01:35:55 - 1.200 +++ dsdt.c 20 May 2013 16:55:27 - @@ -2221,8 +2221,9 @@ aml_evalhid(struct aml_node *node, struc return (0); } -void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); void aml_rwgas(struct aml_value *, int, int, struct aml_value *, int, int); +void aml_rwindexfield(struct aml_value *, struct aml_value *val, int); +void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); /* Get PCI address for opregion objects */ int @@ -2341,6 +2342,81 @@ aml_rwgas(struct aml_value *rgn, int bpo aml_freevalue(tmp); } + +void +aml_rwindexfield(struct aml_value *fld, struct aml_value *val, int mode) +{ + struct aml_value tmp, *ref1, *ref2; + void *tbit, *vbit; + int vpos, bpos, blen; + int indexval; + int sz, len; + + ref2 = fld-v_field.ref2; + ref1 = fld-v_field.ref1; + bpos = fld-v_field.bitpos; + blen = fld-v_field.bitlen; + + memset(tmp, 0, sizeof(tmp)); + tmp.refcnt = 99; + + /* Get field access size */ + switch (AML_FIELD_ACCESS(fld-v_field.flags)) { + case AML_FIELD_WORDACC: + sz = 2; + break; + case AML_FIELD_DWORDACC: + sz = 4; + break; + case AML_FIELD_QWORDACC: + sz = 8; + break; + default: + sz = 1; + break; + } + + if (blen aml_intlen) { + if (mode == ACPI_IOREAD) { + /* Read from a large field: create buffer */ + _aml_setvalue(val, AML_OBJTYPE_BUFFER, + (blen + 7) 3, 0); + } + vbit = val-v_buffer; + } else { + if (mode == ACPI_IOREAD) { + /* Read from a short field: initialize integer */ + _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); + } + vbit = val-v_integer; + } + tbit = tmp.v_integer; + vpos = 0; + + indexval = (bpos 3) ~(sz - 1); + bpos = bpos - (indexval 3); + + while (blen 0) { + len = min(blen, (sz 3) - bpos); + + /* Write index register */ + _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, indexval, 0); + aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); + indexval += sz; + + /* Read/write data register */ + _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, 0, 0); + if (mode == ACPI_IOWRITE) + aml_bufcpy(tbit, 0, vbit, vpos, len); + aml_rwfield(ref1, bpos, len, tmp, mode); + if (mode == ACPI_IOREAD) + aml_bufcpy(vbit, vpos, tbit, 0, len); + vpos += len; + blen -= len; + bpos = 0; + } +} + void aml_rwfield(struct aml_value *fld, int bpos, int blen, struct aml_value *val, int mode) @@ -2356,10 +2432,7 @@ aml_rwfield(struct aml_value *fld, int b memset(tmp, 0, sizeof(tmp)); aml_addref(tmp, fld.write); if (fld-v_field.type == AMLOP_INDEXFIELD) { - _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, fld-v_field.ref3, 0); - aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); - aml_rwfield(ref1, fld-v_field.bitpos, fld-v_field.bitlen, - val, mode); + aml_rwindexfield(fld, val, mode); } else if (fld-v_field.type == AMLOP_BANKFIELD) { _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, fld-v_field.ref3, 0); aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); @@ -2414,10 +2487,6 @@ aml_createfield(struct aml_value *field, opcode == AMLOP_BANKFIELD) ? AML_OBJTYPE_FIELDUNIT : AML_OBJTYPE_BUFFERFIELD; - if (opcode == AMLOP_INDEXFIELD)
Re: Somewhat important ACPI diff
On Tue, May 21, 2013 at 10:15:02AM +0400, Vadim Zhukov wrote: [...] ThinkPad X201i, fine here for an half a day (running since the time you posted the diff). dmesg doesn't have any borked stuff, suspend/resume works fine, both for short and long periods. [...] Likewise with my Thinkpad R61i. -- Gregor Best
Somewhat important ACPI diff
As diagnosed by some other people (armani@, jcs@?) a while ago, our code to deal with IndexField() operators in our AML interpreter is quite broken. It works for fields that are less than a byte in size, but anything else is pretty much completely busted. I wouldn't be surprised if this is the cause of many ACPI-related problems. One that comes to mind are the ridiculous temperatures reported by acpitz(4) that have been plaguing us since basically forever. I don't have a lot of machines that have AML with IndexField() operators. I've verified that those return the correct values, but this defenitely could use further testing on a wide variety of i386/amd64 hardware please. Index: dsdt.c === RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v retrieving revision 1.200 diff -u -p -r1.200 dsdt.c --- dsdt.c 10 Apr 2013 01:35:55 - 1.200 +++ dsdt.c 20 May 2013 16:55:27 - @@ -2221,8 +2221,9 @@ aml_evalhid(struct aml_node *node, struc return (0); } -void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); void aml_rwgas(struct aml_value *, int, int, struct aml_value *, int, int); +void aml_rwindexfield(struct aml_value *, struct aml_value *val, int); +void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); /* Get PCI address for opregion objects */ int @@ -2341,6 +2342,81 @@ aml_rwgas(struct aml_value *rgn, int bpo aml_freevalue(tmp); } + +void +aml_rwindexfield(struct aml_value *fld, struct aml_value *val, int mode) +{ + struct aml_value tmp, *ref1, *ref2; + void *tbit, *vbit; + int vpos, bpos, blen; + int indexval; + int sz, len; + + ref2 = fld-v_field.ref2; + ref1 = fld-v_field.ref1; + bpos = fld-v_field.bitpos; + blen = fld-v_field.bitlen; + + memset(tmp, 0, sizeof(tmp)); + tmp.refcnt = 99; + + /* Get field access size */ + switch (AML_FIELD_ACCESS(fld-v_field.flags)) { + case AML_FIELD_WORDACC: + sz = 2; + break; + case AML_FIELD_DWORDACC: + sz = 4; + break; + case AML_FIELD_QWORDACC: + sz = 8; + break; + default: + sz = 1; + break; + } + + if (blen aml_intlen) { + if (mode == ACPI_IOREAD) { + /* Read from a large field: create buffer */ + _aml_setvalue(val, AML_OBJTYPE_BUFFER, + (blen + 7) 3, 0); + } + vbit = val-v_buffer; + } else { + if (mode == ACPI_IOREAD) { + /* Read from a short field: initialize integer */ + _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); + } + vbit = val-v_integer; + } + tbit = tmp.v_integer; + vpos = 0; + + indexval = (bpos 3) ~(sz - 1); + bpos = bpos - (indexval 3); + + while (blen 0) { + len = min(blen, (sz 3) - bpos); + + /* Write index register */ + _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, indexval, 0); + aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); + indexval += sz; + + /* Read/write data register */ + _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, 0, 0); + if (mode == ACPI_IOWRITE) + aml_bufcpy(tbit, 0, vbit, vpos, len); + aml_rwfield(ref1, bpos, len, tmp, mode); + if (mode == ACPI_IOREAD) + aml_bufcpy(vbit, vpos, tbit, 0, len); + vpos += len; + blen -= len; + bpos = 0; + } +} + void aml_rwfield(struct aml_value *fld, int bpos, int blen, struct aml_value *val, int mode) @@ -2356,10 +2432,7 @@ aml_rwfield(struct aml_value *fld, int b memset(tmp, 0, sizeof(tmp)); aml_addref(tmp, fld.write); if (fld-v_field.type == AMLOP_INDEXFIELD) { - _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, fld-v_field.ref3, 0); - aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); - aml_rwfield(ref1, fld-v_field.bitpos, fld-v_field.bitlen, - val, mode); + aml_rwindexfield(fld, val, mode); } else if (fld-v_field.type == AMLOP_BANKFIELD) { _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, fld-v_field.ref3, 0); aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); @@ -2414,10 +2487,6 @@ aml_createfield(struct aml_value *field, opcode == AMLOP_BANKFIELD) ? AML_OBJTYPE_FIELDUNIT : AML_OBJTYPE_BUFFERFIELD; - if (opcode == AMLOP_INDEXFIELD) { - indexval = bpos 3; - bpos = 7; - } if (field-type == AML_OBJTYPE_BUFFERFIELD data-type != AML_OBJTYPE_BUFFER)
Re: Somewhat important ACPI diff
Mark Kettenis mark.kette...@xs4all.nl writes: As diagnosed by some other people (armani@, jcs@?) a while ago, our code to deal with IndexField() operators in our AML interpreter is quite broken. It works for fields that are less than a byte in size, but anything else is pretty much completely busted. I wouldn't be surprised if this is the cause of many ACPI-related problems. One that comes to mind are the ridiculous temperatures reported by acpitz(4) that have been plaguing us since basically forever. I don't have a lot of machines that have AML with IndexField() operators. I've verified that those return the correct values, but this defenitely could use further testing on a wide variety of i386/amd64 hardware please. Index: dsdt.c === RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v retrieving revision 1.200 diff -u -p -r1.200 dsdt.c --- dsdt.c10 Apr 2013 01:35:55 - 1.200 +++ dsdt.c20 May 2013 16:55:27 - @@ -2221,8 +2221,9 @@ aml_evalhid(struct aml_node *node, struc return (0); } -void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); void aml_rwgas(struct aml_value *, int, int, struct aml_value *, int, int); +void aml_rwindexfield(struct aml_value *, struct aml_value *val, int); +void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); /* Get PCI address for opregion objects */ int @@ -2341,6 +2342,81 @@ aml_rwgas(struct aml_value *rgn, int bpo aml_freevalue(tmp); } + +void +aml_rwindexfield(struct aml_value *fld, struct aml_value *val, int mode) +{ + struct aml_value tmp, *ref1, *ref2; + void *tbit, *vbit; + int vpos, bpos, blen; + int indexval; + int sz, len; + + ref2 = fld-v_field.ref2; + ref1 = fld-v_field.ref1; + bpos = fld-v_field.bitpos; + blen = fld-v_field.bitlen; + + memset(tmp, 0, sizeof(tmp)); + tmp.refcnt = 99; + + /* Get field access size */ + switch (AML_FIELD_ACCESS(fld-v_field.flags)) { + case AML_FIELD_WORDACC: + sz = 2; + break; + case AML_FIELD_DWORDACC: + sz = 4; + break; + case AML_FIELD_QWORDACC: + sz = 8; + break; + default: + sz = 1; + break; + } + + if (blen aml_intlen) { + if (mode == ACPI_IOREAD) { + /* Read from a large field: create buffer */ + _aml_setvalue(val, AML_OBJTYPE_BUFFER, + (blen + 7) 3, 0); + } + vbit = val-v_buffer; + } else { + if (mode == ACPI_IOREAD) { + /* Read from a short field: initialize integer */ + _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); + } + vbit = val-v_integer; + } + tbit = tmp.v_integer; + vpos = 0; + + indexval = (bpos 3) ~(sz - 1); + bpos = bpos - (indexval 3); + + while (blen 0) { + len = min(blen, (sz 3) - bpos); + + /* Write index register */ + _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, indexval, 0); + aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); + indexval += sz; + + /* Read/write data register */ + _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, 0, 0); + if (mode == ACPI_IOWRITE) + aml_bufcpy(tbit, 0, vbit, vpos, len); + aml_rwfield(ref1, bpos, len, tmp, mode); + if (mode == ACPI_IOREAD) + aml_bufcpy(vbit, vpos, tbit, 0, len); + vpos += len; + blen -= len; + bpos = 0; + } +} + void aml_rwfield(struct aml_value *fld, int bpos, int blen, struct aml_value *val, int mode) @@ -2356,10 +2432,7 @@ aml_rwfield(struct aml_value *fld, int b memset(tmp, 0, sizeof(tmp)); aml_addref(tmp, fld.write); if (fld-v_field.type == AMLOP_INDEXFIELD) { - _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, fld-v_field.ref3, 0); - aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); - aml_rwfield(ref1, fld-v_field.bitpos, fld-v_field.bitlen, - val, mode); + aml_rwindexfield(fld, val, mode); } else if (fld-v_field.type == AMLOP_BANKFIELD) { _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, fld-v_field.ref3, 0); aml_rwfield(ref2, 0, aml_intlen, tmp, ACPI_IOWRITE); @@ -2414,10 +2487,6 @@ aml_createfield(struct aml_value *field, opcode == AMLOP_BANKFIELD) ? AML_OBJTYPE_FIELDUNIT : AML_OBJTYPE_BUFFERFIELD; - if (opcode == AMLOP_INDEXFIELD) { - indexval = bpos 3; - bpos = 7; - } if (field-type == AML_OBJTYPE_BUFFERFIELD data-type !=
Re: Somewhat important ACPI diff
On Mon, May 20, 2013 at 06:57:56PM +0200, Mark Kettenis wrote: As diagnosed by some other people (armani@, jcs@?) a while ago, our code to deal with IndexField() operators in our AML interpreter is quite broken. It works for fields that are less than a byte in size, but anything else is pretty much completely busted. I wouldn't be surprised if this is the cause of many ACPI-related problems. One that comes to mind are the ridiculous temperatures reported by acpitz(4) that have been plaguing us since basically forever. I don't have a lot of machines that have AML with IndexField() operators. I've verified that those return the correct values, but this defenitely could use further testing on a wide variety of i386/amd64 hardware please. No regressions on Dell XPS 13 (L321X). hw.sensors.acpitz0.temp0 and hw.sensors.acpitz1.temp0 still go from a normal reading (64 degC) to a somewhat strange reading (27.80 degC) after suspend/resume. A reboot is needed to get the normal temperature reading back. hw.sensors.cpu{0-3}.temp0 continue to output correct readings post suspend/resume. -- James Turner
Re: Somewhat important ACPI diff
On Mon, May 20, 2013 at 06:57:56PM +0200, Mark Kettenis wrote: As diagnosed by some other people (armani@, jcs@?) a while ago, our code to deal with IndexField() operators in our AML interpreter is quite broken. It works for fields that are less than a byte in size, but anything else is pretty much completely busted. I wouldn't be surprised if this is the cause of many ACPI-related problems. One that comes to mind are the ridiculous temperatures reported by acpitz(4) that have been plaguing us since basically forever. I don't have a lot of machines that have AML with IndexField() operators. I've verified that those return the correct values, but this defenitely could use further testing on a wide variety of i386/amd64 hardware please. 6 amd64 boxes checked. 3 laptops, 3 non-laptops. intel procs (core and atom) amd procs. Various vintages, nothing more recent than 12 months or so. No regressions seen. Ken
Re: Somewhat important ACPI diff
On Mon, May 20, 2013 at 06:57:56PM +0200, Mark Kettenis wrote: As diagnosed by some other people (armani@, jcs@?) a while ago, our code to deal with IndexField() operators in our AML interpreter is quite broken. It works for fields that are less than a byte in size, but anything else is pretty much completely busted. I wouldn't be surprised if this is the cause of many ACPI-related problems. One that comes to mind are the ridiculous temperatures reported by acpitz(4) that have been plaguing us since basically forever. I don't have a lot of machines that have AML with IndexField() operators. I've verified that those return the correct values, but this defenitely could use further testing on a wide variety of i386/amd64 hardware please. Asus UX31E ultrabook here. This patch fixes kernel panics on boot in acpivout (get_bcl()), panics on AC plug/unplug, and battery information is now present in sysctl hw. Suspend/resume also gets further but still panics. Thanks for the patch!