-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
driver MMIO virtual address space mapping #26107
Comments
Looks like there isn't a general solution for this. I looked at the NS16550 driver. What it has is two possible locations for the device configuration, plus a
I'd like a general solution to:
I'm wondering if there's some kind of macro magic possible like |
I'm expecting the actual To establish the mapping in the init function, we will need to know the base address and size of the MMIO region. For most drivers we get this out of DT. Per @dcpleung both the base address and size might be a value we only know at runtime via PCI. I expect we will only need the size value in the init function and will not need to store it, but we'll need to be able to query the PCI subsystem for this data inside the driver init function. What would be really cool would be a macro like:
This will let the IO mapping be a nice one-liner in the init function. But I don't know if it's feasible to get the data in, for example, DT_INST(0, ns16550) from the associated device struct for that 16550 instance 🤔 |
I think I have a solution for this. There will be three variants of DEVICE_MMIO macros:
For each variant, we will have APIs:
Attempts at merging VM mapping with PCIe probing/mbar querying ran into too many corner cases, we won't have oneliners for these cases but I think that's OK for now, DEVICE_MMIO_GET() works the same you will just need a few more lines in the init function to control the PCIe stuff. Patches for this pretty soon. |
Is your enhancement proposal related to a problem? Please describe.
All drivers currently assume a physical memory map, and directly read/write MMIO addresses provided by devicetree.
With the introduction of a virtual address space, it's not generally feasible to identity-map MMIO ranges in the page tables. The kernel needs to set up a virtual mapping for driver MMIO ranges, and drivers need to use the virtual address mapping instead of the physical address.
Initial implementations of virtual address spaces will map driver memory at runtime. It may be possible later to establish some driver mappings at build time.
Describe the solution you'd like
This is not a completely fleshed-out spec and I'm hoping to get some feedback from people more experienced with Zephyr drivers and devicetree than I.
What I think I need for runtime mapping is something akin to Linux's
ioremap
:Ours might be something like:
Internally this may call an
arch_mem_map()
function to handle programming the MMU.Drivers at initialization time will need to invoke this mapping function to map the MMIO range provided by DT into a virtual address and store the returned virtual address somewhere. Any MMIO access will need to use the virtual address instead of the physical address provided by DT.
There must be no footprint or performance overhead for devices that do not use virtual memory. It might be useful to define
device_io_map()
on such systems as a constant expression returningphys_addr
simply cast tovoid *
, but no extra memory must be used to store such mapping.Using this mechanism should look clean. There shouldn't be a bunch of #ifdefs to add runtime mapping to a driver. Ideally this support should touch individual drivers as little as possible, I'm hoping just a couple lines of code each.
This might require some thought; a lot of drivers store the base address for a particular driver instance in the read-only config struct, but in this case we would need to store the base virtual address obtained at runtime in the driver_data instead (which lives in RAM and not ROM).
This relates to drivers that enumerate at runtime via PCI, since their MMIO ranges are only known at runtime as well and we need to store their base addresses in RAM and not ROM. I'm not sure if we found a general solution for that.
For the work I'm doing for #26088 I'm just hacking this into the few drivers I need to get up and running in QEMU, but need a better solution than that.
The text was updated successfully, but these errors were encountered: