[Solved] PCI MMIO BAR writes won't go through (Rust, NVMe driver)
Posted: Mon Apr 21, 2025 6:32 pm
Hi all,
I am developing a kernel for x86_64 architecture in rust and had written an NVMe driver quite a while ago which proved to work fine until when I recently decided to implement a proper memory frame & page allocation system (I previously used an allocator which just incremented the frame and page indices), as well as rewriting my PCI driver.
Since then, like the title suggests, any writes to the MMIO BAR for NVMe devices fail to go through. Important to add is that the MMIO BAR is populated with values that aren't garbage. It's likely that this is also the case for other PCI devices but I currently have no other drivers for any of them.
To be very specific this happens when I try to clear the CC.EN bit in the NVMe registers (but also other values that can be modified whenever CC.EN is set, which makes me think this isn't any issue regarding the NVMe driver itself).
I have checked pretty much everything I can think of and still haven't found the cause of this issue. I have used ChatGPT to debug the relevant code, but unfortunately to no success.
Here is a list of things I have checked:
Any help is greatly appreciated.
If more context is needed by sharing certain pieces of code I will happily provide
.
I am developing a kernel for x86_64 architecture in rust and had written an NVMe driver quite a while ago which proved to work fine until when I recently decided to implement a proper memory frame & page allocation system (I previously used an allocator which just incremented the frame and page indices), as well as rewriting my PCI driver.
Since then, like the title suggests, any writes to the MMIO BAR for NVMe devices fail to go through. Important to add is that the MMIO BAR is populated with values that aren't garbage. It's likely that this is also the case for other PCI devices but I currently have no other drivers for any of them.
To be very specific this happens when I try to clear the CC.EN bit in the NVMe registers (but also other values that can be modified whenever CC.EN is set, which makes me think this isn't any issue regarding the NVMe driver itself).
I have checked pretty much everything I can think of and still haven't found the cause of this issue. I have used ChatGPT to debug the relevant code, but unfortunately to no success.
Here is a list of things I have checked:
- Memory allocation: This does not seem to be the problem, using the same implementation for non MMIO memory works as intended, I have also checked relevant page table flags and the Present, Writable, No cache are all set.
- PCI: BAR size is read and original value restored properly, IO & Memory Spaces are enabled along with Bus Master. The MMIO itself seems to have proper values when first read (version 1.4.0 & controller status 1 in NVMe registers).
- I am using volatile reads & writes everywhere regarding MMIO
- Initializing NVMe is currently the first thing done after initializing GDT, memory allocation and the kernel heap (interrupts are currently not yet implemented and are completely disabled except for exceptions), so it would seem highly unlikely anything is messing with it beforehand.
Any help is greatly appreciated.
If more context is needed by sharing certain pieces of code I will happily provide
