From 8131c0de8cae36cb0db778b3a46faf6a48701070 Mon Sep 17 00:00:00 2001 From: Sahan Fernando Date: Sat, 24 Apr 2021 11:30:27 +1000 Subject: [PATCH] Kernel: Move AHCIPort::ScatterList to VM::ScatterGatherList We want to move this out of the AHCI subsystem into the VM system, since other parts of the kernel may need to perform scatter-gather IO. We rename the current VM::ScatterGatherList impl that's used in the virtio subsystem to VM::ScatterGatherRefList, since its distinguishing feature from the AHCI scatter-gather list is that it doesn't own its buffers. --- Kernel/Storage/AHCIPort.cpp | 14 ++------------ Kernel/Storage/AHCIPort.h | 17 ++--------------- Kernel/VM/MemoryManager.h | 2 +- Kernel/VM/ScatterGatherList.cpp | 23 +++++++++++++++++------ Kernel/VM/ScatterGatherList.h | 29 ++++++++++++++++++++++++----- Kernel/VirtIO/VirtIO.cpp | 2 +- Kernel/VirtIO/VirtIO.h | 2 +- Kernel/VirtIO/VirtIOConsole.cpp | 4 ++-- Kernel/VirtIO/VirtIOQueue.cpp | 2 +- Kernel/VirtIO/VirtIOQueue.h | 2 +- Kernel/VirtIO/VirtIORNG.cpp | 2 +- 11 files changed, 53 insertions(+), 46 deletions(-) diff --git a/Kernel/Storage/AHCIPort.cpp b/Kernel/Storage/AHCIPort.cpp index e6c9b8faa13..0899cb000b7 100644 --- a/Kernel/Storage/AHCIPort.cpp +++ b/Kernel/Storage/AHCIPort.cpp @@ -11,22 +11,12 @@ #include #include #include +#include #include #include namespace Kernel { -NonnullRefPtr AHCIPort::ScatterList::create(AsyncBlockDeviceRequest& request, NonnullRefPtrVector allocated_pages, size_t device_block_size) -{ - return adopt_ref(*new ScatterList(request, allocated_pages, device_block_size)); -} - -AHCIPort::ScatterList::ScatterList(AsyncBlockDeviceRequest& request, NonnullRefPtrVector allocated_pages, size_t device_block_size) - : m_vm_object(AnonymousVMObject::create_with_physical_pages(allocated_pages)) -{ - m_dma_region = MM.allocate_kernel_region_with_vmobject(m_vm_object, page_round_up((request.block_count() * device_block_size)), "AHCI Scattered DMA", Region::Access::Read | Region::Access::Write, Region::Cacheable::Yes); -} - NonnullRefPtr AHCIPort::create(const AHCIPortHandler& handler, volatile AHCI::PortRegisters& registers, u32 port_index) { return adopt_ref(*new AHCIPort(handler, registers, port_index)); @@ -443,7 +433,7 @@ Optional AHCIPort::prepare_and_set_scatter_li allocated_dma_regions.append(m_dma_buffers.at(index)); } - m_current_scatter_list = ScatterList::create(request, allocated_dma_regions, m_connected_device->block_size()); + m_current_scatter_list = ScatterGatherList::create(request, allocated_dma_regions, m_connected_device->block_size()); if (request.request_type() == AsyncBlockDeviceRequest::Write) { if (!request.read_from_buffer(request.buffer(), m_current_scatter_list->dma_region().as_ptr(), m_connected_device->block_size() * request.block_count())) { return AsyncDeviceRequest::MemoryFault; diff --git a/Kernel/Storage/AHCIPort.h b/Kernel/Storage/AHCIPort.h index 02c3eba20bd..0b49490e980 100644 --- a/Kernel/Storage/AHCIPort.h +++ b/Kernel/Storage/AHCIPort.h @@ -20,6 +20,7 @@ #include #include #include +#include #include namespace Kernel { @@ -32,20 +33,6 @@ class AHCIPort : public RefCounted { friend class AHCIPortHandler; friend class SATADiskDevice; -private: - class ScatterList : public RefCounted { - public: - static NonnullRefPtr create(AsyncBlockDeviceRequest&, NonnullRefPtrVector allocated_pages, size_t device_block_size); - const VMObject& vmobject() const { return m_vm_object; } - VirtualAddress dma_region() const { return m_dma_region->vaddr(); } - size_t scatters_count() const { return m_vm_object->physical_pages().size(); } - - private: - ScatterList(AsyncBlockDeviceRequest&, NonnullRefPtrVector allocated_pages, size_t device_block_size); - NonnullRefPtr m_vm_object; - OwnPtr m_dma_region; - }; - public: UNMAP_AFTER_INIT static NonnullRefPtr create(const AHCIPortHandler&, volatile AHCI::PortRegisters&, u32 port_index); @@ -132,7 +119,7 @@ private: AHCI::PortInterruptStatusBitField m_interrupt_status; AHCI::PortInterruptEnableBitField m_interrupt_enable; - RefPtr m_current_scatter_list; + RefPtr m_current_scatter_list; bool m_disabled_by_firmware { false }; }; } diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h index cb5cc44beba..138f16865ba 100644 --- a/Kernel/VM/MemoryManager.h +++ b/Kernel/VM/MemoryManager.h @@ -104,7 +104,7 @@ class MemoryManager { friend class PhysicalRegion; friend class AnonymousVMObject; friend class Region; - friend class ScatterGatherList; + friend class ScatterGatherRefList; friend class VMObject; public: diff --git a/Kernel/VM/ScatterGatherList.cpp b/Kernel/VM/ScatterGatherList.cpp index 10441ecd771..2ae1de1cece 100644 --- a/Kernel/VM/ScatterGatherList.cpp +++ b/Kernel/VM/ScatterGatherList.cpp @@ -8,10 +8,21 @@ namespace Kernel { -ScatterGatherList ScatterGatherList::create_from_buffer(const u8* buffer, size_t size) +NonnullRefPtr ScatterGatherList::create(AsyncBlockDeviceRequest& request, NonnullRefPtrVector allocated_pages, size_t device_block_size) +{ + return adopt_ref(*new ScatterGatherList(request, allocated_pages, device_block_size)); +} + +ScatterGatherList::ScatterGatherList(AsyncBlockDeviceRequest& request, NonnullRefPtrVector allocated_pages, size_t device_block_size) + : m_vm_object(AnonymousVMObject::create_with_physical_pages(allocated_pages)) +{ + m_dma_region = MM.allocate_kernel_region_with_vmobject(m_vm_object, page_round_up((request.block_count() * device_block_size)), "AHCI Scattered DMA", Region::Access::Read | Region::Access::Write, Region::Cacheable::Yes); +} + +ScatterGatherRefList ScatterGatherRefList::create_from_buffer(const u8* buffer, size_t size) { VERIFY(buffer && size); - ScatterGatherList new_list; + ScatterGatherRefList new_list; auto* region = MM.find_region_from_vaddr(VirtualAddress(buffer)); VERIFY(region); while (size > 0) { @@ -25,20 +36,20 @@ ScatterGatherList ScatterGatherList::create_from_buffer(const u8* buffer, size_t return new_list; } -ScatterGatherList ScatterGatherList::create_from_physical(PhysicalAddress paddr, size_t size) +ScatterGatherRefList ScatterGatherRefList::create_from_physical(PhysicalAddress paddr, size_t size) { VERIFY(!paddr.is_null() && size); - ScatterGatherList new_list; + ScatterGatherRefList new_list; new_list.add_entry(paddr.page_base().get(), paddr.offset_in_page(), size); return new_list; } -void ScatterGatherList::add_entry(FlatPtr addr, size_t offset, size_t size) +void ScatterGatherRefList::add_entry(FlatPtr addr, size_t offset, size_t size) { m_entries.append({ addr, offset, size }); } -void ScatterGatherList::for_each_entry(Function callback) const +void ScatterGatherRefList::for_each_entry(Function callback) const { for (auto& entry : m_entries) callback(entry.page_base + entry.offset, entry.length); diff --git a/Kernel/VM/ScatterGatherList.h b/Kernel/VM/ScatterGatherList.h index 39c6fc74533..526e6acbccc 100644 --- a/Kernel/VM/ScatterGatherList.h +++ b/Kernel/VM/ScatterGatherList.h @@ -7,21 +7,40 @@ #pragma once #include +#include #include +#include #include namespace Kernel { -class ScatterGatherList { - struct ScatterGatherEntry { +/// A Scatter-Gather List type that owns its buffers + +class ScatterGatherList : public RefCounted { +public: + static NonnullRefPtr create(AsyncBlockDeviceRequest&, NonnullRefPtrVector allocated_pages, size_t device_block_size); + const VMObject& vmobject() const { return m_vm_object; } + VirtualAddress dma_region() const { return m_dma_region->vaddr(); } + size_t scatters_count() const { return m_vm_object->physical_pages().size(); } + +private: + ScatterGatherList(AsyncBlockDeviceRequest&, NonnullRefPtrVector allocated_pages, size_t device_block_size); + NonnullRefPtr m_vm_object; + OwnPtr m_dma_region; +}; + +/// A Scatter-Gather List type that doesn't own its buffers + +class ScatterGatherRefList { + struct ScatterGatherRef { FlatPtr page_base; size_t offset; size_t length; }; public: - static ScatterGatherList create_from_buffer(const u8* buffer, size_t); - static ScatterGatherList create_from_physical(PhysicalAddress, size_t); + static ScatterGatherRefList create_from_buffer(const u8* buffer, size_t); + static ScatterGatherRefList create_from_physical(PhysicalAddress, size_t); void add_entry(FlatPtr, size_t offset, size_t size); [[nodiscard]] size_t length() const { return m_entries.size(); } @@ -29,7 +48,7 @@ public: void for_each_entry(Function callback) const; private: - Vector m_entries; + Vector m_entries; }; } diff --git a/Kernel/VirtIO/VirtIO.cpp b/Kernel/VirtIO/VirtIO.cpp index 00649f870a0..6dece01201f 100644 --- a/Kernel/VirtIO/VirtIO.cpp +++ b/Kernel/VirtIO/VirtIO.cpp @@ -335,7 +335,7 @@ void VirtIODevice::finish_init() dbgln_if(VIRTIO_DEBUG, "{}: Finished initialization", m_class_name); } -void VirtIODevice::supply_buffer_and_notify(u16 queue_index, const ScatterGatherList& scatter_list, BufferType buffer_type, void* token) +void VirtIODevice::supply_buffer_and_notify(u16 queue_index, const ScatterGatherRefList& scatter_list, BufferType buffer_type, void* token) { VERIFY(queue_index < m_queue_count); if (get_queue(queue_index).supply_buffer({}, scatter_list, buffer_type, token)) diff --git a/Kernel/VirtIO/VirtIO.h b/Kernel/VirtIO/VirtIO.h index b764bebb008..b30159f2a3b 100644 --- a/Kernel/VirtIO/VirtIO.h +++ b/Kernel/VirtIO/VirtIO.h @@ -196,7 +196,7 @@ protected: return is_feature_set(m_accepted_features, feature); } - void supply_buffer_and_notify(u16 queue_index, const ScatterGatherList&, BufferType, void* token); + void supply_buffer_and_notify(u16 queue_index, const ScatterGatherRefList&, BufferType, void* token); virtual bool handle_device_config_change() = 0; virtual void handle_queue_update(u16 queue_index) = 0; diff --git a/Kernel/VirtIO/VirtIOConsole.cpp b/Kernel/VirtIO/VirtIOConsole.cpp index 49b209bf3a9..3376732d114 100644 --- a/Kernel/VirtIO/VirtIOConsole.cpp +++ b/Kernel/VirtIO/VirtIOConsole.cpp @@ -43,7 +43,7 @@ VirtIOConsole::VirtIOConsole(PCI::Address address) finish_init(); m_receive_region = MM.allocate_contiguous_kernel_region(PAGE_SIZE, "VirtIOConsole Receive", Region::Access::Read | Region::Access::Write); if (m_receive_region) { - supply_buffer_and_notify(RECEIVEQ, ScatterGatherList::create_from_physical(m_receive_region->physical_page(0)->paddr(), m_receive_region->size()), BufferType::DeviceWritable, m_receive_region->vaddr().as_ptr()); + supply_buffer_and_notify(RECEIVEQ, ScatterGatherRefList::create_from_physical(m_receive_region->physical_page(0)->paddr(), m_receive_region->size()), BufferType::DeviceWritable, m_receive_region->vaddr().as_ptr()); } m_transmit_region = MM.allocate_contiguous_kernel_region(PAGE_SIZE, "VirtIOConsole Transmit", Region::Access::Read | Region::Access::Write); } @@ -98,7 +98,7 @@ KResultOr VirtIOConsole::write(FileDescription&, u64, const UserOrKernel if (!size) return 0; - auto scatter_list = ScatterGatherList::create_from_buffer(static_cast(data.user_or_kernel_ptr()), size); + auto scatter_list = ScatterGatherRefList::create_from_buffer(static_cast(data.user_or_kernel_ptr()), size); supply_buffer_and_notify(TRANSMITQ, scatter_list, BufferType::DeviceReadable, const_cast(data.user_or_kernel_ptr())); return size; diff --git a/Kernel/VirtIO/VirtIOQueue.cpp b/Kernel/VirtIO/VirtIOQueue.cpp index 0ae7eccfdb2..1f1151f2d9e 100644 --- a/Kernel/VirtIO/VirtIOQueue.cpp +++ b/Kernel/VirtIO/VirtIOQueue.cpp @@ -48,7 +48,7 @@ void VirtIOQueue::disable_interrupts() m_driver->flags = 1; } -bool VirtIOQueue::supply_buffer(Badge, const ScatterGatherList& scatter_list, BufferType buffer_type, void* token) +bool VirtIOQueue::supply_buffer(Badge, const ScatterGatherRefList& scatter_list, BufferType buffer_type, void* token) { VERIFY(scatter_list.length() && scatter_list.length() <= m_free_buffers); m_free_buffers -= scatter_list.length(); diff --git a/Kernel/VirtIO/VirtIOQueue.h b/Kernel/VirtIO/VirtIOQueue.h index 9fa6ea7330b..2ea8ac38a72 100644 --- a/Kernel/VirtIO/VirtIOQueue.h +++ b/Kernel/VirtIO/VirtIOQueue.h @@ -38,7 +38,7 @@ public: PhysicalAddress driver_area() const { return to_physical(m_driver.ptr()); } PhysicalAddress device_area() const { return to_physical(m_device.ptr()); } - bool supply_buffer(Badge, const ScatterGatherList&, BufferType, void* token); + bool supply_buffer(Badge, const ScatterGatherRefList&, BufferType, void* token); bool new_data_available() const; bool can_write() const; void* get_buffer(size_t*); diff --git a/Kernel/VirtIO/VirtIORNG.cpp b/Kernel/VirtIO/VirtIORNG.cpp index 7d46b99a6bb..2fe5b817e26 100644 --- a/Kernel/VirtIO/VirtIORNG.cpp +++ b/Kernel/VirtIO/VirtIORNG.cpp @@ -23,7 +23,7 @@ VirtIORNG::VirtIORNG(PCI::Address address) m_entropy_buffer = MM.allocate_contiguous_kernel_region(PAGE_SIZE, "VirtIORNG", Region::Access::Read | Region::Access::Write); if (m_entropy_buffer) { memset(m_entropy_buffer->vaddr().as_ptr(), 0, m_entropy_buffer->size()); - supply_buffer_and_notify(REQUESTQ, ScatterGatherList::create_from_physical(m_entropy_buffer->physical_page(0)->paddr(), m_entropy_buffer->size()), BufferType::DeviceWritable, m_entropy_buffer->vaddr().as_ptr()); + supply_buffer_and_notify(REQUESTQ, ScatterGatherRefList::create_from_physical(m_entropy_buffer->physical_page(0)->paddr(), m_entropy_buffer->size()), BufferType::DeviceWritable, m_entropy_buffer->vaddr().as_ptr()); } } }