gpu/intel: add support to report finished batches

- extend gpu multiplexer to report last completed execution buffer
- on client side lookup finished buffers and disable busy state

issue #4233
This commit is contained in:
Alexander Boettcher 2021-06-18 14:07:21 +02:00 committed by Christian Helmuth
parent f8953de7ac
commit b3147050cc
3 changed files with 52 additions and 31 deletions

View File

@ -40,8 +40,9 @@ class Gpu::Session_client : public Genode::Rpc_client<Session>
Info info() const override {
return call<Rpc_info>(); }
void exec_buffer(Genode::Dataspace_capability cap, Genode::size_t size) override {
call<Rpc_exec_buffer>(cap, size); }
Gpu::Info::Execution_buffer_sequence exec_buffer(Genode::Dataspace_capability cap,
Genode::size_t size) override {
return call<Rpc_exec_buffer>(cap, size); }
void completion_sigh(Genode::Signal_context_capability sigh) override {
call<Rpc_completion_sigh>(sigh); }

View File

@ -42,11 +42,17 @@ struct Gpu::Info
size_t aperture_size;
Context_id ctx_id;
Info(Chip_id chip_id, Features features,
size_t aperture_size, Context_id ctx_id)
struct Execution_buffer_sequence {
Genode::uint64_t id;
} last_completed;
Info(Chip_id chip_id, Features features, size_t aperture_size,
Context_id ctx_id, Execution_buffer_sequence last)
:
chip_id(chip_id), features(features),
aperture_size(aperture_size), ctx_id(ctx_id)
aperture_size(aperture_size), ctx_id(ctx_id),
last_completed(last)
{ }
};
@ -56,8 +62,9 @@ struct Gpu::Info
*/
struct Gpu::Session : public Genode::Session
{
struct Out_of_ram : Genode::Exception { };
struct Out_of_caps : Genode::Exception { };
struct Out_of_ram : Genode::Exception { };
struct Out_of_caps : Genode::Exception { };
struct Invalid_state : Genode::Exception { };
enum { REQUIRED_QUOTA = 1024 * 1024, CAP_QUOTA = 8, };
@ -79,8 +86,12 @@ struct Gpu::Session : public Genode::Session
*
* \param cap capability to buffer object containing the exec buffer
* \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 void exec_buffer(Genode::Dataspace_capability cap, Genode::size_t size) = 0;
virtual Gpu::Info::Execution_buffer_sequence exec_buffer(Genode::Dataspace_capability cap, Genode::size_t size) = 0;
/**
* Register completion signal handler
@ -153,8 +164,9 @@ struct Gpu::Session : public Genode::Session
*******************/
GENODE_RPC(Rpc_info, Info, info);
GENODE_RPC(Rpc_exec_buffer, void, exec_buffer, Genode::Dataspace_capability,
Genode::size_t);
GENODE_RPC_THROW(Rpc_exec_buffer, Gpu::Info::Execution_buffer_sequence, exec_buffer,
GENODE_TYPE_LIST(Invalid_state),
Genode::Dataspace_capability, 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,

View File

@ -1366,15 +1366,16 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
struct Buffer
{
Genode::Dataspace_capability cap;
Gpu::addr_t ppgtt_va;
enum { INVALID_FENCE = 0xff, };
Genode::uint32_t fenced;
Gpu::addr_t ppgtt_va { };
bool ppgtt_va_valid { false };
enum { INVALID_FENCE = 0xff };
Genode::uint32_t fenced { INVALID_FENCE };
Igd::Ggtt::Mapping map { };
Buffer(Genode::Dataspace_capability cap)
: cap(cap), ppgtt_va(0), fenced(INVALID_FENCE) { }
Buffer(Genode::Dataspace_capability cap) : cap(cap) { }
virtual ~Buffer() { }
};
@ -1457,31 +1458,37 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
Info info() const override
{
Genode::size_t const aperture_size = Igd::Device::Vgpu::APERTURE_SIZE;
return Info(_device.id(), _device.features(), aperture_size, _vgpu.id());
return Info(_device.id(), _device.features(), aperture_size,
_vgpu.id(), { .id = _vgpu.complete_seqno() });
}
void exec_buffer(Genode::Dataspace_capability cap, Genode::size_t) override
Gpu::Info::Execution_buffer_sequence exec_buffer(Genode::Dataspace_capability cap,
Genode::size_t) override
{
Igd::addr_t ppgtt_va = 0;
bool found = false;
auto lookup = [&] (Buffer &buffer) {
_buffer_registry.for_each([&] (Buffer &buffer) {
if (!(buffer.cap == cap)) { return; }
ppgtt_va = buffer.ppgtt_va;
};
_buffer_registry.for_each(lookup);
if (!ppgtt_va) {
Genode::error("Invalid execbuffer");
Genode::Signal_transmitter(_vgpu.completion_sigh()).submit();
return;
}
if (!buffer.ppgtt_va_valid) {
Genode::error("Invalid execbuffer");
Genode::Signal_transmitter(_vgpu.completion_sigh()).submit();
throw Gpu::Session::Invalid_state();
}
_vgpu.setup_ring_buffer(ppgtt_va, _device._ggtt->scratch_page());
_vgpu.setup_ring_buffer(buffer.ppgtt_va, _device._ggtt->scratch_page());
found = true;
});
if (!found)
throw Gpu::Session::Invalid_state();
try {
_device.vgpu_enqueue(_vgpu);
return { .id = _vgpu.current_seqno() };
} catch (Igd::Device::Already_scheduled &e) {
Genode::error("vGPU already scheduled");
return { .id = _vgpu.current_seqno() }; /* XXX */
}
}
@ -1604,7 +1611,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
auto lookup_and_map = [&] (Buffer &buffer) {
if (!(buffer.cap == cap)) { return; }
if (buffer.ppgtt_va != 0) {
if (buffer.ppgtt_va_valid) {
Genode::error("buffer already mapped");
return;
}
@ -1616,6 +1623,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
Genode::addr_t const phys_addr = buf.phys_addr();
_vgpu.rcs_map_ppgtt(va, phys_addr, actual_size);
buffer.ppgtt_va = va;
buffer.ppgtt_va_valid = true;
result = true;
} catch (Igd::Device::Could_not_map_buffer) {
/* FIXME do not result in Out_of_ram */
@ -1643,7 +1651,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
auto lookup_and_unmap = [&] (Buffer &buffer) {
if (!(buffer.cap == cap)) { return; }
if (buffer.ppgtt_va == 0) {
if (!buffer.ppgtt_va_valid) {
Genode::error("buffer not mapped");
return;
}
@ -1656,7 +1664,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
Genode::Dataspace_client buf(cap);
Genode::size_t const actual_size = buf.size();
_vgpu.rcs_unmap_ppgtt(va, actual_size);
buffer.ppgtt_va = 0;
buffer.ppgtt_va_valid = false;
};
_buffer_registry.for_each(lookup_and_unmap);
}