Simplify core methods in the VirtIO bus handling code by ensuring proper
error propagation. This makes initialization of queues, handling changes
in device configuration, and other core patterns more readable as well.
It also allows us to remove the obnoxious pattern of checking for
boolean "success" and if we get false answer then returning an actual
errno code.
The VirtIO specification defines many types of devices with different
purposes, and it also defines 3 possible transport mediums where devices
could be connected to the host machine.
We only care about the PCIe transport, but this commit puts the actual
foundations for supporting the lean MMIO transport too in the future.
To ensure things are kept abstracted but still functional, the VirtIO
transport code is responsible for what is deemed as related to an actual
transport type - allocation of interrupt handlers and tinkering with low
level transport-related registers, etc.
Rename the initialize method to initialize_virtio_resources so it's
clear what this method is intended for.
To ensure healthier device initialization, we could also return the type
of ErrorOr<void> from this method, so in all overriden instances and in
the original method code, we could leverage TRY() pattern which also
does simplify the code a bit.
Until now, our kernel has reimplemented a number of AK classes to
provide automatic internal locking:
- RefPtr
- NonnullRefPtr
- WeakPtr
- Weakable
This patch renames the Kernel classes so that they can coexist with
the original AK classes:
- RefPtr => LockRefPtr
- NonnullRefPtr => NonnullLockRefPtr
- WeakPtr => LockWeakPtr
- Weakable => LockWeakable
The goal here is to eventually get rid of the Lock* classes in favor of
using external locking.
In most cases it's safe to abort the requested operation and go forward,
however, in some places it's not clear yet how to handle these failures,
therefore, we use the MUST() wrapper to force a kernel panic for now.
We already init receive buffer if we have singleport console, but if
we have multiport console that dynamically allocates ports we never
initted their receive buffers.
Previously, Virtio console ports would not show up in `/sys/dev/char/`.
Also adds support to `SystemServer` to create more than one console
port device in `/dev/` in the multiport case.
Devices might be removed and inserted at anytime, so let's ensure we
always do these kind of operations with a good known state of the
HashMap.
The VirtIO code was modified to create devices outside the IRQ handler,
so now it works with the new locking of the devices singleton, but a
better approach might be needed later on.
This ensures we safely handle interrupts (which can call virtual
functions), so they don't happen in the constructor - this pattern can
lead to a crash, if we are still in the constructor context because
not all methods are available for usage (some are pure virtual,
so it's possible to call __cxa_pure_virtual).
Also, under some conditions like adding a PCI device via PCI-passthrough
mechanism in QEMU, it became exposed to the eye that the code asserts on
RNG::handle_device_config_change(). That device has no configuration but
if the hypervisor still misbehaves and tries to configure it, we should
simply return false to indicate nothing happened.
This leads to a bad pattern where anyone could create an RNG or a
Console object. Instead, let's just use the common pattern of a static
method to instantiate a new object and return it wrapped by a
NonnullRefPtr.