summaryrefslogtreecommitdiff
path: root/Kernel/Bus/VirtIO
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2022-01-21 11:51:02 +0200
committerAndreas Kling <kling@serenityos.org>2022-01-21 16:27:21 +0100
commitc3099382b803a2b3d649e04b1211d3d607eeac58 (patch)
treeab116cd017314d59292c1e7732860088a7ad3d40 /Kernel/Bus/VirtIO
parent17584d8a845652249a3df8bb98ef7ad522b0506c (diff)
downloadserenity-c3099382b803a2b3d649e04b1211d3d607eeac58.zip
Kernel: Make VirtIO::Queue construction fallible
Diffstat (limited to 'Kernel/Bus/VirtIO')
-rw-r--r--Kernel/Bus/VirtIO/Device.cpp5
-rw-r--r--Kernel/Bus/VirtIO/Queue.cpp28
-rw-r--r--Kernel/Bus/VirtIO/Queue.h8
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;