From b80146a6f72f713dfbd362b158c1eee6ec045930 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Thu, 3 Mar 2022 16:11:32 +0100 Subject: [PATCH] genode_c_api: unify shared dataspace callbacks * Unifies the declaration of callbacks which manage driver/client shared dataspaces * Move the Linux driver-specific callback implementation to the lx_emul library from the PC's USB host driver Fix genodelabs/genode#4439 --- .../src/include/lx_emul/shared_dma_buffer.h | 32 +++++ .../src/lib/lx_emul/shared_dma_buffer.cc | 58 +++++++++ repos/os/include/genode_c_api/base.h | 36 ++++-- repos/os/include/genode_c_api/block.h | 16 +-- repos/os/include/genode_c_api/usb.h | 26 +--- repos/os/src/lib/genode_c_api/block.cc | 122 ++++++++++-------- repos/os/src/lib/genode_c_api/usb.cc | 25 ++-- repos/pc/src/drivers/usb_host/pc/main.cc | 28 +--- repos/pc/src/drivers/usb_host/pc/target.inc | 4 +- repos/pc/src/drivers/usb_host/pc/usb.c | 9 +- repos/pc/src/drivers/usb_host/pc/usb.h | 32 ----- 11 files changed, 221 insertions(+), 167 deletions(-) create mode 100644 repos/dde_linux/src/include/lx_emul/shared_dma_buffer.h create mode 100644 repos/dde_linux/src/lib/lx_emul/shared_dma_buffer.cc delete mode 100644 repos/pc/src/drivers/usb_host/pc/usb.h diff --git a/repos/dde_linux/src/include/lx_emul/shared_dma_buffer.h b/repos/dde_linux/src/include/lx_emul/shared_dma_buffer.h new file mode 100644 index 0000000000..1448745642 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/shared_dma_buffer.h @@ -0,0 +1,32 @@ +/* + * \brief Lx_emul support to allocate shared DMA buffer for Genode's C API + * \author Stefan Kalkowski + * \date 2022-03-02 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _LX_EMUL__SHARED_DMA_BUFFER_H_ +#define _LX_EMUL__SHARED_DMA_BUFFER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct genode_shared_dataspace * +lx_emul_shared_dma_buffer_allocate(unsigned long size); + +void lx_emul_shared_dma_buffer_free(struct genode_shared_dataspace * ds); + +#ifdef __cplusplus +} +#endif + +#endif /* _LX_EMUL__SHARED_DMA_BUFFER_H_ */ diff --git a/repos/dde_linux/src/lib/lx_emul/shared_dma_buffer.cc b/repos/dde_linux/src/lib/lx_emul/shared_dma_buffer.cc new file mode 100644 index 0000000000..a8b2217dae --- /dev/null +++ b/repos/dde_linux/src/lib/lx_emul/shared_dma_buffer.cc @@ -0,0 +1,58 @@ +/* + * \brief Lx_emul backend for shared dma buffers + * \author Stefan Kalkowski + * \date 2022-03-02 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include + +#include +#include +#include +#include + +struct genode_shared_dataspace : Genode::Attached_dataspace {}; + + +extern "C" struct genode_shared_dataspace * +lx_emul_shared_dma_buffer_allocate(unsigned long size) +{ + Genode::Attached_dataspace & ds = + Lx_kit::env().memory.alloc_dataspace(size); + + /* + * We have to call virt_to_pages eagerly here, + * to get contingous page objects registered + */ + lx_emul_virt_to_pages(ds.local_addr(), size >> 12); + return static_cast(&ds); +} + + +extern "C" void +lx_emul_shared_dma_buffer_free(struct genode_shared_dataspace * ds) +{ + lx_emul_forget_pages(ds->local_addr(), ds->size()); + Lx_kit::env().memory.free_dataspace(ds->local_addr()); +} + + +Genode::addr_t +genode_shared_dataspace_local_address(struct genode_shared_dataspace * ds) +{ + return (Genode::addr_t)ds->local_addr(); +} + + +Genode::Dataspace_capability +genode_shared_dataspace_capability(struct genode_shared_dataspace * ds) +{ + return ds->cap(); +} diff --git a/repos/os/include/genode_c_api/base.h b/repos/os/include/genode_c_api/base.h index a1835fc7a2..bf7ab2ad61 100644 --- a/repos/os/include/genode_c_api/base.h +++ b/repos/os/include/genode_c_api/base.h @@ -26,7 +26,7 @@ extern "C" { struct genode_env; struct genode_allocator; struct genode_signal_handler; -struct genode_attached_dataspace; +struct genode_shared_dataspace; #ifdef __cplusplus } /* extern "C" */ @@ -43,10 +43,9 @@ struct genode_attached_dataspace; #include #include -struct genode_env : Genode::Env { }; -struct genode_allocator : Genode::Allocator { }; -struct genode_signal_handler : Genode::Signal_dispatcher_base { }; -struct genode_attached_dataspace : Genode::Attached_dataspace { }; +struct genode_env : Genode::Env { }; +struct genode_allocator : Genode::Allocator { }; +struct genode_signal_handler : Genode::Signal_dispatcher_base { }; static inline auto genode_env_ptr(Genode::Env &env) { @@ -69,11 +68,30 @@ static inline Genode::Signal_context_capability cap(genode_signal_handler *sigh_ return *static_cast *>(dispatcher_ptr); } -static inline auto genode_attached_dataspace_ptr(Genode::Attached_dataspace &ds) -{ - return static_cast(&ds); -} +/** + * Returns local address of attached shared dataspace + */ +Genode::addr_t +genode_shared_dataspace_local_address(struct genode_shared_dataspace * ds); + +/** + * Returns capability of shared dataspace + */ +Genode::Dataspace_capability +genode_shared_dataspace_capability(struct genode_shared_dataspace * ds); #endif +/** + * Callback definition to allocate and attach a dataspace to share + */ +typedef struct genode_shared_dataspace * + (*genode_shared_dataspace_alloc_attach_t) (unsigned long size); + +/** + * Callback definition to detach and free dataspace + */ +typedef void + (*genode_shared_dataspace_free_t) (struct genode_shared_dataspace * ds); + #endif /* _INCLUDE__GENODE_C_API__BASE_H_ */ diff --git a/repos/os/include/genode_c_api/block.h b/repos/os/include/genode_c_api/block.h index e7e1a07728..b021790074 100644 --- a/repos/os/include/genode_c_api/block.h +++ b/repos/os/include/genode_c_api/block.h @@ -29,18 +29,6 @@ extern "C" { ** Initialization ** ********************/ -/** - * Callback called during peer session request to allocate dma-capable shared buffer - */ -typedef struct genode_attached_dataspace * (*genode_block_alloc_peer_buffer_t) - (unsigned long size); - -/** - * Callback called when closing peer session to free shared buffer - */ -typedef void (*genode_block_free_peer_buffer_t) - (struct genode_attached_dataspace * ds); - /** * Initialize block root component * @@ -49,8 +37,8 @@ typedef void (*genode_block_free_peer_buffer_t) void genode_block_init(struct genode_env *env, struct genode_allocator *alloc, struct genode_signal_handler *handler, - genode_block_alloc_peer_buffer_t, - genode_block_free_peer_buffer_t); + genode_shared_dataspace_alloc_attach_t, + genode_shared_dataspace_free_t); /************************************** diff --git a/repos/os/include/genode_c_api/usb.h b/repos/os/include/genode_c_api/usb.h index cd316acf09..36e3a39920 100644 --- a/repos/os/include/genode_c_api/usb.h +++ b/repos/os/include/genode_c_api/usb.h @@ -34,18 +34,6 @@ extern "C" { ** Initialization ** ********************/ -/** - * Callback called during peer session request to allocate dma-capable shared buffer - */ -typedef struct genode_attached_dataspace * (*genode_usb_alloc_peer_buffer_t) - (unsigned long size); - -/** - * Callback called when closing peer session to free shared buffer - */ -typedef void (*genode_usb_free_peer_buffer_t) - (struct genode_attached_dataspace * ds); - /** * Callback to copy over config descriptor for given device */ @@ -81,13 +69,13 @@ typedef int (*genode_usb_rpc_endp_desc_t) unsigned alt, unsigned endp, void * buf, unsigned long buf_size); struct genode_usb_rpc_callbacks { - genode_usb_alloc_peer_buffer_t alloc_fn; - genode_usb_free_peer_buffer_t free_fn; - genode_usb_rpc_config_desc_t cfg_desc_fn; - genode_usb_rpc_alt_settings_t alt_settings_fn; - genode_usb_rpc_iface_desc_t iface_desc_fn; - genode_usb_rpc_iface_extra_t iface_extra_fn; - genode_usb_rpc_endp_desc_t endp_desc_fn; + genode_shared_dataspace_alloc_attach_t alloc_fn; + genode_shared_dataspace_free_t free_fn; + genode_usb_rpc_config_desc_t cfg_desc_fn; + genode_usb_rpc_alt_settings_t alt_settings_fn; + genode_usb_rpc_iface_desc_t iface_desc_fn; + genode_usb_rpc_iface_extra_t iface_extra_fn; + genode_usb_rpc_endp_desc_t endp_desc_fn; }; /** diff --git a/repos/os/src/lib/genode_c_api/block.cc b/repos/os/src/lib/genode_c_api/block.cc index bb9e400f30..6f58a11fc6 100644 --- a/repos/os/src/lib/genode_c_api/block.cc +++ b/repos/os/src/lib/genode_c_api/block.cc @@ -24,55 +24,68 @@ using namespace Genode; -struct genode_block_session : Rpc_object +class genode_block_session : public Rpc_object { - enum { MAX_REQUESTS = 32 }; + private: - struct Request { - enum State { FREE, IN_FLY, DONE }; + friend class Root; - State state { FREE }; - genode_block_request dev_req { GENODE_BLOCK_UNAVAIL, 0, 0, nullptr }; - Block::Request peer_req {}; - }; + enum { MAX_REQUESTS = 32 }; - Attached_dataspace & ds; - Block::Request_stream rs; - Request requests[MAX_REQUESTS]; + struct Request { + enum State { FREE, IN_FLY, DONE }; - template - void first_request(Request::State state, FUNC const & fn) - { - for (unsigned idx = 0; idx < MAX_REQUESTS; idx++) { - if (requests[idx].state == state) { - fn(requests[idx]); - return; + State state { FREE }; + genode_block_request dev_req { GENODE_BLOCK_UNAVAIL, + 0, 0, nullptr }; + Block::Request peer_req {}; + }; + + genode_shared_dataspace * _ds; + Block::Request_stream _rs; + Request _requests[MAX_REQUESTS]; + + template + void _first_request(Request::State state, FUNC const & fn) + { + for (unsigned idx = 0; idx < MAX_REQUESTS; idx++) { + if (_requests[idx].state == state) { + fn(_requests[idx]); + return; + } } } - } - template - void for_each_request(Request::State state, FUNC const & fn) - { - for (unsigned idx = 0; idx < MAX_REQUESTS; idx++) { - if (requests[idx].state == state) - fn(requests[idx]); + template + void _for_each_request(Request::State state, FUNC const & fn) + { + for (unsigned idx = 0; idx < MAX_REQUESTS; idx++) { + if (_requests[idx].state == state) + fn(_requests[idx]); + } } - } - genode_block_session(Env & env, - Block::Session::Info info, - Signal_context_capability cap, - size_t buffer_size); + /* + * Non_copyable + */ + genode_block_session(const genode_block_session&); + genode_block_session & operator=(const genode_block_session&); - Info info() const override { return rs.info(); } + public: - Capability tx_cap() override { return rs.tx_cap(); } + genode_block_session(Env & env, + Block::Session::Info info, + Signal_context_capability cap, + size_t buffer_size); - genode_block_request * request(); - void ack(genode_block_request * req, bool success); + Info info() const override { return _rs.info(); } - void notify_peers() { rs.wakeup_client_if_needed(); } + Capability tx_cap() override { return _rs.tx_cap(); } + + genode_block_request * request(); + void ack(genode_block_request * req, bool success); + + void notify_peers() { _rs.wakeup_client_if_needed(); } }; @@ -131,9 +144,9 @@ class Root : public Root_component }; -static ::Root * _block_root = nullptr; -static genode_block_alloc_peer_buffer_t _alloc_peer_buffer = nullptr; -static genode_block_free_peer_buffer_t _free_peer_buffer = nullptr; +static ::Root * _block_root = nullptr; +static genode_shared_dataspace_alloc_attach_t _alloc_peer_buffer = nullptr; +static genode_shared_dataspace_free_t _free_peer_buffer = nullptr; genode_block_request * genode_block_session::request() @@ -142,7 +155,7 @@ genode_block_request * genode_block_session::request() genode_block_request * ret = nullptr; - rs.with_requests([&] (Block::Request request) { + _rs.with_requests([&] (Block::Request request) { if (ret) return Response::RETRY; @@ -156,7 +169,7 @@ genode_block_request * genode_block_session::request() Response response = Response::RETRY; - first_request(Request::FREE, [&] (Request & r) { + _first_request(Request::FREE, [&] (Request & r) { r.state = Request::IN_FLY; r.peer_req = request; @@ -178,8 +191,8 @@ genode_block_request * genode_block_session::request() r.dev_req.blk_nr = op.block_number; r.dev_req.blk_cnt = op.count; - r.dev_req.addr = (void*)((addr_t)ds.local_addr() - + request.offset); + r.dev_req.addr = (void*) + (genode_shared_dataspace_local_address(_ds) + request.offset); ret = &r.dev_req; response = Response::ACCEPTED; @@ -194,14 +207,14 @@ genode_block_request * genode_block_session::request() void genode_block_session::ack(genode_block_request * req, bool success) { - for_each_request(Request::IN_FLY, [&] (Request & r) { + _for_each_request(Request::IN_FLY, [&] (Request & r) { if (&r.dev_req == req) r.state = Request::DONE; }); /* Acknowledge any pending packets */ - rs.try_acknowledge([&](Block::Request_stream::Ack & ack) { - first_request(Request::DONE, [&] (Request & r) { + _rs.try_acknowledge([&](Block::Request_stream::Ack & ack) { + _first_request(Request::DONE, [&] (Request & r) { r.state = Request::FREE; r.peer_req.success = success; ack.submit(r.peer_req); @@ -215,8 +228,8 @@ genode_block_session::genode_block_session(Env & env, Signal_context_capability cap, size_t buffer_size) : - ds(*static_cast(_alloc_peer_buffer(buffer_size))), - rs(env.rm(), ds.cap(), env.ep(), cap, info) { } + _ds(_alloc_peer_buffer(buffer_size)), + _rs(env.rm(), genode_shared_dataspace_capability(_ds), env.ep(), cap, info) { } genode_block_session * ::Root::_create_session(const char * args, @@ -262,9 +275,9 @@ void ::Root::_destroy_session(genode_block_session * session) si.block_session = nullptr; }); - Attached_dataspace & ds = session->ds; + genode_shared_dataspace * ds = session->_ds; Genode::destroy(md_alloc(), session); - _free_peer_buffer(genode_attached_dataspace_ptr(ds)); + _free_peer_buffer(ds); } @@ -344,11 +357,12 @@ void ::Root::notify_peers() _env(env), _sigh_cap(cap) { } -extern "C" void genode_block_init(genode_env *env_ptr, - genode_allocator *alloc_ptr, - genode_signal_handler *sigh_ptr, - genode_block_alloc_peer_buffer_t alloc_func, - genode_block_free_peer_buffer_t free_func) +extern "C" void +genode_block_init(genode_env * env_ptr, + genode_allocator * alloc_ptr, + genode_signal_handler * sigh_ptr, + genode_shared_dataspace_alloc_attach_t alloc_func, + genode_shared_dataspace_free_t free_func) { static ::Root root(*static_cast(env_ptr), *static_cast(alloc_ptr), diff --git a/repos/os/src/lib/genode_c_api/usb.cc b/repos/os/src/lib/genode_c_api/usb.cc index 006d74e0ca..a859859766 100644 --- a/repos/os/src/lib/genode_c_api/usb.cc +++ b/repos/os/src/lib/genode_c_api/usb.cc @@ -60,7 +60,7 @@ class genode_usb_session : public Usb::Session_rpc_object Constructible packets[MAX_PACKETS_IN_FLY] { }; ::Root & _root; - Attached_dataspace & _ds; + genode_shared_dataspace * _ds; Signal_context_capability _sigh_state_cap {}; genode_usb_session_handle_t _id; Session_label const _label; @@ -68,12 +68,16 @@ class genode_usb_session : public Usb::Session_rpc_object void _ack(int err, Usb::Packet_descriptor p); + /* + * Non_copyable + */ genode_usb_session(const genode_usb_session&); + genode_usb_session & operator=(const genode_usb_session&); public: genode_usb_session(::Root & root, - Attached_dataspace & ds, + genode_shared_dataspace * ds, Env & env, Signal_context_capability cap, genode_usb_session_handle_t id, @@ -425,7 +429,8 @@ bool genode_usb_session::request(genode_usb_request_callbacks & req, void * data addr_t offset = (addr_t)sink()->packet_content(p) - (addr_t)sink()->ds_local_base(); - void * addr = (void*)((addr_t)_ds.local_addr() + offset); + void * addr = (void*)(genode_shared_dataspace_local_address(_ds) + + offset); switch (p.type) { case Packet_descriptor::STRING: @@ -482,13 +487,14 @@ void genode_usb_session::handle_response(genode_usb_request_handle_t id, genode_usb_session::genode_usb_session(::Root & root, - Attached_dataspace & ds, + genode_shared_dataspace * ds, Env & env, Signal_context_capability cap, genode_usb_session_handle_t id, Session_label const label) : - Usb::Session_rpc_object(ds.cap(), env.ep().rpc_ep(), env.rm()), + Usb::Session_rpc_object(genode_shared_dataspace_capability(ds), + env.ep().rpc_ep(), env.rm()), _root(root), _ds(ds), _id(id), @@ -548,9 +554,8 @@ genode_usb_session * ::Root::_create_session(const char * args, throw Insufficient_ram_quota(); } - Attached_dataspace & ds = - *static_cast(_callbacks->alloc_fn(tx_buf_size)); - genode_usb_session * ret = new (md_alloc()) + genode_shared_dataspace * ds = _callbacks->alloc_fn(tx_buf_size); + genode_usb_session * ret = new (md_alloc()) genode_usb_session(*this, ds, _env, _sigh_cap, _id_alloc.alloc(), label); _sessions.insert(&ret->_le); @@ -576,11 +581,11 @@ void ::Root::_destroy_session(genode_usb_session * session) }); genode_usb_session_handle_t id = session->_id; - Attached_dataspace & ds = session->_ds; + genode_shared_dataspace * ds = session->_ds; _sessions.remove(&session->_le); Genode::destroy(md_alloc(), session); _id_alloc.free((addr_t)id); - _callbacks->free_fn(genode_attached_dataspace_ptr(ds)); + _callbacks->free_fn(ds); } diff --git a/repos/pc/src/drivers/usb_host/pc/main.cc b/repos/pc/src/drivers/usb_host/pc/main.cc index f8c0c44906..f80934e55f 100644 --- a/repos/pc/src/drivers/usb_host/pc/main.cc +++ b/repos/pc/src/drivers/usb_host/pc/main.cc @@ -16,41 +16,19 @@ #include #include -#include #include #include #include -#include - +#include using namespace Genode; -extern "C" struct genode_attached_dataspace * -genode_usb_allocate_peer_buffer(unsigned long size) -{ - Attached_dataspace & ds = Lx_kit::env().memory.alloc_dataspace(size); - - /* - * We have to call virt_to_pages eagerly here, - * to get contingous page objects registered - */ - lx_emul_virt_to_pages(ds.local_addr(), size >> 12); - return genode_attached_dataspace_ptr(ds); -} - - -extern "C" void genode_usb_free_peer_buffer(struct genode_attached_dataspace * ptr) -{ - Attached_dataspace *ds = static_cast(ptr); - lx_emul_forget_pages(ds->local_addr(), ds->size()); - Lx_kit::env().memory.free_dataspace(ds->local_addr()); -} - - static bool _bios_handoff; +extern struct genode_usb_rpc_callbacks genode_usb_rpc_callbacks_obj; + extern "C" int inhibit_pci_fixup(char const *name) { diff --git a/repos/pc/src/drivers/usb_host/pc/target.inc b/repos/pc/src/drivers/usb_host/pc/target.inc index dc438658dd..f908710215 100644 --- a/repos/pc/src/drivers/usb_host/pc/target.inc +++ b/repos/pc/src/drivers/usb_host/pc/target.inc @@ -4,10 +4,12 @@ REL_PRG_DIR := $(PRG_DIR)/../.. TARGET := pc_usb_host_drv LIBS := base pc_lx_emul -INC_DIR := $(REL_PRG_DIR) + +INC_DIR += $(REL_PRG_DIR) SRC_CC += main.cc SRC_CC += misc.cc SRC_CC += time.cc +SRC_CC += lx_emul/shared_dma_buffer.cc SRC_C += dummies.c SRC_C += lx_emul.c SRC_C += usb.c diff --git a/repos/pc/src/drivers/usb_host/pc/usb.c b/repos/pc/src/drivers/usb_host/pc/usb.c index 9f6fbed42e..66ffb99d60 100644 --- a/repos/pc/src/drivers/usb_host/pc/usb.c +++ b/repos/pc/src/drivers/usb_host/pc/usb.c @@ -15,11 +15,14 @@ #include #include +#include #include #include #include -#include +#include + +struct usb_interface; struct usb_find_request { genode_usb_bus_num_t bus; @@ -153,8 +156,8 @@ static int endpoint_descriptor(genode_usb_bus_num_t bus, struct genode_usb_rpc_callbacks genode_usb_rpc_callbacks_obj = { - .alloc_fn = genode_usb_allocate_peer_buffer, - .free_fn = genode_usb_free_peer_buffer, + .alloc_fn = lx_emul_shared_dma_buffer_allocate, + .free_fn = lx_emul_shared_dma_buffer_free, .cfg_desc_fn = config_descriptor, .alt_settings_fn = alt_settings, .iface_desc_fn = interface_descriptor, diff --git a/repos/pc/src/drivers/usb_host/pc/usb.h b/repos/pc/src/drivers/usb_host/pc/usb.h deleted file mode 100644 index af3a514904..0000000000 --- a/repos/pc/src/drivers/usb_host/pc/usb.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * \brief USB related definitions for kernel/genode c-api - * \author Stefan Kalkowski - * \date 2021-09-17 - */ - -/* - * Copyright (C) 2021 Genode Labs GmbH - * - * This file is distributed under the terms of the GNU General Public License - * version 2. - */ - -#include - -struct usb_interface; - -#ifdef __cplusplus -extern "C" { -#endif - -struct genode_attached_dataspace * -genode_usb_allocate_peer_buffer(unsigned long size); - -void genode_usb_free_peer_buffer(struct genode_attached_dataspace * ptr); - -extern struct genode_usb_rpc_callbacks genode_usb_rpc_callbacks_obj; - -#ifdef __cplusplus -} -#endif -