mirror of
https://github.com/SerenityOS/serenity
synced 2026-05-12 18:06:56 +02:00
Kernel/aarch64: Add basic support for PSCI and HVC calls
This makes it possible to shut down and reboot the QEMU virt machine.
This commit is contained in:
committed by
Sönke Holz
parent
02ce12aeaa
commit
6a21fcec38
73
Kernel/Arch/aarch64/PSCI.cpp
Normal file
73
Kernel/Arch/aarch64/PSCI.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2025, the SerenityOS developers
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Arch/aarch64/PSCI.h>
|
||||
#include <Kernel/Firmware/DeviceTree/DeviceTree.h>
|
||||
|
||||
// https://developer.arm.com/documentation/den0022/latest/
|
||||
namespace Kernel::PSCI {
|
||||
|
||||
enum class Function : u32 {
|
||||
SystemOff = 0x8400'0008,
|
||||
SystemReset = 0x8400'0009,
|
||||
};
|
||||
|
||||
static FlatPtr call(Function function, FlatPtr arg0, FlatPtr arg1, FlatPtr arg2)
|
||||
{
|
||||
// 5.2.1 Register usage in arguments and return values
|
||||
// "For [PSCI] versions using 64-bit parameters, the arguments are passed in X0 to X3, with return values in X0."
|
||||
register FlatPtr x0 asm("x0") = static_cast<FlatPtr>(function);
|
||||
register FlatPtr x1 asm("x1") = arg0;
|
||||
register FlatPtr x2 asm("x2") = arg1;
|
||||
register FlatPtr x3 asm("x3") = arg2;
|
||||
|
||||
// NOTE: x4-x17 are marked as clobbered since SMCCC 1.0 doesn't
|
||||
// require them to be preserved across SMC or HVC calls.
|
||||
asm volatile(
|
||||
"hvc #0"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3)
|
||||
:
|
||||
: "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17");
|
||||
|
||||
return x0;
|
||||
}
|
||||
|
||||
bool is_supported()
|
||||
{
|
||||
// https://www.kernel.org/doc/Documentation/devicetree/bindings/arm/psci.txt
|
||||
// FIXME: Make this a DeviceTree::Driver, and don't assume that the psci node is a child of the root node.
|
||||
auto psci = DeviceTree::get().get_child("psci"sv);
|
||||
if (!psci.has_value())
|
||||
return false;
|
||||
|
||||
// NOTE: We reject "arm,psci" on purpose, since these old devices don't have standardized function IDs.
|
||||
if (!psci->is_compatible_with("arm,psci-0.2"sv) && !psci->is_compatible_with("arm,psci-1.0"sv))
|
||||
return false;
|
||||
|
||||
auto method = psci->get_property("method"sv);
|
||||
if (!method.has_value()) {
|
||||
dbgln("PSCI: No method property found");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Currently, we only support HVC (as opposed to SMC). While SMC is very similar to HVC, only the latter has been tested so far.
|
||||
if (method->as_string() != "hvc"sv)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void poweroff()
|
||||
{
|
||||
call(Function::SystemOff, 0, 0, 0);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
call(Function::SystemReset, 0, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
15
Kernel/Arch/aarch64/PSCI.h
Normal file
15
Kernel/Arch/aarch64/PSCI.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2025, the SerenityOS developers
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Kernel::PSCI {
|
||||
|
||||
bool is_supported();
|
||||
void poweroff();
|
||||
void reset();
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <Kernel/Arch/PowerState.h>
|
||||
#include <Kernel/Arch/aarch64/PSCI.h>
|
||||
#include <Kernel/Arch/aarch64/RPi/Watchdog.h>
|
||||
#include <Kernel/Firmware/DeviceTree/DeviceTree.h>
|
||||
|
||||
@@ -12,10 +13,15 @@ namespace Kernel {
|
||||
|
||||
void arch_specific_reboot()
|
||||
{
|
||||
if (PSCI::is_supported())
|
||||
PSCI::reset();
|
||||
}
|
||||
|
||||
void arch_specific_poweroff()
|
||||
{
|
||||
if (PSCI::is_supported())
|
||||
PSCI::poweroff();
|
||||
|
||||
if (DeviceTree::get().is_compatible_with("raspberrypi,3-model-b"sv) || DeviceTree::get().is_compatible_with("raspberrypi,4-model-b"sv))
|
||||
RPi::Watchdog::the().system_shutdown();
|
||||
}
|
||||
|
||||
@@ -508,6 +508,7 @@ elseif("${SERENITY_ARCH}" STREQUAL "aarch64")
|
||||
Arch/aarch64/Interrupts.cpp
|
||||
Arch/aarch64/Interrupts/GIC.cpp
|
||||
Arch/aarch64/MainIdRegister.cpp
|
||||
Arch/aarch64/PSCI.cpp
|
||||
Arch/aarch64/PageDirectory.cpp
|
||||
Arch/aarch64/Processor.cpp
|
||||
Arch/aarch64/PowerState.cpp
|
||||
|
||||
Reference in New Issue
Block a user