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.
Before of this change, many specific classes to VirtIO were in the
Kernel namespace, which polluted it.
Everything should be more organized now, but there's still room for
improvement later.
This class member was used only to determine the device type when
printing messages to the debug log. Instead, remove this class member,
and add a quick way to find the device type according to how the VirtIO
specification says to do that.
This simplifies construction of VirtIODevices a bit, because now the
constructor doesn't need to ask for a String identified with the device
type.
Now that the old PCI::Device was removed, we can complete the PCI
changes by making the PCI::DeviceController to be named PCI::Device.
Really the entire purpose and the distinction between the two was about
interrupts, but since this is no longer a problem, just rename it to
simplify things further.
This makes for nicer handling of errors compared to checking whether a
RefPtr is null. Additionally, this will give way to return different
types of errors in the future.
...and also RangeAllocator => VirtualRangeAllocator.
This clarifies that the ranges we're dealing with are *virtual* memory
ranges and not anything else.
It's easy to forget the responsibility of validating and safely copying
kernel parameters in code that is far away from syscalls. ioctl's are
one such example, and bugs there are just as dangerous as at the root
syscall level.
To avoid this case, utilize the AK::Userspace<T> template in the ioctl
kernel interface so that implementors have no choice but to properly
validate and copy ioctl pointer arguments.
We don't need to have a dedicated API for creating a VMObject with a
single page, the multi-page API option works in all cases.
Also make the API take a Span<NonnullRefPtr<PhysicalPage>> instead of
a NonnullRefPtrVector<PhysicalPage>.
It is not legal to resize a VMObject after it has been created.
As far as I can tell, this code would never actually run since the
object was already populated with physical pages due to using
AllocationStrategy::AllocateNow.
The spec requires a flush after setting the new buffer resource id,
which is required by QEMUs SDL backend but not the GTK backend. This
brings us in line with the spec and makes it work for the SDL backend.
Some devices may require DMA transfers to flush the updated buffer
areas prior to flipping. For those devices we track the areas that
require flushing prior to the next flip. For devices that do not
support flipping, but require flushing, we'll simply flush after
updating the front buffer.
This also adds a small optimization that skips these steps entirely for
a screen that doesn't have any updates that need to be rendered.
We use a switch-case statements to ensure we try to find the best
suitable driver for a specific graphics card. In case we don't find
such, we use the default statement to initialize the graphics card as a
generic VGA adapter, if the adapter is VGA compatible.
If we couldn't initialize the driver, we don't touch this adapter
anymore.
Also, GraphicsDevice should not be tied to a PCI::Address member, as it
can be theortically be used with other buses (e.g. ISA cards).
We regularily need to flush many rectangles, so instead of making many
expensive ioctl() calls to the framebuffer driver, collect the
rectangles and only make one call. And if we have too many rectangles
then it may be cheaper to just update the entire region, in which case
we simply convert them all into a union and just flush that one
rectangle instead.
This creates /dev/fbX devices for each physical output, owned by the
parent VirtIOGPU instance. This allows mapping and setting resolutions
independently for each output.