mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-23 12:35:41 +00:00
platform/pc: support to suspend via system_control
When the "system" ROM state turns to "suspend", the S3 state information of the sleep_states ROM are determined and are used to invoke the privileged Pd::system_control call. Issue #5180
This commit is contained in:
parent
94b3e30f90
commit
4c79f948ab
@ -419,6 +419,8 @@ install_config {
|
||||
<child name="config_fs_rom" label="managed/modem"/> </service>
|
||||
<service name="ROM" label_last="audio.config">
|
||||
<child name="config_fs_rom" label="managed/audio"/> </service>
|
||||
<service name="ROM" label_last="sleep_states">
|
||||
<child name="report_fs_rom" label="runtime/acpi_support/sleep_states"/> </service>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
<service name="Capture"> <child name="nitpicker"/> </service>
|
||||
<service name="Event"> <child name="event_filter"/> </service>
|
||||
|
@ -89,6 +89,7 @@
|
||||
<provides> <service name="Platform"/> </provides>
|
||||
<route>
|
||||
<service name="ROM" label="system"> <parent label="system"/> </service>
|
||||
<service name="ROM" label="sleep_states"> <parent label="sleep_states"/> </service>
|
||||
<service name="ROM" label="devices"> <child name="report_rom"/> </service>
|
||||
<service name="ROM" label="acpi"> <child name="report_rom"/> </service>
|
||||
<service name="Report" label="devices"> <child name="report_rom"/> </service>
|
||||
|
@ -49,6 +49,8 @@ class Driver::Common : Device_reporter,
|
||||
Constructible<Expanding_reporter> _dev_reporter { };
|
||||
Constructible<Expanding_reporter> _iommu_reporter { };
|
||||
|
||||
uint64_t _resume_counter { };
|
||||
|
||||
void _handle_devices();
|
||||
bool _iommu();
|
||||
|
||||
@ -67,6 +69,7 @@ class Driver::Common : Device_reporter,
|
||||
void handle_config(Xml_node config);
|
||||
void acquire_io_mmu_devices();
|
||||
|
||||
void report_resume();
|
||||
|
||||
/*********************
|
||||
** Device_reporter **
|
||||
@ -174,6 +177,7 @@ void Driver::Common::update_report()
|
||||
{
|
||||
if (_dev_reporter.constructed())
|
||||
_dev_reporter->generate([&] (Xml_generator & xml) {
|
||||
xml.attribute("resumed", _resume_counter);
|
||||
_devices.generate(xml); });
|
||||
if (_iommu_reporter.constructed())
|
||||
_iommu_reporter->generate([&] (Xml_generator & xml) {
|
||||
@ -182,6 +186,12 @@ void Driver::Common::update_report()
|
||||
}
|
||||
|
||||
|
||||
void Driver::Common::report_resume()
|
||||
{
|
||||
_resume_counter ++;
|
||||
update_report();
|
||||
}
|
||||
|
||||
void Driver::Common::disable_device(Device const & device)
|
||||
{
|
||||
_io_mmu_devices.for_each([&] (Io_mmu & io_mmu) {
|
||||
|
@ -24,6 +24,7 @@ struct Driver::Main
|
||||
Attached_rom_dataspace _config_rom { _env, "config" };
|
||||
Attached_rom_dataspace _acpi_rom { _env, "acpi" };
|
||||
Attached_rom_dataspace _system_rom { _env, "system" };
|
||||
Attached_rom_dataspace _sleep_rom { _env, "sleep_states" };
|
||||
Common _common { _env, _config_rom };
|
||||
Signal_handler<Main> _config_handler { _env.ep(), *this,
|
||||
&Main::_handle_config };
|
||||
@ -33,6 +34,7 @@ struct Driver::Main
|
||||
Intel::Io_mmu_factory _intel_iommu { _env, _common.io_mmu_factories() };
|
||||
|
||||
void _handle_config();
|
||||
void _suspend();
|
||||
void _reset();
|
||||
void _system_update();
|
||||
|
||||
@ -40,10 +42,13 @@ struct Driver::Main
|
||||
: _env(e)
|
||||
{
|
||||
_config_rom.sigh(_config_handler);
|
||||
_acpi_rom.sigh(_system_handler);
|
||||
_acpi_rom .sigh(_system_handler);
|
||||
_system_rom.sigh(_system_handler);
|
||||
_sleep_rom .sigh(_system_handler);
|
||||
|
||||
_handle_config();
|
||||
_system_update();
|
||||
|
||||
_common.acquire_io_mmu_devices();
|
||||
_common.announce_service();
|
||||
}
|
||||
@ -53,13 +58,19 @@ struct Driver::Main
|
||||
void Driver::Main::_handle_config()
|
||||
{
|
||||
_config_rom.update();
|
||||
_common.handle_config(_config_rom.xml());
|
||||
|
||||
if (_config_rom.valid())
|
||||
_common.handle_config(_config_rom.xml());
|
||||
}
|
||||
|
||||
|
||||
void Driver::Main::_reset()
|
||||
{
|
||||
_acpi_rom.update();
|
||||
|
||||
if (!_acpi_rom.valid())
|
||||
return;
|
||||
|
||||
_acpi_rom.xml().with_optional_sub_node("reset", [&] (Xml_node reset)
|
||||
{
|
||||
uint16_t const io_port = reset.attribute_value<uint16_t>("io_port", 0);
|
||||
@ -79,8 +90,68 @@ void Driver::Main::_reset()
|
||||
void Driver::Main::_system_update()
|
||||
{
|
||||
_system_rom.update();
|
||||
if (_system_rom.xml().attribute_value("state", String<16>()) == "reset")
|
||||
|
||||
if (!_system_rom.valid())
|
||||
return;
|
||||
|
||||
auto const state = _system_rom.xml().attribute_value("state", String<16>());
|
||||
|
||||
if (state == "reset")
|
||||
_reset();
|
||||
|
||||
if (state == "suspend") {
|
||||
try { _suspend(); } catch (...) { error("suspend failed"); }
|
||||
/* report independent of result */
|
||||
_common.report_resume();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Driver::Main::_suspend()
|
||||
{
|
||||
_sleep_rom .update();
|
||||
|
||||
if (!_sleep_rom.valid())
|
||||
return;
|
||||
|
||||
struct Client: Genode::Rpc_client<Pd_session::System_control>
|
||||
{
|
||||
explicit Client(Genode::Capability<Pd_session::System_control> cap)
|
||||
: Rpc_client<Pd_session::System_control>(cap) { }
|
||||
|
||||
Pd_session::Managing_system_state system_control(Pd_session::Managing_system_state const &state) override {
|
||||
return call<Rpc_system_control>(state); }
|
||||
} system_control { _env.pd().system_control_cap(Affinity::Location()) };
|
||||
|
||||
_sleep_rom.xml().with_sub_node("S3", [&] (auto const &node) {
|
||||
|
||||
auto const typea = "SLP_TYPa";
|
||||
auto const typeb = "SLP_TYPb";
|
||||
auto const valid = node.attribute_value("supported", false) &&
|
||||
node.has_attribute(typea) &&
|
||||
node.has_attribute(typeb);
|
||||
|
||||
if (!valid)
|
||||
return;
|
||||
|
||||
auto s3_sleep_typea = uint8_t(node.attribute_value(typea, 0u));
|
||||
auto s3_sleep_typeb = uint8_t(node.attribute_value(typeb, 0u));
|
||||
|
||||
Pd_session::Managing_system_state in { }, out { };
|
||||
|
||||
in.trapno = Pd_session::Managing_system_state::ACPI_SUSPEND_REQUEST;
|
||||
in.ip = s3_sleep_typea;
|
||||
in.sp = s3_sleep_typeb;
|
||||
|
||||
out = system_control.system_control(in);
|
||||
|
||||
if (!out.trapno)
|
||||
error("S3 suspend failed");
|
||||
else
|
||||
log("resumed from S3");
|
||||
}, [&] {
|
||||
warning("S3 suspend not supported");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user