diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2022-01-21 11:51:02 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-01-21 16:27:21 +0100 |
commit | c3099382b803a2b3d649e04b1211d3d607eeac58 (patch) | |
tree | ab116cd017314d59292c1e7732860088a7ad3d40 /Kernel/Bus/VirtIO | |
parent | 17584d8a845652249a3df8bb98ef7ad522b0506c (diff) | |
download | serenity-c3099382b803a2b3d649e04b1211d3d607eeac58.zip |
Kernel: Make VirtIO::Queue construction fallible
Diffstat (limited to 'Kernel/Bus/VirtIO')
-rw-r--r-- | Kernel/Bus/VirtIO/Device.cpp | 5 | ||||
-rw-r--r-- | Kernel/Bus/VirtIO/Queue.cpp | 28 | ||||
-rw-r--r-- | Kernel/Bus/VirtIO/Queue.h | 8 |
3 files changed, 26 insertions, 15 deletions
diff --git a/Kernel/Bus/VirtIO/Device.cpp b/Kernel/Bus/VirtIO/Device.cpp index cc6199aeb7..885566b5ac 100644 --- a/Kernel/Bus/VirtIO/Device.cpp +++ b/Kernel/Bus/VirtIO/Device.cpp @@ -327,9 +327,10 @@ bool Device::setup_queue(u16 queue_index) u16 queue_notify_offset = config_read16(*m_common_cfg, COMMON_CFG_QUEUE_NOTIFY_OFF); - auto queue = make<Queue>(queue_size, queue_notify_offset); - if (queue->is_null()) + auto queue_or_error = Queue::try_create(queue_size, queue_notify_offset); + if (queue_or_error.is_error()) return false; + auto queue = queue_or_error.release_value(); config_write64(*m_common_cfg, COMMON_CFG_QUEUE_DESC, queue->descriptor_area().get()); config_write64(*m_common_cfg, COMMON_CFG_QUEUE_DRIVER, queue->driver_area().get()); diff --git a/Kernel/Bus/VirtIO/Queue.cpp b/Kernel/Bus/VirtIO/Queue.cpp index df2cc2fa94..0263708170 100644 --- a/Kernel/Bus/VirtIO/Queue.cpp +++ b/Kernel/Bus/VirtIO/Queue.cpp @@ -9,19 +9,28 @@ namespace Kernel::VirtIO { -Queue::Queue(u16 queue_size, u16 notify_offset) - : m_queue_size(queue_size) - , m_notify_offset(notify_offset) - , m_free_buffers(queue_size) +ErrorOr<NonnullOwnPtr<Queue>> Queue::try_create(u16 queue_size, u16 notify_offset) { size_t size_of_descriptors = sizeof(QueueDescriptor) * queue_size; size_t size_of_driver = sizeof(QueueDriver) + queue_size * sizeof(u16); size_t size_of_device = sizeof(QueueDevice) + queue_size * sizeof(QueueDeviceItem); - auto queue_region_size = Memory::page_round_up(size_of_descriptors + size_of_driver + size_of_device).release_value_but_fixme_should_propagate_errors(); + auto queue_region_size = TRY(Memory::page_round_up(size_of_descriptors + size_of_driver + size_of_device)); + OwnPtr<Memory::Region> queue_region; if (queue_region_size <= PAGE_SIZE) - m_queue_region = MM.allocate_kernel_region(queue_region_size, "VirtIO Queue", Memory::Region::Access::ReadWrite).release_value(); + queue_region = TRY(MM.allocate_kernel_region(queue_region_size, "VirtIO Queue"sv, Memory::Region::Access::ReadWrite)); else - m_queue_region = MM.allocate_contiguous_kernel_region(queue_region_size, "VirtIO Queue", Memory::Region::Access::ReadWrite).release_value(); + queue_region = TRY(MM.allocate_contiguous_kernel_region(queue_region_size, "VirtIO Queue"sv, Memory::Region::Access::ReadWrite)); + return adopt_nonnull_own_or_enomem(new (nothrow) Queue(queue_region.release_nonnull(), queue_size, notify_offset)); +} + +Queue::Queue(NonnullOwnPtr<Memory::Region> queue_region, u16 queue_size, u16 notify_offset) + : m_queue_size(queue_size) + , m_notify_offset(notify_offset) + , m_free_buffers(queue_size) + , m_queue_region(move(queue_region)) +{ + size_t size_of_descriptors = sizeof(QueueDescriptor) * queue_size; + size_t size_of_driver = sizeof(QueueDriver) + queue_size * sizeof(u16); // TODO: ensure alignment!!! u8* ptr = m_queue_region->vaddr().as_ptr(); memset(ptr, 0, m_queue_region->size()); @@ -29,9 +38,8 @@ Queue::Queue(u16 queue_size, u16 notify_offset) m_driver = reinterpret_cast<QueueDriver*>(ptr + size_of_descriptors); m_device = reinterpret_cast<QueueDevice*>(ptr + size_of_descriptors + size_of_driver); - for (auto i = 0; i + 1 < queue_size; i++) { - m_descriptors[i].next = i + 1; // link all of the descriptors in a line - } + for (auto i = 0; i + 1 < queue_size; i++) + m_descriptors[i].next = i + 1; // link all the descriptors in a line enable_interrupts(); } diff --git a/Kernel/Bus/VirtIO/Queue.h b/Kernel/Bus/VirtIO/Queue.h index 2b8872fde7..fab091b700 100644 --- a/Kernel/Bus/VirtIO/Queue.h +++ b/Kernel/Bus/VirtIO/Queue.h @@ -28,10 +28,10 @@ enum class BufferType { class Queue { public: - Queue(u16 queue_size, u16 notify_offset); + static ErrorOr<NonnullOwnPtr<Queue>> try_create(u16 queue_size, u16 notify_offset); + ~Queue(); - bool is_null() const { return !m_queue_region; } u16 notify_offset() const { return m_notify_offset; } void enable_interrupts(); @@ -52,6 +52,8 @@ public: bool should_notify() const; private: + Queue(NonnullOwnPtr<Memory::Region> queue_region, u16 queue_size, u16 notify_offset); + void reclaim_buffer_chain(u16 chain_start_index, u16 chain_end_index, size_t length_of_chain); PhysicalAddress to_physical(const void* ptr) const @@ -93,7 +95,7 @@ private: QueueDescriptor* m_descriptors { nullptr }; QueueDriver* m_driver { nullptr }; QueueDevice* m_device { nullptr }; - OwnPtr<Memory::Region> m_queue_region; + NonnullOwnPtr<Memory::Region> m_queue_region; Spinlock m_lock; friend class QueueChain; |