summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@serenityos.org>2022-12-09 14:53:55 +0000
committerLinus Groh <mail@linusgroh.de>2022-12-15 22:04:28 +0000
commit1b5a565e5587bcf58d8801601a2c519771c1e971 (patch)
tree4841bb9dcfdb9f6fada0429e7e73fc41c067f7df /Kernel
parent6d67cb516a78f7d9131cf88cc1bf2d8439d95ee8 (diff)
downloadserenity-1b5a565e5587bcf58d8801601a2c519771c1e971.zip
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--;` :^)
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp4
-rw-r--r--Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp33
-rw-r--r--Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h8
3 files changed, 32 insertions, 13 deletions
diff --git a/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp b/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp
index 90f0fcc4dc..3ed02a12d1 100644
--- a/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp
+++ b/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp
@@ -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 {};
diff --git a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp
index 1c0a37bbed..be3059316d 100644
--- a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp
+++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp
@@ -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>();
diff --git a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h
index 0e35d162b8..81e496a202 100644
--- a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h
+++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h
@@ -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 };