The AHCI code doesn't rely on x86 IO at all as it only uses memory
mapped IO so we can simply remove the header.
We also simply don't use x86 IO in the Intel graphics driver, so we can
simply remove the include of the x86 IO header there too.
Everything else was a bunch of stale includes to the x86 IO header and
are actually not necessary, so let's remove them to make it easier to
compile non-x86 Kernel builds.
It seems more correct to let each platform to define its own sequence of
initialization of the PCI bus, so let's remove the #if flags and just
put the entire Initializer.cpp file in the appropriate code directory.
The simple PCI::HostBridge class implements access to the PCI
configuration space by using x86 IO instructions. Therefore, it should
be put in the Arch/x86/PCI directory so it can be easily omitted for
non-x86 builds.
Many code patterns and hardware procedures rely on reliable delay in the
microseconds granularity, and since they are using such delays which are
valid cases, but should not rely on x86 specific code, we allow to
determine in compile time the proper platform-specific code to use to
invoke such delays.
Using the IO address space is only relevant for x86 machines, so let's
not compile instructions to access the PCI configuration space when we
don't target x86 platforms.
This reworks the way the UHCI schedule is set up to handle interrupt
transfers, creating 11 queue heads each assigned a different
period/latency, so that interrupt transfers can be linked into the
schedule with their specified period more easily.
Modifies the way the UHCI schedule is set up & modified to allow for
multiple transfers of the same type, from one or more devices, to be
queued up and handled simultaneously.
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.
Instead of having two separate implementations of AK::RefCounted, one
for userspace and one for kernelspace, there is now RefCounted and
AtomicRefCounted.
All users which relied on the default constructor use a None lock rank
for now. This will make it easier to in the future remove LockRank and
actually annotate the ranks by searching for None.
Currently the SysFS node for USB devices is only initialized for USB
hubs, which means it will cause a kernel crash upon being dereferenced
in a non-hub device. This fixes the problem by making initialization
happen for all USB devices.
Right now the TD and QH descriptor pools look to be susceptible
to a race condition in the event they are accessed simultaneously
by separate threads making USB transfers. This fix does not seem to
add any noticeable overhead.
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).
No functional changes.
Currently when allocating buffers for USB transfers, it is done
once for every transfer rather than once upon creation of the
USB device. This commit changes that by moving allocation of buffers
to the USB Pipe class where they can be reused.
This change unifies the naming convention for kernel tasks.
The goal of this change is to:
- Make the task names more descriptive, so users can more
easily understand their purpose in System Monitor.
- Unify the naming convention so they are consistent.
This name was misleading, as it wasn't really "getting" anything. It has
hence been renamed to `enumerate_interfaces` to reflect what it's
actually doing.
This creates all interfaces when the device is enumerated, with a link
to the configuration that it is a part of. As such, a new class,
`USBInterface` has been introduced to express this state.
Some other parts of the USB stack may require us to perform a control
transfer. Instead of abusing `friend` to expose the default pipe, let's
just expose it via a function.
This also introduces a new class, `USBConfiguration` that stores a
configuration. The device, when instructed, sets this configuration and
holds a pointer to it so we have a record of what configuration is
currently active.
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.
This is mainly useful when adding an HostController but due to OOM
condition, we abort temporary Vector insertion of a DeviceIdentifier
and then exit the iteration loop to report back the error if occured.
Instead, hold the lock while we copy the contents to a stack-based
Vector then iterate on it without any locking.
Because we rely on heap allocations, we need to propagate errors back
in case of OOM condition, therefore, both PCI::enumerate API function
and PCI::Access::add_host_controller_and_enumerate_attached_devices use
now a ErrorOr<void> return value to propagate errors. OOM Error can only
occur when enumerating the m_device_identifiers vector under a spinlock
and trying to expand the temporary Vector which will be used locklessly
to actually iterate over the PCI::DeviceIdentifiers objects.
Reading from /proc/pci assumes we have PCI enabled and also enumerated.
However, if PCI is disabled for some reason, we can't allow the user to
read from it as there's no valuable data we can supply.
To declare that we don't have a PCI bus in the system we do two things:
1. Probe IO ports before enabling access -
In case we are using the QEMU ISA-PC machine type, IO probing results in
floating bus condition (returning 0xFF values), thus, we know we don't
have PCI bus on the system.
2. Allow the user to specify to not use the PCI bus at all in the kernel
commandline.
This change allow the user to request the kernel to not use any PCI
resources/devices at all.
Also, don't try to initialize devices that rely on PCI if disabled.
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.
There can only be a limited number of functions (only 8).
Also, consider the start bus of the PCI domain when trying to enumerate
other host bridges on bus 0, device 0, functions 1-7 (function 0 is the
main host bridge).
This mostly just moved the problem, as a lot of the callers are not
capable of propagating the errors themselves, but it's a step in the
right direction.
Two classes are added - HostBridge and MemoryBackedHostBridge, which
both derive from HostController class. This allows the kernel to map
different busses from different PCI domains in the same time. Each
HostController implementation doesn't take the Address object to address
PCI devices but instead we take distinct numbers of the PCI bus, device
and function as it allows us to specify arbitrary PCI domains in the
Address structure and still to get the correct PCI devices. This also
matches the hardware behavior of PCI domains - the host bridge merely
takes memory operations or IO operations and translates them to
addressing of three components - PCI bus, device and function.
These changes also greatly simplify how enumeration of Host Bridges work
now - scanning of the hardware depends on what the Host bridges can do
for us, so in case we have multiple host bridges that expose a memory
mapped region or IO ports to access PCI configuration space, we simply
let the code of the host bridge to figure out how to fetch data for us.
Another semantical change is that a PCI domain structure is no longer
attached to a PhysicalAddress, so even in the case that the machine
doesn't implement PCI domains, we still treat that machine to contain 1
PCI domain to treat that one host bridge in the same way, like with a
machine with one or more PCI domains.
The function `KString::must_create()` can only be enforced
during early boot (that is, when `g_in_early_boot` is true), hence
the use of this function during runtime causes a `VERIFY` to assert,
leading to a Kernel Panic.
We should instead use `TRY()` along with `try_create()` to prevent
this from crashing whenever a USB device is inserted into the system,
and we don't have enough memory to allocate the device's KString.
Add a basic NVMe driver support to serenity
based on NVMe spec 1.4.
The driver can support multiple NVMe drives (subsystems).
But in a NVMe drive, the driver can support one controller
with multiple namespaces.
Each core will get a separate NVMe Queue.
As the system lacks MSI support, PIN based interrupts are
used for IO.
Tested the NVMe support by replacing IDE driver
with the NVMe driver :^)
This was a premature optimization from the early days of SerenityOS.
The eternal heap was a simple bump pointer allocator over a static
byte array. My original idea was to avoid heap fragmentation and improve
data locality, but both ideas were rooted in cargo culting, not data.
We would reserve 4 MiB at boot and only ended up using ~256 KiB, wasting
the rest.
This patch replaces all kmalloc_eternal() usage by regular kmalloc().
Instead, allocate before constructing the object and pass NonnullOwnPtr
of KString to the object if needed. Some classes can determine their
names as they have a known attribute to look for or have a static name.
There is no use to create a temporary String of a char const* to just
cast it to a StringView on SysFSComponent construction again.
Also this could have lead to a UAF bug.
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.
This isn't a complete conversion to ErrorOr<void>, but a good chunk.
The end goal here is to propagate buffer allocation failures to the
caller, and allow the use of TRY() with formatting functions.
We now use AK::Error and AK::ErrorOr<T> in both kernel and userspace!
This was a slightly tedious refactoring that took a long time, so it's
not unlikely that some bugs crept in.
Nevertheless, it does pass basic functionality testing, and it's just
real nice to finally see the same pattern in all contexts. :^)
Instead, just ensure we pick the m_access_lock and then m_scan_lock when
doing a scan/re-scan of the PCI configuration space so we know nobody
can actually access the PCI configuration space during the scan.
The m_scan_lock is now a Spinlock, to ensure we cannot yield to other
process while we do the PCI configuration space scanning.
The platform independent Processor.h file includes the shared processor
code and includes the specific platform header file.
All references to the Arch/x86/Processor.h file have been replaced with
a reference to Arch/Processor.h.
Previously there was a mix of returning plain strings and returning
explicit string views using `operator ""sv`. This change switches them
all to standardized on `operator ""sv` as it avoids a call to strlen.
Previously there was a mix of returning plain strings and returning
explicit string views using `operator ""sv`. This change switches them
all to standardized on `operator ""sv` as it avoids a call to strlen.
This allows us to remove the PCI::get_interrupt_line API function. As a
result, this removes a bunch of not so great patterns that we used to
cache PCI interrupt line in many IRQHandler derived classes instead of
just using interrupt_number method of IRQHandler class.
This ensures we dont try to hold the PCI Access mutex under IRQ when
printing VirtIO debug logs (which is not allowed and results in an
assertion). This is also relatively free, as it requires no allocations
(we're just storing a pointer to the rodata section).
This fixes a Kernel Panic where the lazy allocation triggers inside an
ISR and grabs a mutex, which isn't allowed when interrupts are
disabled. This also fixes a bug where the mapping for VirtIO device
BARs is never allocated. #9876
This will somwhat help unify them also under the same SysFS directory in
the commit.
Also, it feels much more like this change reflects the reality that both
ACPI and the BIOS are part of the firmware on x86 computers.
This is a fix so the VirtIO code doesn't lead to assertion because we
try to determine the name based on the PCI values of the VirtIO device,
because trying to read from the PCI configuration space requires to
acquire a Mutex, which fails in an IRQ context.
To ensure we never encounter a situation when we call a pure virtual
function in an IRQ context, let's make class_name() method to be a
non-pure virtual function, so it can be still called at anytime.
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.
These methods are no longer needed because SystemServer is able to
populate the DevFS on its own.
Device absolute_path no longer assume a path to the /dev location,
because it really should not assume any path to a Device node.
Because StorageManagement still needs to know the storage name, we
declare a virtual method only for StorageDevices to override, but this
technique should really be removed later on.
This patch adds KBufferBuilder::try_create() and treats it like anything
else that can fail. And so, failure to allocate the initial internal
buffer of the builder will now propagate an ENOMEM to the caller. :^)
A couple of things were changed:
1. Semantic changes - PCI segments are now called PCI domains, to better
match what they are really. It's also the name that Linux gave, and it
seems that Wikipedia also uses this name.
We also remove PCI::ChangeableAddress, because it was used in the past
but now it's no longer being used.
2. There are no WindowedMMIOAccess or MMIOAccess classes anymore, as
they made a bunch of unnecessary complexity. Instead, Windowed access is
removed entirely (this was tested, but never was benchmarked), so we are
left with IO access and memory access options. The memory access option
is essentially mapping the PCI bus (from the chosen PCI domain), to
virtual memory as-is. This means that unless needed, at any time, there
is only one PCI bus being mapped, and this is changed if access to
another PCI bus in the same PCI domain is needed. For now, we don't
support mapping of different PCI buses from different PCI domains at the
same time, because basically it's still a non-issue for most machines
out there.
2. OOM-safety is increased, especially when constructing the Access
object. It means that we pre-allocating any needed resources, and we try
to find PCI domains (if requested to initialize memory access) after we
attempt to construct the Access object, so it's possible to fail at this
point "gracefully".
3. All PCI API functions are now separated into a different header file,
which means only "clients" of the PCI subsystem API will need to include
that header file.
4. Functional changes - we only allow now to enumerate the bus after
a hardware scan. This means that the old method "enumerate_hardware"
is removed, so, when initializing an Access object, the initializing
function must call rescan on it to force it to find devices. This makes
it possible to fail rescan, and also to defer it after construction from
both OOM-safety terms and hotplug capabilities.
This expands the reach of error propagation greatly throughout the
kernel. Sadly, it also exposes the fact that we're allocating (and
doing other fallible things) in constructors all over the place.
This patch doesn't attempt to address that of course. That's work for
our future selves.
The default template argument is only used in one place, and it
looks like it was probably just an oversight. The rest of the Kernel
code all uses u8 as the type. So lets make that the default and remove
the unused template argument, as there doesn't seem to be a reason to
allow the size to be customizable.
This commit moves the KResult and KResultOr objects to Kernel/API to
signify that they may now be freely used by userspace code at points
where a syscall-related error result is to be expected. It also exposes
KResult and KResultOr to the global namespace to make it nicer to use
for userspace code.
According to the VirtIO 1.0 specification:
"Non-transitional devices SHOULD have a PCI Device ID in the range
0x1040 to 0x107f. Non-transitional devices SHOULD have a PCI Revision ID
of 1 or higher. Non-transitional devices SHOULD have a PCI Subsystem
Device ID of 0x40 or higher."
It also says that:
"Transitional devices MUST have a PCI Revision ID of 0. Transitional
devices MUST have the PCI Subsystem Device ID matching the Virtio
Device ID, as indicated in section 5. Transitional devices MUST have the
Transitional PCI Device ID in the range 0x1000 to 0x103f."
So, for legacy devices, we know that revision ID in the PCI header won't
be 1, so we probe for PCI_SUBSYSTEM_ID value.
Instead of using the subsystem device ID, we can probe the DEVICE_ID
value directly in case it's not a legacy device.
This should cover all possibilities for identifying VirtIO devices, both
per the specification of 0.9.5, and future revisions from 1.0 onwards.
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.
Like with the ProcFS, description data can change at anytime, so it's
wise to ensure that when the userland reads from an Inode, data is
consistent unless the userland indicated it wants to refresh the data
(by seeking to offset 0, or re-attaching the Inode).
Otherwise, if the data changes in the middle of the reading, it can
cause silent corruption in output which can lead to random crashes.