2015-09-09 16:21:19 +02:00
|
|
|
/*
|
|
|
|
* \brief Backend allocator for DMA-capable memory
|
|
|
|
* \author Sebastian Sumpf
|
|
|
|
* \author Josef Soentgen
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2014-10-10
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-11 17:35:30 +01:00
|
|
|
* Copyright (C) 2014-2017 Genode Labs GmbH
|
2015-09-09 16:21:19 +02:00
|
|
|
*
|
2017-02-20 13:23:52 +01:00
|
|
|
* This file is distributed under the terms of the GNU General Public License
|
|
|
|
* version 2.
|
2015-09-09 16:21:19 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <base/object_pool.h>
|
|
|
|
#include <base/env.h>
|
|
|
|
|
2016-03-17 15:19:03 +01:00
|
|
|
/* XXX only because of struct pci_dev */
|
|
|
|
#include <lx_emul.h>
|
|
|
|
|
2015-09-09 16:21:19 +02:00
|
|
|
/* Linux emulation environment includes */
|
2016-03-17 15:19:03 +01:00
|
|
|
#include <lx_kit/backend_alloc.h>
|
|
|
|
#include <lx_kit/pci_dev_registry.h>
|
|
|
|
|
2015-09-09 16:21:19 +02:00
|
|
|
|
2016-03-17 15:19:03 +01:00
|
|
|
namespace Lx_kit {
|
2015-09-09 16:21:19 +02:00
|
|
|
|
|
|
|
struct Memory_object_base;
|
|
|
|
struct Ram_object;
|
|
|
|
struct Dma_object;
|
|
|
|
|
2016-03-17 15:19:03 +01:00
|
|
|
Genode::Object_pool<Memory_object_base> memory_pool;
|
2015-09-09 16:21:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-03-17 15:19:03 +01:00
|
|
|
struct Lx_kit::Memory_object_base : Genode::Object_pool<Memory_object_base>::Entry
|
2015-09-09 16:21:19 +02:00
|
|
|
{
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-03-17 15:19:03 +01:00
|
|
|
struct Lx_kit::Ram_object : Memory_object_base
|
2015-09-09 16:21:19 +02:00
|
|
|
{
|
2019-01-21 14:30:54 +01:00
|
|
|
Genode::Ram_allocator &_ram;
|
2015-09-09 16:21:19 +02:00
|
|
|
|
2019-01-21 14:30:54 +01:00
|
|
|
Ram_object(Genode::Ram_allocator &ram,
|
2017-02-11 17:35:30 +01:00
|
|
|
Genode::Ram_dataspace_capability cap)
|
|
|
|
: Memory_object_base(cap), _ram(ram) {}
|
|
|
|
|
|
|
|
void free() { _ram.free(ram_cap()); }
|
2015-09-09 16:21:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-03-17 15:19:03 +01:00
|
|
|
struct Lx_kit::Dma_object : Memory_object_base
|
2015-09-09 16:21:19 +02:00
|
|
|
{
|
2017-02-11 17:35:30 +01:00
|
|
|
Platform::Connection &_pci;
|
|
|
|
|
|
|
|
Dma_object(Platform::Connection &pci,
|
|
|
|
Genode::Ram_dataspace_capability cap)
|
|
|
|
: Memory_object_base(cap), _pci(pci) {}
|
2015-09-09 16:21:19 +02:00
|
|
|
|
2017-02-11 17:35:30 +01:00
|
|
|
void free() { _pci.free_dma_buffer(ram_cap()); }
|
2015-09-09 16:21:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-02-11 17:35:30 +01:00
|
|
|
/********************
|
|
|
|
** Pci singletons **
|
|
|
|
********************/
|
|
|
|
|
|
|
|
static Genode::Constructible<Platform::Connection> _global_pci;
|
2019-01-21 14:30:54 +01:00
|
|
|
static Genode::Allocator *_global_md_alloc;
|
|
|
|
static Genode::Ram_allocator *_global_ram;
|
2017-02-11 17:35:30 +01:00
|
|
|
|
|
|
|
|
2019-01-21 14:30:54 +01:00
|
|
|
void Lx::pci_init(Genode::Env &env, Genode::Ram_allocator &ram,
|
2017-02-11 17:35:30 +01:00
|
|
|
Genode::Allocator &md_alloc)
|
|
|
|
{
|
|
|
|
_global_pci.construct(env);
|
|
|
|
_global_ram = &ram;
|
|
|
|
_global_md_alloc = &md_alloc;
|
2018-04-10 16:54:01 +02:00
|
|
|
|
|
|
|
Lx::pci_dev_registry(&env);
|
2017-02-11 17:35:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Platform::Connection *Lx::pci()
|
|
|
|
{
|
|
|
|
return &*_global_pci;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-10 16:54:01 +02:00
|
|
|
Lx::Pci_dev_registry *Lx::pci_dev_registry(Genode::Env *env)
|
2017-02-11 17:35:30 +01:00
|
|
|
{
|
2018-04-10 16:54:01 +02:00
|
|
|
static Lx::Pci_dev_registry _pci_dev_registry(*env);
|
2017-02-11 17:35:30 +01:00
|
|
|
return &_pci_dev_registry;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-17 15:19:03 +01:00
|
|
|
/*********************************
|
|
|
|
** Lx::Backend_alloc interface **
|
|
|
|
*********************************/
|
|
|
|
|
2015-09-09 16:21:19 +02:00
|
|
|
Genode::Ram_dataspace_capability
|
|
|
|
Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached)
|
|
|
|
{
|
|
|
|
using namespace Genode;
|
2016-03-17 15:19:03 +01:00
|
|
|
using namespace Lx_kit;
|
2015-09-09 16:21:19 +02:00
|
|
|
|
2017-02-11 17:35:30 +01:00
|
|
|
Memory_object_base *obj;
|
2015-09-09 16:21:19 +02:00
|
|
|
Genode::Ram_dataspace_capability cap;
|
|
|
|
if (cached == CACHED) {
|
2017-02-11 17:35:30 +01:00
|
|
|
cap = _global_ram->alloc(size);
|
|
|
|
obj = new (_global_md_alloc) Ram_object(*_global_ram, cap);
|
2015-09-09 16:21:19 +02:00
|
|
|
} else {
|
2016-09-15 14:40:37 +02:00
|
|
|
Genode::size_t donate = size;
|
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-07 22:03:22 +02:00
|
|
|
cap = retry<Genode::Out_of_ram>(
|
|
|
|
[&] () {
|
|
|
|
return retry<Genode::Out_of_caps>(
|
|
|
|
[&] () { return _global_pci->alloc_dma_buffer(size); },
|
|
|
|
[&] () { _global_pci->upgrade_caps(2); });
|
|
|
|
},
|
2015-09-18 16:34:19 +02:00
|
|
|
[&] () {
|
2017-02-11 17:35:30 +01:00
|
|
|
_global_pci->upgrade_ram(donate);
|
2015-09-18 16:34:19 +02:00
|
|
|
donate = donate * 2 > size ? 4096 : donate * 2;
|
|
|
|
});
|
2015-09-09 16:21:19 +02:00
|
|
|
|
2017-02-11 17:35:30 +01:00
|
|
|
obj = new (_global_md_alloc) Dma_object(*_global_pci, cap);
|
2015-09-09 16:21:19 +02:00
|
|
|
}
|
|
|
|
|
2017-02-11 17:35:30 +01:00
|
|
|
memory_pool.insert(obj);
|
2015-09-09 16:21:19 +02:00
|
|
|
return cap;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Lx::backend_free(Genode::Ram_dataspace_capability cap)
|
|
|
|
{
|
|
|
|
using namespace Genode;
|
2016-03-17 15:19:03 +01:00
|
|
|
using namespace Lx_kit;
|
2015-09-09 16:21:19 +02:00
|
|
|
|
2015-09-18 16:34:19 +02:00
|
|
|
Memory_object_base *object;
|
2017-02-11 17:35:30 +01:00
|
|
|
memory_pool.apply(cap, [&] (Memory_object_base *obj) {
|
|
|
|
object = obj;
|
|
|
|
if (!object) { return; }
|
2015-09-09 16:21:19 +02:00
|
|
|
|
2015-09-18 16:34:19 +02:00
|
|
|
object->free();
|
|
|
|
memory_pool.remove(object);
|
|
|
|
});
|
2017-02-11 17:35:30 +01:00
|
|
|
destroy(_global_md_alloc, object);
|
2016-03-17 15:19:03 +01:00
|
|
|
}
|