Просмотр исходного кода

Kernel: Disable BootFramebufferConsole when drivers create a new one

When GraphicsManagement initializes the drivers we can disable the
bootloader framebuffer console. Right now we don't yet fully destroy
the no longer needed console as it may be in use by another CPU.
Tom 3 лет назад
Родитель
Сommit
4c506f91fe

+ 1 - 2
Kernel/Graphics/Bochs/GraphicsAdapter.cpp

@@ -107,8 +107,7 @@ UNMAP_AFTER_INIT BochsGraphicsAdapter::BochsGraphicsAdapter(PCI::DeviceIdentifie
 {
 {
     // We assume safe resolution is 1024x768x32
     // We assume safe resolution is 1024x768x32
     m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(PhysicalAddress(PCI::get_BAR0(pci_device_identifier.address()) & 0xfffffff0), 1024, 768, 1024 * sizeof(u32));
     m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(PhysicalAddress(PCI::get_BAR0(pci_device_identifier.address()) & 0xfffffff0), 1024, 768, 1024 * sizeof(u32));
-    // FIXME: This is a very wrong way to do this...
-    GraphicsManagement::the().m_console = m_framebuffer_console;
+    GraphicsManagement::the().set_console(*m_framebuffer_console);
 
 
     // Note: If we use VirtualBox graphics adapter (which is based on Bochs one), we need to use IO ports
     // Note: If we use VirtualBox graphics adapter (which is based on Bochs one), we need to use IO ports
     if (pci_device_identifier.hardware_id().vendor_id == 0x80ee && pci_device_identifier.hardware_id().device_id == 0xbeef)
     if (pci_device_identifier.hardware_id().vendor_id == 0x80ee && pci_device_identifier.hardware_id().device_id == 0xbeef)

+ 27 - 0
Kernel/Graphics/GraphicsManagement.cpp

@@ -10,6 +10,7 @@
 #include <Kernel/Bus/PCI/IDs.h>
 #include <Kernel/Bus/PCI/IDs.h>
 #include <Kernel/CommandLine.h>
 #include <Kernel/CommandLine.h>
 #include <Kernel/Graphics/Bochs/GraphicsAdapter.h>
 #include <Kernel/Graphics/Bochs/GraphicsAdapter.h>
+#include <Kernel/Graphics/Console/BootFramebufferConsole.h>
 #include <Kernel/Graphics/GraphicsManagement.h>
 #include <Kernel/Graphics/GraphicsManagement.h>
 #include <Kernel/Graphics/Intel/NativeGraphicsAdapter.h>
 #include <Kernel/Graphics/Intel/NativeGraphicsAdapter.h>
 #include <Kernel/Graphics/VGACompatibleAdapter.h>
 #include <Kernel/Graphics/VGACompatibleAdapter.h>
@@ -22,6 +23,8 @@ namespace Kernel {
 
 
 static Singleton<GraphicsManagement> s_the;
 static Singleton<GraphicsManagement> s_the;
 
 
+extern Atomic<Graphics::BootFramebufferConsole*> boot_framebuffer_console;
+
 GraphicsManagement& GraphicsManagement::the()
 GraphicsManagement& GraphicsManagement::the()
 {
 {
     return *s_the;
     return *s_the;
@@ -215,6 +218,15 @@ UNMAP_AFTER_INIT bool GraphicsManagement::initialize()
         determine_and_initialize_graphics_device(device_identifier);
         determine_and_initialize_graphics_device(device_identifier);
     });
     });
 
 
+    if (!m_console) {
+        // If no graphics driver was instantiated and we had a bootloader provided
+        // framebuffer console we can simply re-use it.
+        if (auto* boot_console = boot_framebuffer_console.load()) {
+            m_console = *boot_console;
+            boot_console->unref(); // Drop the leaked reference from Kernel::init()
+        }
+    }
+
     if (m_graphics_devices.is_empty()) {
     if (m_graphics_devices.is_empty()) {
         dbgln("No graphics adapter was initialized.");
         dbgln("No graphics adapter was initialized.");
         return false;
         return false;
@@ -230,4 +242,19 @@ bool GraphicsManagement::framebuffer_devices_exist() const
     }
     }
     return false;
     return false;
 }
 }
+
+void GraphicsManagement::set_console(Graphics::Console& console)
+{
+    m_console = console;
+
+    if (auto* boot_console = boot_framebuffer_console.exchange(nullptr)) {
+        // Disable the initial boot framebuffer console permanently
+        boot_console->disable();
+        // TODO: Even though we swapped the pointer and disabled the console
+        // we technically can't safely destroy it as other CPUs might still
+        // try to use it. Once we solve this problem we can drop the reference
+        // that we intentionally leaked in Kernel::init().
+    }
+}
+
 }
 }

