From fd2a21690988c4a89902f5f4a02e0dae8307a013 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Thu, 29 Sep 2022 14:32:36 +0200 Subject: [PATCH] base: support ACPI suspend via Pd::managing_system Issue #4669 --- .../base-nova/src/core/pd_session_support.cc | 35 ++++++++++++++++++- .../base/include/spec/x86_32/cpu/cpu_state.h | 4 +++ .../base/include/spec/x86_64/cpu/cpu_state.h | 4 +++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/repos/base-nova/src/core/pd_session_support.cc b/repos/base-nova/src/core/pd_session_support.cc index 99b0726c4f..344a623d15 100644 --- a/repos/base-nova/src/core/pd_session_support.cc +++ b/repos/base-nova/src/core/pd_session_support.cc @@ -109,4 +109,37 @@ void Pd_session_component::map(addr_t virt, addr_t size) using State = Genode::Pd_session::Managing_system_state; -State Pd_session_component::managing_system(State const &) { return State(); } +State Pd_session_component::managing_system(State const &request) +{ + bool const suspend = (_managing_system == Managing_system::PERMITTED) && + (request.trapno == State::ACPI_SUSPEND_REQUEST); + State respond { }; + + if (!suspend) { + /* report failed attempt */ + respond.trapno = 0; + return respond; + } + + /* + * The trapno/ip/sp registers used below are just convention to transfer + * the intended sleep state S0 ... S5. The values are read out by an + * ACPI AML component and are of type TYP_SLPx as described in the + * ACPI specification, e.g. TYP_SLPa and TYP_SLPb. The values differ + * between different PC systems/boards. + * + * \note trapno/ip/sp registers are chosen because they exist in + * Managing_system_state for x86_32 and x86_64. + */ + uint8_t const sleep_type_a = uint8_t(request.ip); + uint8_t const sleep_type_b = uint8_t(request.sp); + + auto const cap_suspend = platform_specific().core_pd_sel() + 3; + auto const result = Nova::acpi_suspend(cap_suspend, sleep_type_a, + sleep_type_b); + + if (result == Nova::NOVA_OK) + respond.trapno = 1 /* success, which means we resumed already */; + + return respond; +} diff --git a/repos/base/include/spec/x86_32/cpu/cpu_state.h b/repos/base/include/spec/x86_32/cpu/cpu_state.h index 2b88fd613f..61d459021a 100644 --- a/repos/base/include/spec/x86_32/cpu/cpu_state.h +++ b/repos/base/include/spec/x86_32/cpu/cpu_state.h @@ -36,6 +36,10 @@ struct Genode::Cpu_state addr_t fs = 0; addr_t eflags = 0; addr_t trapno = 0; + + enum { + ACPI_SUSPEND_REQUEST = 0x100, /* convention for managing_system() */ + }; }; #endif /* _INCLUDE__SPEC__X86_32__CPU__CPU_STATE_H_ */ diff --git a/repos/base/include/spec/x86_64/cpu/cpu_state.h b/repos/base/include/spec/x86_64/cpu/cpu_state.h index 7ab0324be9..4388a90596 100644 --- a/repos/base/include/spec/x86_64/cpu/cpu_state.h +++ b/repos/base/include/spec/x86_64/cpu/cpu_state.h @@ -57,6 +57,10 @@ struct Genode::Cpu_state addr_t eflags = 0; addr_t sp = 0; addr_t ss = 0; + + enum { + ACPI_SUSPEND_REQUEST = 0x100, /* convention for managing_system() */ + }; }; #endif /* _INCLUDE__SPEC__X86_64__CPU__CPU_STATE_H_ */