c450c13615f7af0673230041da4216b3de5bc4d3.patch

This patch fixes 2 issues in AccessWidth/BitOffset support and adds
comments to justify the BitOffset/BitWidth style macro usages. Lv Zheng.

This patch introduces ACPI_IS_ALIGNED() macro. Lv Zheng.

The old register descriptors are translated in AcpiTbInitGenericAddress()
with AccessWidth being filled with 0. This breaks code in
AcpiHwGetAccessBitWidth() when the registers are 16-bit IO ports and their
BitWidth fields are filled with 16. The rapid fix is meant to make code
written for AcpiHwGetAccessBitWidth() regression safer before the issue is
correctly fixed from AcpiTbInitGenericAddress(). Reported by
John Baldwin <jhb@freebsd.org>, Fixed by Lv Zheng <lv.zheng@intel.com>,
Tested by Jung-uk Kim <jkim@freebsd.org>.
This commit is contained in:
christos 2016-05-25 18:35:13 +00:00
parent 19ea743456
commit 1c46e02997
2 changed files with 64 additions and 13 deletions

View File

@ -92,16 +92,34 @@ AcpiHwGetAccessBitWidth (
ACPI_GENERIC_ADDRESS *Reg,
UINT8 MaxBitWidth)
{
UINT64 Address;
if (!Reg->AccessWidth)
{
if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
/*
* Detect old register descriptors where only the BitWidth field
* makes senses. The target address is copied to handle possible
* alignment issues.
*/
ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
if (!Reg->BitOffset && Reg->BitWidth &&
ACPI_IS_POWER_OF_TWO (Reg->BitWidth) &&
ACPI_IS_ALIGNED (Reg->BitWidth, 8) &&
ACPI_IS_ALIGNED (Address, Reg->BitWidth))
{
return (32);
return (Reg->BitWidth);
}
else
{
return (MaxBitWidth);
if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
{
return (32);
}
else
{
return (MaxBitWidth);
}
}
}
else
@ -250,7 +268,7 @@ AcpiHwRead (
Index = 0;
while (BitWidth)
{
if (BitOffset > AccessWidth)
if (BitOffset >= AccessWidth)
{
Value32 = 0;
BitOffset -= AccessWidth;
@ -271,6 +289,12 @@ AcpiHwRead (
&Value32, AccessWidth);
}
/*
* Use offset style bit masks because:
* BitOffset < AccessWidth/BitWidth < AccessWidth, and
* AccessWidth is ensured to be less than 32-bits by
* AcpiHwValidateRegister().
*/
if (BitOffset)
{
Value32 &= ACPI_MASK_BITS_BELOW (BitOffset);
@ -282,6 +306,10 @@ AcpiHwRead (
}
}
/*
* Use offset style bit writes because "Index * AccessWidth" is
* ensured to be less than 32-bits by AcpiHwValidateRegister().
*/
ACPI_SET_BITS (Value, Index * AccessWidth,
ACPI_MASK_BITS_ABOVE_32 (AccessWidth), Value32);
@ -352,20 +380,28 @@ AcpiHwWrite (
Index = 0;
while (BitWidth)
{
/*
* Use offset style bit reads because "Index * AccessWidth" is
* ensured to be less than 32-bits by AcpiHwValidateRegister().
*/
NewValue32 = ACPI_GET_BITS (&Value, Index * AccessWidth,
ACPI_MASK_BITS_ABOVE_32 (AccessWidth));
if (BitOffset > AccessWidth)
if (BitOffset >= AccessWidth)
{
BitOffset -= AccessWidth;
}
else
{
/*
* Use offset style bit masks because AccessWidth is ensured
* to be less than 32-bits by AcpiHwValidateRegister() and
* BitOffset/BitWidth is less than AccessWidth here.
*/
if (BitOffset)
{
NewValue32 &= ACPI_MASK_BITS_BELOW (BitOffset);
}
if (BitWidth < AccessWidth)
{
NewValue32 &= ACPI_MASK_BITS_ABOVE (BitWidth);
@ -384,15 +420,20 @@ AcpiHwWrite (
&Value64, AccessWidth);
OldValue32 = (UINT32) Value64;
/*
* Use offset style bit masks because AccessWidth is
* ensured to be less than 32-bits by
* AcpiHwValidateRegister() and BitOffset/BitWidth is
* less than AccessWidth here.
*/
if (BitOffset)
{
OldValue32 &= ACPI_MASK_BITS_ABOVE (BitOffset + 1);
OldValue32 &= ACPI_MASK_BITS_ABOVE (BitOffset);
BitOffset = 0;
}
if (BitWidth < AccessWidth)
{
OldValue32 &= ACPI_MASK_BITS_BELOW (BitWidth - 1);
OldValue32 &= ACPI_MASK_BITS_BELOW (BitWidth);
}
NewValue32 |= OldValue32;
@ -415,15 +456,20 @@ AcpiHwWrite (
Address + Index * ACPI_DIV_8 (AccessWidth),
&OldValue32, AccessWidth);
/*
* Use offset style bit masks because AccessWidth is
* ensured to be less than 32-bits by
* AcpiHwValidateRegister() and BitOffset/BitWidth is
* less than AccessWidth here.
*/
if (BitOffset)
{
OldValue32 &= ACPI_MASK_BITS_ABOVE (BitOffset + 1);
OldValue32 &= ACPI_MASK_BITS_ABOVE (BitOffset);
BitOffset = 0;
}
if (BitWidth < AccessWidth)
{
OldValue32 &= ACPI_MASK_BITS_BELOW (BitWidth - 1);
OldValue32 &= ACPI_MASK_BITS_BELOW (BitWidth);
}
NewValue32 |= OldValue32;
@ -435,6 +481,10 @@ AcpiHwWrite (
}
}
/*
* Index * AccessWidth is ensured to be less than 32-bits by
* AcpiHwValidateRegister().
*/
BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
Index++;
}

View File

@ -266,7 +266,8 @@
/* Generic (power-of-two) rounding */
#define ACPI_IS_POWER_OF_TWO(a) (((a) & ((a) - 1)) == 0)
#define ACPI_IS_ALIGNED(a, s) (((a) & ((s) - 1)) == 0)
#define ACPI_IS_POWER_OF_TWO(a) ACPI_IS_ALIGNED(a, a)
/*
* Bitmask creation