From 1a80f166c5d03f52bdeff3137746f5867ea08a61 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Thu, 14 May 2020 15:35:40 +0200 Subject: [PATCH] os: introduce common platform driver for ARM Ref #3299 --- .../x86 => }/platform_device/capability.h | 2 +- .../include/spec/arm/platform_device/client.h | 58 +++++ .../arm/platform_device/platform_device.h | 56 +++++ .../spec/arm/platform_session/client.h | 52 +++++ .../spec/arm/platform_session/connection.h | 132 ++++++++++++ .../arm/platform_session/platform_session.h | 108 ++++++++++ .../spec/imx53/platform_session/connection.h | 35 ++++ .../rpi}/platform_session/connection.h | 10 +- .../x86/platform_session/platform_session.h | 2 +- .../recipes/api/platform_session/content.mk | 4 +- .../src/drivers/platform/spec/arm/device.cc | 162 ++++++++++++++ .../os/src/drivers/platform/spec/arm/device.h | 144 +++++++++++++ .../platform/spec/arm/device_component.cc | 75 +++++++ .../platform/spec/arm/device_component.h | 71 +++++++ .../platform/spec/arm/device_model_policy.cc | 169 +++++++++++++++ .../os/src/drivers/platform/spec/arm/main.cc | 53 +++++ .../os/src/drivers/platform/spec/arm/policy.h | 0 .../os/src/drivers/platform/spec/arm/root.cc | 89 ++++++++ repos/os/src/drivers/platform/spec/arm/root.h | 49 +++++ .../platform/spec/arm/session_component.cc | 198 ++++++++++++++++++ .../platform/spec/arm/session_component.h | 123 +++++++++++ .../src/drivers/platform/spec/arm/target.mk | 5 + 22 files changed, 1589 insertions(+), 8 deletions(-) rename repos/os/include/{spec/x86 => }/platform_device/capability.h (91%) create mode 100644 repos/os/include/spec/arm/platform_device/client.h create mode 100644 repos/os/include/spec/arm/platform_device/platform_device.h create mode 100644 repos/os/include/spec/arm/platform_session/client.h create mode 100644 repos/os/include/spec/arm/platform_session/connection.h create mode 100644 repos/os/include/spec/arm/platform_session/platform_session.h create mode 100644 repos/os/include/spec/imx53/platform_session/connection.h rename repos/os/include/{ => spec/rpi}/platform_session/connection.h (65%) create mode 100644 repos/os/src/drivers/platform/spec/arm/device.cc create mode 100644 repos/os/src/drivers/platform/spec/arm/device.h create mode 100644 repos/os/src/drivers/platform/spec/arm/device_component.cc create mode 100644 repos/os/src/drivers/platform/spec/arm/device_component.h create mode 100644 repos/os/src/drivers/platform/spec/arm/device_model_policy.cc create mode 100644 repos/os/src/drivers/platform/spec/arm/main.cc create mode 100644 repos/os/src/drivers/platform/spec/arm/policy.h create mode 100644 repos/os/src/drivers/platform/spec/arm/root.cc create mode 100644 repos/os/src/drivers/platform/spec/arm/root.h create mode 100644 repos/os/src/drivers/platform/spec/arm/session_component.cc create mode 100644 repos/os/src/drivers/platform/spec/arm/session_component.h create mode 100644 repos/os/src/drivers/platform/spec/arm/target.mk diff --git a/repos/os/include/spec/x86/platform_device/capability.h b/repos/os/include/platform_device/capability.h similarity index 91% rename from repos/os/include/spec/x86/platform_device/capability.h rename to repos/os/include/platform_device/capability.h index f7141182c9..ec47393cc6 100644 --- a/repos/os/include/spec/x86/platform_device/capability.h +++ b/repos/os/include/platform_device/capability.h @@ -1,5 +1,5 @@ /* - * \brief PCI device capability type + * \brief Device capability type * \author Norman Feske * \date 2008-08-16 */ diff --git a/repos/os/include/spec/arm/platform_device/client.h b/repos/os/include/spec/arm/platform_device/client.h new file mode 100644 index 0000000000..2e8d0fa4ff --- /dev/null +++ b/repos/os/include/spec/arm/platform_device/client.h @@ -0,0 +1,58 @@ +/* + * \brief Client-side interface for ARM device + * \author Stefan Kalkowski + * \date 2020-04-15 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__CLIENT_H_ +#define _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__CLIENT_H_ + +#include +#include +#include +#include + +namespace Platform { struct Device_client; } + + +struct Platform::Device_client : Genode::Rpc_client +{ + Device_client(Device_capability device) + : Genode::Rpc_client(device) {} + + Genode::Irq_session_capability irq(unsigned id = 0) override + { + return call(id); + } + + Genode::Io_mem_session_capability + io_mem(unsigned id = 0, + Genode::Cache_attribute caching = + Genode::Cache_attribute::UNCACHED) override + { + return call(id, caching); + } + + + /*************************** + ** Convenience utilities ** + ***************************/ + + Genode::Io_mem_dataspace_capability + io_mem_dataspace(unsigned id = 0, + Genode::Cache_attribute caching = + Genode::Cache_attribute::UNCACHED) + { + Genode::Io_mem_session_client session(io_mem(id, caching)); + return session.dataspace(); + } +}; + +#endif /* _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__CLIENT_H_ */ diff --git a/repos/os/include/spec/arm/platform_device/platform_device.h b/repos/os/include/spec/arm/platform_device/platform_device.h new file mode 100644 index 0000000000..a736166347 --- /dev/null +++ b/repos/os/include/spec/arm/platform_device/platform_device.h @@ -0,0 +1,56 @@ +/* + * \brief ARM-device interface + * \author Stefan Kalkowski + * \date 2020-04-15 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ +#define _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ + +#include +#include +#include +#include +#include + +namespace Platform { struct Device; } + +struct Platform::Device : Genode::Session +{ + enum { DEVICE_NAME_LEN = 64 }; + + using Name = Genode::String; + + virtual ~Device() { } + + /** + * Get IRQ session capability + */ + virtual Genode::Irq_session_capability irq(unsigned id) = 0; + + /** + * Get IO mem session capability of specified resource id + */ + virtual Genode::Io_mem_session_capability + io_mem(unsigned id, Genode::Cache_attribute attr) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_irq, Genode::Irq_session_capability, irq, unsigned); + GENODE_RPC(Rpc_io_mem, Genode::Io_mem_session_capability, io_mem, + unsigned, Genode::Cache_attribute); + + GENODE_RPC_INTERFACE(Rpc_irq, Rpc_io_mem); +}; + +#endif /* _INCLUDE__SPEC__ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */ diff --git a/repos/os/include/spec/arm/platform_session/client.h b/repos/os/include/spec/arm/platform_session/client.h new file mode 100644 index 0000000000..c919f5b0d7 --- /dev/null +++ b/repos/os/include/spec/arm/platform_session/client.h @@ -0,0 +1,52 @@ +/* + * \brief Client-side Platform-session interface + * \author Stefan Kalkowski + * \date 2020-04-28 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CLIENT_H_ +#define _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CLIENT_H_ + +#include +#include +#include + +namespace Platform { + using namespace Genode; + + struct Client; +} + + +struct Platform::Client : public Genode::Rpc_client +{ + Client(Session_capability session) + : Rpc_client(session) { } + + Rom_session_capability devices_rom() override { + return call(); } + + Device_capability acquire_device(String const &device) override { + return call(device); } + + void release_device(Device_capability device) override { + call(device); } + + Ram_dataspace_capability alloc_dma_buffer(size_t size) override { + return call(size); } + + void free_dma_buffer(Ram_dataspace_capability cap) override { + call(cap); } + + addr_t bus_addr_dma_buffer(Ram_dataspace_capability cap) override { + return call(cap); } +}; + +#endif /* _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CLIENT_H_ */ diff --git a/repos/os/include/spec/arm/platform_session/connection.h b/repos/os/include/spec/arm/platform_session/connection.h new file mode 100644 index 0000000000..1f1660f34c --- /dev/null +++ b/repos/os/include/spec/arm/platform_session/connection.h @@ -0,0 +1,132 @@ +/* + * \brief Connection to Platform service + * \author Stefan Kalkowski + * \date 2020-05-13 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CONNECTION_H_ +#define _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CONNECTION_H_ + +#include +#include +#include +#include +#include + +namespace Platform { struct Connection; } + + +class Platform::Connection : public Genode::Connection, + public Client +{ + private: + + Region_map & _rm; + Rom_session_client _rom {devices_rom()}; + Constructible _ds {}; + + void _try_attach() + { + _ds.destruct(); + try { _ds.construct(_rm, _rom.dataspace()); } + catch (Attached_dataspace::Invalid_dataspace) { + warning("Invalid devices rom dataspace returned!");} + } + + public: + + Connection(Env &env) + : Genode::Connection(env, session(env.parent(), + "ram_quota=%u, cap_quota=%u", + RAM_QUOTA, CAP_QUOTA)), + Client(cap()), + _rm(env.rm()) { _try_attach(); } + + Device_capability acquire_device(String const &device) override + { + return retry_with_upgrade(Ram_quota{6*1024}, Cap_quota{6}, [&] () { + return Client::acquire_device(device); }); + } + + Ram_dataspace_capability alloc_dma_buffer(size_t size) override + { + return retry_with_upgrade(Ram_quota{size}, Cap_quota{2}, [&] () { + return Client::alloc_dma_buffer(size); }); + } + + template + void with_xml(FN const & fn) + { + try { + if (_ds.constructed() && _ds->local_addr()) { + Xml_node xml(_ds->local_addr(), _ds->size()); + fn(xml); + } + } catch (Xml_node::Invalid_syntax) { + warning("Devices rom has invalid XML syntax"); } + } + + Device_capability device_by_index(unsigned idx) + { + Device_capability cap; + + with_xml([&] (Xml_node & xml) { + try { + Xml_node node = xml.sub_node(idx); + Device::Name name = node.attribute_value("name", + Device::Name()); + cap = acquire_device(name.string()); + } catch(Xml_node::Nonexistent_sub_node) { + error(__func__, ": invalid device index ", idx); + error("device ROM content: ", xml); + } + }); + + return cap; + } + + Device_capability device_by_property(char const * property, + char const * value) + { + using String = Genode::String<64>; + + Device_capability cap; + + with_xml([&] (Xml_node & xml) { + xml.for_each_sub_node("device", [&] (Xml_node node) { + /* already found a device? */ + if (cap.valid()) { return; } + + bool found = false; + node.for_each_sub_node("property", [&] (Xml_node node) { + if ((node.attribute_value("name", String()) == property) && + (node.attribute_value("value", String()) == value)) { + found = true; + } + }); + + if (found) { + Device::Name name = node.attribute_value("name", + Device::Name()); + cap = acquire_device(name.string()); + } + }); + if (!cap.valid()) { + error(__func__, ": property=", property, " value=", + value, " not found!"); + error("device ROM content: ", xml); + } + }); + + return cap; + } +}; + +#endif /* _INCLUDE__SPEC__ARM__PLATFORM_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/spec/arm/platform_session/platform_session.h b/repos/os/include/spec/arm/platform_session/platform_session.h new file mode 100644 index 0000000000..efcd40b7e3 --- /dev/null +++ b/repos/os/include/spec/arm/platform_session/platform_session.h @@ -0,0 +1,108 @@ +/* + * \brief Platform session interface + * \author Stefan Kalkowski + * \date 2020-04-28 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__ARM__PLATFORM_SESSION__PLATFORM_SESSION_H_ +#define _INCLUDE__SPEC__ARM__PLATFORM_SESSION__PLATFORM_SESSION_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace Platform { + using namespace Genode; + + struct Session; +} + + +struct Platform::Session : Genode::Session +{ + /********************* + ** Exception types ** + *********************/ + + class Fatal : public Out_of_ram { }; + + /** + * \noapi + */ + static const char *service_name() { return "Platform"; } + + enum { RAM_QUOTA = 16 * 1024, CAP_QUOTA = 6 }; + + virtual ~Session() { } + + using String = Rpc_in_buffer; + + /** + * Request ROM session containing the information about available devices. + * + * \return capability to ROM dataspace + */ + virtual Rom_session_capability devices_rom() = 0; + + /** + * Acquire device known by unique 'name'. + */ + virtual Device_capability acquire_device(String const &name) = 0; + + /** + * Free server-internal data structures representing the device + * + * Use this method to relax the resource-allocation of the Platform session. + */ + virtual void release_device(Device_capability device) = 0; + + /** + * Allocate memory suitable for DMA. + */ + virtual Ram_dataspace_capability alloc_dma_buffer(size_t) = 0; + + /** + * Free previously allocated DMA memory + */ + virtual void free_dma_buffer(Ram_dataspace_capability) = 0; + + /** + * Return the bus address of the previously allocated DMA memory + */ + virtual addr_t bus_addr_dma_buffer(Ram_dataspace_capability) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_devices_rom, Rom_session_capability, devices_rom); + GENODE_RPC_THROW(Rpc_acquire_device, Device_capability, acquire_device, + GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), + String const &); + GENODE_RPC(Rpc_release_device, void, release_device, Device_capability); + GENODE_RPC_THROW(Rpc_alloc_dma_buffer, Ram_dataspace_capability, + alloc_dma_buffer, + GENODE_TYPE_LIST(Out_of_ram, Out_of_caps, Fatal), size_t); + GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer, + Ram_dataspace_capability); + GENODE_RPC(Rpc_bus_addr_dma_buffer, addr_t, bus_addr_dma_buffer, + Ram_dataspace_capability); + + GENODE_RPC_INTERFACE(Rpc_devices_rom, Rpc_acquire_device, Rpc_release_device, + Rpc_alloc_dma_buffer, Rpc_free_dma_buffer, + Rpc_bus_addr_dma_buffer); +}; + +#endif /* _INCLUDE__SPEC__ARM__PLATFORM_SESSION__PLATFORM_SESSION_H_ */ diff --git a/repos/os/include/spec/imx53/platform_session/connection.h b/repos/os/include/spec/imx53/platform_session/connection.h new file mode 100644 index 0000000000..0b2afa28e3 --- /dev/null +++ b/repos/os/include/spec/imx53/platform_session/connection.h @@ -0,0 +1,35 @@ +/* + * \brief Connection to platform service + * \author Stefan Kalkowski + * \date 2013-04-29 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__SPEC__IMX53__PLATFORM_SESSION__CONNECTION_H_ +#define _INCLUDE__SPEC__IMX53__PLATFORM_SESSION__CONNECTION_H_ + +#include +#include +#include + +namespace Platform { struct Connection; } + + +struct Platform::Connection : Genode::Connection, Client +{ + /** + * Constructor + */ + Connection(Genode::Env &env) + : Genode::Connection(env, session(env.parent(), + "ram_quota=6K, cap_quota=%u", CAP_QUOTA)), + Client(cap()) { } +}; + +#endif /* _INCLUDE__SPEC__IMX53__PLATFORM_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/platform_session/connection.h b/repos/os/include/spec/rpi/platform_session/connection.h similarity index 65% rename from repos/os/include/platform_session/connection.h rename to repos/os/include/spec/rpi/platform_session/connection.h index 24e82bb4b1..9a81bc1ef2 100644 --- a/repos/os/include/platform_session/connection.h +++ b/repos/os/include/spec/rpi/platform_session/connection.h @@ -11,14 +11,14 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _INCLUDE__PLATFORM_SESSION__CONNECTION_H_ -#define _INCLUDE__PLATFORM_SESSION__CONNECTION_H_ +#ifndef _INCLUDE__SPEC__RPI__PLATFORM_SESSION__CONNECTION_H_ +#define _INCLUDE__SPEC__RPI__PLATFORM_SESSION__CONNECTION_H_ #include #include #include -namespace Platform { class Connection; } +namespace Platform { struct Connection; } struct Platform::Connection : Genode::Connection, Client @@ -28,8 +28,8 @@ struct Platform::Connection : Genode::Connection, Client */ Connection(Genode::Env &env) : Genode::Connection(env, session(env.parent(), - "ram_quota=6K, cap_quota=%ld", CAP_QUOTA)), + "ram_quota=6K, cap_quota=%u", CAP_QUOTA)), Client(cap()) { } }; -#endif /* _INCLUDE__PLATFORM_SESSION__CONNECTION_H_ */ +#endif /* _INCLUDE__SPEC__RPI__PLATFORM_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/spec/x86/platform_session/platform_session.h b/repos/os/include/spec/x86/platform_session/platform_session.h index 831f72e139..02b9718259 100644 --- a/repos/os/include/spec/x86/platform_session/platform_session.h +++ b/repos/os/include/spec/x86/platform_session/platform_session.h @@ -38,7 +38,7 @@ struct Platform::Session : Genode::Session */ static const char *service_name() { return "Platform"; } - enum { CAP_QUOTA = 2 }; + enum { RAM_QUOTA = 16 * 1024, CAP_QUOTA = 2 }; virtual ~Session() { } diff --git a/repos/os/recipes/api/platform_session/content.mk b/repos/os/recipes/api/platform_session/content.mk index 8b50285148..fab30e1a94 100644 --- a/repos/os/recipes/api/platform_session/content.mk +++ b/repos/os/recipes/api/platform_session/content.mk @@ -1,9 +1,11 @@ INCLUDE_SUB_DIRS := platform_session \ + platform_device \ + spec/arm/platform_session \ + spec/arm/platform_device \ spec/imx53/platform_session \ spec/rpi/platform \ spec/rpi/platform_session \ spec/x86/platform_session \ - platform_device \ spec/x86/platform_device INCLUDE_DIRS := $(addprefix include/,$(INCLUDE_SUB_DIRS)) diff --git a/repos/os/src/drivers/platform/spec/arm/device.cc b/repos/os/src/drivers/platform/spec/arm/device.cc new file mode 100644 index 0000000000..4317398e05 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/device.cc @@ -0,0 +1,162 @@ +/* + * \brief Platform driver - Device abstraction + * \author Stefan Kalkowski + * \date 2020-04-30 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include + +Driver::Device::Name Driver::Device::name() const { return _name; } + + +bool Driver::Device::acquire(Session_component & sc) +{ + using namespace Genode; + + if (_session.valid() && _session != sc.label()) { return false; } + + /** + * FIXME: By now, we cannot use the connection objects for IRQ and + * IOMEM and propagate missing resources when opening the + * sessions, because the combination of Genode::Env and + * Genode::Connection object transparently does quota upgrades. + * If we like to account those costs per client, we actually + * need to explicitely forward exceptions during session + * requests. + * For now, we try to measure the probable costs. + */ + Cap_quota_guard::Reservation caps(sc.cap_quota_guard(), + Cap_quota{_cap_quota_required()}); + Ram_quota_guard::Reservation ram(sc.ram_quota_guard(), + Ram_quota{_ram_quota_required()}); + + _session = sc.label(); + + caps.acknowledge(); + ram.acknowledge(); + return true; +} + + +void Driver::Device::release(Session_component & sc) +{ + if (_session != sc.label()) { return; } + + sc.replenish(Genode::Cap_quota{_cap_quota_required()}); + sc.replenish(Genode::Ram_quota{_ram_quota_required()}); + + _io_mem_list.for_each([&] (Io_mem & io_mem) { + if (io_mem.io_mem) { + Genode::destroy(sc.heap(), io_mem.io_mem); + } + }); + + _irq_list.for_each([&] (Irq & irq) { + if (irq.irq) { + Genode::destroy(sc.heap(), irq.irq); + } + }); + + _session = Platform::Session::Label();; +} + + +Genode::Irq_session_capability Driver::Device::irq(unsigned idx, + Session_component & sc) +{ + Genode::Irq_session_capability cap; + + if (_session != sc.label()) { return cap; } + + unsigned i = 0; + _irq_list.for_each([&] (Irq & irq) + { + if (i++ != idx) return; + + if (!irq.irq) { + irq.irq = new (sc.heap()) + Genode::Irq_connection(sc.env(), irq.number); + } + cap = irq.irq->cap(); + }); + + return cap; +} + + +Genode::Io_mem_session_capability +Driver::Device::io_mem(unsigned idx, Genode::Cache_attribute attr, + Session_component & sc) +{ + Genode::Io_mem_session_capability cap; + + if (_session != sc.label()) return cap; + + unsigned i = 0; + _io_mem_list.for_each([&] (Io_mem & io_mem) + { + if (i++ != idx) return; + + if (!io_mem.io_mem) { + io_mem.io_mem = new (sc.heap()) + Genode::Io_mem_connection(sc.env(), io_mem.base, io_mem.size, + (attr == Genode::WRITE_COMBINED)); + } + cap = io_mem.io_mem->cap(); + }); + + return cap; +} + + +void Driver::Device::report(Genode::Xml_generator & xml) +{ + xml.node("device", [&] () { + xml.attribute("name", name()); + _property_list.for_each([&] (Property & p) { + xml.node("property", [&] () { + xml.attribute("name", p.name); + xml.attribute("value", p.value); + }); + }); + }); +} + + +Genode::size_t Driver::Device::_cap_quota_required() +{ + Genode::size_t total = 0; + _io_mem_list.for_each([&] (Io_mem &) { + total += Genode::Io_mem_session::CAP_QUOTA; }); + return total; +} + + +Genode::size_t Driver::Device::_ram_quota_required() +{ + Genode::size_t total = 0; + _io_mem_list.for_each([&] (Io_mem & io_mem) { + total += io_mem.size + 2*1024; }); + return total; +} + + +Driver::Device::Device(Name name) +: _name(name) { } + + +Driver::Device::~Device() +{ + if (_session.valid()) { + Genode::error("Device to be destroyed, still obtained by session ", + _session); + } +} diff --git a/repos/os/src/drivers/platform/spec/arm/device.h b/repos/os/src/drivers/platform/spec/arm/device.h new file mode 100644 index 0000000000..78b4b29e67 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/device.h @@ -0,0 +1,144 @@ +/* + * \brief Platform driver - Device abstraction + * \author Stefan Kalkowski + * \date 2020-04-30 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_ +#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Driver { + class Device; + struct Device_model; + class Session_component; +} + + +class Driver::Device : public Genode::List_model::Element +{ + public: + + struct Io_mem : Genode::List_model::Element + { + Genode::addr_t base; + Genode::size_t size; + Genode::Io_mem_connection * io_mem { nullptr }; + + Io_mem(Genode::addr_t base, Genode::size_t size) + : base(base), size(size) {} + }; + + struct Irq : Genode::List_model::Element + { + unsigned number; + Genode::Irq_connection * irq { nullptr }; + + Irq(unsigned number) : number(number) {} + }; + + struct Property : Genode::List_model::Element + { + using Name = Genode::String<64>; + using Value = Genode::String<64>; + + Name name; + Value value; + + Property(Name name, Value value) + : name(name), value(value) {} + }; + + using Name = Genode::String<64>; + + Device(Name name); + ~Device(); + + Name name() const; + + bool acquire(Session_component &); + void release(Session_component &); + + Genode::Irq_session_capability irq(unsigned idx, + Session_component & session); + Genode::Io_mem_session_capability io_mem(unsigned idx, + Genode::Cache_attribute, + Session_component & session); + + void report(Genode::Xml_generator &); + + private: + + Genode::size_t _cap_quota_required(); + Genode::size_t _ram_quota_required(); + + friend class Driver::Device_model; + + Name _name; + Platform::Session::Label _session {}; + Genode::List_model _io_mem_list {}; + Genode::List_model _irq_list {}; + Genode::List_model _property_list {}; + + /* + * Noncopyable + */ + Device(Device const &); + Device &operator = (Device const &); +}; + + +class Driver::Device_model : + public Genode::List_model::Update_policy +{ + private: + + Genode::Allocator & _alloc; + Genode::List_model _model {}; + + public: + + void update(Genode::Xml_node const & node) { + _model.update_from_xml(*this, node); + } + + Device_model(Genode::Allocator & alloc, + Genode::Xml_node const & node) + : _alloc(alloc) { update(node); } + + ~Device_model() { + _model.destroy_all_elements(*this); } + + + template + void for_each(FN const & fn) { _model.for_each(fn); } + + + /*********************** + ** Update_policy API ** + ***********************/ + + void destroy_element(Device & device); + Device & create_element(Genode::Xml_node node); + void update_element(Device & device, Genode::Xml_node node); + static bool element_matches_xml_node(Device const &, + Genode::Xml_node); + static bool node_is_element(Genode::Xml_node); +}; + +#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/device_component.cc b/repos/os/src/drivers/platform/spec/arm/device_component.cc new file mode 100644 index 0000000000..0c032af8eb --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/device_component.cc @@ -0,0 +1,75 @@ +/* + * \brief Platform driver for ARM device component + * \author Stefan Kalkowski + * \date 2020-04-20 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include +#include + +using Driver::Device_component; + +Driver::Device::Name Device_component::device() const { return _device; } + + +Driver::Session_component & Device_component::session() { return _session; } + + +bool Driver::Device_component::acquire() +{ + bool acquired = false; + _session.devices().for_each([&] (Driver::Device & device) { + if (device.name() == _device) { + acquired = device.acquire(_session); }}); + return acquired; +} + + +void Driver::Device_component::release() +{ + _session.devices().for_each([&] (Driver::Device & device) { + if (device.name() == _device) { device.release(_session); }}); +} + + +Genode::Io_mem_session_capability +Device_component::io_mem(unsigned idx, Genode::Cache_attribute attr) +{ + Genode::Io_mem_session_capability cap; + _session.devices().for_each([&] (Driver::Device & device) { + if (device.name() == _device) { + cap = device.io_mem(idx, attr, _session); }}); + return cap; +} + + +Genode::Irq_session_capability Device_component::irq(unsigned idx) +{ + Genode::Irq_session_capability cap; + _session.devices().for_each([&] (Driver::Device & device) { + if (device.name() == _device) { cap = device.irq(idx, _session); }}); + return cap; +} + + +void Driver::Device_component::report(Genode::Xml_generator & xml) +{ + _session.devices().for_each([&] (Driver::Device & device) { + if (device.name() == _device) { device.report(xml); }}); +} + + +Device_component::Device_component(Driver::Session_component & session, + Driver::Device::Name const device) +: _session(session), _device(device) { } + + +Device_component::~Device_component() { release(); } diff --git a/repos/os/src/drivers/platform/spec/arm/device_component.h b/repos/os/src/drivers/platform/spec/arm/device_component.h new file mode 100644 index 0000000000..41428e34d6 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/device_component.h @@ -0,0 +1,71 @@ +/* + * \brief Platform driver for ARM device component + * \author Stefan Kalkowski + * \date 2020-04-20 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_COMPONENT_H_ +#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_COMPONENT_H_ + +#include +#include +#include + +#include + +namespace Driver { + class Device_component; + class Session_component; +} + + +class Driver::Device_component : public Genode::Rpc_object +{ + public: + + Device_component(Session_component & session, + Driver::Device::Name const device); + ~Device_component(); + + Driver::Device::Name device() const; + Session_component & session(); + + bool acquire(); + void release(); + + void report(Genode::Xml_generator&); + + + /************************** + ** Platform::Device API ** + **************************/ + + Genode::Irq_session_capability irq(unsigned) override; + + Genode::Io_mem_session_capability + io_mem(unsigned, Genode::Cache_attribute) override; + + private: + + friend class Session_component; + + Session_component & _session; + Driver::Device::Name const _device; + Platform::Device_capability _cap {}; + Genode::List_element _list_elem { this }; + + /* + * Noncopyable + */ + Device_component(Device_component const &); + Device_component &operator = (Device_component const &); +}; + +#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_COMPONENT_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/device_model_policy.cc b/repos/os/src/drivers/platform/spec/arm/device_model_policy.cc new file mode 100644 index 0000000000..112df74665 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/device_model_policy.cc @@ -0,0 +1,169 @@ +/* + * \brief Platform driver - Device model policy + * \author Stefan Kalkowski + * \date 2020-05-13 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +using Driver::Device_model; +using Driver::Device; + +struct Irq_update_policy : Genode::List_model::Update_policy +{ + Genode::Allocator & alloc; + + Irq_update_policy(Genode::Allocator & alloc) : alloc(alloc) {} + + void destroy_element(Element & irq) { + Genode::destroy(alloc, &irq); } + + Element & create_element(Genode::Xml_node node) + { + unsigned number = node.attribute_value("number", 0); + return *(new (alloc) Element(number)); + } + + void update_element(Element &, Genode::Xml_node) {} + + static bool element_matches_xml_node(Element const & irq, Genode::Xml_node node) + { + unsigned number = node.attribute_value("number", 0); + return number == irq.number; + } + + static bool node_is_element(Genode::Xml_node node) + { + using Name = Genode::String<16>; + return node.has_type("resource") && + (node.attribute_value("name", Name()) == "IRQ"); + } +}; + + +struct Io_mem_update_policy : Genode::List_model::Update_policy +{ + Genode::Allocator & alloc; + + Io_mem_update_policy(Genode::Allocator & alloc) : alloc(alloc) {} + + void destroy_element(Element & iomem) { + Genode::destroy(alloc, &iomem); } + + Element & create_element(Genode::Xml_node node) + { + Genode::addr_t base = node.attribute_value("address", 0); + Genode::size_t size = node.attribute_value("size", 0); + return *(new (alloc) Element(base, size)); + } + + void update_element(Element &, Genode::Xml_node) {} + + static bool element_matches_xml_node(Element const & iomem, Genode::Xml_node node) + { + Genode::addr_t base = node.attribute_value("address", 0); + Genode::size_t size = node.attribute_value("size", 0); + return (base == iomem.base) && (size == iomem.size); + } + + static bool node_is_element(Genode::Xml_node node) + { + bool iomem = node.attribute_value("name", Genode::String<16>()) + == "IO_MEM"; + return node.has_type("resource") && iomem; + } +}; + + +struct Property_update_policy : Genode::List_model::Update_policy +{ + Genode::Allocator & alloc; + + Property_update_policy(Genode::Allocator & alloc) : alloc(alloc) {} + + void destroy_element(Element & p) { + Genode::destroy(alloc, &p); } + + Element & create_element(Genode::Xml_node node) + { + return *(new (alloc) + Element(node.attribute_value("name", Element::Name()), + node.attribute_value("value", Element::Value()))); + } + + void update_element(Element &, Genode::Xml_node) {} + + static bool element_matches_xml_node(Element const & prop, Genode::Xml_node node) + { + Element::Name n = node.attribute_value("name", Element::Name()); + Element::Value v = node.attribute_value("value", Element::Value()); + return (n == prop.name) && (v == prop.value); + } + + static bool node_is_element(Genode::Xml_node node) { + return node.has_type("property"); } +}; + + +void Device_model::destroy_element(Device & device) +{ + { + Irq_update_policy policy(_alloc); + device._irq_list.destroy_all_elements(policy); + } + + { + Io_mem_update_policy policy(_alloc); + device._io_mem_list.destroy_all_elements(policy); + } + + { + Property_update_policy policy(_alloc); + device._property_list.destroy_all_elements(policy); + } + + Genode::destroy(_alloc, &device); +} + + +Device & Device_model::create_element(Genode::Xml_node node) +{ + Device::Name name = node.attribute_value("name", Device::Name()); + return *(new (_alloc) Device(name)); +} + + +void Device_model::update_element(Device & device, + Genode::Xml_node node) +{ + { + Irq_update_policy policy(_alloc); + device._irq_list.update_from_xml(policy, node); + } + + { + Io_mem_update_policy policy(_alloc); + device._io_mem_list.update_from_xml(policy, node); + } + + { + Property_update_policy policy(_alloc); + device._property_list.update_from_xml(policy, node); + } +} + + +bool Device_model::element_matches_xml_node(Device const & dev, + Genode::Xml_node n) { + return dev.name() == n.attribute_value("name", Device::Name()); } + + +bool Device_model::node_is_element(Genode::Xml_node node) { + return node.has_type("device"); } diff --git a/repos/os/src/drivers/platform/spec/arm/main.cc b/repos/os/src/drivers/platform/spec/arm/main.cc new file mode 100644 index 0000000000..304f74c072 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/main.cc @@ -0,0 +1,53 @@ +/* + * \brief Platform driver for ARM + * \author Stefan Kalkowski + * \date 2020-04-12 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include +#include + +#include + +namespace Driver { struct Main; }; + +struct Driver::Main +{ + void update_config(); + + Genode::Env & env; + Genode::Heap heap { env.ram(), env.rm() }; + Genode::Sliced_heap sliced_heap { env.ram(), env.rm() }; + Genode::Attached_rom_dataspace config { env, "config" }; + Genode::Signal_handler
config_handler { env.ep(), *this, + &Main::update_config }; + Driver::Device_model devices { heap, config.xml() }; + Driver::Root root { env, sliced_heap, + config, devices }; + + Main(Genode::Env &env) + : env(env) + { + config.sigh(config_handler); + env.parent().announce(env.ep().manage(root)); + } +}; + + +void Driver::Main::update_config() +{ + config.update(); + devices.update(config.xml()); + root.update_policy(); +} + +void Component::construct(Genode::Env &env) { + static Driver::Main main(env); } diff --git a/repos/os/src/drivers/platform/spec/arm/policy.h b/repos/os/src/drivers/platform/spec/arm/policy.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/repos/os/src/drivers/platform/spec/arm/root.cc b/repos/os/src/drivers/platform/spec/arm/root.cc new file mode 100644 index 0000000000..bd28de6d29 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/root.cc @@ -0,0 +1,89 @@ +/* + * \brief Platform driver for ARM root component + * \author Stefan Kalkowski + * \date 2020-04-13 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +void Driver::Root::update_policy() +{ + _sessions.for_each([&] (Session_component & sc) { + + bool policy_changed = false; + unsigned device_count = 0; + + try { + Genode::Session_policy const policy { sc._label, _config.xml() }; + + policy.for_each_sub_node("device", [&] (Genode::Xml_node node) { + device_count++; + if (!sc.has_device(node.attribute_value("name", + Device::Name()))) { + policy_changed = true; } + }); + + if (device_count != sc.devices_count()) { policy_changed = true; } + } + catch (Genode::Session_policy::No_policy_defined) { + policy_changed = true; + Genode::error("No matching policy for '", sc._label.string(), + "' anymore, will close the session!"); + } + + if (policy_changed) { close(sc.cap()); } + }); +} + + +Driver::Session_component * Driver::Root::_create_session(const char *args) +{ + using namespace Genode; + + Session_component * sc = nullptr; + + try { + sc = new (md_alloc()) Session_component(_env, + _devices, + _sessions, + session_label_from_args(args), + session_resources_from_args(args), + session_diag_from_args(args)); + + Session_policy const policy { sc->_label, _config.xml() }; + policy.for_each_sub_node("device", [&] (Xml_node node) { + sc->add(node.attribute_value("name", Driver::Device::Name())); }); + } catch (Session_policy::No_policy_defined) { + if (sc) { Genode::destroy(md_alloc(), sc); } + error("Invalid session request, no matching policy for ", + "'", Genode::label_from_args(args).string(), "'"); + throw Service_denied(); + } catch (...) { + if (sc) { Genode::destroy(md_alloc(), sc); } + throw; + } + + return sc; +} + + +void Driver::Root::_upgrade_session(Session_component * sc, const char * args) +{ + sc->upgrade(Genode::ram_quota_from_args(args)); + sc->upgrade(Genode::cap_quota_from_args(args)); +} + + +Driver::Root::Root(Genode::Env & env, + Genode::Allocator & alloc, + Genode::Attached_rom_dataspace & config, + Driver::Device_model & devices) +: Genode::Root_component(env.ep(), alloc), + _env(env), _config(config), _devices(devices) { } diff --git a/repos/os/src/drivers/platform/spec/arm/root.h b/repos/os/src/drivers/platform/spec/arm/root.h new file mode 100644 index 0000000000..e084cb7a8e --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/root.h @@ -0,0 +1,49 @@ +/* + * \brief Platform driver for ARM root component + * \author Stefan Kalkowski + * \date 2020-04-13 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__ROOT_H_ +#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__ROOT_H_ + +#include +#include +#include +#include + +#include + +namespace Driver { class Root; } + +class Driver::Root : public Genode::Root_component +{ + public: + + Root(Genode::Env & env, + Genode::Allocator & alloc, + Genode::Attached_rom_dataspace & config, + Device_model & devices); + + void update_policy(); + + private: + + Session_component * _create_session(const char * args) override; + + void _upgrade_session(Session_component *, const char *) override; + + Genode::Env & _env; + Genode::Attached_rom_dataspace & _config; + Driver::Device_model & _devices; + Genode::Registry _sessions {}; +}; + +#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__ROOT_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/session_component.cc b/repos/os/src/drivers/platform/spec/arm/session_component.cc new file mode 100644 index 0000000000..cfb47be13b --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/session_component.cc @@ -0,0 +1,198 @@ +/* + * \brief Platform driver - session component + * \author Stefan Kalkowski + * \date 2020-04-13 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +#include +#include + +using Driver::Session_component; + +void Session_component::produce_xml(Genode::Xml_generator &xml) +{ + for (Device_list_element * e = _device_list.first(); e; e = e->next()) { + e->object()->report(xml); } +} + + +Genode::Heap & Session_component::heap() { return _md_alloc; } + + +Genode::Env & Session_component::env() { return _env; } + + +Driver::Device_model & Session_component::devices() { return _device_model; } + + +void Session_component::add(Device::Name const & device) +{ + if (has_device(device)) return; + + Device_component * new_dc = + new (_md_alloc) Device_component(*this, device); + + Device_list_element * last = nullptr; + for (last = _device_list.first(); last; last = last->next()) { + if (!last->next()) break; } + _device_list.insert(&new_dc->_list_elem, last); +} + + +bool Session_component::has_device(Device::Name const & device) const +{ + for (Device_list_element const * e = _device_list.first(); e; + e = e->next()) { + if (e->object()->device() == device) { return true; } + } + return false; +} + + +unsigned Session_component::devices_count() const +{ + unsigned counter = 0; + for (Device_list_element const * e = _device_list.first(); + e; e = e->next()) { counter++; } + return counter; +} + + +Genode::Rom_session_capability Session_component::devices_rom() { + return _rom_session.cap(); } + + +Platform::Device_capability +Session_component::acquire_device(Platform::Session::String const &name) +{ + for (Device_list_element * e = _device_list.first(); e; e = e->next()) { + if (e->object()->device() != name.string()) { continue; } + + if (!e->object()->acquire()) { + Genode::error("Device ", e->object()->device(), + " already acquired!"); + break; + } + + /* account one device capability needed */ + _cap_quota_guard().replenish(Genode::Cap_quota{1}); + + return _env.ep().rpc_ep().manage(e->object()); + } + + return Platform::Device_capability(); +} + + +void Session_component::release_device(Platform::Device_capability device_cap) +{ + _env.ep().rpc_ep().apply(device_cap, [&] (Device_component * dc) { + _env.ep().rpc_ep().dissolve(dc); + _cap_quota_guard().replenish(Genode::Cap_quota{1}); + dc->release(); + }); +} + + +Genode::Ram_dataspace_capability +Session_component::alloc_dma_buffer(Genode::size_t const size) +{ + Genode::Ram_dataspace_capability ram_cap = + _env_ram.alloc(size, Genode::UNCACHED); + + if (!ram_cap.valid()) return ram_cap; + + try { + _buffer_list.insert(new (_md_alloc) Dma_buffer(ram_cap)); + } catch (Genode::Out_of_ram) { + _env_ram.free(ram_cap); + throw; + } catch (Genode::Out_of_caps) { + _env_ram.free(ram_cap); + throw; + } + + return ram_cap; +} + + +void Session_component::free_dma_buffer(Genode::Ram_dataspace_capability ram_cap) +{ + if (!ram_cap.valid()) { return; } + + for (Dma_buffer * buf = _buffer_list.first(); buf; buf = buf->next()) { + + if (buf->cap.local_name() != ram_cap.local_name()) continue; + + _buffer_list.remove(buf); + destroy(_md_alloc, buf); + _env_ram.free(ram_cap); + return; + } +} + + +Genode::addr_t Session_component::bus_addr_dma_buffer(Ram_dataspace_capability ram_cap) +{ + if (!ram_cap.valid()) { return 0; } + + for (Dma_buffer * buf = _buffer_list.first(); buf; buf = buf->next()) { + + if (buf->cap.local_name() != ram_cap.local_name()) continue; + + Genode::Dataspace_client dsc(buf->cap); + return dsc.phys_addr(); + } + + return 0; +} + + +Session_component::Session_component(Genode::Env & env, + Device_model & devices, + Registry & registry, + Label const & label, + Resources const & resources, + Diag const & diag) +: Genode::Session_object(env.ep(), resources, + label, diag), + Registry::Element(registry, *this), + Genode::Dynamic_rom_session::Xml_producer("devices"), + _env(env), + _device_model(devices) +{ + /* + * FIXME: As the ROM session does not propagate Out_of_* + * exceptions resp. does not account costs for the ROM + * dataspace to the client for the moment, we cannot do + * so in the dynamic rom session, and cannot use the + * constrained ram allocator within it. Therefore, + * we account the costs here until the ROM session interface + * changes. + */ + _cap_quota_guard().withdraw(Genode::Cap_quota{1}); + _ram_quota_guard().withdraw(Genode::Ram_quota{5*1024}); +} + + +Session_component::~Session_component() +{ + while (_device_list.first()) { + Device_list_element * e = _device_list.first(); + _device_list.remove(e); + destroy(_md_alloc, e->object()); + } + + /* replenish quota for rom sessions, see constructor for explanation */ + _cap_quota_guard().replenish(Genode::Cap_quota{1}); + _ram_quota_guard().replenish(Genode::Ram_quota{5*1024}); +} diff --git a/repos/os/src/drivers/platform/spec/arm/session_component.h b/repos/os/src/drivers/platform/spec/arm/session_component.h new file mode 100644 index 0000000000..3d9f0d3c78 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/session_component.h @@ -0,0 +1,123 @@ +/* + * \brief Platform driver - session component + * \author Stefan Kalkowski + * \date 2020-04-13 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_ +#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Driver { + class Session_component; + class Root; +} + + +class Driver::Session_component : + public Genode::Session_object, + private Genode::Registry::Element, + private Genode::Dynamic_rom_session::Xml_producer +{ + public: + + using Registry = Genode::Registry; + + Session_component(Genode::Env & env, + Device_model & devices, + Registry & registry, + Label const & label, + Resources const & resources, + Diag const & diag); + ~Session_component(); + + Genode::Heap & heap(); + Genode::Env & env(); + Device_model & devices(); + + void add(Device::Name const &); + bool has_device(Device::Name const &) const; + unsigned devices_count() const; + + Genode::Ram_quota_guard &ram_quota_guard() { + return _ram_quota_guard(); } + + Genode::Cap_quota_guard &cap_quota_guard() { + return _cap_quota_guard(); } + + + /************************** + ** Platform Session API ** + **************************/ + + using Rom_session_capability = Genode::Rom_session_capability; + using Device_capability = Platform::Device_capability; + using Ram_dataspace_capability = Genode::Ram_dataspace_capability; + using String = Platform::Session::String; + using size_t = Genode::size_t; + + Rom_session_capability devices_rom() override; + Device_capability acquire_device(String const &) override; + void release_device(Device_capability) override; + Ram_dataspace_capability alloc_dma_buffer(size_t const) override; + void free_dma_buffer(Ram_dataspace_capability ram_cap) override; + Genode::addr_t bus_addr_dma_buffer(Ram_dataspace_capability) override; + + private: + + friend class Root; + + struct Dma_buffer : Genode::List::Element + { + Genode::Ram_dataspace_capability const cap; + + Dma_buffer(Genode::Ram_dataspace_capability const cap) + : cap(cap) {} + }; + + using Device_list_element = Genode::List_element; + using Device_list = Genode::List; + + Genode::Env & _env; + Genode::Constrained_ram_allocator _env_ram { _env.pd(), + _ram_quota_guard(), + _cap_quota_guard() }; + Genode::Heap _md_alloc { _env_ram, _env.rm() }; + Device_list _device_list { }; + Genode::List _buffer_list { }; + Genode::Dynamic_rom_session _rom_session { _env.ep(), _env.ram(), + _env.rm(), *this }; + Device_model & _device_model; + + /* + * Noncopyable + */ + Session_component(Session_component const &); + Session_component &operator = (Session_component const &); + + + /******************************************* + ** Dynamic_rom_session::Xml_producer API ** + *******************************************/ + + void produce_xml(Genode::Xml_generator &xml) override; +}; + +#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/target.mk b/repos/os/src/drivers/platform/spec/arm/target.mk new file mode 100644 index 0000000000..ba727603ac --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/target.mk @@ -0,0 +1,5 @@ +TARGET = platform_drv +REQUIRES = arm +SRC_CC = device.cc device_component.cc device_model_policy.cc main.cc session_component.cc root.cc +INC_DIR = $(PRG_DIR) +LIBS = base