diff --git a/repos/os/include/gpu_session/client.h b/repos/os/include/gpu_session/client.h index 7fbaec96bb..16548c2975 100644 --- a/repos/os/include/gpu_session/client.h +++ b/repos/os/include/gpu_session/client.h @@ -40,8 +40,9 @@ class Gpu::Session_client : public Genode::Rpc_client Info info() const override { return call(); } - void exec_buffer(Genode::Dataspace_capability cap, Genode::size_t size) override { - call(cap, size); } + Gpu::Info::Execution_buffer_sequence exec_buffer(Genode::Dataspace_capability cap, + Genode::size_t size) override { + return call(cap, size); } void completion_sigh(Genode::Signal_context_capability sigh) override { call(sigh); } diff --git a/repos/os/include/gpu_session/gpu_session.h b/repos/os/include/gpu_session/gpu_session.h index e4be24e55c..9a801116fc 100644 --- a/repos/os/include/gpu_session/gpu_session.h +++ b/repos/os/include/gpu_session/gpu_session.h @@ -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, diff --git a/repos/os/src/drivers/gpu/intel/main.cc b/repos/os/src/drivers/gpu/intel/main.cc index 8b42a77718..b1b5a192e6 100644 --- a/repos/os/src/drivers/gpu/intel/main.cc +++ b/repos/os/src/drivers/gpu/intel/main.cc @@ -1366,15 +1366,16 @@ class Gpu::Session_component : public Genode::Session_object 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 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 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 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 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 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); }