Skip to content

Commit

Permalink
Hardware: Enable firmware waking vector for both 32-bit and 64-bit FACS.
Browse files Browse the repository at this point in the history
The root cause of the reported bug might be one of the followings:
1. BIOS may favor the 64-bit firmware waking vector address when the
   version of the FACS is greater than 0 and Linux currently only supports
   resuming from the real mode, so the 64-bit firmware waking vector has
   never been set and might be invalid to BIOS while the commit enables
   higher version FACS.
2. BIOS may favor the FACS reported via the "FIRMWARE_CTRL" field in the
   FADT while the commit doesn't set the firmware waking vector address of
   the FACS reported by "FIRMWARE_CTRL", it only sets the firware waking
   vector address of the FACS reported by "X_FIRMWARE_CTRL".

This patch excludes the cases that can trigger the bugs caused by the root
cause 2.

There is no handshaking mechanism can be used by OSPM to tell BIOS which
FACS is currently used. Thus the FACS reported by "FIRMWARE_CTRL" may still
be used by BIOS and the 0 value of the 32-bit firmware waking vector might
trigger such failure.

This patch enables the firmware waking vectors for both 32bit/64bit FACS
tables in order to ensure we can exclude the cases that trigger the bugs
caused by the root cause 2. The exclusion is split into 2 commits so that
if it turns out not to be necessary, this single commit can be reverted
without affecting the useful one. Lv Zheng.

Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=74021
Reported-and-tested-by: Oswald Buddenhagen <ossi@kde.org>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
  • Loading branch information
Lv Zheng committed May 30, 2014
1 parent f7b86f3 commit 368eb60
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 18 deletions.
73 changes: 63 additions & 10 deletions source/components/hardware/hwxfsleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@

/* Local prototypes */

static ACPI_STATUS
AcpiHwSetFirmwareWakingVector (
ACPI_TABLE_FACS *Facs,
ACPI_PHYSICAL_ADDRESS PhysicalAddress,
ACPI_PHYSICAL_ADDRESS PhysicalAddress64);

static ACPI_STATUS
AcpiHwSleepDispatch (
UINT8 SleepState,
Expand Down Expand Up @@ -155,9 +161,10 @@ static ACPI_SLEEP_FUNCTIONS AcpiSleepDispatch[] =
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
* FUNCTION: AcpiSetFirmwareWakingVector
* FUNCTION: AcpiHwSetFirmwareWakingVector
*
* PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode
* PARAMETERS: Facs - Pointer to FACS table
* PhysicalAddress - 32-bit physical address of ACPI real mode
* entry point
* PhysicalAddress64 - 64-bit physical address of ACPI protected
* entry point
Expand All @@ -168,12 +175,13 @@ static ACPI_SLEEP_FUNCTIONS AcpiSleepDispatch[] =
*
******************************************************************************/

ACPI_STATUS
AcpiSetFirmwareWakingVector (
static ACPI_STATUS
AcpiHwSetFirmwareWakingVector (
ACPI_TABLE_FACS *Facs,
ACPI_PHYSICAL_ADDRESS PhysicalAddress,
ACPI_PHYSICAL_ADDRESS PhysicalAddress64)
{
ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector);
ACPI_FUNCTION_TRACE (AcpiHwSetFirmwareWakingVector);


/*
Expand All @@ -186,27 +194,72 @@ AcpiSetFirmwareWakingVector (

/* Set the 32-bit vector */

AcpiGbl_FACS->FirmwareWakingVector = (UINT32) PhysicalAddress;
Facs->FirmwareWakingVector = (UINT32) PhysicalAddress;

if (AcpiGbl_FACS->Length > 32)
if (Facs->Length > 32)
{
if (AcpiGbl_FACS->Version >= 1)
if (Facs->Version >= 1)
{
/* Set the 64-bit vector */

AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress64;
Facs->XFirmwareWakingVector = PhysicalAddress64;
}
else
{
/* Clear the 64-bit vector if it exists */

AcpiGbl_FACS->XFirmwareWakingVector = 0;
Facs->XFirmwareWakingVector = 0;
}
}

return_ACPI_STATUS (AE_OK);
}


/*******************************************************************************
*
* FUNCTION: AcpiSetFirmwareWakingVector
*
* PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode
* entry point
* PhysicalAddress64 - 64-bit physical address of ACPI protected
* entry point
*
* RETURN: Status
*
* DESCRIPTION: Sets the FirmwareWakingVector fields of the FACS
*
******************************************************************************/

ACPI_STATUS
AcpiSetFirmwareWakingVector (
ACPI_PHYSICAL_ADDRESS PhysicalAddress,
ACPI_PHYSICAL_ADDRESS PhysicalAddress64)
{

ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector);

/* If Hardware Reduced flag is set, there is no FACS */

if (AcpiGbl_ReducedHardware)
{
return (AE_OK);
}

if (AcpiGbl_Facs32)
{
(void) AcpiHwSetFirmwareWakingVector (AcpiGbl_Facs32,
PhysicalAddress, PhysicalAddress64);
}
if (AcpiGbl_Facs64)
{
(void) AcpiHwSetFirmwareWakingVector (AcpiGbl_Facs64,
PhysicalAddress, PhysicalAddress64);
}

return_ACPI_STATUS (AE_OK);
}

ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector)


Expand Down
13 changes: 5 additions & 8 deletions source/components/tables/tbutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,6 @@ ACPI_STATUS
AcpiTbInitializeFacs (
void)
{
ACPI_TABLE_FACS *Facs32;
ACPI_TABLE_FACS *Facs64;


/* If Hardware Reduced flag is set, there is no FACS */

Expand All @@ -162,21 +159,21 @@ AcpiTbInitializeFacs (
}

(void) AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS,
ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs32));
ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_Facs32));
(void) AcpiGetTableByIndex (ACPI_TABLE_INDEX_X_FACS,
ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs64));
if (!Facs32 && !Facs64)
ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_Facs64));
if (!AcpiGbl_Facs32 && !AcpiGbl_Facs64)
{
return (AE_NO_MEMORY);
}

if (AcpiGbl_Use32BitFacsAddresses)
{
AcpiGbl_FACS = Facs32 ? Facs32 : Facs64;
AcpiGbl_FACS = AcpiGbl_Facs32 ? AcpiGbl_Facs32 : AcpiGbl_Facs64;
}
else
{
AcpiGbl_FACS = Facs64 ? Facs64 : Facs32;
AcpiGbl_FACS = AcpiGbl_Facs64 ? AcpiGbl_Facs64 : AcpiGbl_Facs32;
}

return (AE_OK);
Expand Down
2 changes: 2 additions & 0 deletions source/include/acglobal.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ ACPI_GLOBAL (ACPI_TABLE_HEADER, AcpiGbl_OriginalDsdtHeader);

#if (!ACPI_REDUCED_HARDWARE)
ACPI_GLOBAL (ACPI_TABLE_FACS *, AcpiGbl_FACS);
ACPI_GLOBAL (ACPI_TABLE_FACS *, AcpiGbl_Facs32);
ACPI_GLOBAL (ACPI_TABLE_FACS *, AcpiGbl_Facs64);

#endif /* !ACPI_REDUCED_HARDWARE */

Expand Down

0 comments on commit 368eb60

Please sign in to comment.