From 7625f7db739d7ce4e0b398e1f3d555960304366d Mon Sep 17 00:00:00 2001 From: Liav A Date: Thu, 22 Dec 2022 11:35:35 +0200 Subject: [PATCH] Kernel/Graphics: Allocate 16 MiB framebuffer if failed allocating larger We try our best to ensure a DisplayConnector initialization succeeds, and this makes the Intel driver to work again, because if we can't allocate a Region for the whole PCI BAR mapped region, then we will try to allocate a Region with 16 MiB window size, so it doesn't eat the entire Kernel-allocated virtual memory space. --- Kernel/Graphics/DisplayConnector.cpp | 37 +++++++++++++++++++--------- Kernel/Graphics/DisplayConnector.h | 4 ++- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/Kernel/Graphics/DisplayConnector.cpp b/Kernel/Graphics/DisplayConnector.cpp index 1e969deda8..056f95c597 100644 --- a/Kernel/Graphics/DisplayConnector.cpp +++ b/Kernel/Graphics/DisplayConnector.cpp @@ -74,6 +74,23 @@ void DisplayConnector::will_be_destroyed() before_will_be_destroyed_remove_from_device_management(); } +ErrorOr DisplayConnector::allocate_framebuffer_resources(size_t rounded_size) +{ + VERIFY((rounded_size % PAGE_SIZE) == 0); + if (!m_framebuffer_at_arbitrary_physical_range) { + VERIFY(m_framebuffer_address.value().page_base() == m_framebuffer_address.value()); + m_shared_framebuffer_vmobject = TRY(Memory::SharedFramebufferVMObject::try_create_for_physical_range(m_framebuffer_address.value(), rounded_size)); + m_framebuffer_region = TRY(MM.allocate_kernel_region(m_framebuffer_address.value().page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite)); + } else { + m_shared_framebuffer_vmobject = TRY(Memory::SharedFramebufferVMObject::try_create_at_arbitrary_physical_range(rounded_size)); + m_framebuffer_region = TRY(MM.allocate_kernel_region_with_vmobject(m_shared_framebuffer_vmobject->real_writes_framebuffer_vmobject(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite)); + } + + m_framebuffer_data = m_framebuffer_region->vaddr().as_ptr(); + m_fake_writes_framebuffer_region = TRY(MM.allocate_kernel_region_with_vmobject(m_shared_framebuffer_vmobject->fake_writes_framebuffer_vmobject(), rounded_size, "Fake Writes Framebuffer"sv, Memory::Region::Access::ReadWrite)); + return {}; +} + ErrorOr DisplayConnector::after_inserting() { after_inserting_add_to_device_management(); @@ -99,20 +116,18 @@ ErrorOr DisplayConnector::after_inserting() m_symlink_sysfs_component.clear(); }); - auto rounded_size = TRY(Memory::page_round_up(m_framebuffer_resource_size)); - - if (!m_framebuffer_at_arbitrary_physical_range) { - VERIFY(m_framebuffer_address.value().page_base() == m_framebuffer_address.value()); - m_shared_framebuffer_vmobject = TRY(Memory::SharedFramebufferVMObject::try_create_for_physical_range(m_framebuffer_address.value(), rounded_size)); - m_framebuffer_region = TRY(MM.allocate_kernel_region(m_framebuffer_address.value().page_base(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite)); + if (auto result_or_error = Memory::page_round_up(m_framebuffer_resource_size); result_or_error.is_error()) { + // NOTE: The amount of framebuffer resource being specified is erroneous, then default to 16 MiB. + TRY(allocate_framebuffer_resources(16 * MiB)); + m_framebuffer_resource_size = 16 * MiB; } else { - m_shared_framebuffer_vmobject = TRY(Memory::SharedFramebufferVMObject::try_create_at_arbitrary_physical_range(rounded_size)); - m_framebuffer_region = TRY(MM.allocate_kernel_region_with_vmobject(m_shared_framebuffer_vmobject->real_writes_framebuffer_vmobject(), rounded_size, "Framebuffer"sv, Memory::Region::Access::ReadWrite)); + if (auto allocation_result = allocate_framebuffer_resources(result_or_error.release_value()); allocation_result.is_error()) { + // NOTE: The amount of framebuffer resource being specified is too big, use 16 MiB just to get going. + TRY(allocate_framebuffer_resources(16 * MiB)); + m_framebuffer_resource_size = 16 * MiB; + } } - m_framebuffer_data = m_framebuffer_region->vaddr().as_ptr(); - m_fake_writes_framebuffer_region = TRY(MM.allocate_kernel_region_with_vmobject(m_shared_framebuffer_vmobject->fake_writes_framebuffer_vmobject(), rounded_size, "Fake Writes Framebuffer"sv, Memory::Region::Access::ReadWrite)); - clean_from_device_management.disarm(); clean_from_sysfs_display_connector_device_directory.disarm(); clean_symlink_to_device_identifier_directory.disarm(); diff --git a/Kernel/Graphics/DisplayConnector.h b/Kernel/Graphics/DisplayConnector.h index 8c9db63807..5448ecce47 100644 --- a/Kernel/Graphics/DisplayConnector.h +++ b/Kernel/Graphics/DisplayConnector.h @@ -148,6 +148,8 @@ private: virtual void will_be_destroyed() override; virtual ErrorOr after_inserting() override; + ErrorOr allocate_framebuffer_resources(size_t rounded_size); + ErrorOr ioctl_requires_ownership(unsigned request) const; OwnPtr m_framebuffer_region; @@ -159,7 +161,7 @@ private: protected: Optional const m_framebuffer_address; - size_t const m_framebuffer_resource_size; + size_t m_framebuffer_resource_size; private: LockRefPtr m_shared_framebuffer_vmobject;