mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-26 12:41:59 +03:00
Kernel: Add RPi Watchdog and use it for system shutdown
The Raspberry Pi hardware doesn't support a proper software-initiated shutdown, so this instead uses the watchdog to reboot to a special partition which the firmware interprets as an immediate halt on shutdown. When running under Qemu, this causes the emulator to exit.
This commit is contained in:
parent
555d301e3b
commit
d9c557d0b4
Notes:
sideshowbarker
2024-07-18 03:35:30 +09:00
Author: https://github.com/BertalanD Commit: https://github.com/SerenityOS/serenity/commit/d9c557d0b4 Pull-request: https://github.com/SerenityOS/serenity/pull/18845 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/FireFox317 Reviewed-by: https://github.com/Hendiadyoin1 Reviewed-by: https://github.com/caoimhebyrne ✅
47
Kernel/Arch/aarch64/RPi/Watchdog.cpp
Normal file
47
Kernel/Arch/aarch64/RPi/Watchdog.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Daniel Bertalan <dani@danielbertalan.dev>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Arch/aarch64/RPi/MMIO.h>
|
||||
#include <Kernel/Arch/aarch64/RPi/Watchdog.h>
|
||||
|
||||
namespace Kernel::RPi {
|
||||
struct WatchdogRegisters {
|
||||
u32 rstc;
|
||||
u32 rsts;
|
||||
u32 wdog;
|
||||
};
|
||||
|
||||
constexpr u32 PASSWORD = 0x5a000000;
|
||||
constexpr u32 RSTS_PARTITION_MASK = 0xfffffaaa;
|
||||
constexpr u32 RSTS_PARTITION_SHUTDOWN = 0x00000555;
|
||||
constexpr u32 RSTC_WRCFG_MASK = 0xffffffcf;
|
||||
constexpr u32 RSTC_WRCFG_FULL_RESET = 0x00000020;
|
||||
|
||||
Watchdog::Watchdog()
|
||||
: m_registers(MMIO::the().peripheral<WatchdogRegisters>(0x10'001c))
|
||||
{
|
||||
}
|
||||
|
||||
Watchdog& Watchdog::the()
|
||||
{
|
||||
static Watchdog watchdog;
|
||||
return watchdog;
|
||||
}
|
||||
|
||||
// This is the same mechanism used by Linux, the ARM Trusted Firmware and U-Boot to trigger a system shutdown.
|
||||
// See e.g. https://github.com/ARM-software/arm-trusted-firmware/blob/dcf430656ca8ef964fa55ad9eb81cf838c7837f2/plat/rpi/common/rpi3_pm.c#L231-L249
|
||||
void Watchdog::system_shutdown()
|
||||
{
|
||||
// The Raspberry Pi hardware doesn't support powering off. Setting the reboot target partition to this
|
||||
// special value will cause the firmware to halt the CPU and put it in a low power state when the watchdog
|
||||
// timer expires. When running under Qemu, this will cause the emulator to exit.
|
||||
m_registers->rsts = PASSWORD | (m_registers->rsts & RSTS_PARTITION_MASK) | RSTS_PARTITION_SHUTDOWN;
|
||||
// Set the timeout to 10 ticks (~150us).
|
||||
m_registers->wdog = PASSWORD | 10;
|
||||
// Start the watchdog.
|
||||
m_registers->rstc = PASSWORD | (m_registers->rstc & RSTC_WRCFG_MASK) | RSTC_WRCFG_FULL_RESET;
|
||||
}
|
||||
}
|
24
Kernel/Arch/aarch64/RPi/Watchdog.h
Normal file
24
Kernel/Arch/aarch64/RPi/Watchdog.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Daniel Bertalan <dani@danielbertalan.dev>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Kernel::RPi {
|
||||
|
||||
struct WatchdogRegisters;
|
||||
|
||||
class Watchdog {
|
||||
public:
|
||||
static Watchdog& the();
|
||||
|
||||
void system_shutdown();
|
||||
|
||||
private:
|
||||
Watchdog();
|
||||
|
||||
WatchdogRegisters volatile* m_registers;
|
||||
};
|
||||
}
|
@ -446,6 +446,7 @@ elseif("${SERENITY_ARCH}" STREQUAL "aarch64")
|
||||
Arch/aarch64/RPi/SDHostController.cpp
|
||||
Arch/aarch64/RPi/Timer.cpp
|
||||
Arch/aarch64/RPi/UART.cpp
|
||||
Arch/aarch64/RPi/Watchdog.cpp
|
||||
)
|
||||
set(SOURCES_RUNNING_WITHOUT_MMU
|
||||
Arch/aarch64/Exceptions.cpp
|
||||
|
@ -9,6 +9,8 @@
|
||||
#if ARCH(X86_64)
|
||||
# include <Kernel/Arch/x86_64/I8042Reboot.h>
|
||||
# include <Kernel/Arch/x86_64/Shutdown.h>
|
||||
#elif ARCH(AARCH64)
|
||||
# include <Kernel/Arch/aarch64/RPi/Watchdog.h>
|
||||
#endif
|
||||
#include <Kernel/FileSystem/FileSystem.h>
|
||||
#include <Kernel/FileSystem/SysFS/Subsystems/Kernel/PowerStateSwitch.h>
|
||||
@ -101,6 +103,8 @@ void SysFSPowerStateSwitchNode::poweroff()
|
||||
#if ARCH(X86_64)
|
||||
qemu_shutdown();
|
||||
virtualbox_shutdown();
|
||||
#elif ARCH(AARCH64)
|
||||
RPi::Watchdog::the().system_shutdown();
|
||||
#endif
|
||||
dbgln("shutdown attempts failed, applications will stop responding.");
|
||||
dmesgln("Shutdown can't be completed. It's safe to turn off the computer!");
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <Kernel/Arch/Processor.h>
|
||||
#if ARCH(X86_64)
|
||||
# include <Kernel/Arch/x86_64/Shutdown.h>
|
||||
#elif ARCH(AARCH64)
|
||||
# include <Kernel/Arch/aarch64/RPi/Watchdog.h>
|
||||
#endif
|
||||
#include <Kernel/CommandLine.h>
|
||||
#include <Kernel/KSyms.h>
|
||||
@ -21,6 +23,8 @@ namespace Kernel {
|
||||
#if ARCH(X86_64)
|
||||
qemu_shutdown();
|
||||
virtualbox_shutdown();
|
||||
#elif ARCH(AARCH64)
|
||||
RPi::Watchdog::the().system_shutdown();
|
||||
#endif
|
||||
// Note: If we failed to invoke platform shutdown, we need to halt afterwards
|
||||
// to ensure no further execution on any CPU still happens.
|
||||
|
Loading…
Reference in New Issue
Block a user