diff --git a/repos/dde_linux/src/include/lx_emul/alloc.h b/repos/dde_linux/src/include/lx_emul/alloc.h
index 8f5fbbddf4..60bfa59a3e 100644
--- a/repos/dde_linux/src/include/lx_emul/alloc.h
+++ b/repos/dde_linux/src/include/lx_emul/alloc.h
@@ -23,6 +23,7 @@ void * lx_emul_mem_alloc_uncached(unsigned long size);
void * lx_emul_mem_alloc_aligned(unsigned long size, unsigned long align);
void * lx_emul_mem_alloc_aligned_uncached(unsigned long size, unsigned long align);
unsigned long lx_emul_mem_dma_addr(void * addr);
+unsigned long lx_emul_mem_virt_addr(void * dma_addr);
void lx_emul_mem_free(const void * ptr);
unsigned long lx_emul_mem_size(const void * ptr);
void lx_emul_mem_cache_clean_invalidate(const void * ptr, unsigned long size);
diff --git a/repos/dde_linux/src/include/lx_kit/memory.h b/repos/dde_linux/src/include/lx_kit/memory.h
index 737626db3a..20dbab7104 100644
--- a/repos/dde_linux/src/include/lx_kit/memory.h
+++ b/repos/dde_linux/src/include/lx_kit/memory.h
@@ -18,7 +18,8 @@
#include
#include
#include
-#include
+#include
+#include
namespace Platform { class Connection; };
namespace Lx_kit {
@@ -31,7 +32,7 @@ class Lx_kit::Mem_allocator
{
private:
- class Buffer : Interface
+ class Buffer
{
private:
@@ -45,18 +46,56 @@ class Lx_kit::Mem_allocator
addr_t dma_addr)
: _ds(rm, cap), _dma_addr(dma_addr) {}
- addr_t dma_addr() const { return _dma_addr; }
- Attached_dataspace & ds() { return _ds; }
+ 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(); }
+
+ Attached_dataspace & ds() { return _ds; }
};
- using Buffer_registry = Registry>;
+ struct Buffer_info
+ {
+ struct Key { addr_t addr; } key;
+ Buffer & buffer;
+
+ size_t size() const { return buffer.size(); }
+
+ bool higher(Key const other_key) const
+ {
+ return key.addr > other_key.addr;
+ }
+
+ struct Query_range
+ {
+ addr_t addr;
+ size_t size;
+
+ bool matches(Buffer_info const & bi) const
+ {
+ Lx_kit::Byte_range buf_range { bi.key.addr, bi.size() };
+ Lx_kit::Byte_range range { addr, size };
+
+ return buf_range.intersects(range);
+ }
+
+ Key key() const { return Key { addr }; }
+ };
+
+ struct Query_addr : Query_range
+ {
+ Query_addr(void const * addr)
+ : Query_range{(addr_t)addr, 1} { }
+ };
+ };
Env & _env;
Heap & _heap;
Platform::Connection & _platform;
Cache _cache_attr;
Allocator_avl _mem;
- Buffer_registry _buffers {};
+ Map _virt_to_dma { _heap };
+ Map _dma_to_virt { _heap };
public:
@@ -69,8 +108,8 @@ class Lx_kit::Mem_allocator
void * alloc(size_t size, size_t align);
addr_t dma_addr(void * addr);
+ addr_t virt_addr(void * dma_addr);
size_t size(const void * ptr);
- void free(Attached_dataspace * ds);
bool free(const void * ptr);
};
diff --git a/repos/dde_linux/src/lib/lx_emul/alloc.cc b/repos/dde_linux/src/lib/lx_emul/alloc.cc
index 4c11920b0c..fa46c24137 100644
--- a/repos/dde_linux/src/lib/lx_emul/alloc.cc
+++ b/repos/dde_linux/src/lib/lx_emul/alloc.cc
@@ -64,6 +64,17 @@ extern "C" unsigned long lx_emul_mem_dma_addr(void * addr)
}
+extern "C" unsigned long lx_emul_mem_virt_addr(void * dma_addr)
+{
+ unsigned long ret = Lx_kit::env().memory.virt_addr(dma_addr);
+ if (ret)
+ return ret;
+ if (!(ret = Lx_kit::env().uncached_memory.virt_addr(dma_addr)))
+ Genode::error(__func__, " called with invalid addr ", dma_addr);
+ return ret;
+}
+
+
extern "C" void lx_emul_mem_free(const void * ptr)
{
if (!ptr)
diff --git a/repos/dde_linux/src/lib/lx_kit/memory.cc b/repos/dde_linux/src/lib/lx_kit/memory.cc
index a7dc51ea95..85a8f3fd95 100644
--- a/repos/dde_linux/src/lib/lx_kit/memory.cc
+++ b/repos/dde_linux/src/lib/lx_kit/memory.cc
@@ -19,6 +19,8 @@
/* local includes */
#include
+#include
+#include
Genode::Attached_dataspace & Lx_kit::Mem_allocator::alloc_dataspace(size_t size)
@@ -26,17 +28,18 @@ Genode::Attached_dataspace & Lx_kit::Mem_allocator::alloc_dataspace(size_t size)
Ram_dataspace_capability ds_cap;
try {
- size_t ds_size = align_addr(size, 12);
- ds_cap = _platform.alloc_dma_buffer(ds_size, _cache_attr);
- addr_t dma_addr = _platform.dma_addr(ds_cap);
+ Ram_dataspace_capability ds_cap =
+ _platform.alloc_dma_buffer(align_addr(size, 12), _cache_attr);
Buffer & buffer = *new (_heap)
- Registered(_buffers, _env.rm(), ds_cap, dma_addr);
- addr_t addr = (addr_t)buffer.ds().local_addr();
+ Buffer(_env.rm(), ds_cap, _platform.dma_addr(ds_cap));
/* map eager by touching all pages once */
- for (size_t sz = 0; sz < ds_size; sz += 4096) {
- touch_read((unsigned char const volatile*)(addr + sz)); }
+ 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) {
@@ -70,7 +73,8 @@ 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));
+ Attached_dataspace & ds = alloc_dataspace(max(size + 1,
+ min_buffer_size));
_mem.add_range((addr_t)ds.local_addr(), ds.size() - 1);
@@ -93,15 +97,24 @@ Genode::addr_t Lx_kit::Mem_allocator::dma_addr(void * addr)
{
addr_t ret = 0UL;
- _buffers.for_each([&] (Buffer & b) {
- addr_t other = (addr_t)addr;
- addr_t addr = (addr_t)b.ds().local_addr();
- if (addr > other || (addr+b.ds().size()) <= other)
- return;
+ _virt_to_dma.apply(Buffer_info::Query_addr(addr),
+ [&] (Buffer_info const & info) {
+ addr_t const offset = (addr_t)addr - info.buffer.virt_addr();
+ ret = info.buffer.dma_addr() + offset;
+ });
- /* byte offset of 'addr' from start of block */
- addr_t const offset = other - addr;
- ret = b.dma_addr() + offset;
+ return ret;
+}
+
+
+Genode::addr_t Lx_kit::Mem_allocator::virt_addr(void * dma_addr)
+{
+ addr_t ret = 0UL;
+
+ _dma_to_virt.apply(Buffer_info::Query_addr(dma_addr),
+ [&] (Buffer_info const & info) {
+ addr_t const offset = (addr_t)dma_addr - info.buffer.dma_addr();
+ ret = info.buffer.virt_addr() + offset;
});
return ret;
@@ -118,21 +131,6 @@ bool Lx_kit::Mem_allocator::free(const void * ptr)
}
-void Lx_kit::Mem_allocator::free(Attached_dataspace * ds)
-{
- Dataspace_capability cap = ds->cap();
-
- Registered * buffer = nullptr;
- _buffers.for_each([&] (Buffer & b) {
- if (&b.ds() == ds)
- buffer = static_cast*>(&b);
- });
-
- destroy(_heap, buffer);
- _platform.free_dma_buffer(static_cap_cast(cap));
-}
-
-
Genode::size_t Lx_kit::Mem_allocator::size(const void * ptr)
{
return ptr ? _mem.size_at(ptr) : 0;