mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-15 04:13:11 +00:00
Kernel: Make VirtIO::Queue construction fallible
This commit is contained in:
parent
17584d8a84
commit
c3099382b8
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue