mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:27:35 +00:00
Kernel: Make VirtIO::Queue construction fallible
This commit is contained in:
parent
17584d8a84
commit
c3099382b8
3 changed files with 26 additions and 15 deletions
|
@ -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);
|
u16 queue_notify_offset = config_read16(*m_common_cfg, COMMON_CFG_QUEUE_NOTIFY_OFF);
|
||||||
|
|
||||||
auto queue = make<Queue>(queue_size, queue_notify_offset);
|
auto queue_or_error = Queue::try_create(queue_size, queue_notify_offset);
|
||||||
if (queue->is_null())
|
if (queue_or_error.is_error())
|
||||||
return false;
|
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_DESC, queue->descriptor_area().get());
|
||||||
config_write64(*m_common_cfg, COMMON_CFG_QUEUE_DRIVER, queue->driver_area().get());
|
config_write64(*m_common_cfg, COMMON_CFG_QUEUE_DRIVER, queue->driver_area().get());
|
||||||
|
|
|
@ -9,19 +9,28 @@
|
||||||
|
|
||||||
namespace Kernel::VirtIO {
|
namespace Kernel::VirtIO {
|
||||||
|
|
||||||
Queue::Queue(u16 queue_size, u16 notify_offset)
|
ErrorOr<NonnullOwnPtr<Queue>> Queue::try_create(u16 queue_size, u16 notify_offset)
|
||||||
: m_queue_size(queue_size)
|
|
||||||
, m_notify_offset(notify_offset)
|
|
||||||
, m_free_buffers(queue_size)
|
|
||||||
{
|
{
|
||||||
size_t size_of_descriptors = sizeof(QueueDescriptor) * queue_size;
|
size_t size_of_descriptors = sizeof(QueueDescriptor) * queue_size;
|
||||||
size_t size_of_driver = sizeof(QueueDriver) + queue_size * sizeof(u16);
|
size_t size_of_driver = sizeof(QueueDriver) + queue_size * sizeof(u16);
|
||||||
size_t size_of_device = sizeof(QueueDevice) + queue_size * sizeof(QueueDeviceItem);
|
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)
|
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
|
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!!!
|
// TODO: ensure alignment!!!
|
||||||
u8* ptr = m_queue_region->vaddr().as_ptr();
|
u8* ptr = m_queue_region->vaddr().as_ptr();
|
||||||
memset(ptr, 0, m_queue_region->size());
|
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_driver = reinterpret_cast<QueueDriver*>(ptr + size_of_descriptors);
|
||||||
m_device = reinterpret_cast<QueueDevice*>(ptr + size_of_descriptors + size_of_driver);
|
m_device = reinterpret_cast<QueueDevice*>(ptr + size_of_descriptors + size_of_driver);
|
||||||
|
|
||||||
for (auto i = 0; i + 1 < queue_size; i++) {
|
for (auto i = 0; i + 1 < queue_size; i++)
|
||||||
m_descriptors[i].next = i + 1; // link all of the descriptors in a line
|
m_descriptors[i].next = i + 1; // link all the descriptors in a line
|
||||||
}
|
|
||||||
|
|
||||||
enable_interrupts();
|
enable_interrupts();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,10 @@ enum class BufferType {
|
||||||
|
|
||||||
class Queue {
|
class Queue {
|
||||||
public:
|
public:
|
||||||
Queue(u16 queue_size, u16 notify_offset);
|
static ErrorOr<NonnullOwnPtr<Queue>> try_create(u16 queue_size, u16 notify_offset);
|
||||||
|
|
||||||
~Queue();
|
~Queue();
|
||||||
|
|
||||||
bool is_null() const { return !m_queue_region; }
|
|
||||||
u16 notify_offset() const { return m_notify_offset; }
|
u16 notify_offset() const { return m_notify_offset; }
|
||||||
|
|
||||||
void enable_interrupts();
|
void enable_interrupts();
|
||||||
|
@ -52,6 +52,8 @@ public:
|
||||||
bool should_notify() const;
|
bool should_notify() const;
|
||||||
|
|
||||||
private:
|
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);
|
void reclaim_buffer_chain(u16 chain_start_index, u16 chain_end_index, size_t length_of_chain);
|
||||||
|
|
||||||
PhysicalAddress to_physical(const void* ptr) const
|
PhysicalAddress to_physical(const void* ptr) const
|
||||||
|
@ -93,7 +95,7 @@ private:
|
||||||
QueueDescriptor* m_descriptors { nullptr };
|
QueueDescriptor* m_descriptors { nullptr };
|
||||||
QueueDriver* m_driver { nullptr };
|
QueueDriver* m_driver { nullptr };
|
||||||
QueueDevice* m_device { nullptr };
|
QueueDevice* m_device { nullptr };
|
||||||
OwnPtr<Memory::Region> m_queue_region;
|
NonnullOwnPtr<Memory::Region> m_queue_region;
|
||||||
Spinlock m_lock;
|
Spinlock m_lock;
|
||||||
|
|
||||||
friend class QueueChain;
|
friend class QueueChain;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue