From 4e9aeb45ea566a1547d0e0db0d926c982e73e0ea Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 1 Jun 2016 22:26:54 +0200 Subject: [PATCH] platform_drv: sync startup between acpica - platform_drv announces a separate "Acpi" session - platform_drv waits for ROM "system" to change state to "acpi_ready" - acpica waits for "Acpi" announcement - acpica uses the platform driver via "Acpi" to reconfigure PCI devices - acpica changes "system" state to "acpi_ready" after it ready with initialization - platform_drv reacts on "system" state change to "acpi_ready" by announcing "Platform" session - drivers start to operate as usual Issue #2009 --- repos/base/run/platform_drv.inc | 3 + repos/libports/run/acpica.run | 8 ++- repos/libports/src/app/acpica/README | 11 ++- repos/libports/src/app/acpica/os.cc | 31 ++++++--- repos/libports/src/lib/acpica/pci.cc | 56 ++++++++++----- repos/os/src/drivers/platform/spec/x86/README | 54 +++++++++++---- .../os/src/drivers/platform/spec/x86/main.cc | 69 ++++++++++++++----- 7 files changed, 175 insertions(+), 57 deletions(-) diff --git a/repos/base/run/platform_drv.inc b/repos/base/run/platform_drv.inc index b964293bdc..2374af82b3 100644 --- a/repos/base/run/platform_drv.inc +++ b/repos/base/run/platform_drv.inc @@ -119,6 +119,9 @@ proc append_platform_drv_config {} { } + append_if [have_spec acpi] config { + } + append_if [have_spec arm] config { } diff --git a/repos/libports/run/acpica.run b/repos/libports/run/acpica.run index 30ddd80d79..9f6994d294 100644 --- a/repos/libports/run/acpica.run +++ b/repos/libports/run/acpica.run @@ -30,13 +30,14 @@ proc platform_drv_policy {} { # add routing information to dynamically generate change of 'system' ROM proc platform_drv_add_routing {} { return { - } + + } } # override default config to react on 'system' ROM changes for reset proc platform_drv_config_config {} { return { - } + } } append_platform_drv_build_components @@ -66,7 +67,7 @@ set config { - + ! ... -! +! ! ! ! diff --git a/repos/libports/src/app/acpica/os.cc b/repos/libports/src/app/acpica/os.cc index 2b39a5b198..9215bc857d 100644 --- a/repos/libports/src/app/acpica/os.cc +++ b/repos/libports/src/app/acpica/os.cc @@ -10,6 +10,7 @@ * under the terms of the GNU General Public License version 2. */ +#include #include #include #include @@ -215,6 +216,7 @@ struct Acpica::Main { bool enable_reset = Genode::config()->xml_node().attribute_value("reset", false); bool enable_poweroff = Genode::config()->xml_node().attribute_value("poweroff", false); bool enable_report = Genode::config()->xml_node().attribute_value("report", false); + bool enable_ready = Genode::config()->xml_node().attribute_value("acpi_ready", false); if (enable_report) _report = new (Genode::env()->heap()) Acpica::Reportstate(); @@ -229,16 +231,29 @@ struct Acpica::Main { enable_poweroff); /* setup IRQ */ - if (irq_handler.handler) { - _sci_conn.construct(irq_handler.irq); - - PINF("SCI IRQ: %u", irq_handler.irq); - - _sci_conn->sigh(_sci_irq); - _sci_conn->ack_irq(); - } else + if (!irq_handler.handler) { PWRN("no IRQ handling available"); + return; + } + _sci_conn.construct(irq_handler.irq); + + PINF("SCI IRQ: %u", irq_handler.irq); + + _sci_conn->sigh(_sci_irq); + _sci_conn->ack_irq(); + + if (!enable_ready) + return; + + /* we are ready - signal it via changing system state */ + const char * system_file = "system"; + + static Genode::Reporter _system_rom { "system", "acpi_ready" }; + _system_rom.enabled(true); + Genode::Reporter::Xml_generator xml(_system_rom, [&] () { + xml.attribute("state", "acpi_ready"); + }); } void acpi_irq() diff --git a/repos/libports/src/lib/acpica/pci.cc b/repos/libports/src/lib/acpica/pci.cc index 27453d2bb6..e370ffaa20 100644 --- a/repos/libports/src/lib/acpica/pci.cc +++ b/repos/libports/src/lib/acpica/pci.cc @@ -12,20 +12,46 @@ */ #include -#include +#include +#include +#include extern "C" { #include "acpi.h" #include "acpiosxf.h" } + +static Platform::Client & platform() +{ + static bool connected = false; + + typedef Genode::Capability Platform_session_capability; + Platform_session_capability platform_cap; + + if (!connected) { + Genode::Parent::Service_name announce_for_acpica("Acpi"); + Genode::Native_capability cap = Genode::env()->parent()->session(announce_for_acpica, "ram_quota=20K"); + + platform_cap = Genode::reinterpret_cap_cast(cap); + connected = true; + } + + static Platform::Client conn(platform_cap); + return conn; +} + ACPI_STATUS AcpiOsInitialize (void) { - /* XXX - acpi_drv uses IOMEM concurrently to us - wait until it is done */ + /* acpi_drv uses IOMEM concurrently to us - wait until it is done */ PINF("wait for platform drv"); try { - Platform::Connection conn; - } catch (...) { PERR("did not get Platform connection"); } + platform(); + } catch (...) { + PERR("did not get Platform connection"); + Genode::Lock lock(Genode::Lock::LOCKED); + lock.lock(); + } PINF("wait for platform drv - done"); return AE_OK; } @@ -33,8 +59,7 @@ ACPI_STATUS AcpiOsInitialize (void) ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg, UINT64 *value, UINT32 width) { - Platform::Connection conn; - Platform::Device_capability cap = conn.first_device(); + Platform::Device_capability cap = platform().first_device(); while (cap.valid()) { Platform::Device_client client(cap); @@ -58,7 +83,7 @@ ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg, break; default: PERR("%s : unsupported access size %u", __func__, width); - conn.release_device(client); + platform().release_device(client); return AE_ERROR; }; @@ -67,13 +92,13 @@ ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg, PINF("%s: %x:%x.%x reg=0x%x width=%u -> value=0x%llx", __func__, bus, dev, fn, reg, width, *value); - conn.release_device(client); + platform().release_device(client); return AE_OK; } - cap = conn.next_device(cap); + cap = platform().next_device(cap); - conn.release_device(client); + platform().release_device(client); } PERR("%s unknown device - segment=%u bdf=%x:%x.%x reg=0x%x width=0x%x", @@ -86,8 +111,7 @@ ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg, ACPI_STATUS AcpiOsWritePciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg, UINT64 value, UINT32 width) { - Platform::Connection conn; - Platform::Device_capability cap = conn.first_device(); + Platform::Device_capability cap = platform().first_device(); while (cap.valid()) { Platform::Device_client client(cap); @@ -111,7 +135,7 @@ ACPI_STATUS AcpiOsWritePciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg, break; default: PERR("%s : unsupported access size %u", __func__, width); - conn.release_device(client); + platform().release_device(client); return AE_ERROR; }; @@ -120,13 +144,13 @@ ACPI_STATUS AcpiOsWritePciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg, PWRN("%s: %x:%x.%x reg=0x%x width=%u value=0x%llx", __func__, bus, dev, fn, reg, width, value); - conn.release_device(client); + platform().release_device(client); return AE_OK; } - cap = conn.next_device(cap); + cap = platform().next_device(cap); - conn.release_device(client); + platform().release_device(client); } PERR("%s unknown device - segment=%u bdf=%x:%x.%x reg=0x%x width=0x%x", diff --git a/repos/os/src/drivers/platform/spec/x86/README b/repos/os/src/drivers/platform/spec/x86/README index fd235f53f5..1508c437d4 100644 --- a/repos/os/src/drivers/platform/spec/x86/README +++ b/repos/os/src/drivers/platform/spec/x86/README @@ -98,8 +98,8 @@ in the following: ! ! ... ! -! -! +! +! ! ! ... ! @@ -111,26 +111,56 @@ configured to not wait for the acpi report: ! ! ... -! +! ! ... ! ! ... +Synchronize ACPI startup and platform driver +-------------------------------------------- + +If the config attribute 'system' is set to 'yes', the platform driver monitors +a ROM in XML format named 'system'. + +! +! + +Additionally, the platform driver will announce the service as 'Acpi' first. +An ACPI application like acpica can connect to the platform driver and may +reconfigure hardware devices according to the ACPI table findings. If the +system state changes to "acpi_ready in the XML ROM 'acpi_ready': + +! + +the platform driver will announce the platform session, so that drivers may +start to operate with the platform driver. + +Hardware reset +-------------- +If the attribute 'state' in the system XML ROM turns to 'reset' + +! + +the platform driver will try to reset the machine, if the required I/O ports +are owned by it. + Supported PCI class aliases --------------------------- The following class names are supported which corresponds to the specified PCI class(C), subclass(S) and programming interface(P): -alias C S P -********************* -ALL 0x0 0x00 0x0 -AHCI 0x1 0x06 0x0 -AUDIO 0x4 0x00 0x0 -ETHERNET 0x2 0x00 0x0 -USB 0xc 0x03 0x0 -VGA 0x3 0x00 0x0 -WIFI 0x2 0x80 0x0 +alias C S P +********************** +ALL 0x0 0x00 0x0 +AHCI 0x1 0x06 0x0 +AUDIO 0x4 0x01 0x0 +ETHERNET 0x2 0x00 0x0 +HDAUDIO 0x4 0x03 0x0 +USB 0xc 0x03 0x0 +VGA 0x3 0x00 0x0 +WIFI 0x2 0x80 0x0 +ISABRIDGE 0x6 0x01 0x0 Supported non PCI devices diff --git a/repos/os/src/drivers/platform/spec/x86/main.cc b/repos/os/src/drivers/platform/spec/x86/main.cc index f977ef75fe..aedd4dd42c 100644 --- a/repos/os/src/drivers/platform/spec/x86/main.cc +++ b/repos/os/src/drivers/platform/spec/x86/main.cc @@ -40,10 +40,15 @@ struct Platform::Main Genode::Lazy_volatile_object root; Genode::Lazy_volatile_object system_state; + Genode::Lazy_volatile_object acpi_ready; Genode::Signal_handler _acpi_report; Genode::Signal_handler _system_report; + Genode::Capability > root_cap; + + bool _system_rom = false; + void acpi_update() { acpi_rom->update(); @@ -54,24 +59,50 @@ struct Platform::Main const char * report_addr = acpi_rom->local_addr(); root.construct(_env, &sliced_heap, report_addr); - _env.parent().announce(_env.ep().manage(*root)); + + root_cap = _env.ep().manage(*root); + + if (_system_rom) { + Genode::Parent::Service_name announce_for_acpi("Acpi"); + _env.parent().announce(announce_for_acpi, root_cap); + } else + _env.parent().announce(root_cap); } void system_update() { - system_state->update(); - - if (!system_state->is_valid() || !root.is_constructed()) + if (!_system_rom || !system_state.is_constructed() || + !acpi_ready.is_constructed()) return; - Genode::Xml_node system(system_state->local_addr(), - system_state->size()); + system_state->update(); + acpi_ready->update(); - typedef Genode::String<16> Value; - const Value state = system.attribute_value("state", Value("unknown")); + if (!root.is_constructed()) + return; - if (state == "reset") - root->system_reset(); + if (system_state->is_valid()) { + Genode::Xml_node system(system_state->local_addr(), + system_state->size()); + + typedef Genode::String<16> Value; + const Value state = system.attribute_value("state", Value("unknown")); + + if (state == "reset") + root->system_reset(); + } + if (acpi_ready->is_valid()) { + Genode::Xml_node system(acpi_ready->local_addr(), + acpi_ready->size()); + + typedef Genode::String<16> Value; + const Value state = system.attribute_value("state", Value("unknown")); + + if (state == "acpi_ready" && root_cap.valid()) { + _env.parent().announce(root_cap); + root_cap = Genode::Capability > (); + } + } } Main(Genode::Env &env) @@ -83,22 +114,26 @@ struct Platform::Main { const Genode::Xml_node &config = Genode::config()->xml_node(); + _system_rom = config.attribute_value("system", false); + typedef Genode::String<8> Value; Value const wait_for_acpi = config.attribute_value("acpi", Value("yes")); - if (wait_for_acpi == "yes") { - bool system_reset = config.attribute_value("system", false); - if (system_reset) { - /* wait for system state changes and react upon, e.g. reset */ - system_state.construct("system"); - system_state->sigh(_system_report); - } + if (_system_rom) { + /* wait for system state changes, e.g. reset and acpi_ready */ + system_state.construct("system"); + system_state->sigh(_system_report); + acpi_ready.construct("acpi_ready"); + acpi_ready->sigh(_system_report); + } + if (wait_for_acpi == "yes") { /* for ACPI support, wait for the first valid acpi report */ acpi_rom.construct("acpi"); acpi_rom->sigh(_acpi_report); /* check if already valid */ acpi_update(); + system_update(); return; }