genode/repos/dde_linux/src/lx_kit/pci.cc
Norman Feske 4d442bca30 Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.

Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.

This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-31 13:16:07 +02:00

160 lines
3.4 KiB
C++

/*
* \brief Backend allocator for DMA-capable memory
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/object_pool.h>
#include <base/env.h>
/* XXX only because of struct pci_dev */
#include <lx_emul.h>
/* Linux emulation environment includes */
#include <lx_kit/backend_alloc.h>
#include <lx_kit/pci_dev_registry.h>
namespace Lx_kit {
struct Memory_object_base;
struct Ram_object;
struct Dma_object;
Genode::Object_pool<Memory_object_base> memory_pool;
};
struct Lx_kit::Memory_object_base : Genode::Object_pool<Memory_object_base>::Entry
{
Memory_object_base(Genode::Ram_dataspace_capability cap)
: Genode::Object_pool<Memory_object_base>::Entry(cap) {}
virtual ~Memory_object_base() {};
virtual void free() = 0;
Genode::Ram_dataspace_capability ram_cap()
{
using namespace Genode;
return reinterpret_cap_cast<Ram_dataspace>(cap());
}
};
struct Lx_kit::Ram_object : Memory_object_base
{
Genode::Ram_session &_ram;
Ram_object(Genode::Ram_session &ram,
Genode::Ram_dataspace_capability cap)
: Memory_object_base(cap), _ram(ram) {}
void free() { _ram.free(ram_cap()); }
};
struct Lx_kit::Dma_object : Memory_object_base
{
Platform::Connection &_pci;
Dma_object(Platform::Connection &pci,
Genode::Ram_dataspace_capability cap)
: Memory_object_base(cap), _pci(pci) {}
void free() { _pci.free_dma_buffer(ram_cap()); }
};
/********************
** Pci singletons **
********************/
static Genode::Constructible<Platform::Connection> _global_pci;
static Genode::Allocator *_global_md_alloc;
static Genode::Ram_session *_global_ram;
void Lx::pci_init(Genode::Env &env, Genode::Ram_session &ram,
Genode::Allocator &md_alloc)
{
_global_pci.construct(env);
_global_ram = &ram;
_global_md_alloc = &md_alloc;
}
Platform::Connection *Lx::pci()
{
return &*_global_pci;
}
Lx::Pci_dev_registry *Lx::pci_dev_registry()
{
static Lx::Pci_dev_registry _pci_dev_registry;
return &_pci_dev_registry;
}
/*********************************
** Lx::Backend_alloc interface **
*********************************/
Genode::Ram_dataspace_capability
Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached)
{
using namespace Genode;
using namespace Lx_kit;
Memory_object_base *obj;
Genode::Ram_dataspace_capability cap;
if (cached == CACHED) {
cap = _global_ram->alloc(size);
obj = new (_global_md_alloc) Ram_object(*_global_ram, cap);
} else {
Genode::size_t donate = size;
cap = retry<Genode::Out_of_ram>(
[&] () {
return retry<Genode::Out_of_caps>(
[&] () { return _global_pci->alloc_dma_buffer(size); },
[&] () { _global_pci->upgrade_caps(2); });
},
[&] () {
_global_pci->upgrade_ram(donate);
donate = donate * 2 > size ? 4096 : donate * 2;
});
obj = new (_global_md_alloc) Dma_object(*_global_pci, cap);
}
memory_pool.insert(obj);
return cap;
}
void Lx::backend_free(Genode::Ram_dataspace_capability cap)
{
using namespace Genode;
using namespace Lx_kit;
Memory_object_base *object;
memory_pool.apply(cap, [&] (Memory_object_base *obj) {
object = obj;
if (!object) { return; }
object->free();
memory_pool.remove(object);
});
destroy(_global_md_alloc, object);
}