mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-13 22:23:45 +00:00
parent
16914bddc8
commit
8d797105b3
109
repos/base/include/base/attached_dataspace.h
Normal file
109
repos/base/include/base/attached_dataspace.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* \brief Utility to attach a dataspace to the local address space
|
||||
* \author Norman Feske
|
||||
* \date 2014-01-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__ATTACHED_DATASPACE_H_
|
||||
#define _INCLUDE__BASE__ATTACHED_DATASPACE_H_
|
||||
|
||||
#include <dataspace/client.h>
|
||||
#include <base/env.h>
|
||||
|
||||
namespace Genode { class Attached_dataspace; }
|
||||
|
||||
|
||||
class Genode::Attached_dataspace : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Exception type
|
||||
*/
|
||||
class Invalid_dataspace { };
|
||||
|
||||
private:
|
||||
|
||||
Dataspace_capability _ds;
|
||||
|
||||
size_t const _size = { Dataspace_client(_ds).size() };
|
||||
|
||||
void * _local_addr = nullptr;
|
||||
|
||||
Dataspace_capability _check(Dataspace_capability ds)
|
||||
{
|
||||
if (ds.valid())
|
||||
return ds;
|
||||
|
||||
throw Invalid_dataspace();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \throw Rm_session::Attach_failed
|
||||
* \throw Invalid_dataspace
|
||||
*/
|
||||
Attached_dataspace(Region_map &rm, Dataspace_capability ds)
|
||||
: _ds(_check(ds)), _local_addr(rm.attach(_ds)) { }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \noapi
|
||||
* \deprecated Use the constructor with 'Region_map &' as first
|
||||
* argument instead
|
||||
*/
|
||||
Attached_dataspace(Dataspace_capability ds)
|
||||
: _ds(_check(ds)), _local_addr(env()->rm_session()->attach(_ds)) { }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Attached_dataspace()
|
||||
{
|
||||
if (_local_addr)
|
||||
env()->rm_session()->detach(_local_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return capability of the used dataspace
|
||||
*/
|
||||
Dataspace_capability cap() const { return _ds; }
|
||||
|
||||
/**
|
||||
* Request local address
|
||||
*
|
||||
* This is a template to avoid inconvenient casts at the caller.
|
||||
* A newly attached dataspace is untyped memory anyway.
|
||||
*/
|
||||
template <typename T>
|
||||
T *local_addr() { return static_cast<T *>(_local_addr); }
|
||||
|
||||
/**
|
||||
* Return size
|
||||
*/
|
||||
size_t size() const { return _size; }
|
||||
|
||||
/**
|
||||
* Forget dataspace, thereby skipping the detachment on destruction
|
||||
*
|
||||
* This method can be called if the the dataspace is known to be
|
||||
* physically destroyed, e.g., because the session where the dataspace
|
||||
* originated from was closed. In this case, core will already have
|
||||
* removed the memory mappings of the dataspace. So we have to omit the
|
||||
* detach operation in '~Attached_dataspace'.
|
||||
*/
|
||||
void invalidate() { _local_addr = nullptr; }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__BASE__ATTACHED_DATASPACE_H_ */
|
104
repos/base/include/base/attached_io_mem_dataspace.h
Normal file
104
repos/base/include/base/attached_io_mem_dataspace.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* \brief I/O MEM dataspace utility
|
||||
* \author Norman Feske
|
||||
* \date 2011-05-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__ATTACHED_IO_MEM_DATASPACE_H_
|
||||
#define _INCLUDE__BASE__ATTACHED_IO_MEM_DATASPACE_H_
|
||||
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <base/env.h>
|
||||
|
||||
namespace Genode { class Attached_io_mem_dataspace; }
|
||||
|
||||
|
||||
/**
|
||||
* Request and locally attach a memory-mapped I/O resource
|
||||
*
|
||||
* This class is a wrapper for a typical sequence of operations performed
|
||||
* by device drivers to access memory-mapped device resources. Its sole
|
||||
* purpose is to avoid duplicated code.
|
||||
*/
|
||||
class Genode::Attached_io_mem_dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
Region_map &_env_rm;
|
||||
Io_mem_connection _mmio;
|
||||
Io_mem_dataspace_capability _ds;
|
||||
void *_local_addr;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param base base address of memory-mapped I/O resource
|
||||
* \param size size of resource
|
||||
* \param write_combined enable write combining for the resource
|
||||
*
|
||||
* \throw Parent::Service_denied
|
||||
* \throw Parent::Quota_exceeded
|
||||
* \throw Parent::Unavailable
|
||||
* \throw Rm_session::Attach_failed
|
||||
*/
|
||||
Attached_io_mem_dataspace(Env &env, Genode::addr_t base, Genode::size_t size,
|
||||
bool write_combined = false)
|
||||
:
|
||||
_env_rm(env.rm()),
|
||||
_mmio(env, base, size, write_combined),
|
||||
_ds(_mmio.dataspace()),
|
||||
_local_addr(env.rm().attach(_ds))
|
||||
{
|
||||
/* apply sub-page offset to virtual address */
|
||||
_local_addr = (void *)((addr_t)_local_addr | (base & (addr_t)0xfff));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \noapi
|
||||
* \deprecated Use the constructor with 'Env &' as first
|
||||
* argument instead
|
||||
*/
|
||||
Attached_io_mem_dataspace(Genode::addr_t base, Genode::size_t size,
|
||||
bool write_combined = false)
|
||||
:
|
||||
_env_rm(*env()->rm_session()),
|
||||
_mmio(base, size, write_combined),
|
||||
_ds(_mmio.dataspace()),
|
||||
_local_addr(_env_rm.attach(_ds))
|
||||
{
|
||||
/* apply sub-page offset to virtual address */
|
||||
_local_addr = (void *)((addr_t)_local_addr | (base & (addr_t)0xfff));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Attached_io_mem_dataspace() { _env_rm.detach(_local_addr); }
|
||||
|
||||
/**
|
||||
* Return capability of the used RAM dataspace
|
||||
*/
|
||||
Io_mem_dataspace_capability cap() { return _ds; }
|
||||
|
||||
/**
|
||||
* Request local address
|
||||
*
|
||||
* This is a template to avoid inconvenient casts at the caller.
|
||||
* A newly allocated I/O MEM dataspace is untyped memory anyway.
|
||||
*/
|
||||
template <typename T>
|
||||
T *local_addr() { return static_cast<T *>(_local_addr); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__BASE__ATTACHED_IO_MEM_DATASPACE_H_ */
|
170
repos/base/include/base/attached_ram_dataspace.h
Normal file
170
repos/base/include/base/attached_ram_dataspace.h
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* \brief Utility to allocate and locally attach a RAM dataspace
|
||||
* \author Norman Feske
|
||||
* \date 2008-03-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__ATTACHED_RAM_DATASPACE_H_
|
||||
#define _INCLUDE__BASE__ATTACHED_RAM_DATASPACE_H_
|
||||
|
||||
#include <ram_session/ram_session.h>
|
||||
#include <util/touch.h>
|
||||
#include <base/env.h>
|
||||
|
||||
namespace Genode { class Attached_ram_dataspace; }
|
||||
|
||||
|
||||
/*
|
||||
* Utility for allocating and attaching a RAM dataspace
|
||||
*
|
||||
* The combination of RAM allocation and a local RM attachment is a frequent
|
||||
* use case. Each function may fail, which makes error handling inevitable.
|
||||
* This utility class encapsulates this functionality to handle both operations
|
||||
* as a transaction. When embedded as a member, this class also takes care
|
||||
* about freeing and detaching the dataspace at destruction time.
|
||||
*/
|
||||
class Genode::Attached_ram_dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
size_t _size;
|
||||
Ram_session *_ram;
|
||||
Region_map *_rm;
|
||||
Ram_dataspace_capability _ds;
|
||||
void *_local_addr = nullptr;
|
||||
Cache_attribute const _cached;
|
||||
|
||||
template <typename T>
|
||||
static void _swap(T &v1, T &v2) { T tmp = v1; v1 = v2; v2 = tmp; }
|
||||
|
||||
void _detach_and_free_dataspace()
|
||||
{
|
||||
if (_local_addr)
|
||||
_rm->detach(_local_addr);
|
||||
|
||||
if (_ds.valid())
|
||||
_ram->free(_ds);
|
||||
}
|
||||
|
||||
void _alloc_and_attach()
|
||||
{
|
||||
if (!_size) return;
|
||||
|
||||
try {
|
||||
_ds = _ram->alloc(_size, _cached);
|
||||
_local_addr = _rm->attach(_ds);
|
||||
|
||||
/* revert allocation if attaching the dataspace failed */
|
||||
} catch (Region_map::Attach_failed) {
|
||||
_ram->free(_ds);
|
||||
throw;
|
||||
}
|
||||
|
||||
/*
|
||||
* Eagerly map dataspace if used for DMA
|
||||
*
|
||||
* On some platforms, namely Fiasco.OC on ARMv7, the handling
|
||||
* of page faults interferes with the caching attributes used
|
||||
* for uncached DMA memory. See issue #452 for more details
|
||||
* (https://github.com/genodelabs/genode/issues/452). As a
|
||||
* work-around for this issues, we eagerly map the whole
|
||||
* dataspace before writing actual content to it.
|
||||
*/
|
||||
if (_cached != CACHED) {
|
||||
enum { PAGE_SIZE = 4096 };
|
||||
unsigned char volatile *base = (unsigned char volatile *)_local_addr;
|
||||
for (size_t i = 0; i < _size; i += PAGE_SIZE)
|
||||
touch_read_write(base + i);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \throw Ram_session::Alloc_failed
|
||||
* \throw Rm_session::Attach_failed
|
||||
*/
|
||||
Attached_ram_dataspace(Ram_session &ram, Region_map &rm,
|
||||
size_t size, Cache_attribute cached = CACHED)
|
||||
:
|
||||
_size(size), _ram(&ram), _rm(&rm), _cached(cached)
|
||||
{
|
||||
_alloc_and_attach();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \noapi
|
||||
* \deprecated Use the constructor with the 'Ram_session &' and
|
||||
* 'Region_map &' arguments instead.
|
||||
*/
|
||||
Attached_ram_dataspace(Ram_session *ram, size_t size,
|
||||
Cache_attribute cached = CACHED)
|
||||
:
|
||||
_size(size), _ram(ram), _rm(env()->rm_session()), _cached(cached)
|
||||
{
|
||||
_alloc_and_attach();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Attached_ram_dataspace() { _detach_and_free_dataspace(); }
|
||||
|
||||
/**
|
||||
* Return capability of the used RAM dataspace
|
||||
*/
|
||||
Ram_dataspace_capability cap() const { return _ds; }
|
||||
|
||||
/**
|
||||
* Request local address
|
||||
*
|
||||
* This is a template to avoid inconvenient casts at
|
||||
* the caller. A newly allocated RAM dataspace is
|
||||
* untyped memory anyway.
|
||||
*/
|
||||
template <typename T>
|
||||
T *local_addr() const { return static_cast<T *>(_local_addr); }
|
||||
|
||||
/**
|
||||
* Return size
|
||||
*/
|
||||
size_t size() const { return _size; }
|
||||
|
||||
void swap(Attached_ram_dataspace &other)
|
||||
{
|
||||
_swap(_size, other._size);
|
||||
_swap(_ram, other._ram);
|
||||
_swap(_ds, other._ds);
|
||||
_swap(_local_addr, other._local_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-allocate dataspace with a new size
|
||||
*
|
||||
* The content of the original dataspace is not retained.
|
||||
*/
|
||||
void realloc(Ram_session *ram_session, size_t new_size)
|
||||
{
|
||||
if (new_size < _size) return;
|
||||
|
||||
_detach_and_free_dataspace();
|
||||
|
||||
_size = new_size;
|
||||
_ram = ram_session;
|
||||
|
||||
_alloc_and_attach();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__BASE__ATTACHED_RAM_DATASPACE_H_ */
|
124
repos/base/include/base/attached_rom_dataspace.h
Normal file
124
repos/base/include/base/attached_rom_dataspace.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* \brief Utility to open a ROM session and locally attach its content
|
||||
* \author Norman Feske
|
||||
* \date 2012-01-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__ATTACHED_ROM_DATASPACE_H_
|
||||
#define _INCLUDE__BASE__ATTACHED_ROM_DATASPACE_H_
|
||||
|
||||
#include <util/volatile_object.h>
|
||||
#include <base/attached_dataspace.h>
|
||||
#include <rom_session/connection.h>
|
||||
|
||||
namespace Genode { class Attached_rom_dataspace; }
|
||||
|
||||
|
||||
class Genode::Attached_rom_dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
Region_map &_rm;
|
||||
Rom_connection _rom;
|
||||
|
||||
/*
|
||||
* A ROM module may change or disappear over the lifetime of a ROM
|
||||
* session. In contrast to the plain 'Attached_dataspace', which is
|
||||
* always be valid once constructed, a 'Attached_rom_dataspace' has
|
||||
* to handle the validity of the dataspace.
|
||||
*/
|
||||
Lazy_volatile_object<Attached_dataspace> _ds;
|
||||
|
||||
/**
|
||||
* Try to attach the ROM module, ignore invalid dataspaces
|
||||
*/
|
||||
void _try_attach()
|
||||
{
|
||||
/*
|
||||
* Normally, '_ds.construct()' would implicitly destruct an
|
||||
* existing dataspace upon re-construction. However, we have to
|
||||
* explicitly destruct the original dataspace prior calling
|
||||
* '_rom.dataspace()'.
|
||||
*
|
||||
* The ROM server may destroy the original dataspace when the
|
||||
* 'dataspace()' method is called. In this case, all existing
|
||||
* mappings of the dataspace will be flushed by core. A destruction
|
||||
* of 'Attached_dataspace' after this point will attempt to detach
|
||||
* the already flushed mappings, thereby producing error messages
|
||||
* at core.
|
||||
*/
|
||||
_ds.destruct();
|
||||
try { _ds.construct(_rm, _rom.dataspace()); }
|
||||
catch (Attached_dataspace::Invalid_dataspace) { }
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \throw Rom_connection::Rom_connection_failed
|
||||
* \throw Rm_session::Attach_failed
|
||||
*/
|
||||
Attached_rom_dataspace(Env &env, char const *name)
|
||||
: _rm(env.rm()), _rom(env, name) { _try_attach(); }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \noapi
|
||||
* \deprecated Use the constructor with 'Env &' as first
|
||||
* argument instead
|
||||
*/
|
||||
Attached_rom_dataspace(char const *name)
|
||||
: _rm(*env()->rm_session()), _rom(name) { _try_attach(); }
|
||||
|
||||
/**
|
||||
* Return capability of the used dataspace
|
||||
*/
|
||||
Dataspace_capability cap() const { return _ds->cap(); }
|
||||
|
||||
template <typename T> T *local_addr() { return _ds->local_addr<T>(); }
|
||||
|
||||
size_t size() const { return _ds->size(); }
|
||||
|
||||
/**
|
||||
* Register signal handler for ROM module changes
|
||||
*/
|
||||
void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); }
|
||||
|
||||
/**
|
||||
* Update ROM module content, re-attach if needed
|
||||
*/
|
||||
void update()
|
||||
{
|
||||
/*
|
||||
* If the dataspace is already attached and the update fits into
|
||||
* the existing dataspace, we can keep everything in place. The
|
||||
* dataspace content gets updated by the call of '_rom.update'.
|
||||
*/
|
||||
if (_ds.is_constructed() && _rom.update() == true)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If there was no valid dataspace attached beforehand or the
|
||||
* new data size exceeds the capacity of the existing dataspace,
|
||||
* replace the current dataspace by a new one.
|
||||
*/
|
||||
_try_attach();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true of content is present
|
||||
*/
|
||||
bool is_valid() const { return _ds.is_constructed(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__BASE__ATTACHED_ROM_DATASPACE_H_ */
|
@ -29,6 +29,22 @@ struct Genode::Io_mem_connection : Connection<Io_mem_session>, Io_mem_session_cl
|
||||
* \param size size memory-mapped I/O resource
|
||||
* \param write_combined enable write-combined access to I/O memory
|
||||
*/
|
||||
Io_mem_connection(Env &env, addr_t base, size_t size, bool write_combined = false)
|
||||
:
|
||||
Connection<Io_mem_session>(
|
||||
session("ram_quota=4K, base=0x%p, size=0x%zx, wc=%s",
|
||||
base, size, write_combined ? "yes" : "no")),
|
||||
|
||||
Io_mem_session_client(cap())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \noapi
|
||||
* \deprecated Use the constructor with 'Env &' as first
|
||||
* argument instead
|
||||
*/
|
||||
Io_mem_connection(addr_t base, size_t size, bool write_combined = false)
|
||||
:
|
||||
Connection<Io_mem_session>(
|
||||
|
@ -51,6 +51,19 @@ class Genode::Rom_connection : public Connection<Rom_session>,
|
||||
*
|
||||
* \throw Rom_connection_failed
|
||||
*/
|
||||
Rom_connection(Env &env, const char *module_name, const char *label = 0)
|
||||
:
|
||||
Connection<Rom_session>(_create_session(module_name, label)),
|
||||
Rom_session_client(cap())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \noapi
|
||||
* \deprecated Use the constructor with 'Env &' as first
|
||||
* argument instead
|
||||
*/
|
||||
Rom_connection(const char *module_name, const char *label = 0)
|
||||
:
|
||||
Connection<Rom_session>(_create_session(module_name, label)),
|
||||
|
@ -2,6 +2,8 @@
|
||||
* \brief Dataspace utility
|
||||
* \author Norman Feske
|
||||
* \date 2014-01-10
|
||||
*
|
||||
* \deprecated This header exists for API compatibility only.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -14,85 +16,6 @@
|
||||
#ifndef _INCLUDE__OS__ATTACHED_DATASPACE_H_
|
||||
#define _INCLUDE__OS__ATTACHED_DATASPACE_H_
|
||||
|
||||
#include <dataspace/client.h>
|
||||
#include <base/env.h>
|
||||
|
||||
namespace Genode { class Attached_dataspace; }
|
||||
|
||||
|
||||
class Genode::Attached_dataspace : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Exception type
|
||||
*/
|
||||
class Invalid_dataspace { };
|
||||
|
||||
private:
|
||||
|
||||
Dataspace_capability _ds;
|
||||
|
||||
size_t const _size = { Dataspace_client(_ds).size() };
|
||||
|
||||
void *_local_addr = { env()->rm_session()->attach(_ds) };
|
||||
|
||||
Dataspace_capability _check(Dataspace_capability ds)
|
||||
{
|
||||
if (ds.valid())
|
||||
return ds;
|
||||
|
||||
throw Invalid_dataspace();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \throw Rm_session::Attach_failed
|
||||
* \throw Invalid_dataspace
|
||||
*/
|
||||
Attached_dataspace(Dataspace_capability ds) : _ds(_check(ds)) { }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Attached_dataspace()
|
||||
{
|
||||
if (_local_addr)
|
||||
env()->rm_session()->detach(_local_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return capability of the used dataspace
|
||||
*/
|
||||
Dataspace_capability cap() const { return _ds; }
|
||||
|
||||
/**
|
||||
* Request local address
|
||||
*
|
||||
* This is a template to avoid inconvenient casts at the caller.
|
||||
* A newly attached dataspace is untyped memory anyway.
|
||||
*/
|
||||
template <typename T>
|
||||
T *local_addr() { return static_cast<T *>(_local_addr); }
|
||||
|
||||
/**
|
||||
* Return size
|
||||
*/
|
||||
size_t size() const { return _size; }
|
||||
|
||||
/**
|
||||
* Forget dataspace, thereby skipping the detachment on destruction
|
||||
*
|
||||
* This method can be called if the the dataspace is known to be
|
||||
* physically destroyed, e.g., because the session where the dataspace
|
||||
* originated from was closed. In this case, core will already have
|
||||
* removed the memory mappings of the dataspace. So we have to omit the
|
||||
* detach operation in '~Attached_dataspace'.
|
||||
*/
|
||||
void invalidate() { _local_addr = nullptr; }
|
||||
};
|
||||
#include <base/attached_dataspace.h>
|
||||
|
||||
#endif /* _INCLUDE__OS__ATTACHED_DATASPACE_H_ */
|
||||
|
@ -2,6 +2,8 @@
|
||||
* \brief I/O MEM dataspace utility
|
||||
* \author Norman Feske
|
||||
* \date 2011-05-19
|
||||
*
|
||||
* \deprecated This header exists for API compatibility only.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -14,73 +16,6 @@
|
||||
#ifndef _INCLUDE__OS__ATTACHED_IO_MEM_DATASPACE_H_
|
||||
#define _INCLUDE__OS__ATTACHED_IO_MEM_DATASPACE_H_
|
||||
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <base/env.h>
|
||||
|
||||
namespace Genode { class Attached_io_mem_dataspace; }
|
||||
|
||||
|
||||
/**
|
||||
* Request and locally attach a memory-mapped I/O resource
|
||||
*
|
||||
* This class is a wrapper for a typical sequence of operations performed
|
||||
* by device drivers to access memory-mapped device resources. Its sole
|
||||
* purpose is to avoid duplicated code.
|
||||
*/
|
||||
class Genode::Attached_io_mem_dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
Io_mem_connection _mmio;
|
||||
Io_mem_dataspace_capability _ds;
|
||||
void *_local_addr;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param base base address of memory-mapped I/O resource
|
||||
* \param size size of resource
|
||||
* \param write_combined enable write combining for the resource
|
||||
*
|
||||
* \throw Parent::Service_denied
|
||||
* \throw Parent::Quota_exceeded
|
||||
* \throw Parent::Unavailable
|
||||
* \throw Rm_session::Attach_failed
|
||||
*/
|
||||
Attached_io_mem_dataspace(Genode::addr_t base, Genode::size_t size,
|
||||
bool write_combined = false)
|
||||
:
|
||||
_mmio(base, size, write_combined),
|
||||
_ds(_mmio.dataspace()),
|
||||
_local_addr(env()->rm_session()->attach(_ds))
|
||||
{
|
||||
/* apply sub-page offset to virtual address */
|
||||
_local_addr = (void *)((addr_t)_local_addr | (base & (addr_t)0xfff));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Attached_io_mem_dataspace()
|
||||
{
|
||||
env()->rm_session()->detach(_local_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return capability of the used RAM dataspace
|
||||
*/
|
||||
Io_mem_dataspace_capability cap() { return _ds; }
|
||||
|
||||
/**
|
||||
* Request local address
|
||||
*
|
||||
* This is a template to avoid inconvenient casts at the caller.
|
||||
* A newly allocated I/O MEM dataspace is untyped memory anyway.
|
||||
*/
|
||||
template <typename T>
|
||||
T *local_addr() { return static_cast<T *>(_local_addr); }
|
||||
};
|
||||
#include <base/attached_io_mem_dataspace.h>
|
||||
|
||||
#endif /* _INCLUDE__OS__ATTACHED_IO_MEM_DATASPACE_H_ */
|
||||
|
@ -2,6 +2,8 @@
|
||||
* \brief RAM dataspace utility
|
||||
* \author Norman Feske
|
||||
* \date 2008-03-22
|
||||
*
|
||||
* \deprecated This header exists for API compatibility only.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -14,142 +16,6 @@
|
||||
#ifndef _INCLUDE__OS__ATTACHED_RAM_DATASPACE_H_
|
||||
#define _INCLUDE__OS__ATTACHED_RAM_DATASPACE_H_
|
||||
|
||||
#include <ram_session/ram_session.h>
|
||||
#include <util/touch.h>
|
||||
#include <base/env.h>
|
||||
|
||||
namespace Genode { class Attached_ram_dataspace; }
|
||||
|
||||
|
||||
/*
|
||||
* Utility for allocating and attaching a RAM dataspace
|
||||
*
|
||||
* The combination of RAM allocation and a local RM attachment is a frequent
|
||||
* use case. Each function may fail, which makes error handling inevitable.
|
||||
* This utility class encapsulates this functionality to handle both operations
|
||||
* as a transaction. When embedded as a member, this class also takes care
|
||||
* about freeing and detaching the dataspace at destruction time.
|
||||
*/
|
||||
class Genode::Attached_ram_dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
size_t _size;
|
||||
Ram_session *_ram_session;
|
||||
Ram_dataspace_capability _ds;
|
||||
void *_local_addr;
|
||||
Cache_attribute const _cached;
|
||||
|
||||
template <typename T>
|
||||
static void _swap(T &v1, T &v2) { T tmp = v1; v1 = v2; v2 = tmp; }
|
||||
|
||||
void _detach_and_free_dataspace()
|
||||
{
|
||||
if (_local_addr)
|
||||
env()->rm_session()->detach(_local_addr);
|
||||
|
||||
if (_ram_session && _ds.valid())
|
||||
_ram_session->free(_ds);
|
||||
}
|
||||
|
||||
void _alloc_and_attach()
|
||||
{
|
||||
if (!_size || !_ram_session) return;
|
||||
|
||||
try {
|
||||
_ds = _ram_session->alloc(_size, _cached);
|
||||
_local_addr = env()->rm_session()->attach(_ds);
|
||||
|
||||
/* revert allocation if attaching the dataspace failed */
|
||||
} catch (Rm_session::Attach_failed) {
|
||||
_ram_session->free(_ds);
|
||||
throw;
|
||||
}
|
||||
|
||||
/*
|
||||
* Eagerly map dataspace if used for DMA
|
||||
*
|
||||
* On some platforms, namely Fiasco.OC on ARMv7, the handling
|
||||
* of page faults interferes with the caching attributes used
|
||||
* for uncached DMA memory. See issue #452 for more details
|
||||
* (https://github.com/genodelabs/genode/issues/452). As a
|
||||
* work-around for this issues, we eagerly map the whole
|
||||
* dataspace before writing actual content to it.
|
||||
*/
|
||||
if (_cached != CACHED) {
|
||||
enum { PAGE_SIZE = 4096 };
|
||||
unsigned char volatile *base = (unsigned char volatile *)_local_addr;
|
||||
for (size_t i = 0; i < _size; i += PAGE_SIZE)
|
||||
touch_read_write(base + i);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \throw Ram_session::Alloc_failed
|
||||
* \throw Rm_session::Attach_failed
|
||||
*/
|
||||
Attached_ram_dataspace(Ram_session *ram_session, size_t size,
|
||||
Cache_attribute cached = CACHED)
|
||||
:
|
||||
_size(size), _ram_session(ram_session), _local_addr(0),
|
||||
_cached(cached)
|
||||
{
|
||||
_alloc_and_attach();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Attached_ram_dataspace() { _detach_and_free_dataspace(); }
|
||||
|
||||
/**
|
||||
* Return capability of the used RAM dataspace
|
||||
*/
|
||||
Ram_dataspace_capability cap() const { return _ds; }
|
||||
|
||||
/**
|
||||
* Request local address
|
||||
*
|
||||
* This is a template to avoid inconvenient casts at
|
||||
* the caller. A newly allocated RAM dataspace is
|
||||
* untyped memory anyway.
|
||||
*/
|
||||
template <typename T>
|
||||
T *local_addr() const { return static_cast<T *>(_local_addr); }
|
||||
|
||||
/**
|
||||
* Return size
|
||||
*/
|
||||
size_t size() const { return _size; }
|
||||
|
||||
void swap(Attached_ram_dataspace &other)
|
||||
{
|
||||
_swap(_size, other._size);
|
||||
_swap(_ram_session, other._ram_session);
|
||||
_swap(_ds, other._ds);
|
||||
_swap(_local_addr, other._local_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-allocate dataspace with a new size
|
||||
*
|
||||
* The content of the original dataspace is not retained.
|
||||
*/
|
||||
void realloc(Ram_session *ram_session, size_t new_size)
|
||||
{
|
||||
if (new_size < _size) return;
|
||||
|
||||
_detach_and_free_dataspace();
|
||||
|
||||
_size = new_size;
|
||||
_ram_session = ram_session;
|
||||
|
||||
_alloc_and_attach();
|
||||
}
|
||||
};
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
|
||||
#endif /* _INCLUDE__OS__ATTACHED_RAM_DATASPACE_H_ */
|
||||
|
@ -2,6 +2,8 @@
|
||||
* \brief ROM dataspace utility
|
||||
* \author Norman Feske
|
||||
* \date 2012-01-09
|
||||
*
|
||||
* \deprecated This header exists for API compatibility only.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -14,100 +16,6 @@
|
||||
#ifndef _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_
|
||||
#define _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_
|
||||
|
||||
#include <util/volatile_object.h>
|
||||
#include <os/attached_dataspace.h>
|
||||
#include <rom_session/connection.h>
|
||||
|
||||
namespace Genode { class Attached_rom_dataspace; }
|
||||
|
||||
|
||||
class Genode::Attached_rom_dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
Rom_connection _rom;
|
||||
|
||||
/*
|
||||
* A ROM module may change or disappear over the lifetime of a ROM
|
||||
* session. In contrast to the plain 'Attached_dataspace', which is
|
||||
* always be valid once constructed, a 'Attached_rom_dataspace' has
|
||||
* to handle the validity of the dataspace.
|
||||
*/
|
||||
Lazy_volatile_object<Attached_dataspace> _ds;
|
||||
|
||||
/**
|
||||
* Try to attach the ROM module, ignore invalid dataspaces
|
||||
*/
|
||||
void _try_attach()
|
||||
{
|
||||
/*
|
||||
* Normally, '_ds.construct()' would implicitly destruct an
|
||||
* existing dataspace upon re-construction. However, we have to
|
||||
* explicitly destruct the original dataspace prior calling
|
||||
* '_rom.dataspace()'.
|
||||
*
|
||||
* The ROM server may destroy the original dataspace when the
|
||||
* 'dataspace()' method is called. In this case, all existing
|
||||
* mappings of the dataspace will be flushed by core. A destruction
|
||||
* of 'Attached_dataspace' after this point will attempt to detach
|
||||
* the already flushed mappings, thereby producing error messages
|
||||
* at core.
|
||||
*/
|
||||
_ds.destruct();
|
||||
try { _ds.construct(_rom.dataspace()); }
|
||||
catch (Attached_dataspace::Invalid_dataspace) { }
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \throw Rom_connection::Rom_connection_failed
|
||||
* \throw Rm_session::Attach_failed
|
||||
*/
|
||||
Attached_rom_dataspace(char const *name)
|
||||
: _rom(name) { _try_attach(); }
|
||||
|
||||
/**
|
||||
* Return capability of the used dataspace
|
||||
*/
|
||||
Dataspace_capability cap() const { return _ds->cap(); }
|
||||
|
||||
template <typename T> T *local_addr() { return _ds->local_addr<T>(); }
|
||||
|
||||
size_t size() const { return _ds->size(); }
|
||||
|
||||
/**
|
||||
* Register signal handler for ROM module changes
|
||||
*/
|
||||
void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); }
|
||||
|
||||
/**
|
||||
* Update ROM module content, re-attach if needed
|
||||
*/
|
||||
void update()
|
||||
{
|
||||
/*
|
||||
* If the dataspace is already attached and the update fits into
|
||||
* the existing dataspace, we can keep everything in place. The
|
||||
* dataspace content gets updated by the call of '_rom.update'.
|
||||
*/
|
||||
if (_ds.is_constructed() && _rom.update() == true)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If there was no valid dataspace attached beforehand or the
|
||||
* new data size exceeds the capacity of the existing dataspace,
|
||||
* replace the current dataspace by a new one.
|
||||
*/
|
||||
_try_attach();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true of content is present
|
||||
*/
|
||||
bool is_valid() const { return _ds.is_constructed(); }
|
||||
};
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
|
||||
#endif /* _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user