mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 03:45:24 +00:00
gpu: use Buffer_id to identify buffers
Rather than using the dataspace capability directly, let the client choose its own local identifier that is linked to the underlying capability. Fixes #4265.
This commit is contained in:
parent
9a80c3a618
commit
3b40790e02
@ -152,6 +152,70 @@ static void dump_ioctl(unsigned long request)
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
using Offset = unsigned long;
|
||||
|
||||
struct Gpu_virtual_address {
|
||||
uint64_t addr;
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
||||
|
||||
struct Gpu::Buffer
|
||||
{
|
||||
Gpu::Connection &_gpu;
|
||||
|
||||
Genode::Id_space<Gpu::Buffer>::Element const _elem;
|
||||
|
||||
Genode::Dataspace_capability const cap;
|
||||
Genode::size_t const size;
|
||||
|
||||
Constructible<Attached_dataspace> buffer_attached { };
|
||||
|
||||
Genode::Dataspace_capability map_cap { };
|
||||
Offset map_offset { 0 };
|
||||
|
||||
Gpu_virtual_address gpu_vaddr { };
|
||||
Gpu::Info::Execution_buffer_sequence seqno { };
|
||||
|
||||
bool gpu_vaddr_valid { false };
|
||||
bool busy { false };
|
||||
|
||||
Buffer(Gpu::Connection &gpu,
|
||||
Genode::size_t size,
|
||||
Genode::Id_space<Buffer> &space)
|
||||
:
|
||||
_gpu { gpu },
|
||||
_elem { *this, space },
|
||||
cap { _gpu.alloc_buffer(_elem.id(), size) },
|
||||
size { size }
|
||||
{ }
|
||||
|
||||
virtual ~Buffer()
|
||||
{
|
||||
_gpu.free_buffer(_elem.id());
|
||||
}
|
||||
|
||||
bool mmap(Genode::Env &env)
|
||||
{
|
||||
if (!buffer_attached.constructed())
|
||||
buffer_attached.construct(env.rm(), cap);
|
||||
|
||||
return buffer_attached.constructed();
|
||||
}
|
||||
|
||||
addr_t mmap_addr() {
|
||||
return reinterpret_cast<addr_t>(buffer_attached->local_addr<addr_t>());
|
||||
}
|
||||
|
||||
Gpu::Buffer_id id() const
|
||||
{
|
||||
return _elem.id();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Drm_call
|
||||
{
|
||||
private:
|
||||
@ -163,69 +227,9 @@ class Drm_call
|
||||
size_t _available_gtt_size { _gpu_info.aperture_size };
|
||||
bool _complete { false };
|
||||
|
||||
using Offset = unsigned long;
|
||||
using Buffer = Gpu::Buffer;
|
||||
|
||||
struct Gpu_virtual_address {
|
||||
uint64_t addr;
|
||||
};
|
||||
|
||||
struct Buffer_handle;
|
||||
typedef Genode::Id_space<Buffer_handle>::Element Handle;
|
||||
typedef Genode::Id_space<Buffer_handle>::Id Handle_id;
|
||||
|
||||
struct Buffer_handle
|
||||
{
|
||||
Genode::Dataspace_capability const cap;
|
||||
Genode::size_t const size;
|
||||
Handle const handle;
|
||||
|
||||
Constructible<Attached_dataspace> buffer_attached { };
|
||||
|
||||
Genode::Dataspace_capability map_cap { };
|
||||
Offset map_offset { 0 };
|
||||
|
||||
Gpu_virtual_address gpu_vaddr { };
|
||||
Gpu::Info::Execution_buffer_sequence seqno { };
|
||||
|
||||
bool gpu_vaddr_valid { false };
|
||||
bool busy { false };
|
||||
|
||||
Buffer_handle(Genode::Dataspace_capability cap,
|
||||
Genode::size_t size,
|
||||
Genode::Id_space<Buffer_handle> &space)
|
||||
:
|
||||
cap(cap), size(size),
|
||||
handle(*this, space)
|
||||
{
|
||||
if (!cap.valid() || !size)
|
||||
Genode::warning("invalid Buffer_handle ?");
|
||||
}
|
||||
|
||||
virtual ~Buffer_handle() { }
|
||||
|
||||
bool valid() const { return cap.valid() && size != 0; }
|
||||
|
||||
bool mmap(Genode::Env &env)
|
||||
{
|
||||
if (!valid())
|
||||
return false;
|
||||
|
||||
if (!buffer_attached.constructed())
|
||||
buffer_attached.construct(env.rm(), cap);
|
||||
|
||||
return buffer_attached.constructed();
|
||||
}
|
||||
|
||||
addr_t mmap_addr() {
|
||||
return reinterpret_cast<addr_t>(buffer_attached->local_addr<addr_t>());
|
||||
}
|
||||
};
|
||||
|
||||
Genode::Id_space<Buffer_handle> _buffer_handles { };
|
||||
|
||||
using Buffer = Genode::Registered<Buffer_handle>;
|
||||
|
||||
Genode::Registry<Buffer> _buffer_registry { };
|
||||
Genode::Id_space<Gpu::Buffer> _buffer_space { };
|
||||
|
||||
struct Sync_obj
|
||||
{
|
||||
@ -241,7 +245,7 @@ class Drm_call
|
||||
|
||||
Genode::Id_space<Sync_obj> _sync_objects { };
|
||||
|
||||
bool _map_buffer_ppgtt(Buffer_handle &buffer, Gpu_virtual_address const vaddr)
|
||||
bool _map_buffer_ppgtt(Buffer &buffer, Gpu_virtual_address const vaddr)
|
||||
{
|
||||
if (buffer.gpu_vaddr_valid)
|
||||
Genode::warning(__func__, " already have a gpu virtual address ",
|
||||
@ -250,7 +254,7 @@ class Drm_call
|
||||
|
||||
/* XXX out of cap XXX */
|
||||
bool const ppgtt = Genode::retry<Gpu::Session::Out_of_ram>(
|
||||
[&]() { return _gpu_session.map_buffer_ppgtt(buffer.cap,
|
||||
[&]() { return _gpu_session.map_buffer_ppgtt(buffer.id(),
|
||||
Utils::limit_to_48bit(vaddr.addr)); },
|
||||
[&]() { _gpu_session.upgrade_ram(4096); }
|
||||
);
|
||||
@ -265,11 +269,12 @@ class Drm_call
|
||||
return true;
|
||||
}
|
||||
|
||||
void _unmap_buffer_ppgtt(Buffer_handle &buffer)
|
||||
void _unmap_buffer_ppgtt(Buffer &buffer)
|
||||
{
|
||||
if (!buffer.gpu_vaddr_valid) return;
|
||||
|
||||
_gpu_session.unmap_buffer_ppgtt(buffer.cap, Utils::limit_to_48bit(buffer.gpu_vaddr.addr));
|
||||
_gpu_session.unmap_buffer_ppgtt(buffer.id(),
|
||||
Utils::limit_to_48bit(buffer.gpu_vaddr.addr));
|
||||
buffer.gpu_vaddr_valid = false;
|
||||
}
|
||||
|
||||
@ -277,115 +282,94 @@ class Drm_call
|
||||
void _alloc_buffer(uint64_t const size, FUNC const &fn)
|
||||
{
|
||||
Genode::size_t donate = size;
|
||||
Genode::Dataspace_capability cap = Genode::retry<Gpu::Session::Out_of_ram>(
|
||||
[&] () { return _gpu_session.alloc_buffer(size); },
|
||||
Buffer *buffer = nullptr;
|
||||
Genode::retry<Gpu::Session::Out_of_ram>(
|
||||
[&] () {
|
||||
buffer =
|
||||
new (&_heap) Buffer(_gpu_session, size, _buffer_space);
|
||||
},
|
||||
[&] () {
|
||||
_gpu_session.upgrade_ram(donate);
|
||||
donate /= 4;
|
||||
});
|
||||
|
||||
try {
|
||||
Buffer * buffer = new (&_heap) Buffer(_buffer_registry, cap, size, _buffer_handles);
|
||||
fn(buffer->handle);
|
||||
} catch (...) {
|
||||
_gpu_session.free_buffer(cap);
|
||||
throw;
|
||||
}
|
||||
if (buffer)
|
||||
fn(*buffer);
|
||||
}
|
||||
|
||||
void _unmap_buffer(Buffer_handle &h)
|
||||
void _unmap_buffer(Buffer &h)
|
||||
{
|
||||
_env.rm().detach(h.map_offset);
|
||||
h.map_offset = 0;
|
||||
|
||||
_gpu_session.unmap_buffer(h.map_cap);
|
||||
_gpu_session.unmap_buffer(h.id());
|
||||
h.map_cap = Genode::Dataspace_capability();
|
||||
|
||||
_available_gtt_size += h.size;
|
||||
}
|
||||
|
||||
int _free_buffer(Handle_id const &id)
|
||||
int _free_buffer(Gpu::Buffer_id const id)
|
||||
{
|
||||
bool const handled = _apply_buffer(id, [&] (Buffer_handle &bh) {
|
||||
if (bh.map_cap.valid())
|
||||
_unmap_buffer(bh);
|
||||
try {
|
||||
_buffer_space.apply<Buffer>(id, [&] (Buffer &b) {
|
||||
if (b.map_cap.valid())
|
||||
_unmap_buffer(b);
|
||||
|
||||
if (bh.gpu_vaddr_valid) {
|
||||
_gpu_session.unmap_buffer_ppgtt(bh.cap, bh.gpu_vaddr.addr);
|
||||
bh.gpu_vaddr_valid = false;
|
||||
}
|
||||
_gpu_session.free_buffer(bh.cap);
|
||||
|
||||
Genode::destroy(&_heap, &bh);
|
||||
});
|
||||
|
||||
if (!handled) {
|
||||
if (b.gpu_vaddr_valid) {
|
||||
_gpu_session.unmap_buffer_ppgtt(b.id(), b.gpu_vaddr.addr);
|
||||
b.gpu_vaddr_valid = false;
|
||||
}
|
||||
Genode::destroy(&_heap, &b);
|
||||
});
|
||||
return 0;
|
||||
} catch (Genode::Id_space<Buffer>::Unknown_id) {
|
||||
Genode::error(__func__, ": invalid handle ", id.value);
|
||||
Genode::sleep_forever();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return handled ? 0 : -1;
|
||||
}
|
||||
|
||||
Offset _map_buffer(Buffer_handle &bh)
|
||||
Offset _map_buffer(Buffer &b)
|
||||
{
|
||||
Offset offset = 0;
|
||||
|
||||
if (bh.map_cap.valid()) {
|
||||
offset = bh.map_offset;
|
||||
if (b.map_cap.valid()) {
|
||||
offset = b.map_offset;
|
||||
return offset;
|
||||
}
|
||||
|
||||
try {
|
||||
_gpu_session.upgrade_ram(4096);
|
||||
bh.map_cap = _gpu_session.map_buffer(bh.cap, true);
|
||||
bh.map_offset = static_cast<Offset>(_env.rm().attach(bh.map_cap));
|
||||
offset = bh.map_offset;
|
||||
b.map_cap = _gpu_session.map_buffer(b.id(), true);
|
||||
b.map_offset = static_cast<Offset>(_env.rm().attach(b.map_cap));
|
||||
offset = b.map_offset;
|
||||
|
||||
_available_gtt_size -= bh.size;
|
||||
_available_gtt_size -= b.size;
|
||||
} catch (...) {
|
||||
if (bh.map_cap.valid()) { _gpu_session.unmap_buffer(bh.map_cap); }
|
||||
bh.map_cap = Genode::Dataspace_capability();
|
||||
Genode::error("could not attach GEM buffer handle: ", bh.handle);
|
||||
if (b.map_cap.valid())
|
||||
_gpu_session.unmap_buffer(b.id());
|
||||
|
||||
b.map_cap = Genode::Dataspace_capability();
|
||||
Genode::error("could not attach GEM buffer handle: ", b.id().value);
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
Offset _map_buffer(Handle_id const &id)
|
||||
Offset _map_buffer(Gpu::Buffer_id const id)
|
||||
{
|
||||
Offset offset = 0;
|
||||
|
||||
bool handled = _apply_buffer(id, [&] (Buffer_handle &bh) {
|
||||
offset = _map_buffer(bh);
|
||||
});
|
||||
|
||||
if (!handled) {
|
||||
try {
|
||||
_buffer_space.apply<Buffer>(id, [&] (Buffer &b) {
|
||||
offset = _map_buffer(b);
|
||||
});
|
||||
} catch (Genode::Id_space<Buffer>::Unknown_id) {
|
||||
Genode::error(__func__, ": invalid handle ", id.value);
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/*******************
|
||||
** lookup buffer **
|
||||
*******************/
|
||||
|
||||
template <typename FUNC>
|
||||
bool _apply_buffer(Handle_id const &id, FUNC const &fn)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
_buffer_handles.apply<Buffer_handle>(id, [&](Buffer_handle &bh) {
|
||||
fn(bh);
|
||||
found = true;
|
||||
});
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/***************************
|
||||
** execbuffer completion **
|
||||
***************************/
|
||||
@ -419,42 +403,46 @@ class Drm_call
|
||||
|
||||
uint64_t const size = (p->size + 0xfff) & ~0xfff;
|
||||
|
||||
_alloc_buffer(size, [&](Handle const &handle) {
|
||||
p->size = size;
|
||||
p->handle = handle.id().value;
|
||||
try {
|
||||
_alloc_buffer(size, [&](Buffer const &b) {
|
||||
p->size = size;
|
||||
p->handle = b.id().value;
|
||||
|
||||
if (verbose_ioctl) {
|
||||
Genode::error(__func__, ": ", "handle: ", handle.id().value,
|
||||
" size: ", size);
|
||||
}
|
||||
});
|
||||
|
||||
return 0;
|
||||
if (verbose_ioctl) {
|
||||
Genode::error(__func__, ": ", "handle: ", b.id().value,
|
||||
" size: ", size);
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
} catch (...) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int _device_gem_mmap(void *arg)
|
||||
{
|
||||
auto const p = reinterpret_cast<drm_i915_gem_mmap *>(arg);
|
||||
Handle_id const handle { .value = p->handle };
|
||||
Gpu::Buffer_id const id { .value = p->handle };
|
||||
|
||||
bool map_failed { true };
|
||||
|
||||
bool handled = _apply_buffer(handle, [&] (Buffer_handle &bh) {
|
||||
if (bh.mmap(_env)) {
|
||||
p->addr_ptr = bh.mmap_addr();
|
||||
map_failed = false;
|
||||
}
|
||||
});
|
||||
try {
|
||||
_buffer_space.apply<Buffer>(id, [&] (Buffer &b) {
|
||||
if (b.mmap(_env)) {
|
||||
p->addr_ptr = b.mmap_addr();
|
||||
map_failed = false;
|
||||
}
|
||||
});
|
||||
} catch (Genode::Id_space<Buffer>::Unknown_id) { }
|
||||
|
||||
if (verbose_ioctl) {
|
||||
Genode::error(__func__, ": ", "handle: ", handle,
|
||||
!handled ? " buffer unknown" : "",
|
||||
Genode::error(__func__, ": ", "handle: ", id,
|
||||
map_failed ? " buffer inaccessible" : "",
|
||||
" flags=", p->flags,
|
||||
" addr=", Genode::Hex(p->addr_ptr));
|
||||
}
|
||||
|
||||
if (!handled || map_failed)
|
||||
if (map_failed)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@ -463,7 +451,7 @@ class Drm_call
|
||||
int _device_gem_mmap_gtt(void *arg)
|
||||
{
|
||||
auto const p = reinterpret_cast<drm_i915_gem_mmap_gtt *>(arg);
|
||||
Handle_id const id { .value = p->handle };
|
||||
Gpu::Buffer_id const id { .value = p->handle };
|
||||
|
||||
if (verbose_ioctl) {
|
||||
Genode::error(__func__, ": ", "handle: ", id.value,
|
||||
@ -499,7 +487,7 @@ class Drm_call
|
||||
{
|
||||
/* XXX check read_domains/write_domain */
|
||||
auto const p = reinterpret_cast<drm_i915_gem_set_domain*>(arg);
|
||||
Handle_id const id { .value = p->handle };
|
||||
Gpu::Buffer_id const id { .value = p->handle };
|
||||
uint32_t const rd = p->read_domains;
|
||||
uint32_t const wd = p->write_domain;
|
||||
|
||||
@ -610,7 +598,7 @@ class Drm_call
|
||||
int _device_gem_set_tiling(void *arg)
|
||||
{
|
||||
auto const p = reinterpret_cast<drm_i915_gem_set_tiling*>(arg);
|
||||
Handle_id const id { .value = p->handle };
|
||||
Gpu::Buffer_id const id { .value = p->handle };
|
||||
uint32_t const mode = p->tiling_mode;
|
||||
uint32_t const stride = p->stride;
|
||||
uint32_t const swizzle = p->swizzle_mode;
|
||||
@ -623,21 +611,20 @@ class Drm_call
|
||||
"swizzle: ", swizzle);
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
bool handled = _apply_buffer(id, [&] (Buffer_handle &bh) {
|
||||
if (!bh.cap.valid())
|
||||
return;
|
||||
bool ok = false;
|
||||
try {
|
||||
_buffer_space.apply<Buffer>(id, [&] (Buffer &b) {
|
||||
|
||||
/* we need a valid GGTT mapping for fencing */
|
||||
if (!bh.map_cap.valid() && !_map_buffer(bh))
|
||||
return;
|
||||
/* we need a valid GGTT mapping for fencing */
|
||||
if (!b.map_cap.valid() && !_map_buffer(b))
|
||||
return;
|
||||
|
||||
uint32_t const m = (stride << 16) | (mode == 1 ? 1 : 0);
|
||||
ok = _gpu_session.set_tiling(bh.map_cap, m);
|
||||
});
|
||||
|
||||
if (!handled)
|
||||
uint32_t const m = (stride << 16) | (mode == 1 ? 1 : 0);
|
||||
ok = _gpu_session.set_tiling(b.id(), m);
|
||||
});
|
||||
} catch (Genode::Id_space<Buffer>::Unknown_id) {
|
||||
Genode::error(__func__, ": invalid handle: ", id.value);
|
||||
}
|
||||
|
||||
return ok ? 0 : -1;
|
||||
}
|
||||
@ -657,7 +644,7 @@ class Drm_call
|
||||
/* batch-buffer index and cap */
|
||||
unsigned const bb_id = (p->flags & I915_EXEC_BATCH_FIRST) ? 0 : p->buffer_count - 1;
|
||||
|
||||
Buffer_handle *command_buffer = nullptr;
|
||||
Buffer *command_buffer = nullptr;
|
||||
|
||||
if (verbose_ioctl) {
|
||||
uint64_t const ctx_id = p->rsvd1;
|
||||
@ -722,38 +709,40 @@ class Drm_call
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = -1;
|
||||
Handle_id const id { .value = obj[i].handle };
|
||||
int ret = -1;
|
||||
Gpu::Buffer_id const id { .value = obj[i].handle };
|
||||
|
||||
bool handled = _apply_buffer(id, [&](Buffer_handle &bh) {
|
||||
if (!bh.valid())
|
||||
return;
|
||||
try {
|
||||
_buffer_space.apply<Buffer>(id, [&](Buffer &b) {
|
||||
|
||||
if (bh.busy)
|
||||
Genode::warning("handle: ", obj[i].handle, " reused but is busy");
|
||||
if (b.busy)
|
||||
Genode::warning("handle: ", obj[i].handle, " reused but is busy");
|
||||
|
||||
if (bh.gpu_vaddr_valid && bh.gpu_vaddr.addr != obj[i].offset) {
|
||||
Genode::error("unmap already mapped ", bh.handle, " ", Genode::Hex(bh.gpu_vaddr.addr), "->", Genode::Hex(obj[i].offset));
|
||||
_unmap_buffer_ppgtt(bh);
|
||||
}
|
||||
if (b.gpu_vaddr_valid && b.gpu_vaddr.addr != obj[i].offset) {
|
||||
Genode::error("unmap already mapped ", b.id().value, " ",
|
||||
Genode::Hex(b.gpu_vaddr.addr), "->",
|
||||
Genode::Hex(obj[i].offset));
|
||||
_unmap_buffer_ppgtt(b);
|
||||
}
|
||||
|
||||
if (!bh.gpu_vaddr_valid)
|
||||
_map_buffer_ppgtt(bh, Gpu_virtual_address { .addr = obj[i].offset });
|
||||
if (!b.gpu_vaddr_valid)
|
||||
_map_buffer_ppgtt(b, Gpu_virtual_address { .addr = obj[i].offset });
|
||||
|
||||
if (!bh.gpu_vaddr_valid) {
|
||||
Genode::error("handle: ", obj[i].handle, " gpu_vaddr invalid");
|
||||
return;
|
||||
}
|
||||
if (!b.gpu_vaddr_valid) {
|
||||
Genode::error("handle: ", obj[i].handle, " gpu_vaddr invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
bh.busy = true;
|
||||
b.busy = true;
|
||||
|
||||
if (i == bb_id)
|
||||
command_buffer = &bh;
|
||||
if (i == bb_id)
|
||||
command_buffer = &b;
|
||||
|
||||
ret = 0;
|
||||
});
|
||||
ret = 0;
|
||||
});
|
||||
} catch (Genode::Id_space<Buffer>::Unknown_id) { }
|
||||
|
||||
if (!handled || ret) {
|
||||
if (ret) {
|
||||
Genode::error("handle: ", obj[i].handle, " invalid, ret=", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -762,13 +751,13 @@ class Drm_call
|
||||
if (!command_buffer)
|
||||
return -1;
|
||||
|
||||
command_buffer->seqno = _gpu_session.exec_buffer(command_buffer->cap,
|
||||
command_buffer->seqno = _gpu_session.exec_buffer(command_buffer->id(),
|
||||
p->batch_len);
|
||||
|
||||
for (uint64_t i = 0; i < p->buffer_count; i++) {
|
||||
Handle_id const id { .value = obj[i].handle };
|
||||
_apply_buffer(id, [&](Buffer_handle &bh) {
|
||||
bh.seqno = command_buffer->seqno;
|
||||
Gpu::Buffer_id const id { .value = obj[i].handle };
|
||||
_buffer_space.apply<Buffer>(id, [&](Buffer &b) {
|
||||
b.seqno = command_buffer->seqno;
|
||||
});
|
||||
}
|
||||
|
||||
@ -777,7 +766,7 @@ class Drm_call
|
||||
* of signal ep, the original drm_i915_gem_wait simply 0 now
|
||||
*/
|
||||
struct drm_i915_gem_wait wait = {
|
||||
.bo_handle = (__u32)command_buffer->handle.id().value,
|
||||
.bo_handle = (__u32)command_buffer->id().value,
|
||||
.flags = 0,
|
||||
.timeout_ns = -1LL
|
||||
};
|
||||
@ -789,13 +778,16 @@ class Drm_call
|
||||
int _device_gem_busy(void *arg)
|
||||
{
|
||||
auto const p = reinterpret_cast<drm_i915_gem_busy*>(arg);
|
||||
Handle_id const id { .value = p->handle };
|
||||
Gpu::Buffer_id const id { .value = p->handle };
|
||||
|
||||
bool handled = _apply_buffer(id, [&](Buffer_handle const &bh) {
|
||||
p->busy = bh.busy;
|
||||
});
|
||||
|
||||
return handled ? 0 : -1;
|
||||
try {
|
||||
_buffer_space.apply<Buffer>(id, [&](Buffer const &b) {
|
||||
p->busy = b.busy;
|
||||
});
|
||||
return 0;
|
||||
} catch (Genode::Id_space<Buffer>::Unknown_id) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int _device_gem_madvise(void *arg)
|
||||
@ -811,16 +803,17 @@ class Drm_call
|
||||
int _device_gem_wait(void *arg)
|
||||
{
|
||||
auto const p = reinterpret_cast<drm_i915_gem_wait*>(arg);
|
||||
Handle_id const id { .value = p->bo_handle };
|
||||
Gpu::Buffer_id const id { .value = p->bo_handle };
|
||||
|
||||
bool busy = true;
|
||||
|
||||
while (busy) {
|
||||
bool handled = _apply_buffer(id, [&](Buffer_handle &bh) {
|
||||
busy = bh.busy;
|
||||
});
|
||||
|
||||
if (!handled) {
|
||||
try {
|
||||
_buffer_space.apply<Buffer>(id, [&](Buffer &b) {
|
||||
busy = b.busy;
|
||||
});
|
||||
} catch (Genode::Id_space<Buffer>::Unknown_id) {
|
||||
Genode::error(__func__, ": handle ", p->bo_handle, " invalid");
|
||||
return -1;
|
||||
}
|
||||
@ -892,7 +885,7 @@ class Drm_call
|
||||
int _generic_gem_close(void *arg)
|
||||
{
|
||||
auto const p = reinterpret_cast<drm_gem_close*>(arg);
|
||||
Handle_id const id { .value = p->handle };
|
||||
Gpu::Buffer_id const id { .value = p->handle };
|
||||
return _free_buffer(id);
|
||||
}
|
||||
|
||||
@ -993,7 +986,7 @@ class Drm_call
|
||||
}
|
||||
|
||||
int const prime_fd { 44 };
|
||||
Handle_id prime_handle { };
|
||||
Gpu::Buffer_id prime_handle { };
|
||||
|
||||
int _generic_prime_fd_to_handle(void *arg)
|
||||
{
|
||||
@ -1010,16 +1003,18 @@ class Drm_call
|
||||
{
|
||||
auto const p = reinterpret_cast<drm_prime_handle *>(arg);
|
||||
|
||||
Handle_id const handle { .value = p->handle };
|
||||
bool handled = _apply_buffer(handle, [&](Buffer_handle const &bh) {
|
||||
if (!prime_handle.value)
|
||||
prime_handle = handle;
|
||||
Gpu::Buffer_id const id { .value = p->handle };
|
||||
try {
|
||||
_buffer_space.apply<Buffer>(id, [&](Buffer const &b) {
|
||||
if (!prime_handle.value)
|
||||
prime_handle = id;
|
||||
|
||||
if (prime_handle.value != handle.value)
|
||||
Genode::error("prime handle changed - ignored ", bh.handle);
|
||||
});
|
||||
if (!handled)
|
||||
if (prime_handle.value != id.value)
|
||||
Genode::error("prime handle changed - ignored ", b.id().value);
|
||||
});
|
||||
} catch (Genode::Id_space<Buffer>::Unknown_id) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->fd = prime_fd;
|
||||
return 0;
|
||||
@ -1069,7 +1064,7 @@ class Drm_call
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
_buffer_registry.for_each([&] (Buffer_handle &h) {
|
||||
_buffer_space.for_each<Buffer>([&] (Buffer &h) {
|
||||
if (h.map_offset != offset) { return; }
|
||||
if (length > h.size) { Genode::error("map_buffer_ggtt: size mismatch"); return; }
|
||||
result = true;
|
||||
@ -1085,20 +1080,20 @@ class Drm_call
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
_buffer_registry.for_each([&] (Buffer_handle &bh) {
|
||||
if (found || !bh.buffer_attached.constructed())
|
||||
_buffer_space.for_each<Buffer>([&] (Buffer &b) {
|
||||
if (found || !b.buffer_attached.constructed())
|
||||
return;
|
||||
|
||||
if (reinterpret_cast<void *>(bh.mmap_addr()) != addr)
|
||||
if (reinterpret_cast<void *>(b.mmap_addr()) != addr)
|
||||
return;
|
||||
|
||||
if (bh.buffer_attached->size() != length) {
|
||||
if (b.buffer_attached->size() != length) {
|
||||
Genode::warning(__func__, " size mismatch");
|
||||
Genode::sleep_forever();
|
||||
return;
|
||||
}
|
||||
|
||||
bh.buffer_attached.destruct();
|
||||
b.buffer_attached.destruct();
|
||||
found = true;
|
||||
});
|
||||
|
||||
@ -1115,7 +1110,7 @@ class Drm_call
|
||||
|
||||
bool handled = false;
|
||||
|
||||
_buffer_registry.for_each([&] (Buffer_handle &h) {
|
||||
_buffer_space.for_each<Buffer>([&] (Buffer &h) {
|
||||
if (handled) return;
|
||||
if (h.map_offset != offset) return;
|
||||
if (length > h.size) { Genode::error("unmap_buffer_ggtt: size mismatch"); return; }
|
||||
@ -1152,7 +1147,7 @@ class Drm_call
|
||||
/* make done buffer objects */
|
||||
Gpu::Info gpu_info { _gpu_session.info() };
|
||||
|
||||
_buffer_registry.for_each([&] (Buffer_handle &h) {
|
||||
_buffer_space.for_each<Buffer>([&] (Buffer &h) {
|
||||
if (!h.busy) return;
|
||||
if (h.seqno.id > gpu_info.last_completed.id) return;
|
||||
h.busy = false;
|
||||
|
@ -40,35 +40,34 @@ class Gpu::Session_client : public Genode::Rpc_client<Session>
|
||||
Info info() const override {
|
||||
return call<Rpc_info>(); }
|
||||
|
||||
Gpu::Info::Execution_buffer_sequence exec_buffer(Genode::Dataspace_capability cap,
|
||||
Gpu::Info::Execution_buffer_sequence exec_buffer(Buffer_id id,
|
||||
Genode::size_t size) override {
|
||||
return call<Rpc_exec_buffer>(cap, size); }
|
||||
return call<Rpc_exec_buffer>(id, size); }
|
||||
|
||||
void completion_sigh(Genode::Signal_context_capability sigh) override {
|
||||
call<Rpc_completion_sigh>(sigh); }
|
||||
|
||||
Genode::Dataspace_capability alloc_buffer(Genode::size_t size) override {
|
||||
return call<Rpc_alloc_buffer>(size); }
|
||||
Genode::Dataspace_capability alloc_buffer(Buffer_id id, Genode::size_t size) override {
|
||||
return call<Rpc_alloc_buffer>(id, size); }
|
||||
|
||||
void free_buffer(Genode::Dataspace_capability ds) override {
|
||||
call<Rpc_free_buffer>(ds); }
|
||||
void free_buffer(Gpu::Buffer_id id) override {
|
||||
call<Rpc_free_buffer>(id); }
|
||||
|
||||
Genode::Dataspace_capability map_buffer(Genode::Dataspace_capability ds,
|
||||
Genode::Dataspace_capability map_buffer(Buffer_id id,
|
||||
bool aperture) override {
|
||||
return call<Rpc_map_buffer>(ds, aperture); }
|
||||
return call<Rpc_map_buffer>(id, aperture); }
|
||||
|
||||
void unmap_buffer(Genode::Dataspace_capability ds) override {
|
||||
call<Rpc_unmap_buffer>(ds); }
|
||||
void unmap_buffer(Buffer_id id) override {
|
||||
call<Rpc_unmap_buffer>(id); }
|
||||
|
||||
bool map_buffer_ppgtt(Genode::Dataspace_capability ds,
|
||||
Gpu::addr_t va) override {
|
||||
return call<Rpc_map_buffer_ppgtt>(ds, va); }
|
||||
bool map_buffer_ppgtt(Buffer_id id, Gpu::addr_t va) override {
|
||||
return call<Rpc_map_buffer_ppgtt>(id, va); }
|
||||
|
||||
void unmap_buffer_ppgtt(Genode::Dataspace_capability ds, Gpu::addr_t va) override {
|
||||
call<Rpc_unmap_buffer_ppgtt>(ds, va); }
|
||||
void unmap_buffer_ppgtt(Buffer_id id, Gpu::addr_t va) override {
|
||||
call<Rpc_unmap_buffer_ppgtt>(id, va); }
|
||||
|
||||
bool set_tiling(Genode::Dataspace_capability ds, unsigned mode) override {
|
||||
return call<Rpc_set_tiling>(ds, mode); }
|
||||
bool set_tiling(Buffer_id id, unsigned mode) override {
|
||||
return call<Rpc_set_tiling>(id, mode); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__GPU_SESSION__CLIENT_H_ */
|
||||
|
@ -14,12 +14,16 @@
|
||||
#ifndef _INCLUDE__GPU_SESSION__GPU_SESSION_H_
|
||||
#define _INCLUDE__GPU_SESSION__GPU_SESSION_H_
|
||||
|
||||
#include <base/id_space.h>
|
||||
#include <session/session.h>
|
||||
|
||||
namespace Gpu {
|
||||
|
||||
using addr_t = Genode::uint64_t;
|
||||
|
||||
struct Buffer;
|
||||
using Buffer_id = Genode::Id_space<Buffer>::Id;
|
||||
|
||||
struct Info;
|
||||
struct Session;
|
||||
}
|
||||
@ -74,9 +78,10 @@ struct Gpu::Info
|
||||
*/
|
||||
struct Gpu::Session : public Genode::Session
|
||||
{
|
||||
struct Out_of_ram : Genode::Exception { };
|
||||
struct Out_of_caps : Genode::Exception { };
|
||||
struct Invalid_state : Genode::Exception { };
|
||||
struct Out_of_ram : Genode::Exception { };
|
||||
struct Out_of_caps : Genode::Exception { };
|
||||
struct Invalid_state : Genode::Exception { };
|
||||
struct Conflicting_id : Genode::Exception { };
|
||||
struct Mapping_buffer_failed : Genode::Exception { };
|
||||
|
||||
enum { REQUIRED_QUOTA = 1024 * 1024, CAP_QUOTA = 8, };
|
||||
@ -97,14 +102,14 @@ struct Gpu::Session : public Genode::Session
|
||||
/**
|
||||
* Execute commands from given buffer
|
||||
*
|
||||
* \param cap capability to buffer object containing the exec buffer
|
||||
* \param id buffer id
|
||||
* \param size size of the batch buffer in bytes
|
||||
*
|
||||
* \return execution buffer sequence number for complete checks
|
||||
*
|
||||
* \throw Invalid_state is thrown if the provided buffer is not valid, e.g not mapped
|
||||
*/
|
||||
virtual Gpu::Info::Execution_buffer_sequence exec_buffer(Genode::Dataspace_capability cap, Genode::size_t size) = 0;
|
||||
virtual Gpu::Info::Execution_buffer_sequence exec_buffer(Buffer_id id, Genode::size_t size) = 0;
|
||||
|
||||
/**
|
||||
* Register completion signal handler
|
||||
@ -117,65 +122,66 @@ struct Gpu::Session : public Genode::Session
|
||||
/**
|
||||
* Allocate buffer dataspace
|
||||
*
|
||||
* \param id buffer id to be associated with the buffer
|
||||
* \param size size of buffer in bytes
|
||||
*
|
||||
* \throw Out_of_ram
|
||||
* \throw Out_of_caps
|
||||
* \throw Conflicting_id
|
||||
*/
|
||||
virtual Genode::Dataspace_capability alloc_buffer(Genode::size_t size) = 0;
|
||||
virtual Genode::Dataspace_capability alloc_buffer(Buffer_id id, Genode::size_t size) = 0;
|
||||
|
||||
/**
|
||||
* Free buffer dataspace
|
||||
*
|
||||
* \param ds dataspace capability for buffer
|
||||
*/
|
||||
virtual void free_buffer(Genode::Dataspace_capability ds) = 0;
|
||||
virtual void free_buffer(Buffer_id id) = 0;
|
||||
|
||||
/**
|
||||
* Map buffer
|
||||
*
|
||||
* \param ds dataspace capability for buffer
|
||||
* \param id buffer id
|
||||
* \param aperture if true create CPU accessible mapping through
|
||||
* GGTT window, otherwise create PPGTT mapping
|
||||
*
|
||||
* \throw Mapping_buffer_failed
|
||||
*/
|
||||
virtual Genode::Dataspace_capability map_buffer(Genode::Dataspace_capability ds,
|
||||
virtual Genode::Dataspace_capability map_buffer(Buffer_id id,
|
||||
bool aperture) = 0;
|
||||
|
||||
/**
|
||||
* Unmap buffer
|
||||
*
|
||||
* \param ds dataspace capability for buffer
|
||||
* \param id buffer id
|
||||
*/
|
||||
virtual void unmap_buffer(Genode::Dataspace_capability ds) = 0;
|
||||
virtual void unmap_buffer(Buffer_id id) = 0;
|
||||
|
||||
/**
|
||||
* Map buffer in PPGTT
|
||||
*
|
||||
* \param ds dataspace capability for buffer
|
||||
* \param id buffer id
|
||||
* \param va virtual address
|
||||
*
|
||||
* \throw Mapping_buffer_failed
|
||||
* \throw Out_of_ram
|
||||
*/
|
||||
virtual bool map_buffer_ppgtt(Genode::Dataspace_capability ds,
|
||||
Gpu::addr_t va) = 0;
|
||||
virtual bool map_buffer_ppgtt(Buffer_id id, Gpu::addr_t va) = 0;
|
||||
|
||||
/**
|
||||
* Unmap buffer
|
||||
*
|
||||
* \param ds dataspace capability for buffer
|
||||
* \param id buffer id
|
||||
*/
|
||||
virtual void unmap_buffer_ppgtt(Genode::Dataspace_capability ds, Gpu::addr_t) = 0;
|
||||
virtual void unmap_buffer_ppgtt(Buffer_id id, Gpu::addr_t) = 0;
|
||||
|
||||
/**
|
||||
* Set tiling for buffer
|
||||
*
|
||||
* \param ds dataspace capability for buffer
|
||||
* \param id buffer id
|
||||
* \param mode tiling mode
|
||||
*/
|
||||
virtual bool set_tiling(Genode::Dataspace_capability ds, unsigned mode) = 0;
|
||||
virtual bool set_tiling(Buffer_id id, unsigned mode) = 0;
|
||||
|
||||
/*******************
|
||||
** RPC interface **
|
||||
@ -184,25 +190,25 @@ struct Gpu::Session : public Genode::Session
|
||||
GENODE_RPC(Rpc_info, Info, info);
|
||||
GENODE_RPC_THROW(Rpc_exec_buffer, Gpu::Info::Execution_buffer_sequence, exec_buffer,
|
||||
GENODE_TYPE_LIST(Invalid_state),
|
||||
Genode::Dataspace_capability, Genode::size_t);
|
||||
Gpu::Buffer_id, Genode::size_t);
|
||||
GENODE_RPC(Rpc_completion_sigh, void, completion_sigh,
|
||||
Genode::Signal_context_capability);
|
||||
GENODE_RPC_THROW(Rpc_alloc_buffer, Genode::Dataspace_capability, alloc_buffer,
|
||||
GENODE_TYPE_LIST(Out_of_ram),
|
||||
Genode::size_t);
|
||||
GENODE_RPC(Rpc_free_buffer, void, free_buffer, Genode::Dataspace_capability);
|
||||
Gpu::Buffer_id, Genode::size_t);
|
||||
GENODE_RPC(Rpc_free_buffer, void, free_buffer, Gpu::Buffer_id);
|
||||
GENODE_RPC_THROW(Rpc_map_buffer, Genode::Dataspace_capability, map_buffer,
|
||||
GENODE_TYPE_LIST(Mapping_buffer_failed, Out_of_ram),
|
||||
Genode::Dataspace_capability, bool);
|
||||
Gpu::Buffer_id, bool);
|
||||
GENODE_RPC(Rpc_unmap_buffer, void, unmap_buffer,
|
||||
Genode::Dataspace_capability);
|
||||
Gpu::Buffer_id);
|
||||
GENODE_RPC_THROW(Rpc_map_buffer_ppgtt, bool, map_buffer_ppgtt,
|
||||
GENODE_TYPE_LIST(Mapping_buffer_failed, Out_of_ram),
|
||||
Genode::Dataspace_capability, Gpu::addr_t);
|
||||
Gpu::Buffer_id, Gpu::addr_t);
|
||||
GENODE_RPC(Rpc_unmap_buffer_ppgtt, void, unmap_buffer_ppgtt,
|
||||
Genode::Dataspace_capability, Gpu::addr_t);
|
||||
Gpu::Buffer_id, Gpu::addr_t);
|
||||
GENODE_RPC(Rpc_set_tiling, bool, set_tiling,
|
||||
Genode::Dataspace_capability, unsigned);
|
||||
Gpu::Buffer_id, unsigned);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_info, Rpc_exec_buffer,
|
||||
Rpc_completion_sigh, Rpc_alloc_buffer,
|
||||
|
@ -1462,6 +1462,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
|
||||
struct Buffer
|
||||
{
|
||||
Gpu::Buffer_id const id;
|
||||
Genode::Dataspace_capability cap;
|
||||
|
||||
Gpu::addr_t ppgtt_va { };
|
||||
@ -1472,13 +1473,26 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
|
||||
Igd::Ggtt::Mapping map { };
|
||||
|
||||
Buffer(Genode::Dataspace_capability cap) : cap(cap) { }
|
||||
Buffer(Gpu::Buffer_id id, Genode::Dataspace_capability cap)
|
||||
: id { id }, cap { cap } { }
|
||||
|
||||
virtual ~Buffer() { }
|
||||
};
|
||||
|
||||
Genode::Registry<Genode::Registered<Buffer>> _buffer_registry { };
|
||||
|
||||
template <typename FN>
|
||||
void _apply_buffer(Gpu::Buffer_id id, FN const &fn)
|
||||
{
|
||||
_buffer_registry.for_each([&] (Buffer &buffer) {
|
||||
if (id.value != buffer.id.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
fn(buffer);
|
||||
});
|
||||
}
|
||||
|
||||
Genode::uint64_t seqno { 0 };
|
||||
|
||||
void _free_buffers()
|
||||
@ -1559,13 +1573,12 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
_device._subslices);
|
||||
}
|
||||
|
||||
Gpu::Info::Execution_buffer_sequence exec_buffer(Genode::Dataspace_capability cap,
|
||||
Gpu::Info::Execution_buffer_sequence exec_buffer(Buffer_id id,
|
||||
Genode::size_t) override
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
_buffer_registry.for_each([&] (Buffer &buffer) {
|
||||
if (found || !(buffer.cap == cap)) { return; }
|
||||
_apply_buffer(id, [&] (Buffer &buffer) {
|
||||
|
||||
if (!buffer.ppgtt_va_valid) {
|
||||
Genode::error("Invalid execbuffer");
|
||||
@ -1588,8 +1601,15 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
_vgpu.completion_sigh(sigh);
|
||||
}
|
||||
|
||||
Genode::Dataspace_capability alloc_buffer(Genode::size_t size) override
|
||||
Genode::Dataspace_capability alloc_buffer(Gpu::Buffer_id id,
|
||||
Genode::size_t size) override
|
||||
{
|
||||
bool found = false;
|
||||
_apply_buffer(id, [&] (Buffer &) {
|
||||
found = true;
|
||||
});
|
||||
if (found) { throw Conflicting_id(); }
|
||||
|
||||
/*
|
||||
* XXX allocator overhead is not
|
||||
* included, mapping costs are not included and we throw at
|
||||
@ -1605,7 +1625,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
Genode::Dataspace_capability cap = _device.alloc_buffer(_heap, size);
|
||||
|
||||
try {
|
||||
new (&_heap) Genode::Registered<Buffer>(_buffer_registry, cap);
|
||||
new (&_heap) Genode::Registered<Buffer>(_buffer_registry, id, cap);
|
||||
} catch (...) {
|
||||
if (cap.valid())
|
||||
_device.free_buffer(_heap, cap);
|
||||
@ -1619,33 +1639,27 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
return Genode::Dataspace_capability();
|
||||
}
|
||||
|
||||
void free_buffer(Genode::Dataspace_capability cap) override
|
||||
void free_buffer(Gpu::Buffer_id id) override
|
||||
{
|
||||
if (!cap.valid()) { return; }
|
||||
|
||||
auto lookup_and_free = [&] (Buffer &buffer) {
|
||||
if (!(buffer.cap == cap)) { return; }
|
||||
|
||||
if (buffer.map.offset != Igd::Ggtt::Mapping::INVALID_OFFSET) {
|
||||
Genode::error("cannot free mapped buffer");
|
||||
/* XXX throw */
|
||||
}
|
||||
|
||||
_device.free_buffer(_heap, cap);
|
||||
_device.free_buffer(_heap, buffer.cap);
|
||||
Genode::destroy(&_heap, &buffer);
|
||||
};
|
||||
_buffer_registry.for_each(lookup_and_free);
|
||||
_apply_buffer(id, lookup_and_free);
|
||||
}
|
||||
|
||||
Genode::Dataspace_capability map_buffer(Genode::Dataspace_capability cap,
|
||||
Genode::Dataspace_capability map_buffer(Gpu::Buffer_id id,
|
||||
bool aperture) override
|
||||
{
|
||||
if (!cap.valid()) { return Genode::Dataspace_capability(); }
|
||||
|
||||
Genode::Dataspace_capability map_cap;
|
||||
|
||||
auto lookup_and_map = [&] (Buffer &buffer) {
|
||||
if (!(buffer.cap == cap)) { return; }
|
||||
|
||||
if (buffer.map.offset != Igd::Ggtt::Mapping::INVALID_OFFSET) {
|
||||
Genode::error("buffer already mapped");
|
||||
@ -1653,7 +1667,8 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
}
|
||||
|
||||
try {
|
||||
Igd::Ggtt::Mapping const &map = _device.map_buffer(_heap, cap, aperture);
|
||||
Igd::Ggtt::Mapping const &map =
|
||||
_device.map_buffer(_heap, buffer.cap, aperture);
|
||||
buffer.map.cap = map.cap;
|
||||
buffer.map.offset = map.offset;
|
||||
map_cap = buffer.map.cap;
|
||||
@ -1662,19 +1677,17 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
throw Gpu::Session::Out_of_ram();
|
||||
}
|
||||
};
|
||||
_buffer_registry.for_each(lookup_and_map);
|
||||
_apply_buffer(id, lookup_and_map);
|
||||
|
||||
return map_cap;
|
||||
}
|
||||
|
||||
void unmap_buffer(Genode::Dataspace_capability cap) override
|
||||
void unmap_buffer(Gpu::Buffer_id id) override
|
||||
{
|
||||
if (!cap.valid()) { return; }
|
||||
|
||||
bool unmapped = false;
|
||||
|
||||
auto lookup_and_unmap = [&] (Buffer &buffer) {
|
||||
if (!(buffer.map.cap == cap)) { return; }
|
||||
if (!buffer.map.cap.valid()) { return; }
|
||||
|
||||
if (buffer.fenced != Buffer::INVALID_FENCE) {
|
||||
_device.clear_tiling(buffer.fenced);
|
||||
@ -1685,20 +1698,16 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
buffer.map.offset = Igd::Ggtt::Mapping::INVALID_OFFSET;
|
||||
unmapped = true;
|
||||
};
|
||||
_buffer_registry.for_each(lookup_and_unmap);
|
||||
_apply_buffer(id, lookup_and_unmap);
|
||||
|
||||
if (!unmapped) { Genode::error("buffer not mapped"); }
|
||||
}
|
||||
|
||||
bool map_buffer_ppgtt(Genode::Dataspace_capability cap,
|
||||
Gpu::addr_t va) override
|
||||
bool map_buffer_ppgtt(Gpu::Buffer_id id, Gpu::addr_t va) override
|
||||
{
|
||||
if (!cap.valid()) { return false; }
|
||||
|
||||
enum { ALLOC_FAILED, MAP_FAILED, OK } result = ALLOC_FAILED;
|
||||
|
||||
auto lookup_and_map = [&] (Buffer &buffer) {
|
||||
if (!(buffer.cap == cap)) { return; }
|
||||
|
||||
if (buffer.ppgtt_va_valid) {
|
||||
Genode::error("buffer already mapped");
|
||||
@ -1706,7 +1715,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
}
|
||||
|
||||
try {
|
||||
Genode::Dataspace_client buf(cap);
|
||||
Genode::Dataspace_client buf(buffer.cap);
|
||||
/* XXX check that actual_size matches alloc_buffer size */
|
||||
Genode::size_t const actual_size = buf.size();
|
||||
Genode::addr_t const phys_addr = buf.phys_addr();
|
||||
@ -1724,7 +1733,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
return;
|
||||
}
|
||||
};
|
||||
_buffer_registry.for_each(lookup_and_map);
|
||||
_apply_buffer(id, lookup_and_map);
|
||||
|
||||
switch (result) {
|
||||
case ALLOC_FAILED: throw Gpu::Session::Out_of_ram();
|
||||
@ -1735,16 +1744,10 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
}
|
||||
}
|
||||
|
||||
void unmap_buffer_ppgtt(Genode::Dataspace_capability cap,
|
||||
void unmap_buffer_ppgtt(Gpu::Buffer_id id,
|
||||
Gpu::addr_t va) override
|
||||
{
|
||||
if (!cap.valid()) {
|
||||
Genode::error("invalid buffer capability");
|
||||
return;
|
||||
}
|
||||
|
||||
auto lookup_and_unmap = [&] (Buffer &buffer) {
|
||||
if (!(buffer.cap == cap)) { return; }
|
||||
|
||||
if (!buffer.ppgtt_va_valid) {
|
||||
Genode::error("buffer not mapped");
|
||||
@ -1756,15 +1759,15 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Dataspace_client buf(cap);
|
||||
Genode::Dataspace_client buf(buffer.cap);
|
||||
Genode::size_t const actual_size = buf.size();
|
||||
_vgpu.rcs_unmap_ppgtt(va, actual_size);
|
||||
buffer.ppgtt_va_valid = false;
|
||||
};
|
||||
_buffer_registry.for_each(lookup_and_unmap);
|
||||
_apply_buffer(id, lookup_and_unmap);
|
||||
}
|
||||
|
||||
bool set_tiling(Genode::Dataspace_capability cap,
|
||||
bool set_tiling(Gpu::Buffer_id id,
|
||||
Genode::uint32_t const mode) override
|
||||
{
|
||||
if (_vgpu.active_fences > Igd::Device::Vgpu::MAX_FENCES) {
|
||||
@ -1774,10 +1777,10 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
|
||||
Buffer *b = nullptr;
|
||||
auto lookup = [&] (Buffer &buffer) {
|
||||
if (!(buffer.map.cap == cap)) { return; }
|
||||
if (!buffer.map.cap.valid()) { return; }
|
||||
b = &buffer;
|
||||
};
|
||||
_buffer_registry.for_each(lookup);
|
||||
_apply_buffer(id, lookup);
|
||||
|
||||
if (b == nullptr) {
|
||||
Genode::error("attempt to set tiling for non-mapped buffer");
|
||||
|
Loading…
x
Reference in New Issue
Block a user