lx_kit/lx_emul: make memory backend configureable

* Drivers have to use lx_kit/memory_dma.cc
* Protocol-stacks use lx_kit/memory_non_dma.cc
* Moreover the device-dependent lx_emul parts get removed
  from the common lx_emul import rules

Fix #4443
This commit is contained in:
Stefan Kalkowski 2022-03-07 15:26:13 +01:00
parent d473bed4b7
commit 0fa695dbd7
9 changed files with 182 additions and 90 deletions

View File

@ -10,12 +10,8 @@ LD_OPT += --defsym=jiffies=jiffies_64
#
SRC_CC += lx_emul/alloc.cc
SRC_CC += lx_emul/clock.cc
SRC_CC += lx_emul/debug.cc
SRC_CC += lx_emul/init.cc
SRC_CC += lx_emul/io_mem.cc
SRC_CC += lx_emul/io_port.cc
SRC_CC += lx_emul/irq.cc
SRC_CC += lx_emul/log.cc
SRC_CC += lx_emul/page_virt.cc
SRC_CC += lx_emul/task.cc

View File

@ -0,0 +1,42 @@
/*
* \brief Lx_kit dma memory buffer
* \author Stefan Kalkowski
* \date 2021-03-25
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__DMA_BUFFER_H_
#define _LX_KIT__DMA_BUFFER_H_
#include <lx_kit/memory.h>
#include <platform_session/dma_buffer.h>
namespace Lx_kit { class Dma_buffer; }
class Lx_kit::Dma_buffer : Platform::Dma_buffer, public Lx_kit::Mem_allocator::Buffer
{
public:
using Platform::Dma_buffer::Dma_buffer;
size_t dma_addr() const override {
return Platform::Dma_buffer::dma_addr(); }
size_t size() const override {
return Platform::Dma_buffer::size(); }
size_t virt_addr() const override {
return (size_t) Platform::Dma_buffer::local_addr<void>(); }
Dataspace_capability cap() override {
return Platform::Dma_buffer::cap(); }
};
#endif /* _LX_KIT__DMA_BUFFER_H_ */

View File