+ 1 - 7
Kernel/Graphics/GraphicsManagement.h

@@ -19,14 +19,7 @@
 
 
 namespace Kernel {
 namespace Kernel {
 
 
-class BochsGraphicsAdapter;
-class IntelNativeGraphicsAdapter;
-class VGACompatibleAdapter;
 class GraphicsManagement {
 class GraphicsManagement {
-    friend class BochsGraphicsAdapter;
-    friend class IntelNativeGraphicsAdapter;
-    friend class VGACompatibleAdapter;
-    friend class Graphics::VirtIOGPU::GraphicsAdapter;
 
 
 public:
 public:
     static GraphicsManagement& the();
     static GraphicsManagement& the();
@@ -42,6 +35,7 @@ public:
 
 
     Spinlock& main_vga_lock() { return m_main_vga_lock; }
     Spinlock& main_vga_lock() { return m_main_vga_lock; }
     RefPtr<Graphics::Console> console() const { return m_console; }
     RefPtr<Graphics::Console> console() const { return m_console; }
+    void set_console(Graphics::Console&);
 
 
     void deactivate_graphical_mode();
     void deactivate_graphical_mode();
     void activate_graphical_mode();
     void activate_graphical_mode();

+ 1 - 2
Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp

@@ -209,8 +209,7 @@ IntelNativeGraphicsAdapter::IntelNativeGraphicsAdapter(PCI::Address address)
     VERIFY(m_framebuffer_height != 0);
     VERIFY(m_framebuffer_height != 0);
     VERIFY(m_framebuffer_width != 0);
     VERIFY(m_framebuffer_width != 0);
     m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(framebuffer_address, m_framebuffer_width, m_framebuffer_height, m_framebuffer_pitch);
     m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(framebuffer_address, m_framebuffer_width, m_framebuffer_height, m_framebuffer_pitch);
-    // FIXME: This is a very wrong way to do this...
-    GraphicsManagement::the().m_console = m_framebuffer_console;
+    GraphicsManagement::the().set_console(*m_framebuffer_console);
 }
 }
 
 
 void IntelNativeGraphicsAdapter::enable_vga_plane()
 void IntelNativeGraphicsAdapter::enable_vga_plane()

+ 2 - 4
Kernel/Graphics/VGACompatibleAdapter.cpp

@@ -40,8 +40,7 @@ UNMAP_AFTER_INIT VGACompatibleAdapter::VGACompatibleAdapter(PCI::Address address
     : PCI::Device(address)
     : PCI::Device(address)
 {
 {
     m_framebuffer_console = Graphics::TextModeConsole::initialize(*this);
     m_framebuffer_console = Graphics::TextModeConsole::initialize(*this);
-    // FIXME: This is a very wrong way to do this...
-    GraphicsManagement::the().m_console = m_framebuffer_console;
+    GraphicsManagement::the().set_console(*m_framebuffer_console);
 }
 }
 
 
 UNMAP_AFTER_INIT VGACompatibleAdapter::VGACompatibleAdapter(PCI::Address address, PhysicalAddress framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch)
 UNMAP_AFTER_INIT VGACompatibleAdapter::VGACompatibleAdapter(PCI::Address address, PhysicalAddress framebuffer_address, size_t framebuffer_width, size_t framebuffer_height, size_t framebuffer_pitch)
@@ -52,8 +51,7 @@ UNMAP_AFTER_INIT VGACompatibleAdapter::VGACompatibleAdapter(PCI::Address address
     , m_framebuffer_pitch(framebuffer_pitch)
     , m_framebuffer_pitch(framebuffer_pitch)
 {
 {
     m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch);
     m_framebuffer_console = Graphics::ContiguousFramebufferConsole::initialize(framebuffer_address, framebuffer_width, framebuffer_height, framebuffer_pitch);
-    // FIXME: This is a very wrong way to do this...
-    GraphicsManagement::the().m_console = m_framebuffer_console;
+    GraphicsManagement::the().set_console(*m_framebuffer_console);
 }
 }
 
 
 void VGACompatibleAdapter::enable_consoles()
 void VGACompatibleAdapter::enable_consoles()

+ 1 - 2
Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp

@@ -43,8 +43,7 @@ void GraphicsAdapter::initialize_framebuffer_devices()
     create_framebuffer_devices();
     create_framebuffer_devices();
     m_created_framebuffer_devices = true;
     m_created_framebuffer_devices = true;
 
 
-    // FIXME: This is a very wrong way to do this...
-    GraphicsManagement::the().m_console = default_console();
+    GraphicsManagement::the().set_console(*default_console());
 }
 }
 
 
 void GraphicsAdapter::enable_consoles()
 void GraphicsAdapter::enable_consoles()