mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01:00
base: introduce caching attributes (fix #1184)
On ARM it's relevant to not only distinguish between ordinary cached memory and write-combined one, but also having non-cached memory too. To insert the appropriated page table entries e.g.: in the base-hw kernel, we need to preserve the information about the kind of memory from allocation until the pager resolves a page fault. Therefore, this commit introduces a new Cache_attribute type, and replaces the write_combined boolean with the new type where necessary.
This commit is contained in:
committed by
Norman Feske
parent
9580954d81
commit
786fe805da
20
repos/base/include/base/cache.h
Normal file
20
repos/base/include/base/cache.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* \brief Generic cache declarations
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-06-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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__CACHE_H_
|
||||
#define _INCLUDE__BASE__CACHE_H_
|
||||
|
||||
namespace Genode {
|
||||
enum Cache_attribute { UNCACHED, WRITE_COMBINED, CACHED };
|
||||
}
|
||||
#endif /* _INCLUDE__BASE__CACHE_H_ */
|
||||
@@ -25,7 +25,8 @@ namespace Genode {
|
||||
explicit Ram_session_client(Ram_session_capability session)
|
||||
: Rpc_client<Ram_session>(session) { }
|
||||
|
||||
Ram_dataspace_capability alloc(size_t size, bool cached = true) {
|
||||
Ram_dataspace_capability alloc(size_t size,
|
||||
Cache_attribute cached = CACHED) {
|
||||
return call<Rpc_alloc>(size, cached); }
|
||||
|
||||
void free(Ram_dataspace_capability ds) { call<Rpc_free>(ds); }
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <base/stdint.h>
|
||||
#include <base/capability.h>
|
||||
#include <base/exception.h>
|
||||
#include <base/cache.h>
|
||||
#include <dataspace/capability.h>
|
||||
#include <ram_session/capability.h>
|
||||
#include <session/session.h>
|
||||
@@ -49,7 +50,7 @@ namespace Genode {
|
||||
* Allocate RAM dataspace
|
||||
*
|
||||
* \param size size of RAM dataspace
|
||||
* \param cached true for cached memory, false for allocating
|
||||
* \param cached selects cacheability attributes of the memory,
|
||||
* uncached memory, i.e., for DMA buffers
|
||||
*
|
||||
* \throw Quota_exceeded
|
||||
@@ -57,7 +58,7 @@ namespace Genode {
|
||||
* \return capability to new RAM dataspace
|
||||
*/
|
||||
virtual Ram_dataspace_capability alloc(size_t size,
|
||||
bool cached = true) = 0;
|
||||
Cache_attribute cached = CACHED) = 0;
|
||||
|
||||
/**
|
||||
* Free RAM dataspace
|
||||
@@ -116,7 +117,7 @@ namespace Genode {
|
||||
|
||||
GENODE_RPC_THROW(Rpc_alloc, Ram_dataspace_capability, alloc,
|
||||
GENODE_TYPE_LIST(Quota_exceeded, Out_of_metadata),
|
||||
size_t, bool);
|
||||
size_t, Cache_attribute);
|
||||
GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability);
|
||||
GENODE_RPC(Rpc_ref_account, int, ref_account, Ram_session_capability);
|
||||
GENODE_RPC(Rpc_transfer_quota, int, transfer_quota, Ram_session_capability, size_t);
|
||||
|
||||
@@ -87,7 +87,7 @@ struct Genode::Expanding_ram_session_client : Upgradeable_client<Genode::Ram_ses
|
||||
Expanding_ram_session_client(Ram_session_capability cap)
|
||||
: Upgradeable_client<Genode::Ram_session_client>(cap) { }
|
||||
|
||||
Ram_dataspace_capability alloc(size_t size, bool cached = true)
|
||||
Ram_dataspace_capability alloc(size_t size, Cache_attribute cached = UNCACHED)
|
||||
{
|
||||
/*
|
||||
* If the RAM session runs out of quota, issue a resource request
|
||||
|
||||
@@ -135,7 +135,7 @@ class Context_area_ram_session : public Ram_session
|
||||
|
||||
public:
|
||||
|
||||
Ram_dataspace_capability alloc(size_t size, bool cached)
|
||||
Ram_dataspace_capability alloc(size_t size, Cache_attribute cached)
|
||||
{
|
||||
/* find free context */
|
||||
unsigned i;
|
||||
@@ -161,7 +161,7 @@ class Context_area_ram_session : public Ram_session
|
||||
PDBG("phys_base = %p, size = 0x%zx", phys_base, size);
|
||||
|
||||
context_ds[i] = new (&_ds_slab)
|
||||
Dataspace_component(size, 0, (addr_t)phys_base, false, true, 0);
|
||||
Dataspace_component(size, 0, (addr_t)phys_base, CACHED, true, 0);
|
||||
|
||||
Dataspace_capability cap = Dataspace_capability::local_cap(context_ds[i]);
|
||||
return static_cap_cast<Ram_dataspace>(cap);
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Genode {
|
||||
** RAM-session interface **
|
||||
***************************/
|
||||
|
||||
Ram_dataspace_capability alloc(size_t size, bool cached)
|
||||
Ram_dataspace_capability alloc(size_t size, Cache_attribute cached)
|
||||
{
|
||||
Lock::Guard lock_guard(_lock);
|
||||
return RAM_SESSION_IMPL::alloc(size, cached);
|
||||
|
||||
@@ -41,8 +41,8 @@ namespace Genode {
|
||||
addr_t _core_local_addr; /* address of core-local mapping */
|
||||
size_t const _size; /* size of dataspace in bytes */
|
||||
bool const _is_io_mem; /* dataspace is I/O mem, not to be touched */
|
||||
bool const _write_combined; /* access I/O memory write-combined, or
|
||||
RAM uncacheable respectively */
|
||||
Cache_attribute const _cache; /* access memory cached, write-combined, or
|
||||
uncached respectively */
|
||||
bool const _writable; /* false if dataspace is read-only */
|
||||
|
||||
List<Rm_region> _regions; /* regions this is attached to */
|
||||
@@ -73,7 +73,7 @@ namespace Genode {
|
||||
Dataspace_component()
|
||||
:
|
||||
_phys_addr(0), _core_local_addr(0), _size(0),
|
||||
_is_io_mem(false), _write_combined(false), _writable(false),
|
||||
_is_io_mem(false), _cache(CACHED), _writable(false),
|
||||
_owner(0), _managed(false) { }
|
||||
|
||||
/**
|
||||
@@ -82,12 +82,12 @@ namespace Genode {
|
||||
* This constructor is used by RAM and ROM dataspaces.
|
||||
*/
|
||||
Dataspace_component(size_t size, addr_t core_local_addr,
|
||||
bool write_combined, bool writable,
|
||||
Cache_attribute cache, bool writable,
|
||||
Dataspace_owner *owner)
|
||||
:
|
||||
_phys_addr(core_local_addr), _core_local_addr(core_local_addr),
|
||||
_size(round_page(size)), _is_io_mem(false),
|
||||
_write_combined(write_combined), _writable(writable),
|
||||
_cache(cache), _writable(writable),
|
||||
_owner(owner), _managed(false) { }
|
||||
|
||||
/**
|
||||
@@ -101,11 +101,11 @@ namespace Genode {
|
||||
* space is needed to send a mapping to another address space.
|
||||
*/
|
||||
Dataspace_component(size_t size, addr_t core_local_addr,
|
||||
addr_t phys_addr, bool write_combined,
|
||||
addr_t phys_addr, Cache_attribute cache,
|
||||
bool writable, Dataspace_owner *owner)
|
||||
:
|
||||
_phys_addr(phys_addr), _core_local_addr(core_local_addr),
|
||||
_size(size), _is_io_mem(true), _write_combined(write_combined),
|
||||
_size(size), _is_io_mem(true), _cache(cache),
|
||||
_writable(writable), _owner(owner), _managed(false) { }
|
||||
|
||||
/**
|
||||
@@ -120,9 +120,9 @@ namespace Genode {
|
||||
*/
|
||||
virtual Native_capability sub_rm_session() { return Dataspace_capability(); }
|
||||
|
||||
addr_t core_local_addr() const { return _core_local_addr; }
|
||||
bool is_io_mem() const { return _is_io_mem; }
|
||||
bool write_combined() const { return _write_combined; }
|
||||
addr_t core_local_addr() const { return _core_local_addr; }
|
||||
bool is_io_mem() const { return _is_io_mem; }
|
||||
Cache_attribute cacheability() const { return _cache; }
|
||||
|
||||
/**
|
||||
* Return dataspace base address to be used for map operations
|
||||
|
||||
@@ -35,10 +35,10 @@ namespace Genode {
|
||||
*/
|
||||
struct Dataspace_attr
|
||||
{
|
||||
size_t size;
|
||||
addr_t core_local_addr;
|
||||
addr_t phys_addr;
|
||||
bool write_combined;
|
||||
size_t size;
|
||||
addr_t core_local_addr;
|
||||
addr_t phys_addr;
|
||||
Cache_attribute cacheable;
|
||||
|
||||
/**
|
||||
* Base address of request used for freeing mem-ranges
|
||||
@@ -59,11 +59,11 @@ namespace Genode {
|
||||
* An invalid dataspace is represented by setting all
|
||||
* arguments to zero.
|
||||
*/
|
||||
Dataspace_attr(size_t s, addr_t cla, addr_t pa, bool write_combined,
|
||||
Dataspace_attr(size_t s, addr_t cla, addr_t pa, Cache_attribute c,
|
||||
addr_t req_base)
|
||||
:
|
||||
size(s), core_local_addr(cla), phys_addr(pa),
|
||||
write_combined(write_combined), req_base(req_base) { }
|
||||
cacheable(c), req_base(req_base) { }
|
||||
};
|
||||
|
||||
struct Io_dataspace_component : Dataspace_component
|
||||
@@ -76,7 +76,7 @@ namespace Genode {
|
||||
Io_dataspace_component(Dataspace_attr da)
|
||||
:
|
||||
Dataspace_component(da.size, da.core_local_addr,
|
||||
da.phys_addr, da.write_combined,
|
||||
da.phys_addr, da.cacheable,
|
||||
true, 0),
|
||||
req_base(da.req_base) { }
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Genode {
|
||||
Io_dataspace_component _ds;
|
||||
Rpc_entrypoint *_ds_ep;
|
||||
Io_mem_dataspace_capability _ds_cap;
|
||||
bool _write_combined;
|
||||
Cache_attribute _cacheable;
|
||||
|
||||
Dataspace_attr _prepare_io_mem(const char *args, Range_allocator *ram_alloc);
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace Genode {
|
||||
** RAM Session interface **
|
||||
***************************/
|
||||
|
||||
Ram_dataspace_capability alloc(size_t, bool);
|
||||
Ram_dataspace_capability alloc(size_t, Cache_attribute);
|
||||
void free(Ram_dataspace_capability);
|
||||
int ref_account(Ram_session_capability);
|
||||
int transfer_quota(Ram_session_capability, size_t);
|
||||
|
||||
@@ -263,7 +263,7 @@ namespace Genode {
|
||||
*/
|
||||
Rm_dataspace_component(size_t size)
|
||||
:
|
||||
Dataspace_component(size, 0, false, false, 0)
|
||||
Dataspace_component(size, 0, CACHED, false, 0)
|
||||
{ _managed = true; }
|
||||
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@ Io_mem_session_component::_prepare_io_mem(const char *args,
|
||||
addr_t base = req_base & ~(get_page_size() - 1);
|
||||
size_t size = end - base;
|
||||
|
||||
_write_combined = false;
|
||||
_cacheable = UNCACHED;
|
||||
|
||||
Arg a = Arg_string::find_arg(args, "wc");
|
||||
if (a.valid())
|
||||
_write_combined = a.bool_value(0);
|
||||
if (a.valid() && a.bool_value(0))
|
||||
_cacheable = WRITE_COMBINED;
|
||||
|
||||
/* check for RAM collision */
|
||||
int ret;
|
||||
@@ -69,9 +69,9 @@ Io_mem_session_component::_prepare_io_mem(const char *args,
|
||||
if (verbose)
|
||||
PDBG("I/O mem [%lx,%lx) => [%lx,%lx)%s",
|
||||
base, base + size, local_addr, local_addr + size,
|
||||
_write_combined ? " (write-combined)" : "");
|
||||
(_cacheable == WRITE_COMBINED) ? " (write-combined)" : "");
|
||||
|
||||
return Dataspace_attr(size, local_addr, base, _write_combined, req_base);
|
||||
return Dataspace_attr(size, local_addr, base, _cacheable, req_base);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ void Ram_session_component::_remove_ref_account_member(Ram_session_component *me
|
||||
}
|
||||
|
||||
|
||||
Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, bool cached)
|
||||
Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, Cache_attribute cached)
|
||||
{
|
||||
/* zero-sized dataspaces are not allowed */
|
||||
if (!ds_size) return Ram_dataspace_capability();
|
||||
@@ -171,7 +171,7 @@ Ram_dataspace_capability Ram_session_component::alloc(size_t ds_size, bool cache
|
||||
* when resolving page faults.
|
||||
*/
|
||||
ds = new (&_ds_slab)
|
||||
Dataspace_component(ds_size, (addr_t)ds_addr, !cached, true, this);
|
||||
Dataspace_component(ds_size, (addr_t)ds_addr, cached, true, this);
|
||||
} catch (Allocator::Out_of_memory) {
|
||||
PWRN("Could not allocate metadata");
|
||||
/* cleanup unneeded resources */
|
||||
|
||||
@@ -280,7 +280,7 @@ int Rm_client::pager(Ipc_pager &pager)
|
||||
|
||||
Mapping mapping(dst_fault_area.base(),
|
||||
src_fault_area.base(),
|
||||
src_dataspace->write_combined(),
|
||||
src_dataspace->cacheability(),
|
||||
src_dataspace->is_io_mem(),
|
||||
map_size_log2,
|
||||
src_dataspace->writable());
|
||||
|
||||
@@ -25,7 +25,7 @@ Rom_session_component::Rom_session_component(Rom_fs *rom_fs,
|
||||
:
|
||||
_rom_module(_find_rom(rom_fs, args)),
|
||||
_ds(_rom_module ? _rom_module->size() : 0,
|
||||
_rom_module ? _rom_module->addr() : 0, false, false, 0),
|
||||
_rom_module ? _rom_module->addr() : 0, CACHED, false, 0),
|
||||
_ds_ep(ds_ep)
|
||||
{
|
||||
/* ROM module not found */
|
||||
|
||||
Reference in New Issue
Block a user