@ -15,14 +15,14 @@
#define _LX_KIT__MEMORY_H_
#include <base/allocator_avl.h>
#include <base/attached_dataspace.h>
#include <base/cache.h>
#include <base/env.h>
#include <base/heap.h>
#include <lx_kit/byte_range.h>
#include <lx_kit/map.h>
namespace Platform { class Connection; };
namespace Platform { class Connection; }
namespace Lx_kit {
using namespace Genode;
class Mem_allocator;
@ -31,33 +31,20 @@ namespace Lx_kit {
class Lx_kit::Mem_allocator
{
private:
public:
class Buffer
struct Buffer
{
private:
virtual ~Buffer() {}
Ram_dataspace_capability _ram_ds_cap;
Attached_dataspace _ds;
addr_t const _dma_addr;
public:
Buffer(Region_map & rm,
Ram_dataspace_capability cap,
addr_t dma_addr)
: _ram_ds_cap(cap), _ds(rm, cap), _dma_addr(dma_addr) {}
size_t dma_addr() const { return _dma_addr; }
size_t size() const { return _ds.size(); }
size_t virt_addr() const {
return (addr_t) _ds.local_addr<void*>(); }
Attached_dataspace & ds() { return _ds; }
Ram_dataspace_capability ram_ds_cap() { return _ram_ds_cap; }
virtual size_t dma_addr() const = 0;
virtual size_t size() const = 0;
virtual size_t virt_addr() const = 0;
virtual Dataspace_capability cap() = 0;
};
private:
struct Buffer_info
{
struct Key { addr_t addr; } key;
@ -97,9 +84,9 @@ class Lx_kit::Mem_allocator
Heap & _heap;
Platform::Connection & _platform;
Cache _cache_attr;
Allocator_avl _mem;
Map<Buffer_info> _virt_to_dma { _heap };
Map<Buffer_info> _dma_to_virt { _heap };
Allocator_avl _mem { &_heap };
Map<Buffer_info> _virt_to_dma { _heap };
Map<Buffer_info> _dma_to_virt { _heap };
public:
@ -108,8 +95,8 @@ class Lx_kit::Mem_allocator
Platform::Connection & platform,
Cache cache_attr);
Attached_dataspace & alloc_dataspace(size_t size);
void free_dataspace(void *addr);
Buffer & alloc_buffer(size_t size);
void free_buffer(void *addr);
Dataspace_capability attached_dataspace_cap(void *addr);
void * alloc(size_t size, size_t align);

View File

@ -22,6 +22,7 @@
namespace Platform {
struct Connection;
class Dma_buffer;
using namespace Genode;
}
@ -33,8 +34,8 @@ namespace Platform {
struct Platform::Connection
{
Env &_env;
Env &_env;
Region_map &_rm { _env.rm() };
char _devices_node_buffer[4096u] { };
Constructible<Xml_node> _devices_node { };
@ -74,6 +75,12 @@ struct Platform::Connection
void free_dma_buffer(Ram_dataspace_capability);
addr_t dma_addr(Ram_dataspace_capability);
template <typename FUNC>
auto retry_with_upgrade(Ram_quota ram, Cap_quota caps, FUNC func) -> decltype(func())
{
return _legacy_platform->retry_with_upgrade<FUNC>(ram, caps, func);
}
};

View File

@ -11,43 +11,40 @@
* version 2.
*/
#include <base/attached_dataspace.h>
#include <lx_kit/env.h>
#include <lx_kit/memory.h>
#include <lx_kit/dma_buffer.h>
#include <lx_emul/page_virt.h>
#include <lx_emul/shared_dma_buffer.h>
struct genode_shared_dataspace : Genode::Attached_dataspace {};
struct genode_shared_dataspace : Lx_kit::Dma_buffer {};
extern "C" struct genode_shared_dataspace *
lx_emul_shared_dma_buffer_allocate(unsigned long size)
{
Genode::Attached_dataspace & ds =
Lx_kit::env().memory.alloc_dataspace(size);
Lx_kit::Mem_allocator::Buffer & b = Lx_kit::env().memory.alloc_buffer(size);
/*
* We have to call virt_to_pages eagerly here,
* to get contingous page objects registered
*/
lx_emul_virt_to_pages(ds.local_addr<void>(), size >> 12);
return static_cast<genode_shared_dataspace*>(&ds);
lx_emul_virt_to_pages((void*)b.virt_addr(), size >> 12);
return static_cast<genode_shared_dataspace*>(&b);
}
extern "C" void
lx_emul_shared_dma_buffer_free(struct genode_shared_dataspace * ds)
{
lx_emul_forget_pages(ds->local_addr<void>(), ds->size());
Lx_kit::env().memory.free_dataspace(ds->local_addr<void>());
lx_emul_forget_pages((void*)ds->virt_addr(), ds->size());
Lx_kit::env().memory.free_buffer((void*)ds->virt_addr());
}
Genode::addr_t
genode_shared_dataspace_local_address(struct genode_shared_dataspace * ds)
{
return (Genode::addr_t)ds->local_addr<void>();
return ds->virt_addr();
}

View File

@ -13,9 +13,6 @@
/* Genode includes */
#include <base/log.h>
#include <os/backtrace.h>
#include <platform_session/connection.h>
#include <util/touch.h>
/* local includes */
#include <lx_kit/memory.h>
@ -23,35 +20,9 @@
#include <lx_kit/byte_range.h>
Genode::Attached_dataspace & Lx_kit::Mem_allocator::alloc_dataspace(size_t size)
void Lx_kit::Mem_allocator::free_buffer(void * addr)
{
Ram_dataspace_capability ds_cap;
try {
Ram_dataspace_capability ds_cap =
_platform.alloc_dma_buffer(align_addr(size, 12), _cache_attr);
Buffer & buffer = *new (_heap)
Buffer(_env.rm(), ds_cap, _platform.dma_addr(ds_cap));
/* map eager by touching all pages once */
for (size_t sz = 0; sz < buffer.size(); sz += 4096) {
touch_read((unsigned char const volatile*)(buffer.virt_addr() + sz)); }
_virt_to_dma.insert(buffer.virt_addr(), buffer);
_dma_to_virt.insert(buffer.dma_addr(), buffer);
return buffer.ds();
} catch (Out_of_caps) {
_platform.free_dma_buffer(ds_cap);
throw;
}
}
void Lx_kit::Mem_allocator::free_dataspace(void * addr)
{
Buffer *buffer = nullptr;
Buffer * buffer = nullptr;
_virt_to_dma.apply(Buffer_info::Query_addr(addr),
[&] (Buffer_info const & info) {
@ -59,7 +30,7 @@ void Lx_kit::Mem_allocator::free_dataspace(void * addr)
});
if (!buffer) {
warning(__func__, ": no buffer for addr: ", addr, " found");
warning(__func__, ": no memory buffer for addr: ", addr, " found");
return;
}
@ -69,11 +40,7 @@ void Lx_kit::Mem_allocator::free_dataspace(void * addr)
_virt_to_dma.remove(Buffer_info::Query_addr(virt_addr));
_dma_to_virt.remove(Buffer_info::Query_addr(dma_addr));
Ram_dataspace_capability ds_cap = buffer->ram_ds_cap();
destroy(_heap, buffer);
_platform.free_dma_buffer(ds_cap);
}
@ -83,7 +50,7 @@ Genode::Dataspace_capability Lx_kit::Mem_allocator::attached_dataspace_cap(void
_virt_to_dma.apply(Buffer_info::Query_addr(addr),
[&] (Buffer_info const & info) {
ret = info.buffer.ds().cap();
ret = info.buffer.cap();
});
return ret;
@ -118,10 +85,9 @@ void * Lx_kit::Mem_allocator::alloc(size_t size, size_t align)
* and physical addresses of a multi-page allocation are always
* contiguous.
*/
Attached_dataspace & ds = alloc_dataspace(max(size + 1,
min_buffer_size));
Buffer & buffer = alloc_buffer(max(size + 1, min_buffer_size));
_mem.add_range((addr_t)ds.local_addr<void>(), ds.size() - 1);
_mem.add_range(buffer.virt_addr(), buffer.size() - 1);
/* re-try allocation */
return _mem.alloc_aligned(size, (unsigned)log2(align)).convert<void *>(
@ -132,7 +98,6 @@ void * Lx_kit::Mem_allocator::alloc(size_t size, size_t align)
[&] (Range_allocator::Alloc_error) -> void * {
error("memory allocation failed for ", size, " align ", align);
backtrace();
return nullptr; }
);
}
@ -198,6 +163,4 @@ Lx_kit::Mem_allocator::Mem_allocator(Genode::Env & env,
Heap & heap,
Platform::Connection & platform,
Cache cache_attr)
:
_env(env), _heap(heap), _platform(platform),
_cache_attr(cache_attr), _mem(&heap) {}
: _env(env), _heap(heap), _platform(platform), _cache_attr(cache_attr) {}

View File

@ -0,0 +1,37 @@
/*
* \brief Lx_kit DMA-capable memory allocation backend
* \author Stefan Kalkowski
* \date 2021-03-25
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <util/touch.h>
/* local includes */
#include <lx_kit/dma_buffer.h>
#include <lx_kit/memory.h>
Lx_kit::Mem_allocator::Buffer &
Lx_kit::Mem_allocator::alloc_buffer(size_t size)
{
size = align_addr(size, 12);
Buffer & buffer = *static_cast<Buffer*>(new (_heap)
Lx_kit::Dma_buffer(_platform, size, _cache_attr));
/* map eager by touching all pages once */
for (size_t sz = 0; sz < buffer.size(); sz += 4096) {
touch_read((unsigned char const volatile*)(buffer.virt_addr() + sz)); }
_virt_to_dma.insert(buffer.virt_addr(), buffer);
_dma_to_virt.insert(buffer.dma_addr(), buffer);
return buffer;
}

View File

@ -0,0 +1,58 @@
/*
* \brief Lx_kit without DMA-capable memory allocation backend
* \author Stefan Kalkowski
* \date 2021-03-25
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/attached_ram_dataspace.h>
#include <util/touch.h>
/* local includes */
#include <lx_kit/memory.h>
using namespace Genode;
class Non_dma_buffer : Attached_ram_dataspace,
public Lx_kit::Mem_allocator::Buffer
{
public:
using Attached_ram_dataspace::Attached_ram_dataspace;
size_t dma_addr() const override { return 0UL; }
size_t size() const override {
return Attached_ram_dataspace::size(); }
size_t virt_addr() const override {
return (size_t) Attached_ram_dataspace::local_addr<void>(); }
Dataspace_capability cap() override {
return Attached_ram_dataspace::cap(); }
};
Lx_kit::Mem_allocator::Buffer &
Lx_kit::Mem_allocator::alloc_buffer(size_t size)
{
size = align_addr(size, 12);
Buffer & buffer = *static_cast<Buffer*>(new (_heap)
Non_dma_buffer(_env.ram(), _env.rm(), size, _cache_attr));
/* map eager by touching all pages once */
for (size_t sz = 0; sz < buffer.size(); sz += 4096) {
touch_read((unsigned char const volatile*)(buffer.virt_addr() + sz)); }
_virt_to_dma.insert(buffer.virt_addr(), buffer);
_dma_to_virt.insert(buffer.dma_addr(), buffer);
return buffer;
}

View File

@ -12,6 +12,10 @@ include $(call select_from_repositories,lib/import/import-lx_emul_common.inc)
# Handle specific source requirements
CC_OPT_drivers/usb/host/xhci-trace += -I$(LX_SRC_DIR)/drivers/usb/host
SRC_CC += lx_emul/clock.cc
SRC_CC += lx_emul/io_mem.cc
SRC_CC += lx_emul/io_port.cc
SRC_CC += lx_emul/irq.cc
SRC_C += lx_emul/shadow/kernel/dma/mapping.c
SRC_C += lx_emul/shadow/kernel/irq/spurious.c
SRC_C += lx_emul/shadow/kernel/rcu/tree.c
@ -22,4 +26,5 @@ SRC_C += lx_emul/shadow/mm/memblock.c
SRC_CC += lx_emul/pci_config_space.cc
SRC_CC += lx_emul/pci_init.cc
SRC_CC += lx_kit/device.cc
SRC_CC += lx_kit/memory_dma.cc
SRC_CC += lx_kit/spec/x86/platform.cc