Remix.run Logo
cakehonolulu 3 hours ago

Indeed, the project has gone through a few iterations already (It was first a monolithic kernel module that required a secondary module to call into the API and whatnot). I've went towards a more userspace-friendly usage mainly so that you can iterate your changes much, much faster. Creating the synthetic PCI device is as easy as opening the userspace shim you program, it'll then appear on your bus. When you want to test new changes, you close the shim normally (Effectively removing it from the bus) and you can do this process as many times as needed.

LarsKrimi 3 hours ago | parent [-]

Latching on to this thread, but can you make as simple as possible of an example?

Something like just a single BAR with a register that printfs whatever is written

cakehonolulu 3 hours ago | parent [-]

Hi! I do have some rudimentary docs on which I made a simple device for example pruposes: https://cakehonolulu.github.io/docs/pciem/simple_device_walk...

Hopefully this is what you're searching for!

LarsKrimi 2 hours ago | parent [-]

Hi, thanks. That's almost it. The remaining problem is just how to tie it together (where do I put the handle_mmio_read pointer or which event should it be handled in?)

PCIEM_EVENT_MMIO_READ is defined but not used anywhere in the codebase

cakehonolulu an hour ago | parent [-]

Hi! Sorry, this is an issue on my side; I forgot to update the documentation's example with the latest changes.

You basically have the kernel eventfd notify you about any access triggered (Based on your configuration), so from userspace, you have the eventfd and then you mmap the shared lock-less ring buffer that actually contains the events PCIem notifies (So you don't end up busy polling).

You basically mmap a struct pciem_shared_ring where you'll have your usual head/tail pointers.

From then on, on your main, you'd have a select() or a poll() for the eventfd; when PCIem notifies the userspace you'd check head != tail (Which means there are events to process) and you can basically do:

struct pciem_event *event = &event_ring->events[head]; atomic_thread_fence(memory_order_acquire); if (event->type == PCIEM_EVENT_MMIO_WRITE) handle_mmio_read(...);

And that's it, don't forget to update the head pointer!

I'll go and update the docs now. Hopefully this clears stuff up!