mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-15 13:48:17 +00:00
usb: Rewrote back-end allocators
Allocate back-end memory dynamically.
This commit is contained in:
committed by
Norman Feske
parent
87f83c1cff
commit
78c752b1c7
@ -1,6 +1,4 @@
|
|||||||
SRC_C += platform_device.c
|
SRC_C += platform_device.c
|
||||||
SRC_CC += mem.cc
|
|
||||||
INC_DIR += $(LIB_INC_DIR)/arm
|
INC_DIR += $(LIB_INC_DIR)/arm
|
||||||
|
|
||||||
vpath platform_device.c $(LIB_DIR)/arm
|
vpath platform_device.c $(LIB_DIR)/arm
|
||||||
vpath mem.cc $(LIB_DIR)/arm
|
|
||||||
|
@ -17,6 +17,9 @@ build {
|
|||||||
test/lwip/http_srv
|
test/lwip/http_srv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lappend_if [have_spec acpi] build_components drivers/acpi
|
||||||
|
lappend_if [have_spec pci] build_components drivers/pci/device_pd
|
||||||
|
|
||||||
create_boot_directory
|
create_boot_directory
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -58,7 +61,29 @@ set config {
|
|||||||
</start>
|
</start>
|
||||||
<start name="test-lwip_httpsrv">
|
<start name="test-lwip_httpsrv">
|
||||||
<resource name="RAM" quantum="2M"/>
|
<resource name="RAM" quantum="2M"/>
|
||||||
</start>
|
</start>}
|
||||||
|
|
||||||
|
append_if [have_spec acpi] config {
|
||||||
|
<start name="acpi">
|
||||||
|
<resource name="RAM" quantum="5M"/>
|
||||||
|
<binary name="acpi_drv"/>
|
||||||
|
<provides>
|
||||||
|
<service name="PCI"/>
|
||||||
|
<service name="IRQ" />
|
||||||
|
</provides>
|
||||||
|
<route>
|
||||||
|
<service name="PCI"> <any-child /> </service>
|
||||||
|
<any-service> <parent/> <any-child /> </any-service>
|
||||||
|
</route>
|
||||||
|
</start>}
|
||||||
|
|
||||||
|
append_if [expr ![have_spec acpi] && [have_spec pci]] config {
|
||||||
|
<start name="pci_drv">
|
||||||
|
<resource name="RAM" quantum="3M"/>
|
||||||
|
<provides> <service name="PCI"/> </provides>
|
||||||
|
</start> }
|
||||||
|
|
||||||
|
append config {
|
||||||
</config>
|
</config>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +100,10 @@ set boot_modules {
|
|||||||
ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so test-lwip_httpsrv
|
ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so test-lwip_httpsrv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lappend_if [have_spec acpi] boot_modules acpi_drv
|
||||||
|
lappend_if [have_spec pci] boot_modules pci_drv
|
||||||
|
lappend_if [have_spec nova] boot_modules pci_device_pd
|
||||||
|
|
||||||
build_boot_image $boot_modules
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
# vi: set ft=tcl :
|
# vi: set ft=tcl :
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Backend for allocating DMA memory on ARM
|
|
||||||
* \author Alexander Boettcher
|
|
||||||
* \date 2013-02-19
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <base/env.h>
|
|
||||||
#include "mem.h"
|
|
||||||
|
|
||||||
Genode::Ram_dataspace_capability Genode::Mem::alloc_dma_buffer(size_t size) {
|
|
||||||
return Genode::env()->ram_session()->alloc(size, false); }
|
|
26
dde_linux/src/lib/usb/include/arm/platform/lx_mem.h
Normal file
26
dde_linux/src/lib/usb/include/arm/platform/lx_mem.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* \brief Platform specific part of memory allocation
|
||||||
|
* \author Alexander Boettcher
|
||||||
|
* \date 2013-03-18
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-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 _ARM__PLATFORM__LX_MEM_
|
||||||
|
#define _ARM__PLATFORM__LX_MEM_
|
||||||
|
|
||||||
|
class Backend_memory {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static Genode::Ram_dataspace_capability alloc(Genode::addr_t size,
|
||||||
|
bool cached) {
|
||||||
|
return Genode::env()->ram_session()->alloc(size, cached); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _ARM__PLATFORM__LX_MEM_ */
|
@ -1,251 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Memory pool
|
|
||||||
* \author Sebastian Sumpf
|
|
||||||
* \date 2012-06-18
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _MEM_H_
|
|
||||||
#define _MEM_H_
|
|
||||||
|
|
||||||
#include <base/allocator_avl.h>
|
|
||||||
#include <dataspace/client.h>
|
|
||||||
#include <lx_emul.h>
|
|
||||||
|
|
||||||
/*********************
|
|
||||||
** linux/dmapool.h **
|
|
||||||
*********************/
|
|
||||||
|
|
||||||
namespace Genode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory back-end
|
|
||||||
*/
|
|
||||||
class Mem
|
|
||||||
{
|
|
||||||
/* configurable sizes of memory pools */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MEM_POOL_SHARE = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
addr_t _base; /* virt base of pool */
|
|
||||||
addr_t _base_phys; /* phys base of pool */
|
|
||||||
size_t _size; /* size of backng store */
|
|
||||||
Allocator_avl _range; /* range allocator for pool */
|
|
||||||
addr_t *_zones; /* bases of zones */
|
|
||||||
int _zone_count; /* number of zones */
|
|
||||||
int _zone_alloc; /* currently allocated zones */
|
|
||||||
|
|
||||||
Ram_dataspace_capability _ds_cap; /* backing store */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates memory which can be used for DMA.
|
|
||||||
*/
|
|
||||||
Genode::Ram_dataspace_capability alloc_dma_buffer(size_t size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private constructor
|
|
||||||
*/
|
|
||||||
Mem(size_t size, bool cached = true)
|
|
||||||
: _size(size), _range(env()->heap()),_zone_count(0), _zone_alloc(0)
|
|
||||||
{
|
|
||||||
if (cached)
|
|
||||||
_ds_cap = env()->ram_session()->alloc(_size, cached);
|
|
||||||
else
|
|
||||||
_ds_cap = alloc_dma_buffer(_size);
|
|
||||||
|
|
||||||
_base_phys = Dataspace_client(_ds_cap).phys_addr();
|
|
||||||
_base = (addr_t)env()->rm_session()->attach(_ds_cap);
|
|
||||||
|
|
||||||
dde_kit_log(DEBUG_DMA, "New DMA range [%lx-%lx)", _base, _base + _size);
|
|
||||||
_range.add_range(_base, _size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert 'Mem' addres to zone address
|
|
||||||
*/
|
|
||||||
void *_to_zone(void const *addr, int i)
|
|
||||||
{
|
|
||||||
if (i < 0)
|
|
||||||
return (void *)addr;
|
|
||||||
|
|
||||||
addr_t zone_base = _zones[i];
|
|
||||||
addr_t offset = (addr_t)addr - _base;
|
|
||||||
return (void *)(zone_base + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert zone addres to 'Mem' address
|
|
||||||
*/
|
|
||||||
void *_from_zone(void const *addr, int i)
|
|
||||||
{
|
|
||||||
if (i < 0)
|
|
||||||
return (void *)addr;
|
|
||||||
|
|
||||||
addr_t zone_base = _zones[i];
|
|
||||||
addr_t offset = (addr_t)addr - zone_base;
|
|
||||||
return (void *)(_base + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory usable by back-end allocators
|
|
||||||
*/
|
|
||||||
static size_t _mem_avail() {
|
|
||||||
return env()->ram_session()->avail() - (1024 * 1024); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory zone within Mem allocator
|
|
||||||
*/
|
|
||||||
class Zone_alloc : public Allocator
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Mem *_pool; /* pool of zone */
|
|
||||||
int _zone; /* zone number */
|
|
||||||
addr_t _base; /* base address of zone */
|
|
||||||
size_t _size; /* size of zone */
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Zone_alloc(Mem *pool, int zone, addr_t base, size_t size)
|
|
||||||
: _pool(pool), _zone(zone), _base(base), _size(size) { }
|
|
||||||
|
|
||||||
|
|
||||||
/*************************
|
|
||||||
** Alocator interface **
|
|
||||||
*************************/
|
|
||||||
|
|
||||||
bool alloc(size_t size, void **out_addr)
|
|
||||||
{
|
|
||||||
*out_addr = _pool->alloc(size, _zone);
|
|
||||||
if (!*out_addr) {
|
|
||||||
PERR("Zone of %zu bytes allocation failed", size);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void free(void *addr, size_t /* size */) { _pool->free(addr, _zone); }
|
|
||||||
size_t overhead(size_t size) { return 0; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if address matches zone
|
|
||||||
*/
|
|
||||||
bool match(void const *addr)
|
|
||||||
{
|
|
||||||
addr_t a = (addr_t)addr;
|
|
||||||
bool ret = ((a >= _base) && (a < (_base + _size)));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve virt to phys mapping
|
|
||||||
*/
|
|
||||||
addr_t phys_addr(void const *addr) { return _pool->phys_addr(addr, _zone); }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gernal purpose memory pool
|
|
||||||
*/
|
|
||||||
static Mem* pool()
|
|
||||||
{
|
|
||||||
static Mem _p(_mem_avail() / MEM_POOL_SHARE);
|
|
||||||
return &_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DMA memory pool
|
|
||||||
*/
|
|
||||||
static Mem* dma()
|
|
||||||
{
|
|
||||||
static Mem _p(_mem_avail() - (_mem_avail() / MEM_POOL_SHARE), false);
|
|
||||||
return &_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocator interface
|
|
||||||
*/
|
|
||||||
void *alloc(size_t size, int zone = -1, int align = 2)
|
|
||||||
{
|
|
||||||
void *addr;
|
|
||||||
if (_range.alloc_aligned(size, &addr, align).is_error()) {
|
|
||||||
PERR("Memory allocation of %zu bytes failed", size);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _to_zone(addr, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free addr in zone
|
|
||||||
*/
|
|
||||||
void free(void *addr, int zone = -1) { _range.free(_from_zone(addr, zone)); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get phys for virt address
|
|
||||||
*/
|
|
||||||
addr_t phys_addr(void const *addr, int zone = - 1)
|
|
||||||
{
|
|
||||||
addr_t a = (addr_t)_from_zone(addr, zone);
|
|
||||||
if (a < _base || a >= _base + _size) {
|
|
||||||
PERR("No DMA phys addr for %lx zone: %d", a, zone);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (a - _base) + _base_phys;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iinit allocator with count zones
|
|
||||||
*/
|
|
||||||
void init_zones(int count)
|
|
||||||
{
|
|
||||||
if (_zone_count)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_zones = (addr_t *)env()->heap()->alloc(count * sizeof(addr_t));
|
|
||||||
_zone_count = count;
|
|
||||||
|
|
||||||
for (int i = 0; i < _zone_count; i++) {
|
|
||||||
_zones[i] = (addr_t)env()->rm_session()->attach(_ds_cap);
|
|
||||||
dde_kit_log(DEBUG_DMA, "Zone %d: base: %lx end %lx", i, _zones[i], _zones[i] + _size);
|
|
||||||
}
|
|
||||||
|
|
||||||
PINF("Registered %d zone allocators", count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new zone allocator
|
|
||||||
*
|
|
||||||
* 'init_zones' must have been called beforehand
|
|
||||||
*/
|
|
||||||
Zone_alloc *new_zone_allocator()
|
|
||||||
{
|
|
||||||
if(_zone_alloc >= _zone_count) {
|
|
||||||
PERR("Zone allocators exhausted");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Zone_alloc *zone = new(env()->heap()) Zone_alloc(this,
|
|
||||||
_zone_alloc,
|
|
||||||
_zones[_zone_alloc],
|
|
||||||
_size);
|
|
||||||
_zone_alloc++;
|
|
||||||
return zone;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _MEM_H_ */
|
|
25
dde_linux/src/lib/usb/include/x86/platform/lx_mem.h
Normal file
25
dde_linux/src/lib/usb/include/x86/platform/lx_mem.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* \brief Platform specific part of memory allocation
|
||||||
|
* \author Alexander Boettcher
|
||||||
|
* \date 2013-03-18
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-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 _X86__PLATFORM__LX_MEM_
|
||||||
|
#define _X86__PLATFORM__LX_MEM_
|
||||||
|
|
||||||
|
class Backend_memory {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static Genode::Ram_dataspace_capability alloc(Genode::addr_t size,
|
||||||
|
bool cached);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _X86__PLATFORM__LX_MEM_ */
|
@ -20,10 +20,10 @@
|
|||||||
#include <util/string.h>
|
#include <util/string.h>
|
||||||
|
|
||||||
/* Local includes */
|
/* Local includes */
|
||||||
#include "mem.h"
|
|
||||||
#include "routine.h"
|
#include "routine.h"
|
||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
#include "lx_emul.h"
|
#include "lx_emul.h"
|
||||||
|
#include "platform/lx_mem.h"
|
||||||
|
|
||||||
/* DDE kit includes */
|
/* DDE kit includes */
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -38,19 +38,126 @@ extern "C" {
|
|||||||
|
|
||||||
#if VERBOSE_LX_EMUL
|
#if VERBOSE_LX_EMUL
|
||||||
#define TRACE dde_kit_printf("\033[35m%s\033[0m called\n", __PRETTY_FUNCTION__)
|
#define TRACE dde_kit_printf("\033[35m%s\033[0m called\n", __PRETTY_FUNCTION__)
|
||||||
#define UNSUPPORTED dde_kit_printf("\033[31m%s\033[0m unsupported arguments\n", __PRETTY_FUNCTION__)
|
|
||||||
#else
|
#else
|
||||||
#define TRACE
|
#define TRACE
|
||||||
#define UNSUPPORTED
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
class Slab_backend_alloc;
|
||||||
|
class Slab_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
class Slab_alloc : public Slab
|
/**
|
||||||
|
* Back-end allocator for Genode's slab allocator
|
||||||
|
*/
|
||||||
|
class Genode::Slab_backend_alloc : public Genode::Allocator,
|
||||||
|
public Genode::Rm_connection
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Mem::Zone_alloc *_allocator;
|
enum {
|
||||||
|
VM_SIZE = 10 * 1024 * 1024, /* size of VM region to reserve */
|
||||||
|
BLOCK_SIZE = 768 * 1024, /* 1 MB */
|
||||||
|
ELEMENTS = VM_SIZE / BLOCK_SIZE, /* MAX number of dataspaces in VM */
|
||||||
|
};
|
||||||
|
|
||||||
|
addr_t _base; /* virt. base address */
|
||||||
|
bool _cached; /* non-/cached RAM */
|
||||||
|
Ram_dataspace_capability _ds_cap[ELEMENTS]; /* dataspaces to put in VM */
|
||||||
|
addr_t _ds_phys[ELEMENTS]; /* physical bases of dataspaces */
|
||||||
|
int _index; /* current index in ds_cap */
|
||||||
|
Allocator_avl _range; /* manage allocations */
|
||||||
|
|
||||||
|
bool _alloc_block()
|
||||||
|
{
|
||||||
|
if (_index == ELEMENTS) {
|
||||||
|
PERR("Slab-backend exhausted!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
_ds_cap[_index] = Backend_memory::alloc(BLOCK_SIZE, _cached);
|
||||||
|
/* attach at index * BLOCK_SIZE */
|
||||||
|
Rm_connection::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0);
|
||||||
|
|
||||||
|
/* lookup phys. address */
|
||||||
|
_ds_phys[_index] = Dataspace_client(_ds_cap[_index]).phys_addr();
|
||||||
|
} catch (...) { return false; }
|
||||||
|
|
||||||
|
/* return base + offset in VM area */
|
||||||
|
addr_t block_base = _base + (_index * BLOCK_SIZE);
|
||||||
|
++_index;
|
||||||
|
|
||||||
|
_range.add_range(block_base, BLOCK_SIZE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Slab_backend_alloc(bool cached)
|
||||||
|
: Rm_connection(0, VM_SIZE), _cached(cached), _index(0),
|
||||||
|
_range(env()->heap())
|
||||||
|
{
|
||||||
|
/* reserver attach us, anywere */
|
||||||
|
_base = env()->rm_session()->attach(dataspace());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate
|
||||||
|
*/
|
||||||
|
bool alloc(size_t size, void **out_addr)
|
||||||
|
{
|
||||||
|
bool done = _range.alloc(size, out_addr);
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
return done;
|
||||||
|
|
||||||
|
done = _alloc_block();
|
||||||
|
if (!done) {
|
||||||
|
PERR("Backend allocator exhausted\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _range.alloc(size, out_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void *addr, size_t /* size */) { }
|
||||||
|
size_t overhead(size_t size) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return phys address for given virtual addr.
|
||||||
|
*/
|
||||||
|
addr_t phys_addr(addr_t addr)
|
||||||
|
{
|
||||||
|
if (addr < _base || addr >= (_base + VM_SIZE))
|
||||||
|
return ~0UL;
|
||||||
|
|
||||||
|
int index = (addr - _base) / BLOCK_SIZE;
|
||||||
|
|
||||||
|
/* physical base of dataspace */
|
||||||
|
addr_t phys = _ds_phys[index];
|
||||||
|
|
||||||
|
if (!phys)
|
||||||
|
return ~0UL;
|
||||||
|
|
||||||
|
/* add offset */
|
||||||
|
phys += (addr - _base - (index * BLOCK_SIZE));
|
||||||
|
return phys;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_t start() const { return _base; }
|
||||||
|
addr_t end() const { return _base + VM_SIZE - 1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slab allocator using our back-end allocator
|
||||||
|
*/
|
||||||
|
class Genode::Slab_alloc : public Genode::Slab
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Slab_backend_alloc *_allocator;
|
||||||
|
|
||||||
size_t _calculate_block_size(size_t object_size)
|
size_t _calculate_block_size(size_t object_size)
|
||||||
{
|
{
|
||||||
@ -60,99 +167,88 @@ namespace Genode {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Slab_alloc(size_t object_size, Mem::Zone_alloc *allocator)
|
Slab_alloc(size_t object_size, Slab_backend_alloc *allocator)
|
||||||
: Slab(object_size, _calculate_block_size(object_size), 0, allocator),
|
: Slab(object_size, _calculate_block_size(object_size), 0, allocator),
|
||||||
_allocator(allocator) { }
|
_allocator(allocator) { }
|
||||||
|
|
||||||
inline void *alloc()
|
inline addr_t alloc()
|
||||||
{
|
{
|
||||||
void *result;
|
addr_t result;
|
||||||
return (Slab::alloc(slab_size(), &result) ? result : 0);
|
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool match(void const *addr) { return _allocator->match(addr); }
|
addr_t phys_addr(addr_t addr) { return _allocator->phys_addr(addr); }
|
||||||
addr_t phys_addr(void const *addr) { return _allocator->phys_addr(addr); }
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory interface used used for Linux emulation
|
||||||
|
*/
|
||||||
class Malloc
|
class Malloc
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Genode::Mem *_pool;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SLAB_START_LOG2 = 3, /* 8 B */
|
SLAB_START_LOG2 = 3, /* 8 B */
|
||||||
SLAB_STOP_LOG2 = 16, /* 64 KB */
|
SLAB_STOP_LOG2 = 16, /* 64 KB */
|
||||||
NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1
|
NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* slab allocator using Mem as back-end */
|
typedef Genode::addr_t addr_t;
|
||||||
Genode::Slab_alloc *_allocator[NUM_SLABS];
|
typedef Genode::Slab_alloc Slab_alloc;
|
||||||
|
typedef Genode::Slab_backend_alloc Slab_backend_alloc;
|
||||||
|
|
||||||
void _init_slabs()
|
Slab_alloc *_allocator[NUM_SLABS];
|
||||||
{
|
bool _cached; /* cached or un-cached memory */
|
||||||
using namespace Genode;
|
addr_t _start; /* VM region of this allocator */
|
||||||
_pool->init_zones(NUM_SLABS);
|
addr_t _end;
|
||||||
for (unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++) {
|
|
||||||
Mem::Zone_alloc *allocator = _pool->new_zone_allocator();
|
|
||||||
_allocator[i - SLAB_START_LOG2] = new (env()->heap()) Slab_alloc(1U << i, allocator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return slab for 'struct dma_pool' of size
|
* Set 'value' at 'addr'
|
||||||
*/
|
*/
|
||||||
int _dma_pool_slab(Genode::size_t size)
|
void _set_at(addr_t addr, addr_t value) { *((addr_t *)addr) = value; }
|
||||||
{
|
|
||||||
int msb = Genode::log2(size);
|
|
||||||
if (size > (1U << msb))
|
|
||||||
msb++;
|
|
||||||
|
|
||||||
/* take next chunk */
|
/**
|
||||||
return msb++;
|
* Retrieve slab index belonging to given address
|
||||||
|
*/
|
||||||
|
unsigned _slab_index(Genode::addr_t **addr)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
/* get index */
|
||||||
|
addr_t index = *(*addr - 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If index large, we use aligned memory, retrieve beginning of slab entry
|
||||||
|
* and read index from there
|
||||||
|
*/
|
||||||
|
if (index > 32) {
|
||||||
|
*addr = (addr_t *)*(*addr - 1);
|
||||||
|
index = *(*addr - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Malloc(Genode::Mem *pool) : _pool(pool) { _init_slabs(); }
|
Malloc(Slab_backend_alloc *alloc, bool cached)
|
||||||
|
: _cached(cached), _start(alloc->start()), _end(alloc->end())
|
||||||
/**
|
|
||||||
* General purpose allcator
|
|
||||||
*/
|
|
||||||
static Malloc *mem()
|
|
||||||
{
|
{
|
||||||
static Malloc _m(Genode::Mem::pool());
|
/* init slab allocators */
|
||||||
return &_m;
|
for (unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++)
|
||||||
|
_allocator[i - SLAB_START_LOG2] = new (Genode::env()->heap())
|
||||||
|
Slab_alloc(1U << i, alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* DMA allocator
|
|
||||||
*/
|
|
||||||
static Malloc *dma()
|
|
||||||
{
|
|
||||||
static Malloc _m(Genode::Mem::dma());
|
|
||||||
return &_m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alloc with alignment (uses back-end when alingment is > 2)
|
|
||||||
*/
|
|
||||||
void *alloc(Genode::size_t size, int align)
|
|
||||||
{
|
|
||||||
if (align <= 2)
|
|
||||||
return alloc(size);
|
|
||||||
|
|
||||||
return _pool->alloc(size, -1, align);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alloc in slabs
|
* Alloc in slabs
|
||||||
*/
|
*/
|
||||||
void *alloc(Genode::size_t size)
|
void *alloc(Genode::size_t size, int align = 0, Genode::addr_t *phys = 0)
|
||||||
{
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
/* += slab index + aligment size */
|
||||||
|
size += sizeof(addr_t) + (align > 2 ? (1 << align) : 0);
|
||||||
|
|
||||||
int msb = Genode::log2(size);
|
int msb = Genode::log2(size);
|
||||||
|
|
||||||
if (size > (1U << msb))
|
if (size > (1U << msb))
|
||||||
@ -162,86 +258,74 @@ class Malloc
|
|||||||
msb = SLAB_STOP_LOG2;
|
msb = SLAB_STOP_LOG2;
|
||||||
|
|
||||||
if (msb > SLAB_STOP_LOG2) {
|
if (msb > SLAB_STOP_LOG2) {
|
||||||
PINF("Slab too large %u", 1U << msb);
|
PERR("Slab too large %u reqested %zu cached %d", 1U << msb, size, _cached);
|
||||||
return _pool->alloc(size);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _allocator[msb - SLAB_START_LOG2]->alloc();
|
addr_t addr = _allocator[msb - SLAB_START_LOG2]->alloc();
|
||||||
|
if (!addr) {
|
||||||
|
PERR("Failed to get slab for %u", 1 << msb);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_set_at(addr, msb - SLAB_START_LOG2);
|
||||||
|
addr += sizeof(addr_t);
|
||||||
|
|
||||||
/**
|
if (align > 2) {
|
||||||
* Free from slabs
|
/* save */
|
||||||
*/
|
addr_t ptr = addr;
|
||||||
void free(void const *addr)
|
addr_t align_val = (1U << align);
|
||||||
{
|
addr_t align_mask = align_val - 2;
|
||||||
|
|
||||||
for (register unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++) {
|
|
||||||
Genode::Slab_alloc *slab = _allocator[i - SLAB_START_LOG2];
|
|
||||||
|
|
||||||
if (!slab->match(addr))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
slab->free((void *)addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_pool->free((void *)addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get phys addr
|
|
||||||
*/
|
|
||||||
Genode::addr_t phys_addr(void *addr)
|
|
||||||
{
|
|
||||||
for (register unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++) {
|
|
||||||
Genode::Slab_alloc *slab = _allocator[i - SLAB_START_LOG2];
|
|
||||||
|
|
||||||
if (!slab->match(addr))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return slab->phys_addr(addr);
|
|
||||||
}
|
|
||||||
/* not found in slabs, try in back-end */
|
|
||||||
return _pool->phys_addr(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate aligned memory in slabs
|
|
||||||
*/
|
|
||||||
void *dma_pool_alloc(size_t size, int align, Genode::addr_t *dma)
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
int msb = _dma_pool_slab(size);
|
|
||||||
addr_t base = (addr_t)_allocator[msb - SLAB_START_LOG2]->alloc();
|
|
||||||
|
|
||||||
unsigned align_val = (1U << align);
|
|
||||||
unsigned align_mask = align_val - 1;
|
|
||||||
|
|
||||||
/* make room for pointer */
|
|
||||||
addr_t addr = base + sizeof(Genode::addr_t);
|
|
||||||
|
|
||||||
/* align */
|
/* align */
|
||||||
addr = (addr + align_val - 1) & ~align_mask;
|
addr = (addr + align_val) & ~align_mask;
|
||||||
addr_t *ptr = (addr_t *)addr - 1;
|
/* write start address before aligned address */
|
||||||
*ptr = base;
|
_set_at(addr - sizeof(addr_t), ptr);
|
||||||
|
}
|
||||||
|
|
||||||
*dma = phys_addr((void *)addr);
|
if (phys)
|
||||||
return (void *)addr;
|
*phys = _allocator[msb - SLAB_START_LOG2]->phys_addr(addr);
|
||||||
|
return (addr_t *)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void const *a)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
addr_t *addr = (addr_t *)a;
|
||||||
|
|
||||||
|
unsigned nr = _slab_index(&addr);
|
||||||
|
_allocator[nr]->free((void *)(addr - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Genode::addr_t phys_addr(void *a)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
addr_t *addr = (addr_t *)a;
|
||||||
|
return _allocator[_slab_index(&addr)]->phys_addr((addr_t)a);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free memory allocted with 'dma_pool_alloc'
|
* Belongs given address to this allocator
|
||||||
*/
|
*/
|
||||||
void dma_pool_free(size_t size, void *addr)
|
bool inside(addr_t const addr) const { return (addr > _start) && (addr <= _end); }
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
int msb = _dma_pool_slab(size);
|
/**
|
||||||
addr_t base = *((addr_t *)addr - 1);
|
* Cached memory allocator
|
||||||
_allocator[msb - SLAB_START_LOG2]->free((void *)base);
|
*/
|
||||||
|
static Malloc *mem()
|
||||||
|
{
|
||||||
|
static Slab_backend_alloc _b(true);
|
||||||
|
static Malloc _m(&_b, true);
|
||||||
|
return &_m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DMA allocator
|
||||||
|
*/
|
||||||
|
static Malloc *dma()
|
||||||
|
{
|
||||||
|
static Slab_backend_alloc _b(false);
|
||||||
|
static Malloc _m(&_b, false);
|
||||||
|
return &_m;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -280,6 +364,11 @@ void mutex_unlock(struct mutex *m) { if (m->lock) dde_kit_lock_unlock( m->lock);
|
|||||||
void *kmalloc(size_t size, gfp_t flags)
|
void *kmalloc(size_t size, gfp_t flags)
|
||||||
{
|
{
|
||||||
void *addr = flags & GFP_NOIO ? Malloc::dma()->alloc(size) : Malloc::mem()->alloc(size);
|
void *addr = flags & GFP_NOIO ? Malloc::dma()->alloc(size) : Malloc::mem()->alloc(size);
|
||||||
|
|
||||||
|
unsigned long a = (unsigned long)addr;
|
||||||
|
|
||||||
|
if (a & 0x3)
|
||||||
|
PERR("Unaligned kmalloc %lx", a);
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +393,10 @@ void *kcalloc(size_t n, size_t size, gfp_t flags)
|
|||||||
|
|
||||||
void kfree(const void *p)
|
void kfree(const void *p)
|
||||||
{
|
{
|
||||||
|
if (Malloc::mem()->inside((Genode::addr_t)p))
|
||||||
Malloc::mem()->free(p);
|
Malloc::mem()->free(p);
|
||||||
|
|
||||||
|
if (Malloc::dma()->inside((Genode::addr_t)p))
|
||||||
Malloc::dma()->free(p);
|
Malloc::dma()->free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,7 +848,7 @@ static Timer::Connection _timer;
|
|||||||
|
|
||||||
void udelay(unsigned long usecs)
|
void udelay(unsigned long usecs)
|
||||||
{
|
{
|
||||||
_timer.msleep(usecs < 1000 ? 1 : usecs / 1000);
|
_timer.usleep(usecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -807,25 +899,24 @@ void dma_pool_destroy(struct dma_pool *d)
|
|||||||
|
|
||||||
void *dma_pool_alloc(struct dma_pool *d, gfp_t f, dma_addr_t *dma)
|
void *dma_pool_alloc(struct dma_pool *d, gfp_t f, dma_addr_t *dma)
|
||||||
{
|
{
|
||||||
return Malloc::dma()->dma_pool_alloc(d->size, d->align, (Genode::addr_t*)dma);
|
return Malloc::dma()->alloc(d->size, d->align, (Genode::addr_t*)dma);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void dma_pool_free(struct dma_pool *d, void *vaddr, dma_addr_t a)
|
void dma_pool_free(struct dma_pool *d, void *vaddr, dma_addr_t a)
|
||||||
{
|
{
|
||||||
dde_kit_log(DEBUG_DMA, "free: addr %p, size: %zx", vaddr, d->size);
|
dde_kit_log(DEBUG_DMA, "free: addr %p, size: %zx", vaddr, d->size);
|
||||||
Malloc::dma()->dma_pool_free(d->size, vaddr);
|
Malloc::dma()->free(vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *dma_alloc_coherent(struct device *, size_t size, dma_addr_t *dma, gfp_t)
|
void *dma_alloc_coherent(struct device *, size_t size, dma_addr_t *dma, gfp_t)
|
||||||
{
|
{
|
||||||
void *addr = Malloc::dma()->alloc(size, PAGE_SHIFT);
|
void *addr = Malloc::dma()->alloc(size, PAGE_SHIFT, dma);
|
||||||
|
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*dma = (dma_addr_t)Malloc::dma()->phys_addr(addr);
|
|
||||||
dde_kit_log(DEBUG_DMA, "DMA pool alloc addr: %p size %zx align: %d, phys: %lx",
|
dde_kit_log(DEBUG_DMA, "DMA pool alloc addr: %p size %zx align: %d, phys: %lx",
|
||||||
addr, size, PAGE_SHIFT, *dma);
|
addr, size, PAGE_SHIFT, *dma);
|
||||||
return addr;
|
return addr;
|
||||||
@ -853,6 +944,10 @@ dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
|
|||||||
{
|
{
|
||||||
dma_addr_t phys = (dma_addr_t)Malloc::dma()->phys_addr(ptr);
|
dma_addr_t phys = (dma_addr_t)Malloc::dma()->phys_addr(ptr);
|
||||||
|
|
||||||
|
if (phys == ~0UL)
|
||||||
|
PERR("translation virt->phys %p->%lx failed, return ip %p", ptr, phys,
|
||||||
|
__builtin_return_address(0));
|
||||||
|
|
||||||
dde_kit_log(DEBUG_DMA, "virt: %p phys: %lx", ptr, phys);
|
dde_kit_log(DEBUG_DMA, "virt: %p phys: %lx", ptr, phys);
|
||||||
return phys;
|
return phys;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include <util/xml_node.h>
|
#include <util/xml_node.h>
|
||||||
|
|
||||||
#include <lx_emul.h>
|
#include <lx_emul.h>
|
||||||
#include <mem.h>
|
|
||||||
|
|
||||||
#include <nic/component.h>
|
#include <nic/component.h>
|
||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
@ -69,7 +68,7 @@ class Skb
|
|||||||
Genode::memset(_free, 0xff, sizeof(_free));
|
Genode::memset(_free, 0xff, sizeof(_free));
|
||||||
|
|
||||||
for (unsigned i = 0; i < ENTRIES; i++)
|
for (unsigned i = 0; i < ENTRIES; i++)
|
||||||
_buf[i].start = (unsigned char *)Genode::Mem::dma()->alloc(BUFFER);;
|
_buf[i].start = (unsigned char *)kmalloc(BUFFER, GFP_NOIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_buff *alloc()
|
sk_buff *alloc()
|
||||||
|
@ -17,8 +17,7 @@
|
|||||||
|
|
||||||
/* Linux includes */
|
/* Linux includes */
|
||||||
#include <lx_emul.h>
|
#include <lx_emul.h>
|
||||||
|
#include <platform/lx_mem.h>
|
||||||
#include "mem.h"
|
|
||||||
|
|
||||||
struct bus_type pci_bus_type;
|
struct bus_type pci_bus_type;
|
||||||
|
|
||||||
@ -311,10 +310,14 @@ const char *pci_name(const struct pci_dev *pdev)
|
|||||||
return "dummy";
|
return "dummy";
|
||||||
}
|
}
|
||||||
|
|
||||||
Genode::Ram_dataspace_capability Genode::Mem::alloc_dma_buffer(size_t size)
|
Genode::Ram_dataspace_capability Backend_memory::alloc(Genode::addr_t size,
|
||||||
|
bool cached)
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
Ram_dataspace_capability ram_cap = pci.alloc_dma_buffer(pci_device_cap,
|
|
||||||
size);
|
PERR("use it here %u", cached);
|
||||||
return ram_cap;
|
if (cached)
|
||||||
|
return env()->ram_session()->alloc(size, cached);
|
||||||
|
else
|
||||||
|
return pci.alloc_dma_buffer(pci_device_cap, size);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user