From dd8e13d6fa91c24e68aef3eaeb13ffa14f4f5e41 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 2 Jan 2017 14:23:03 +0100 Subject: [PATCH] platform_drv: remove deprecated env() usage Issue #1987 --- .../platform/spec/x86/device_pd/main.cc | 8 +- repos/os/src/drivers/platform/spec/x86/irq.cc | 143 +++++-------- repos/os/src/drivers/platform/spec/x86/irq.h | 5 +- .../src/drivers/platform/spec/x86/irq_proxy.h | 149 ++----------- .../os/src/drivers/platform/spec/x86/main.cc | 9 +- .../platform/spec/x86/nonpci_devices.cc | 25 ++- .../platform/spec/x86/pci_config_access.h | 6 +- .../drivers/platform/spec/x86/pci_device.cc | 16 +- .../platform/spec/x86/pci_device_component.h | 35 ++-- .../platform/spec/x86/pci_device_pd_ipc.h | 5 +- .../platform/spec/x86/pci_session_component.h | 195 ++++++++++-------- .../src/drivers/platform/spec/x86/session.cc | 67 +++--- 12 files changed, 269 insertions(+), 394 deletions(-) diff --git a/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc b/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc index bf0c567716..9ee7e1111c 100644 --- a/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc +++ b/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc @@ -30,7 +30,7 @@ /** * Custom handling of PD-session depletion during attach operations * - * The default implementation of 'env().rm()' automatically issues a resource + * The default implementation of 'env.rm()' automatically issues a resource * request if the PD session quota gets exhausted. For the device PD, we don't * want to issue resource requests but let the platform driver reflect this * condition to its client. @@ -59,7 +59,7 @@ struct Expanding_region_map_client : Genode::Region_map_client [&] () { enum { UPGRADE_QUOTA = 4096 }; - if (Genode::env()->ram_session()->avail() < UPGRADE_QUOTA) + if (_env.ram().avail() < UPGRADE_QUOTA) throw; Genode::String<32> arg("ram_quota=", (unsigned)UPGRADE_QUOTA); @@ -172,7 +172,7 @@ void Platform::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capabili }; /* try to assign pci device to this protection domain */ - if (!env()->pd_session()->assign_pci(page, rid)) + if (!_env.pd().assign_pci(page, rid)) Genode::error("assignment of PCI device ", Rid(rid), " failed ", "phys=", Genode::Hex(ds_client.phys_addr()), " " "virt=", Genode::Hex(page)); @@ -190,7 +190,7 @@ struct Main Expanding_region_map_client rm { env }; - Platform::Device_pd_component pd_component { rm }; + Platform::Device_pd_component pd_component { rm, env }; Genode::Static_root root { env.ep().manage(pd_component) }; diff --git a/repos/os/src/drivers/platform/spec/x86/irq.cc b/repos/os/src/drivers/platform/spec/x86/irq.cc index 39f1f0d238..4c151cbecf 100644 --- a/repos/os/src/drivers/platform/spec/x86/irq.cc +++ b/repos/os/src/drivers/platform/spec/x86/irq.cc @@ -24,7 +24,6 @@ namespace Platform { class Irq_component; class Irq_allocator; - class Irq_thread; } @@ -32,9 +31,9 @@ using Genode::size_t; using Genode::addr_t; /** - * A simple range allocator implementation used by the Irq_proxy + * A simple allocator implementation used by the Irq_proxy */ -class Platform::Irq_allocator : public Genode::Range_allocator +class Platform::Irq_allocator { private: @@ -64,76 +63,13 @@ class Platform::Irq_allocator : public Genode::Range_allocator void free_msi(unsigned msi) { _msi.free(msi); } - Alloc_return alloc_addr(size_t size, addr_t addr) override + bool alloc_irq(addr_t addr) { try { - _legacy.set(addr, size); - return Alloc_return::OK; + _legacy.set(addr, 1); + return true; } catch (...) { - return Alloc_return::RANGE_CONFLICT; - } - } - - /* unused methods */ - int remove_range(addr_t, size_t) override { return 0; } - int add_range(addr_t, size_t) override { return 0; } - bool valid_addr(addr_t) const override { return false; } - size_t avail() const override { return 0; } - bool alloc(size_t, void **) override { return false; } - void free(void *) override { } - void free(void *, size_t) override { } - size_t overhead(size_t) const override { return 0; } - bool need_size_for_free() const override { return 0; } - - Alloc_return alloc_aligned(size_t, void **, int, addr_t, addr_t) override { - return Alloc_return::RANGE_CONFLICT; } -}; - - -/** - * Required by Irq_proxy if we would like to have a thread per IRQ, - * which we don't want to in the platform driver - one thread is sufficient. - */ -class NoThread -{ - public: - - NoThread(const char *) { } - - void start(void) { } -}; - - -/** - * Thread waiting for signals caused by IRQs - */ -class Platform::Irq_thread : public Genode::Thread_deprecated<4096> -{ - private: - - Genode::Signal_receiver _sig_rec; - - public: - - Irq_thread() : Thread_deprecated<4096>("irq_sig_recv") { start(); } - - Genode::Signal_receiver & sig_rec() { return _sig_rec; } - - void entry() { - - typedef Genode::Signal_dispatcher_base Sdb; - - while (1) { - Genode::Signal sig = _sig_rec.wait_for_signal(); - - Sdb *dispatcher = dynamic_cast(sig.context()); - - if (!dispatcher) { - Genode::error("dispatcher missing for signal ", - sig.context(), " ", sig.num()); - continue; - } - dispatcher->dispatch(sig.num()); + return false; } } }; @@ -144,20 +80,17 @@ class Platform::Irq_thread : public Genode::Thread_deprecated<4096> * for Genode signals of all hardware IRQs. */ static Platform::Irq_allocator irq_alloc; -static Platform::Irq_thread irq_thread; /** * Irq_proxy interface implementation */ -typedef Genode::Irq_proxy Proxy; - -class Platform::Irq_component : public Proxy +class Platform::Irq_component : public Platform::Irq_proxy { private: Genode::Irq_connection _irq; - Genode::Signal_dispatcher _irq_dispatcher; + Genode::Signal_handler _irq_dispatcher; bool _associated; @@ -178,11 +111,8 @@ class Platform::Irq_component : public Proxy _irq.ack_irq(); } - bool _associate() { return _associated; } - void _wait_for_irq() { } - - virtual bool remove_sharer(Genode::Irq_sigh *s) override { - if (!Proxy::remove_sharer(s)) + virtual bool remove_sharer(Platform::Irq_sigh *s) override { + if (!Irq_proxy::remove_sharer(s)) return false; /* De-associate handler. */ @@ -193,15 +123,42 @@ class Platform::Irq_component : public Proxy public: - Irq_component(unsigned gsi, Genode::Irq_session::Trigger trigger, + Irq_component(Genode::Env &env, unsigned gsi, + Genode::Irq_session::Trigger trigger, Genode::Irq_session::Polarity polarity) : - Proxy(gsi), - _irq(gsi, trigger, polarity), - _irq_dispatcher(irq_thread.sig_rec(), *this, - &::Proxy::notify_about_irq), + Irq_proxy(gsi), + _irq(env, gsi, trigger, polarity), + _irq_dispatcher(env.ep(), *this, &Platform::Irq_proxy::notify_about_irq), _associated(false) { } + + static Irq_component *get_irq_proxy(unsigned irq_number, + Irq_allocator *irq_alloc = nullptr, + Genode::Irq_session::Trigger trigger = Genode::Irq_session::TRIGGER_UNCHANGED, + Genode::Irq_session::Polarity polarity = Genode::Irq_session::POLARITY_UNCHANGED, + Genode::Env *env = nullptr, + Genode::Allocator *heap = nullptr) + { + static Genode::List proxies; + static Genode::Lock proxies_lock; + + Genode::Lock::Guard lock_guard(proxies_lock); + + /* lookup proxy in database */ + for (Irq_proxy *p = proxies.first(); p; p = p->next()) + if (p->irq_number() == irq_number) + return static_cast(p); + + /* try to create proxy */ + if (!irq_alloc || !env || !heap || !irq_alloc->alloc_irq(irq_number)) + return 0; + + Irq_component *new_proxy = new (heap) Irq_component(*env, irq_number, trigger, + polarity); + proxies.insert(new_proxy); + return new_proxy; + } }; @@ -218,7 +175,7 @@ void Platform::Irq_session_component::ack_irq() } /* shared irq handling */ - Irq_component *irq_obj = Proxy::get_irq_proxy(_gsi); + Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi); if (!irq_obj) { Genode::error("expected to find IRQ proxy for IRQ ", Genode::Hex(_gsi)); return; @@ -230,7 +187,9 @@ void Platform::Irq_session_component::ack_irq() Platform::Irq_session_component::Irq_session_component(unsigned irq, - addr_t pci_config_space) + addr_t pci_config_space, + Genode::Env &env, + Genode::Allocator &heap) : _gsi(irq) { @@ -245,7 +204,7 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq, try { using namespace Genode; - _irq_conn.construct(msi, Irq_session::TRIGGER_UNCHANGED, + _irq_conn.construct(env, msi, Irq_session::TRIGGER_UNCHANGED, Irq_session::POLARITY_UNCHANGED, pci_config_space); @@ -273,8 +232,8 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq, try { /* check if shared IRQ object was used before */ - if (Proxy::get_irq_proxy(_gsi, &irq_alloc, trigger, - polarity)) + if (Irq_component::get_irq_proxy(_gsi, &irq_alloc, trigger, + polarity, &env, &heap)) return; } catch (Genode::Parent::Service_denied) { } @@ -292,7 +251,7 @@ Platform::Irq_session_component::~Irq_session_component() } /* shared irq handling */ - Irq_component *irq_obj = Proxy::get_irq_proxy(_gsi); + Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi); if (!irq_obj) return; if (_irq_sigh.valid()) @@ -309,7 +268,7 @@ void Platform::Irq_session_component::sigh(Genode::Signal_context_capability sig } /* shared irq handling */ - Irq_component *irq_obj = Proxy::get_irq_proxy(_gsi); + Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi); if (!irq_obj) { Genode::error("signal handler got not registered - irq object unavailable"); return; diff --git a/repos/os/src/drivers/platform/spec/x86/irq.h b/repos/os/src/drivers/platform/spec/x86/irq.h index ec26bef555..8bd69ce650 100644 --- a/repos/os/src/drivers/platform/spec/x86/irq.h +++ b/repos/os/src/drivers/platform/spec/x86/irq.h @@ -34,7 +34,7 @@ class Platform::Irq_session_component : public Genode::Rpc_object _irq_conn; @@ -43,7 +43,8 @@ class Platform::Irq_session_component : public Genode::Rpc_object - - -namespace Genode { +namespace Platform { class Irq_sigh; - template class Irq_proxy; + class Irq_proxy; } -class Genode::Irq_sigh : public Genode::Signal_context_capability, - public Genode::List::Element +class Platform::Irq_sigh : public Genode::Signal_context_capability, + public Genode::List::Element { public: - inline Irq_sigh * operator= (const Signal_context_capability &cap) + inline Irq_sigh * operator= (const Genode::Signal_context_capability &cap) { - Signal_context_capability::operator=(cap); + Genode::Signal_context_capability::operator=(cap); return this; } @@ -47,121 +44,37 @@ class Genode::Irq_sigh : public Genode::Signal_context_capability, * * XXX resources are not accounted as the interrupt is shared */ -template -class Genode::Irq_proxy : public THREAD, - public Genode::List >::Element +class Platform::Irq_proxy : public Genode::List::Element { protected: - char _name[32]; - Lock _startup_lock; - unsigned _irq_number; - Lock _mutex; /* protects this object */ + Genode::Lock _mutex; /* protects this object */ int _num_sharers; /* number of clients sharing this IRQ */ - Semaphore _sleep; /* wake me up if aspired blockers return */ - List _sigh_list; + Genode::List _sigh_list; int _num_acknowledgers; /* number of currently blocked clients */ bool _woken_up; /* client decided to wake me up - this prevents multiple wakeups to happen during initialization */ - /*************** - ** Interface ** - ***************/ - - /** - * Request interrupt - * - * \return true on success - */ - virtual bool _associate() = 0; - - /** - * Wait for associated interrupt - */ - virtual void _wait_for_irq() = 0; - - /** - * Acknowledge interrupt - */ - virtual void _ack_irq() = 0; - - /******************** - ** Implementation ** - ********************/ - - const char *_construct_name(unsigned irq_number) - { - snprintf(_name, sizeof(_name), "irqproxy%02x", irq_number); - return _name; - } - - void _loop() - { - /* wait for first blocker */ - _sleep.down(); - - while (1) { - _wait_for_irq(); - - /* notify all */ - notify_about_irq(1); - - /* - * We must wait for all clients to ack their interrupt, - * otherwise level-triggered interrupts will occur immediately - * after acknowledgement. That's an inherent security problem - * with shared IRQs and induces problems with dynamic driver - * load and unload. - */ - _sleep.down(); - - /* acknowledge previous interrupt */ - _ack_irq(); - } - } - - /** - * Start this thread, should be called externally from derived class - */ - virtual void _start() - { - THREAD::start(); - _startup_lock.lock(); - } - public: Irq_proxy(unsigned irq_number) : - THREAD(_construct_name(irq_number)), - _startup_lock(Lock::LOCKED), _irq_number(irq_number), - _mutex(Lock::UNLOCKED), _num_sharers(0), _num_acknowledgers(0), _woken_up(false) + _irq_number(irq_number), + _mutex(Genode::Lock::UNLOCKED), _num_sharers(0), + _num_acknowledgers(0), _woken_up(false) { } - /** - * Thread interface - */ - void entry() - { - bool const associate_suceeded = _associate(); - - _startup_lock.unlock(); - - if (associate_suceeded) - _loop(); - } - /** * Acknowledgements of clients */ virtual bool ack_irq() { - Lock::Guard lock_guard(_mutex); + Genode::Lock::Guard lock_guard(_mutex); _num_acknowledgers++; @@ -170,7 +83,6 @@ class Genode::Irq_proxy : public THREAD, * before and this client is the last aspired acknowledger. */ if (!_woken_up && _num_acknowledgers == _num_sharers) { - _sleep.up(); _woken_up = true; } @@ -180,9 +92,9 @@ class Genode::Irq_proxy : public THREAD, /** * Notify all clients about irq */ - void notify_about_irq(unsigned) + void notify_about_irq() { - Lock::Guard lock_guard(_mutex); + Genode::Lock::Guard lock_guard(_mutex); /* reset acknowledger state */ _num_acknowledgers = 0; @@ -197,7 +109,7 @@ class Genode::Irq_proxy : public THREAD, virtual bool add_sharer(Irq_sigh *s) { - Lock::Guard lock_guard(_mutex); + Genode::Lock::Guard lock_guard(_mutex); ++_num_sharers; _sigh_list.insert(s); @@ -207,7 +119,7 @@ class Genode::Irq_proxy : public THREAD, virtual bool remove_sharer(Irq_sigh *s) { - Lock::Guard lock_guard(_mutex); + Genode::Lock::Guard lock_guard(_mutex); _sigh_list.remove(s); --_num_sharers; @@ -216,38 +128,11 @@ class Genode::Irq_proxy : public THREAD, return _num_sharers == 0; if (_num_acknowledgers == _num_sharers) { - _sleep.up(); _woken_up = true; } return _num_sharers == 0; } - - template - static PROXY *get_irq_proxy(unsigned irq_number, - Range_allocator *irq_alloc = 0, - Genode::Irq_session::Trigger trigger = Genode::Irq_session::TRIGGER_UNCHANGED, - Genode::Irq_session::Polarity polarity = Genode::Irq_session::POLARITY_UNCHANGED) - { - static List proxies; - static Lock proxies_lock; - - Lock::Guard lock_guard(proxies_lock); - - /* lookup proxy in database */ - for (Irq_proxy *p = proxies.first(); p; p = p->next()) - if (p->irq_number() == irq_number) - return static_cast(p); - - /* try to create proxy */ - if (!irq_alloc || irq_alloc->alloc_addr(1, irq_number).error()) - return 0; - - PROXY *new_proxy = new (env()->heap()) PROXY(irq_number, trigger, - polarity); - proxies.insert(new_proxy); - return new_proxy; - } }; #endif /* _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_ */ diff --git a/repos/os/src/drivers/platform/spec/x86/main.cc b/repos/os/src/drivers/platform/spec/x86/main.cc index d02d9af770..fcd6a6c221 100644 --- a/repos/os/src/drivers/platform/spec/x86/main.cc +++ b/repos/os/src/drivers/platform/spec/x86/main.cc @@ -11,13 +11,12 @@ * under the terms of the GNU General Public License version 2. */ +#include #include #include #include -#include - #include "pci_session_component.h" #include "pci_device_config.h" #include "device_pd.h" @@ -119,15 +118,15 @@ struct Platform::Main if (_system_rom) { /* wait for system state changes, e.g. reset and acpi_ready */ - system_state.construct("system"); + system_state.construct(env, "system"); system_state->sigh(_system_report); - acpi_ready.construct("acpi_ready"); + acpi_ready.construct(env, "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.construct(env, "acpi"); acpi_rom->sigh(_acpi_report); /* check if already valid */ acpi_update(); diff --git a/repos/os/src/drivers/platform/spec/x86/nonpci_devices.cc b/repos/os/src/drivers/platform/spec/x86/nonpci_devices.cc index 2901c42f1a..a304112fcc 100644 --- a/repos/os/src/drivers/platform/spec/x86/nonpci_devices.cc +++ b/repos/os/src/drivers/platform/spec/x86/nonpci_devices.cc @@ -36,12 +36,14 @@ class Nonpci::Ps2 : public Platform::Device_component public: - Ps2(Genode::Rpc_entrypoint &ep, Platform::Session_component &session) + Ps2(Genode::Env &env, Platform::Session_component &session, + Genode::Allocator &heap_for_irq) : - Platform::Device_component(ep, session, IRQ_KEYBOARD), - _ep(ep), - _irq_mouse(IRQ_MOUSE, ~0UL), - _data(REG_DATA, ACCESS_WIDTH), _status(REG_STATUS, ACCESS_WIDTH) + Platform::Device_component(env, session, IRQ_KEYBOARD, heap_for_irq), + _ep(env.ep().rpc_ep()), + _irq_mouse(IRQ_MOUSE, ~0UL, env, heap_for_irq), + _data(env, REG_DATA, ACCESS_WIDTH), + _status(env, REG_STATUS, ACCESS_WIDTH) { _ep.manage(&_irq_mouse); } @@ -97,10 +99,11 @@ class Nonpci::Pit : public Platform::Device_component public: - Pit(Genode::Rpc_entrypoint &ep, Platform::Session_component &session) + Pit(Genode::Env &env, Platform::Session_component &session, + Genode::Allocator &heap_for_irq) : - Platform::Device_component(ep, session, IRQ_PIT), - _ports(PIT_PORT, PORTS_WIDTH) + Platform::Device_component(env, session, IRQ_PIT, heap_for_irq), + _ports(env, PIT_PORT, PORTS_WIDTH) { } Genode::Io_port_session_capability io_port(Genode::uint8_t io_port) override @@ -147,17 +150,17 @@ Platform::Device_capability Platform::Session_component::device(String const &na switch(devices_i) { case 0: - dev = new (_md_alloc) Nonpci::Ps2(_ep, *this); + dev = new (_md_alloc) Nonpci::Ps2(_env, *this, _global_heap); break; case 1: - dev = new (_md_alloc) Nonpci::Pit(_ep, *this); + dev = new (_md_alloc) Nonpci::Pit(_env, *this, _global_heap); break; default: return Device_capability(); } _device_list.insert(dev); - return _ep.manage(dev); + return _env.ep().rpc_ep().manage(dev); } catch (Genode::Allocator::Out_of_memory) { throw Out_of_metadata(); } catch (Genode::Parent::Service_denied) { diff --git a/repos/os/src/drivers/platform/spec/x86/pci_config_access.h b/repos/os/src/drivers/platform/spec/x86/pci_config_access.h index dd1b427464..98788113c4 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_config_access.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_config_access.h @@ -24,6 +24,8 @@ namespace Platform { { private: + Genode::Env &_env; + enum { REG_ADDR = 0xcf8, REG_DATA = 0xcfc, REG_SIZE = 4 }; /** @@ -47,7 +49,7 @@ namespace Platform { * Once created, each I/O-port session persists until * the PCI driver gets killed by its parent. */ - static Genode::Io_port_connection io_port(port, REG_SIZE); + static Genode::Io_port_connection io_port(_env, port, REG_SIZE); return &io_port; } @@ -79,6 +81,8 @@ namespace Platform { public: + Config_access(Genode::Env &env) : _env(env) { } + /** * Read value from config space of specified device/function * diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device.cc b/repos/os/src/drivers/platform/spec/x86/pci_device.cc index e2af26d762..fd482df048 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device.cc +++ b/repos/os/src/drivers/platform/spec/x86/pci_device.cc @@ -32,7 +32,7 @@ Genode::Io_port_session_capability Platform::Device_component::io_port(Genode::u return _io_port_conn[v_id]->cap(); try { - _io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(res.base(), res.size()); + _io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(_env, res.base(), res.size()); return _io_port_conn[v_id]->cap(); } catch (...) { return Genode::Io_port_session_capability(); @@ -68,7 +68,8 @@ Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uin try { bool const wc = caching == Genode::Cache_attribute::WRITE_COMBINED; - Io_mem * io_mem = new (_slab_iomem) Io_mem(res.base() + offset, + Io_mem * io_mem = new (_slab_iomem) Io_mem(_env, + res.base() + offset, res_size, wc); _io_mem[i].insert(io_mem); return io_mem->cap(); @@ -144,16 +145,19 @@ Genode::Irq_session_capability Platform::Device_component::irq(Genode::uint8_t i if (!_device_config.valid()) { /* Non PCI devices */ _irq_session = construct_at(_mem_irq_component, - _irq_line, ~0UL); + _irq_line, ~0UL, + _env, + _global_heap); - _ep.manage(_irq_session); + _env.ep().rpc_ep().manage(_irq_session); return _irq_session->cap(); } _irq_session = construct_at(_mem_irq_component, _configure_irq(_irq_line), - (!_session.msi_usage() || !_msi_cap()) ? ~0UL : _config_space); - _ep.manage(_irq_session); + (!_session.msi_usage() || !_msi_cap()) ? ~0UL : _config_space, + _env, _global_heap); + _env.ep().rpc_ep().manage(_irq_session); Genode::uint16_t msi_cap = _msi_cap(); diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h index 8eeb8ec192..0f7a8dea75 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h @@ -34,22 +34,25 @@ class Platform::Device_component : public Genode::Rpc_object, { private: + Genode::Env &_env; Device_config _device_config; Genode::addr_t _config_space; - Config_access _config_access; - Genode::Rpc_entrypoint &_ep; + Config_access _config_access = { _env }; Platform::Session_component &_session; unsigned short _irq_line; Irq_session_component *_irq_session = nullptr; Genode::Constructible _io_mem_config_extended; + Genode::Allocator &_global_heap; + class Io_mem : public Genode::Io_mem_connection, public Genode::List::Element { public: - Io_mem (Genode::addr_t base, Genode::size_t size, bool wc) - : Genode::Io_mem_connection(base, size, wc) { } + Io_mem (Genode::Env &env, Genode::addr_t base, + Genode::size_t size, bool wc) + : Genode::Io_mem_connection(env, base, size, wc) { } }; enum { @@ -182,15 +185,18 @@ class Platform::Device_component : public Genode::Rpc_object, /** * Constructor */ - Device_component(Device_config device_config, Genode::addr_t addr, - Genode::Rpc_entrypoint &ep, + Device_component(Genode::Env &env, + Device_config device_config, Genode::addr_t addr, Platform::Session_component &session, - Genode::Allocator &md_alloc) + Genode::Allocator &md_alloc, + Genode::Allocator &global_heap) : + _env(env), _device_config(device_config), _config_space(addr), - _ep(ep), _session(session), + _session(session), _irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE, Platform::Device::ACCESS_8BIT)), + _global_heap(global_heap), _slab_ioport(&md_alloc, &_slab_ioport_block_data), _slab_iomem(&md_alloc, &_slab_iomem_block_data) { @@ -204,12 +210,15 @@ class Platform::Device_component : public Genode::Rpc_object, /** * Constructor for non PCI devices */ - Device_component(Genode::Rpc_entrypoint &ep, - Platform::Session_component &session, unsigned irq) + Device_component(Genode::Env &env, + Platform::Session_component &session, unsigned irq, + Genode::Allocator &global_heap) : + _env(env), _config_space(~0UL), - _ep(ep), _session(session), + _session(session), _irq_line(irq), + _global_heap(global_heap), _slab_ioport(nullptr, &_slab_ioport_block_data), _slab_iomem(nullptr, &_slab_iomem_block_data) { @@ -223,7 +232,7 @@ class Platform::Device_component : public Genode::Rpc_object, ~Device_component() { if (_irq_session) { - _ep.dissolve(_irq_session); + _env.ep().rpc_ep().dissolve(_irq_session); _irq_session->~Irq_session(); } @@ -254,7 +263,7 @@ class Platform::Device_component : public Genode::Rpc_object, if (!_io_mem_config_extended.constructed()) { try { - _io_mem_config_extended.construct(_config_space, 0x1000); + _io_mem_config_extended.construct(_env, _config_space, 0x1000); } catch (...) { _config_space = ~0UL; } diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device_pd_ipc.h b/repos/os/src/drivers/platform/spec/x86/pci_device_pd_ipc.h index 9288cd0d2c..b9bb6762a6 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device_pd_ipc.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_device_pd_ipc.h @@ -72,10 +72,11 @@ struct Platform::Device_pd_connection : Genode::Connection, Device_pd struct Platform::Device_pd_component : Genode::Rpc_object { + Genode::Env &_env; Genode::Region_map &_address_space; - Device_pd_component(Genode::Region_map &address_space) - : _address_space(address_space) { } + Device_pd_component(Genode::Region_map &address_space, Genode::Env &env) + : _env(env), _address_space(address_space) { } void attach_dma_mem(Genode::Dataspace_capability); void assign_pci(Genode::Io_mem_dataspace_capability, Genode::uint16_t); diff --git a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h index 458741f446..ba103858fa 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h @@ -37,12 +37,13 @@ #include "device_pd.h" namespace Platform { - bool bus_valid(int bus = 0); unsigned short bridge_bdf(unsigned char bus); + class Pci_buses; + class Ram_dataspace; class Rmrr; class Root; - class Ram_dataspace; + class Session_component; } class Platform::Ram_dataspace : public Genode::List::Element { @@ -92,7 +93,8 @@ class Platform::Rmrr : public Genode::List::Element : _start(start), _end(end) { } - Genode::Io_mem_dataspace_capability match(Device_config config) + Genode::Io_mem_dataspace_capability match(Genode::Env &env, + Device_config config) { Genode::uint8_t bus = config.bus_number(); Genode::uint8_t device = config.device_number(); @@ -105,7 +107,7 @@ class Platform::Rmrr : public Genode::List::Element if (_cap.valid()) return _cap; - _io_mem.construct(_start, _end - _start + 1); + _io_mem.construct(env, _start, _end - _start + 1); _cap = _io_mem->dataspace(); return _cap; } @@ -122,13 +124,79 @@ class Platform::Rmrr : public Genode::List::Element }; -namespace Platform { class Session_component; } +class Platform::Pci_buses +{ + private: + + Genode::Bit_array _valid; + + void scan_bus(Config_access &config_access, Genode::Allocator &heap, + unsigned char bus = 0); + + bool _bus_valid(int bus) + { + if (bus >= Device_config::MAX_BUSES) + return false; + + return _valid.get(bus, 1); + } + + public: + + Pci_buses(Genode::Env &env, Genode::Allocator &heap) + { + Config_access c(env); + scan_bus(c, heap); + } + + /** + * Scan PCI buses for a device + * + * \param bus start scanning at bus number + * \param device start scanning at device number + * \param function start scanning at function number + * \param out_device_config device config information of the + * found device + * \param config_access interface for accessing the PCI + * configuration + * space + * + * \retval true device was found + * \retval false no device was found + */ + bool find_next(int bus, int device, int function, + Device_config *out_device_config, + Config_access *config_access) + { + for (; bus < Device_config::MAX_BUSES; bus++) { + if (!_bus_valid(bus)) + continue; + + for (; device < Device_config::MAX_DEVICES; device++) { + for (; function < Device_config::MAX_FUNCTIONS; function++) { + + /* read config space */ + Device_config config(bus, device, function, config_access); + + if (config.valid()) { + *out_device_config = config; + return true; + } + } + function = 0; /* init value for next device */ + } + device = 0; /* init value for next bus */ + } + return false; + } +}; + class Platform::Session_component : public Genode::Rpc_object { private: - Genode::Rpc_entrypoint &_ep; + Genode::Env &_env; Genode::Rpc_entrypoint &_device_pd_ep; Genode::Ram_session_guard _env_ram; Genode::Ram_session_capability _env_ram_cap; @@ -137,6 +205,8 @@ class Platform::Session_component : public Genode::Rpc_object Genode::Session_label const _label; Genode::Session_policy const _policy { _label }; Genode::List _device_list; + Platform::Pci_buses &_pci_bus; + Genode::Heap &_global_heap; bool _no_device_pd = false; /** @@ -167,8 +237,8 @@ class Platform::Session_component : public Genode::Rpc_object * * Restrict physical address to 3G on 32bit, 4G on 64bit */ - Genode::Ram_connection _ram { - _label.string(), 0, (sizeof(void *) == 4) ? 0xc0000000UL : 0x100000000UL }; + Genode::Ram_connection _ram { _env, _label.string(), 0, + (sizeof(void *) == 4) ? 0xc0000000UL : 0x100000000UL }; /* * Associate session RAM session with platform_drv _ram session and @@ -319,46 +389,6 @@ class Platform::Session_component : public Genode::Rpc_object static Genode::Bit_array bdf_in_use; - /** - * Scan PCI buses for a device - * - * \param bus start scanning at bus number - * \param device start scanning at device number - * \param function start scanning at function number - * \param out_device_config device config information of the - * found device - * \param config_access interface for accessing the PCI - * configuration - * space - * - * \retval true device was found - * \retval false no device was found - */ - bool _find_next(int bus, int device, int function, - Device_config *out_device_config, - Config_access *config_access) - { - for (; bus < Device_config::MAX_BUSES; bus++) { - if (!bus_valid(bus)) - continue; - - for (; device < Device_config::MAX_DEVICES; device++) { - for (; function < Device_config::MAX_FUNCTIONS; function++) { - - /* read config space */ - Device_config config(bus, device, function, config_access); - - if (config.valid()) { - *out_device_config = config; - return true; - } - } - function = 0; /* init value for next device */ - } - device = 0; /* init value for next bus */ - } - return false; - } /** * List containing extended PCI config space information @@ -564,18 +594,20 @@ class Platform::Session_component : public Genode::Rpc_object /** * Constructor */ - Session_component(Genode::Env &env, - Genode::Rpc_entrypoint &ep, + Session_component(Genode::Env &env, Genode::Rpc_entrypoint &device_pd_ep, + Platform::Pci_buses &buses, + Genode::Heap &global_heap, char const *args) : - _ep(ep), _device_pd_ep(device_pd_ep), + _env(env), _device_pd_ep(device_pd_ep), _env_ram(env.ram(), env.ram_session_cap(), Genode::Arg_string::find_arg(args, "ram_quota").long_value(0)), _env_ram_cap(env.ram_session_cap()), _local_rm(env.rm()), _md_alloc(_env_ram, env.rm()), - _label(Genode::label_from_args(args)) + _label(Genode::label_from_args(args)), + _pci_bus(buses), _global_heap(global_heap) { /* non-pci devices */ _policy.for_each_sub_node("device", [&] (Genode::Xml_node device_node) { @@ -689,12 +721,12 @@ class Platform::Session_component : public Genode::Rpc_object static void add_config_space(Genode::uint32_t bdf_start, Genode::uint32_t func_count, - Genode::addr_t base) + Genode::addr_t base, + Genode::Allocator &heap) { using namespace Genode; Config_space * space = - new (env()->heap()) Config_space(bdf_start, func_count, - base); + new (heap) Config_space(bdf_start, func_count, base); config_space_list().insert(space); } @@ -731,7 +763,7 @@ class Platform::Session_component : public Genode::Rpc_object * Create the interface to the PCI config space. * This involves the creation of I/O port sessions. */ - Config_access config_access; + Config_access config_access(_env); /* lookup device component for previous device */ auto lambda = [&] (Device_component *prev) @@ -759,8 +791,8 @@ class Platform::Session_component : public Genode::Rpc_object while (true) { function += 1; - if (!_find_next(bus, device, function, &config, - &config_access)) + if (!_pci_bus.find_next(bus, device, function, &config, + &config_access)) return Device_capability(); /* get new bdf values */ @@ -788,8 +820,8 @@ class Platform::Session_component : public Genode::Rpc_object */ try { Device_component * dev = new (_md_alloc) - Device_component(config, config_space, _ep, *this, - _md_alloc); + Device_component(_env, config, config_space, *this, + _md_alloc, _global_heap); /* if more than one driver uses the device - warn about */ if (bdf_in_use.get(Device_config::MAX_BUSES * bus + @@ -806,12 +838,12 @@ class Platform::Session_component : public Genode::Rpc_object function, 1); _device_list.insert(dev); - return _ep.manage(dev); + return _env.ep().rpc_ep().manage(dev); } catch (Genode::Allocator::Out_of_memory) { throw Out_of_metadata(); } }; - return _ep.apply(prev_device, lambda); + return _env.ep().rpc_ep().apply(prev_device, lambda); } void release_device(Device_capability device_cap) override @@ -834,11 +866,11 @@ class Platform::Session_component : public Genode::Rpc_object Device_config::MAX_DEVICES * dev + func, 1); _device_list.remove(device); - _ep.dissolve(device); + _env.ep().rpc_ep().dissolve(device); }; /* lookup device component for previous device */ - _ep.apply(device_cap, lambda); + _env.ep().rpc_ep().apply(device_cap, lambda); if (!device) return; @@ -865,7 +897,7 @@ class Platform::Session_component : public Genode::Rpc_object _device_pd->session().assign_pci(io_mem, device->config().bdf()); for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) { - Io_mem_dataspace_capability rmrr_cap = r->match(device->config()); + Io_mem_dataspace_capability rmrr_cap = r->match(_env, device->config()); if (rmrr_cap.valid()) _device_pd->session().attach_dma_mem(rmrr_cap); } @@ -991,12 +1023,14 @@ class Platform::Root : public Genode::Root_component Genode::Env &_env; Genode::Rpc_entrypoint _device_pd_ep; + Genode::Heap _heap { _env.ram(), _env.rm() }; + Platform::Pci_buses _buses { _env, _heap }; - void _parse_report_rom(const char * acpi_rom) + void _parse_report_rom(Genode::Env &env, const char * acpi_rom) { using namespace Genode; - Config_access config_access; + Config_access config_access(env); Xml_node xml_acpi(acpi_rom); if (!xml_acpi.has_type("acpi")) @@ -1016,7 +1050,7 @@ class Platform::Root : public Genode::Root_component node.attribute("base").value(&base); Session_component::add_config_space(bdf_start, func_count, - base); + base, _heap); } if (node.has_type("irq_override")) { @@ -1029,9 +1063,8 @@ class Platform::Root : public Genode::Root_component node.attribute("flags").value(&flags); using Platform::Irq_override; - Irq_override * o = new (env()->heap()) Irq_override(irq, - gsi, - flags); + Irq_override * o = new (_heap) Irq_override(irq, gsi, + flags); Irq_override::list()->insert(o); } @@ -1043,7 +1076,7 @@ class Platform::Root : public Genode::Root_component if (node.num_sub_nodes() == 0) throw 2; - Rmrr * rmrr = new (env()->heap()) Rmrr(mem_start, mem_end); + Rmrr * rmrr = new (_heap) Rmrr(mem_start, mem_end); Rmrr::list()->insert(rmrr); for (unsigned s = 0; s < node.num_sub_nodes(); s++) { @@ -1070,8 +1103,7 @@ class Platform::Root : public Genode::Root_component Device::ACCESS_8BIT); } - rmrr->add(new (env()->heap()) Rmrr::Bdf(bus, dev, - func)); + rmrr->add(new (_heap) Rmrr::Bdf(bus, dev, func)); } } @@ -1116,10 +1148,8 @@ class Platform::Root : public Genode::Root_component */ bridge_bdf = 0; - Irq_routing * r = new (env()->heap()) Irq_routing(gsi, - bridge_bdf, - device, - device_pin); + Irq_routing * r = new (_heap) Irq_routing(gsi, bridge_bdf, + device, device_pin); Irq_routing::list()->insert(r); } } @@ -1130,7 +1160,7 @@ class Platform::Root : public Genode::Root_component { try { return new (md_alloc()) - Session_component(_env, *ep(), _device_pd_ep, args); + Session_component(_env, _device_pd_ep, _buses, _heap, args); } catch (Genode::Session_policy::No_policy_defined) { Genode::error("Invalid session request, no matching policy for ", @@ -1164,12 +1194,9 @@ class Platform::Root : public Genode::Root_component _env(env), _device_pd_ep(&env.pd(), STACK_SIZE, "device_pd_slave") { - /* enforce initial bus scan */ - bus_valid(); - if (acpi_rom) { try { - _parse_report_rom(acpi_rom); + _parse_report_rom(env, acpi_rom); } catch (...) { Genode::error("PCI config space data could not be parsed."); } @@ -1183,7 +1210,7 @@ class Platform::Root : public Genode::Root_component if (!io_port_space) return; - Config_access config_access; + Config_access config_access(_env); const unsigned raw_access_size = Fadt::Gas::Access_size::get(fadt.reset_type); const bool reset_support = config_access.reset_support(fadt.reset_addr, raw_access_size); if (!reset_support) diff --git a/repos/os/src/drivers/platform/spec/x86/session.cc b/repos/os/src/drivers/platform/spec/x86/session.cc index e51228a58c..e09b2dbc64 100644 --- a/repos/os/src/drivers/platform/spec/x86/session.cc +++ b/repos/os/src/drivers/platform/spec/x86/session.cc @@ -33,57 +33,40 @@ unsigned short Platform::bridge_bdf(unsigned char bus) return 0; } - -/** - * Check if given PCI bus was found on initial scan - * - * This tremendously speeds up further scans by other drivers. - */ -bool Platform::bus_valid(int bus) +void Platform::Pci_buses::scan_bus(Config_access &config_access, + Genode::Allocator &heap, unsigned char bus) { - struct Valid_buses - { - bool valid[Device_config::MAX_BUSES]; + for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) { + for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) { - void scan_bus(Config_access &config_access, unsigned char bus = 0) - { - for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) { - for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) { + /* read config space */ + Device_config config(bus, dev, fun, &config_access); - /* read config space */ - Device_config config(bus, dev, fun, &config_access); + if (!config.valid()) + continue; - if (!config.valid()) - continue; + /* + * There is at least one device on the current bus, so + * we mark it as valid. + */ + if (!_valid.get(bus, 1)) + _valid.set(bus, 1); - /* - * There is at least one device on the current bus, so - * we mark it as valid. - */ - valid[bus] = true; + /* scan behind bridge */ + if (config.pci_bridge()) { + /* PCI bridge spec 3.2.5.3, 3.2.5.4 */ + unsigned char sec_bus = config.read(&config_access, 0x19, + Device::ACCESS_8BIT); + unsigned char sub_bus = config.read(&config_access, 0x20, + Device::ACCESS_8BIT); - /* scan behind bridge */ - if (config.pci_bridge()) { - /* PCI bridge spec 3.2.5.3, 3.2.5.4 */ - unsigned char sec_bus = config.read(&config_access, - 0x19, Device::ACCESS_8BIT); - unsigned char sub_bus = config.read(&config_access, - 0x20, Device::ACCESS_8BIT); + bridges()->insert(new (heap) Bridge(bus, dev, fun, sec_bus, + sub_bus)); - bridges()->insert(new (Genode::env()->heap()) Bridge(bus, dev, fun, sec_bus, sub_bus)); - - scan_bus(config_access, sec_bus); - } - } + scan_bus(config_access, heap, sec_bus); } } - - Valid_buses() { Config_access c; scan_bus(c); } - }; - - static Valid_buses buses; - - return buses.valid[bus]; + } }