Kernel: Allocate VirtIOGPU context IDs from a bitmap, with ErrorOr

As is, we never *deallocate* them, so we will run out eventually.

Creating a context, or allocating a context ID, now returns ErrorOr if
there are no available free context IDs.

`number_of_fixmes--;` :^)
This commit is contained in:
Sam Atkins 2022-12-09 14:53:55 +00:00 committed by Linus Groh
parent 6d67cb516a
commit 1b5a565e55
Notes: sideshowbarker 2024-07-17 09:56:35 +09:00
3 changed files with 32 additions and 13 deletions

View file

@ -39,7 +39,7 @@ VirtIOGPU3DDevice::VirtIOGPU3DDevice(VirtIOGraphicsAdapter const& graphics_adapt
, m_graphics_adapter(graphics_adapter)
, m_transfer_buffer_region(move(transfer_buffer_region))
{
m_kernel_context_id = m_graphics_adapter->create_context();
m_kernel_context_id = MUST(m_graphics_adapter->create_context());
}
void VirtIOGPU3DDevice::detach(OpenFileDescription& description)
@ -65,7 +65,7 @@ ErrorOr<void> VirtIOGPU3DDevice::ioctl(OpenFileDescription& description, unsigne
return EEXIST;
SpinlockLocker locker(m_graphics_adapter->operation_lock());
// TODO: Delete the context if it fails to be set in m_context_state_lookup
auto context_id = m_graphics_adapter->create_context();
auto context_id = TRY(m_graphics_adapter->create_context());
LockRefPtr<PerContextState> per_context_state = TRY(PerContextState::try_create(context_id));
TRY(m_context_state_lookup.try_set(&description, per_context_state));
return {};

View file

@ -30,7 +30,8 @@ NonnullLockRefPtr<VirtIOGraphicsAdapter> VirtIOGraphicsAdapter::initialize(PCI::
"VirtGPU Scratch Space"sv,
Memory::Region::Access::ReadWrite));
auto adapter = adopt_lock_ref(*new (nothrow) VirtIOGraphicsAdapter(device_identifier, move(scratch_space_region)));
auto active_context_ids = Bitmap::must_create(VREND_MAX_CTX, false);
auto adapter = adopt_lock_ref(*new (nothrow) VirtIOGraphicsAdapter(device_identifier, move(active_context_ids), move(scratch_space_region)));
adapter->initialize();
MUST(adapter->initialize_adapter());
return adapter;
@ -125,10 +126,15 @@ ErrorOr<void> VirtIOGraphicsAdapter::attach_physical_range_to_framebuffer(VirtIO
return {};
}
VirtIOGraphicsAdapter::VirtIOGraphicsAdapter(PCI::DeviceIdentifier const& device_identifier, NonnullOwnPtr<Memory::Region> scratch_space_region)
VirtIOGraphicsAdapter::VirtIOGraphicsAdapter(PCI::DeviceIdentifier const& device_identifier, Bitmap&& active_context_ids, NonnullOwnPtr<Memory::Region> scratch_space_region)
: VirtIO::Device(device_identifier)
, m_scratch_space(move(scratch_space_region))
{
m_active_context_ids.with([&](Bitmap& my_active_context_ids) {
my_active_context_ids = move(active_context_ids);
// Note: Context ID 0 is invalid, so mark it as in use.
my_active_context_ids.set(0, true);
});
}
void VirtIOGraphicsAdapter::initialize()
@ -410,10 +416,23 @@ Graphics::VirtIOGPU::ResourceID VirtIOGraphicsAdapter::allocate_resource_id()
return m_resource_id_counter++;
}
Graphics::VirtIOGPU::ContextID VirtIOGraphicsAdapter::allocate_context_id()
ErrorOr<Graphics::VirtIOGPU::ContextID> VirtIOGraphicsAdapter::allocate_context_id()
{
// FIXME: This should really be tracked using a bitmap, instead of an atomic counter
return m_context_id_counter++;
Optional<Graphics::VirtIOGPU::ContextID> new_context_id;
m_active_context_ids.with([&new_context_id](Bitmap& active_context_ids) {
auto maybe_available_id = active_context_ids.find_first_unset();
if (!maybe_available_id.has_value())
return;
new_context_id = maybe_available_id.value();
active_context_ids.set(maybe_available_id.value(), true);
});
if (new_context_id.has_value())
return new_context_id.value();
dmesgln("VirtIO::GraphicsAdapter: No available context IDs.");
return Error::from_errno(ENXIO);
}
void VirtIOGraphicsAdapter::delete_resource(Graphics::VirtIOGPU::ResourceID resource_id)
@ -439,10 +458,10 @@ void VirtIOGraphicsAdapter::initialize_3d_device()
}
}
Graphics::VirtIOGPU::ContextID VirtIOGraphicsAdapter::create_context()
ErrorOr<Graphics::VirtIOGPU::ContextID> VirtIOGraphicsAdapter::create_context()
{
VERIFY(m_operation_lock.is_locked());
auto ctx_id = allocate_context_id();
auto ctx_id = TRY(allocate_context_id());
auto writer = create_scratchspace_writer();
auto& request = writer.append_structure<Graphics::VirtIOGPU::Protocol::ContextCreate>();
auto& response = writer.append_structure<Graphics::VirtIOGPU::Protocol::ControlHeader>();

View file

@ -63,7 +63,7 @@ private:
PhysicalBuffer back_buffer;
};
VirtIOGraphicsAdapter(PCI::DeviceIdentifier const&, NonnullOwnPtr<Memory::Region> scratch_space_region);
VirtIOGraphicsAdapter(PCI::DeviceIdentifier const&, Bitmap&& active_context_ids, NonnullOwnPtr<Memory::Region> scratch_space_region);
ErrorOr<void> initialize_adapter();
@ -80,14 +80,14 @@ private:
}
// 3D Command stuff
Graphics::VirtIOGPU::ContextID create_context();
ErrorOr<Graphics::VirtIOGPU::ContextID> create_context();
void attach_resource_to_context(Graphics::VirtIOGPU::ResourceID resource_id, Graphics::VirtIOGPU::ContextID context_id);
void submit_command_buffer(Graphics::VirtIOGPU::ContextID, Function<size_t(Bytes)> buffer_writer);
Graphics::VirtIOGPU::Protocol::TextureFormat get_framebuffer_format() const { return Graphics::VirtIOGPU::Protocol::TextureFormat::VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; }
auto& operation_lock() { return m_operation_lock; }
Graphics::VirtIOGPU::ResourceID allocate_resource_id();
Graphics::VirtIOGPU::ContextID allocate_context_id();
ErrorOr<Graphics::VirtIOGPU::ContextID> allocate_context_id();
PhysicalAddress start_of_scratch_space() const { return m_scratch_space->physical_page(0)->paddr(); }
AK::BinaryBufferWriter create_scratchspace_writer()
@ -113,7 +113,7 @@ private:
VirtIO::Configuration const* m_device_configuration { nullptr };
// Note: Resource ID 0 is invalid, and we must not allocate 0 as the first resource ID.
Atomic<u32> m_resource_id_counter { 1 };
Atomic<u32> m_context_id_counter { 1 };
SpinlockProtected<Bitmap> m_active_context_ids { LockRank::None };
LockRefPtr<VirtIOGPU3DDevice> m_3d_device;
bool m_has_virgl_support { false };