:p
atchew
Login
Fixes and improvements to GenericWatchdogDxe. PR: https://github.com/tianocore/edk2/pull/5176 Rebecca Cran (3): ArmPkg: Update GenericWatchdogDxe to allow setting full 48-bit offset ArmPkg: Introduce global mTimerPeriod and remove calculation ArmPkg: Disable watchdog interaction after exiting boot services ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h | 6 ++- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 60 +++++++++++++++++------------- 2 files changed, 40 insertions(+), 26 deletions(-) -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#113209): https://edk2.groups.io/g/devel/message/113209 Mute This Topic: https://groups.io/mt/103537817/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
The generic watchdog offset register is 48 bits wide, and can be set by performing two 32-bit writes. Add support for writing the high 16 bits of the offset register and update the signature of the WatchdogWriteOffsetRegister function to take a UINT64 value. Signed-off-by: Rebecca Cran <rebecca@os.amperecomputing.com> --- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h | 6 +++++- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 14 +++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h index XXXXXXX..XXXXXXX 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h @@ -XXX,XX +XXX,XX @@ /** @file * +* Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> * Copyright (c) 2013-2017, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * +* See Generic Watchdog specification in Arm Base System Architecture 1.0C: +* https://developer.arm.com/documentation/den0094/c/ **/ #ifndef GENERIC_WATCHDOG_H_ @@ -XXX,XX +XXX,XX @@ // Control Frame: #define GENERIC_WDOG_CONTROL_STATUS_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x000) -#define GENERIC_WDOG_OFFSET_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x008) +#define GENERIC_WDOG_OFFSET_REG_LOW ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x008) +#define GENERIC_WDOG_OFFSET_REG_HIGH ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x00C) #define GENERIC_WDOG_COMPARE_VALUE_REG_LOW ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x010) #define GENERIC_WDOG_COMPARE_VALUE_REG_HIGH ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x014) diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c index XXXXXXX..XXXXXXX 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c @@ -XXX,XX +XXX,XX @@ /** @file * +* Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> * Copyright (c) 2013-2018, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent @@ -XXX,XX +XXX,XX @@ STATIC UINTN mTimerFrequencyHz = 0; It is therefore stored here. 0 means the timer is not running. */ STATIC UINT64 mNumTimerTicks = 0; +#define MAX_UINT48 0xFFFFFFFFFFFFULL + STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol; STATIC EFI_WATCHDOG_TIMER_NOTIFY mWatchdogNotify; STATIC VOID WatchdogWriteOffsetRegister ( - UINT32 Value + UINT64 Value ) { - MmioWrite32 (GENERIC_WDOG_OFFSET_REG, Value); + MmioWrite32 (GENERIC_WDOG_OFFSET_REG_LOW, Value & MAX_UINT32); + MmioWrite32 (GENERIC_WDOG_OFFSET_REG_HIGH, (Value >> 32) & MAX_UINT16); } STATIC @@ -XXX,XX +XXX,XX @@ WatchdogSetTimerPeriod ( /* If the number of required ticks is greater than the max the watchdog's offset register (WOR) can hold, we need to manually compute and set the compare register (WCV) */ - if (mNumTimerTicks > MAX_UINT32) { + if (mNumTimerTicks > MAX_UINT48) { /* We need to enable the watchdog *before* writing to the compare register, because enabling the watchdog causes an "explicit refresh", which clobbers the compare register (WCV). In order to make sure this doesn't trigger an interrupt, set the offset to max. */ - WatchdogWriteOffsetRegister (MAX_UINT32); + WatchdogWriteOffsetRegister (MAX_UINT48); WatchdogEnable (); SystemCount = ArmGenericTimerGetSystemCount (); WatchdogWriteCompareRegister (SystemCount + mNumTimerTicks); } else { - WatchdogWriteOffsetRegister ((UINT32)mNumTimerTicks); + WatchdogWriteOffsetRegister (mNumTimerTicks); WatchdogEnable (); } -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#113210): https://edk2.groups.io/g/devel/message/113210 Mute This Topic: https://groups.io/mt/103537818/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
The calculation of the timer period was broken. Introduce a global mTimerPeriod so the calculation can be removed. Since mTimerFrequencyHz is only used in one place, remove the global and make it a local variable. Do the same with mNumTimerTicks. Signed-off-by: Rebecca Cran <rebecca@os.amperecomputing.com> --- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 36 ++++++++++++++---------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c index XXXXXXX..XXXXXXX 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c @@ -XXX,XX +XXX,XX @@ in a second */ #define TIME_UNITS_PER_SECOND 10000000 -// Tick frequency of the generic timer basis of the generic watchdog. -STATIC UINTN mTimerFrequencyHz = 0; - /* In cases where the compare register was set manually, information about how long the watchdog was asked to wait cannot be retrieved from hardware. It is therefore stored here. 0 means the timer is not running. */ -STATIC UINT64 mNumTimerTicks = 0; +STATIC UINT64 mTimerPeriod = 0; #define MAX_UINT48 0xFFFFFFFFFFFFULL @@ -XXX,XX +XXX,XX @@ WatchdogExitBootServicesEvent ( ) { WatchdogDisable (); - mNumTimerTicks = 0; + mNumTimerTicks = 0; + mExitedBootServices = TRUE; } /* This function is called when the watchdog's first signal (WS0) goes high. @@ -XXX,XX +XXX,XX @@ WatchdogInterruptHandler ( ) { STATIC CONST CHAR16 ResetString[] = L"The generic watchdog timer ran out."; - UINT64 TimerPeriod; WatchdogDisable (); @@ -XXX,XX +XXX,XX @@ WatchdogInterruptHandler ( // the timer period plus 1. // if (mWatchdogNotify != NULL) { - TimerPeriod = ((TIME_UNITS_PER_SECOND / mTimerFrequencyHz) * mNumTimerTicks); - mWatchdogNotify (TimerPeriod + 1); + mWatchdogNotify (mTimerPeriod + 1); } gRT->ResetSystem ( @@ -XXX,XX +XXX,XX @@ WatchdogSetTimerPeriod ( IN UINT64 TimerPeriod // In 100ns units ) { - UINTN SystemCount; + UINTN SystemCount; + UINT64 TimerFrequencyHz; + UINT64 NumTimerTicks; // if TimerPeriod is 0, this is a request to stop the watchdog. if (TimerPeriod == 0) { - mNumTimerTicks = 0; + mTimerPeriod = 0; WatchdogDisable (); return EFI_SUCCESS; } // Work out how many timer ticks will equate to TimerPeriod - mNumTimerTicks = (mTimerFrequencyHz * TimerPeriod) / TIME_UNITS_PER_SECOND; + TimerFrequencyHz = ArmGenericTimerGetTimerFreq (); + ASSERT (TimerFrequencyHz != 0); + mTimerPeriod = TimerPeriod; + NumTimerTicks = (TimerFrequencyHz * TimerPeriod) / TIME_UNITS_PER_SECOND; /* If the number of required ticks is greater than the max the watchdog's offset register (WOR) can hold, we need to manually compute and set the compare register (WCV) */ - if (mNumTimerTicks > MAX_UINT48) { + if (NumTimerTicks > MAX_UINT48) { /* We need to enable the watchdog *before* writing to the compare register, because enabling the watchdog causes an "explicit refresh", which clobbers the compare register (WCV). In order to make sure this doesn't @@ -XXX,XX +XXX,XX @@ WatchdogSetTimerPeriod ( WatchdogWriteOffsetRegister (MAX_UINT48); WatchdogEnable (); SystemCount = ArmGenericTimerGetSystemCount (); - WatchdogWriteCompareRegister (SystemCount + mNumTimerTicks); + WatchdogWriteCompareRegister (SystemCount + NumTimerTicks); } else { - WatchdogWriteOffsetRegister (mNumTimerTicks); + WatchdogWriteOffsetRegister (NumTimerTicks); WatchdogEnable (); } @@ -XXX,XX +XXX,XX @@ WatchdogGetTimerPeriod ( return EFI_INVALID_PARAMETER; } - *TimerPeriod = ((TIME_UNITS_PER_SECOND / mTimerFrequencyHz) * mNumTimerTicks); + *TimerPeriod = mTimerPeriod; return EFI_SUCCESS; } @@ -XXX,XX +XXX,XX @@ GenericWatchdogEntry ( This will avoid conflicts with the universal watchdog */ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid); - mTimerFrequencyHz = ArmGenericTimerGetTimerFreq (); - ASSERT (mTimerFrequencyHz != 0); - // Install interrupt handler Status = mInterruptProtocol->RegisterInterruptSource ( mInterruptProtocol, @@ -XXX,XX +XXX,XX @@ GenericWatchdogEntry ( ); ASSERT_EFI_ERROR (Status); - mNumTimerTicks = 0; + mTimerPeriod = 0; WatchdogDisable (); return EFI_SUCCESS; -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#113211): https://edk2.groups.io/g/devel/message/113211 Mute This Topic: https://groups.io/mt/103537819/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
Update GenericWatchdogDxe to disable watchdog interaction after exiting boot services. Also, move the mEfiExitBootServicesEvent event to the top of the file with the other static variables. Signed-off-by: Rebecca Cran <rebecca@os.amperecomputing.com> --- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c index XXXXXXX..XXXXXXX 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c @@ -XXX,XX +XXX,XX @@ It is therefore stored here. 0 means the timer is not running. */ STATIC UINT64 mTimerPeriod = 0; +/* disables watchdog interaction after Exit Boot Services */ +STATIC BOOLEAN mExitedBootServices = FALSE; + #define MAX_UINT48 0xFFFFFFFFFFFFULL STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol; STATIC EFI_WATCHDOG_TIMER_NOTIFY mWatchdogNotify; +STATIC EFI_EVENT mEfiExitBootServicesEvent; STATIC VOID @@ -XXX,XX +XXX,XX @@ WatchdogSetTimerPeriod ( UINT64 TimerFrequencyHz; UINT64 NumTimerTicks; - // if TimerPeriod is 0, this is a request to stop the watchdog. + // If we've exited Boot Services but TimerPeriod isn't zero, this + // indicates that the caller is doing something wrong. + if (mExitedBootServices && (TimerPeriod != 0)) { + return EFI_DEVICE_ERROR; + } + + // If TimerPeriod is 0 this is a request to stop the watchdog. if (TimerPeriod == 0) { mTimerPeriod = 0; WatchdogDisable (); @@ -XXX,XX +XXX,XX @@ STATIC EFI_WATCHDOG_TIMER_ARCH_PROTOCOL mWatchdogTimer = { WatchdogGetTimerPeriod }; -STATIC EFI_EVENT mEfiExitBootServicesEvent; - EFI_STATUS EFIAPI GenericWatchdogEntry ( -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#113212): https://edk2.groups.io/g/devel/message/113212 Mute This Topic: https://groups.io/mt/103537820/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
Fixes and improvements to GenericWatchdogDxe. PR: https://github.com/tianocore/edk2/pull/5176 Changes between v3 and v4: - Check Interface Identification Register for architecture revision before setting the high offset register value. - Use @par for reference. - Move setting of EBS flag from patch 2/3 to 3/3. - Disable the watchdog in the case that EBS has been called and the timer period is non-zero. Rebecca Cran (3): ArmPkg: Update GenericWatchdogDxe to allow setting full 48-bit offset ArmPkg: Introduce global mTimerPeriod and remove calculation ArmPkg: Disable watchdog interaction after exiting boot services ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h | 11 +++- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 69 +++++++++++++------- 2 files changed, 54 insertions(+), 26 deletions(-) -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114086): https://edk2.groups.io/g/devel/message/114086 Mute This Topic: https://groups.io/mt/103832317/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
The generic watchdog offset register is 48 bits wide, and can be set by performing two 32-bit writes. Add support for writing the high 16 bits of the offset register and update the signature of the WatchdogWriteOffsetRegister function to take a UINT64 value. Signed-off-by: Rebecca Cran <rebecca@os.amperecomputing.com> --- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h | 11 +++++++++- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 23 +++++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h index XXXXXXX..XXXXXXX 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h @@ -XXX,XX +XXX,XX @@ /** @file * +* Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> * Copyright (c) 2013-2017, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * +* @par Reference(s): +* - Generic Watchdog specification in Arm Base System Architecture 1.0C: +* https://developer.arm.com/documentation/den0094/c/ **/ #ifndef GENERIC_WATCHDOG_H_ @@ -XXX,XX +XXX,XX @@ // Control Frame: #define GENERIC_WDOG_CONTROL_STATUS_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x000) -#define GENERIC_WDOG_OFFSET_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x008) +#define GENERIC_WDOG_OFFSET_REG_LOW ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x008) +#define GENERIC_WDOG_OFFSET_REG_HIGH ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x00C) #define GENERIC_WDOG_COMPARE_VALUE_REG_LOW ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x010) #define GENERIC_WDOG_COMPARE_VALUE_REG_HIGH ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x014) +#define GENERIC_WDOG_IID_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0xFCC) // Values of bit 0 of the Control/Status Register #define GENERIC_WDOG_ENABLED 1 #define GENERIC_WDOG_DISABLED 0 +#define GENERIC_WDOG_IID_REV_SHIFT 16 +#define GENERIC_WDOG_IID_REV_MASK 0xF + #endif // GENERIC_WATCHDOG_H_ diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c index XXXXXXX..XXXXXXX 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c @@ -XXX,XX +XXX,XX @@ /** @file * +* Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> * Copyright (c) 2013-2018, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent @@ -XXX,XX +XXX,XX @@ STATIC UINTN mTimerFrequencyHz = 0; It is therefore stored here. 0 means the timer is not running. */ STATIC UINT64 mNumTimerTicks = 0; +STATIC UINT8 WatchdogRevision; + +#define MAX_UINT48 0xFFFFFFFFFFFFULL + STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol; STATIC EFI_WATCHDOG_TIMER_NOTIFY mWatchdogNotify; STATIC VOID WatchdogWriteOffsetRegister ( - UINT32 Value + UINT64 Value ) { - MmioWrite32 (GENERIC_WDOG_OFFSET_REG, Value); + MmioWrite32 (GENERIC_WDOG_OFFSET_REG_LOW, Value & MAX_UINT32); + if (WatchdogRevision == 1) { + MmioWrite32 (GENERIC_WDOG_OFFSET_REG_HIGH, (Value >> 32) & MAX_UINT16); + } } STATIC @@ -XXX,XX +XXX,XX @@ WatchdogSetTimerPeriod ( /* If the number of required ticks is greater than the max the watchdog's offset register (WOR) can hold, we need to manually compute and set the compare register (WCV) */ - if (mNumTimerTicks > MAX_UINT32) { + if (mNumTimerTicks > MAX_UINT48) { /* We need to enable the watchdog *before* writing to the compare register, because enabling the watchdog causes an "explicit refresh", which clobbers the compare register (WCV). In order to make sure this doesn't trigger an interrupt, set the offset to max. */ - WatchdogWriteOffsetRegister (MAX_UINT32); + WatchdogWriteOffsetRegister (MAX_UINT48); WatchdogEnable (); SystemCount = ArmGenericTimerGetSystemCount (); WatchdogWriteCompareRegister (SystemCount + mNumTimerTicks); } else { - WatchdogWriteOffsetRegister ((UINT32)mNumTimerTicks); + WatchdogWriteOffsetRegister (mNumTimerTicks); WatchdogEnable (); } @@ -XXX,XX +XXX,XX @@ GenericWatchdogEntry ( { EFI_STATUS Status; EFI_HANDLE Handle; + UINT32 WatchdogIId; Status = gBS->LocateProtocol ( &gHardwareInterrupt2ProtocolGuid, @@ -XXX,XX +XXX,XX @@ GenericWatchdogEntry ( ); ASSERT_EFI_ERROR (Status); - mNumTimerTicks = 0; + mNumTimerTicks = 0; + WatchdogIId = MmioRead32 (GENERIC_WDOG_IID_REG); + WatchdogRevision = (WatchdogIId >> GENERIC_WDOG_IID_REV_SHIFT) & GENERIC_WDOG_IID_REV_MASK; WatchdogDisable (); return EFI_SUCCESS; -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114088): https://edk2.groups.io/g/devel/message/114088 Mute This Topic: https://groups.io/mt/103832319/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
The calculation of the timer period was broken. Introduce a global mTimerPeriod so the calculation can be removed. Since mTimerFrequencyHz is only used in one place, remove the global and make it a local variable. Do the same with mNumTimerTicks. Signed-off-by: Rebecca Cran <rebecca@os.amperecomputing.com> --- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 35 +++++++++----------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c index XXXXXXX..XXXXXXX 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c @@ -XXX,XX +XXX,XX @@ in a second */ #define TIME_UNITS_PER_SECOND 10000000 -// Tick frequency of the generic timer basis of the generic watchdog. -STATIC UINTN mTimerFrequencyHz = 0; - /* In cases where the compare register was set manually, information about how long the watchdog was asked to wait cannot be retrieved from hardware. It is therefore stored here. 0 means the timer is not running. */ -STATIC UINT64 mNumTimerTicks = 0; +STATIC UINT64 mTimerPeriod = 0; STATIC UINT8 WatchdogRevision; @@ -XXX,XX +XXX,XX @@ WatchdogExitBootServicesEvent ( ) { WatchdogDisable (); - mNumTimerTicks = 0; + mTimerPeriod = 0; } /* This function is called when the watchdog's first signal (WS0) goes high. @@ -XXX,XX +XXX,XX @@ WatchdogInterruptHandler ( ) { STATIC CONST CHAR16 ResetString[] = L"The generic watchdog timer ran out."; - UINT64 TimerPeriod; WatchdogDisable (); @@ -XXX,XX +XXX,XX @@ WatchdogInterruptHandler ( // the timer period plus 1. // if (mWatchdogNotify != NULL) { - TimerPeriod = ((TIME_UNITS_PER_SECOND / mTimerFrequencyHz) * mNumTimerTicks); - mWatchdogNotify (TimerPeriod + 1); + mWatchdogNotify (mTimerPeriod + 1); } gRT->ResetSystem ( @@ -XXX,XX +XXX,XX @@ WatchdogSetTimerPeriod ( IN UINT64 TimerPeriod // In 100ns units ) { - UINTN SystemCount; + UINTN SystemCount; + UINT64 TimerFrequencyHz; + UINT64 NumTimerTicks; // if TimerPeriod is 0, this is a request to stop the watchdog. if (TimerPeriod == 0) { - mNumTimerTicks = 0; + mTimerPeriod = 0; WatchdogDisable (); return EFI_SUCCESS; } // Work out how many timer ticks will equate to TimerPeriod - mNumTimerTicks = (mTimerFrequencyHz * TimerPeriod) / TIME_UNITS_PER_SECOND; + TimerFrequencyHz = ArmGenericTimerGetTimerFreq (); + ASSERT (TimerFrequencyHz != 0); + mTimerPeriod = TimerPeriod; + NumTimerTicks = (TimerFrequencyHz * TimerPeriod) / TIME_UNITS_PER_SECOND; /* If the number of required ticks is greater than the max the watchdog's offset register (WOR) can hold, we need to manually compute and set the compare register (WCV) */ - if (mNumTimerTicks > MAX_UINT48) { + if (NumTimerTicks > MAX_UINT48) { /* We need to enable the watchdog *before* writing to the compare register, because enabling the watchdog causes an "explicit refresh", which clobbers the compare register (WCV). In order to make sure this doesn't @@ -XXX,XX +XXX,XX @@ WatchdogSetTimerPeriod ( WatchdogWriteOffsetRegister (MAX_UINT48); WatchdogEnable (); SystemCount = ArmGenericTimerGetSystemCount (); - WatchdogWriteCompareRegister (SystemCount + mNumTimerTicks); + WatchdogWriteCompareRegister (SystemCount + NumTimerTicks); } else { - WatchdogWriteOffsetRegister (mNumTimerTicks); + WatchdogWriteOffsetRegister (NumTimerTicks); WatchdogEnable (); } @@ -XXX,XX +XXX,XX @@ WatchdogGetTimerPeriod ( return EFI_INVALID_PARAMETER; } - *TimerPeriod = ((TIME_UNITS_PER_SECOND / mTimerFrequencyHz) * mNumTimerTicks); + *TimerPeriod = mTimerPeriod; return EFI_SUCCESS; } @@ -XXX,XX +XXX,XX @@ GenericWatchdogEntry ( This will avoid conflicts with the universal watchdog */ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid); - mTimerFrequencyHz = ArmGenericTimerGetTimerFreq (); - ASSERT (mTimerFrequencyHz != 0); - // Install interrupt handler Status = mInterruptProtocol->RegisterInterruptSource ( mInterruptProtocol, @@ -XXX,XX +XXX,XX @@ GenericWatchdogEntry ( ); ASSERT_EFI_ERROR (Status); - mNumTimerTicks = 0; WatchdogIId = MmioRead32 (GENERIC_WDOG_IID_REG); WatchdogRevision = (WatchdogIId >> GENERIC_WDOG_IID_REV_SHIFT) & GENERIC_WDOG_IID_REV_MASK; + mTimerPeriod = 0; WatchdogDisable (); return EFI_SUCCESS; -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114087): https://edk2.groups.io/g/devel/message/114087 Mute This Topic: https://groups.io/mt/103832318/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
Update GenericWatchdogDxe to disable watchdog interaction after exiting boot services. Also, move the mEfiExitBootServicesEvent event to the top of the file with the other static variables. Signed-off-by: Rebecca Cran <rebecca@os.amperecomputing.com> --- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c index XXXXXXX..XXXXXXX 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c @@ -XXX,XX +XXX,XX @@ STATIC UINT64 mTimerPeriod = 0; STATIC UINT8 WatchdogRevision; +/* disables watchdog interaction after Exit Boot Services */ +STATIC BOOLEAN mExitedBootServices = FALSE; + #define MAX_UINT48 0xFFFFFFFFFFFFULL STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol; STATIC EFI_WATCHDOG_TIMER_NOTIFY mWatchdogNotify; +STATIC EFI_EVENT mEfiExitBootServicesEvent; STATIC VOID @@ -XXX,XX +XXX,XX @@ WatchdogExitBootServicesEvent ( { WatchdogDisable (); mTimerPeriod = 0; + mExitedBootServices = TRUE; } /* This function is called when the watchdog's first signal (WS0) goes high. @@ -XXX,XX +XXX,XX @@ WatchdogSetTimerPeriod ( UINT64 TimerFrequencyHz; UINT64 NumTimerTicks; - // if TimerPeriod is 0, this is a request to stop the watchdog. + // If we've exited Boot Services but TimerPeriod isn't zero, this + // indicates that the caller is doing something wrong. + if (mExitedBootServices && (TimerPeriod != 0)) { + mTimerPeriod = 0; + WatchdogDisable (); + return EFI_DEVICE_ERROR; + } + + // If TimerPeriod is 0 this is a request to stop the watchdog. if (TimerPeriod == 0) { mTimerPeriod = 0; WatchdogDisable (); @@ -XXX,XX +XXX,XX @@ STATIC EFI_WATCHDOG_TIMER_ARCH_PROTOCOL mWatchdogTimer = { WatchdogGetTimerPeriod }; -STATIC EFI_EVENT mEfiExitBootServicesEvent; - EFI_STATUS EFIAPI GenericWatchdogEntry ( -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114089): https://edk2.groups.io/g/devel/message/114089 Mute This Topic: https://groups.io/mt/103832320/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-