Remix.run Logo
Surac 6 hours ago

that is a huge win if you are developing drivers or even real hardware. it allows to iterate on protokols just with the press of a button

asimovDev 3 hours ago | parent | next [-]

Could you explain in layman terms how it would help with developing PCIE hardware / drivers? I can immediately imagine something like writing more robust unit tests and maybe developing barebones drivers before you get access to actual hardware, but that's where my imagination runs out of fuel.

cakehonolulu 3 hours ago | parent [-]

Sure! Let's say you (Or the company you work for) are trying to develop an NVME controller card, or a RAID card, or a NIC...

Usually, without actual silicon, you are pretty limited on what you can do in terms of anticipating the software that'll run.

What if you want to write a driver for it w/o having to buy auxiliary boards that act as your card? What happens if you already have a driver and want to do some security testing on it but don't have the card/don't want to use a physical one for any specific reason (Maybe some UB on the driver pokes at some register that kills the card? Just making disastrous scenarios to prove the point hah).

What if you want to add explicit failures to the card so that you can try and make the driver as tamper-proof and as fault-tolerant as possible (Think, getting the PCI card out of the bus w/o switching the computer off)?

Testing your driver functionally and/or behaviourally on CI/CD on any server (Not requiring the actual card!)?

There's quite a bunch of stuff you can do with it, thanks to being in userspace means that you can get as hacky-wacky as you want (Heck, I have a dumb-framebuffer-esque and OpenGL 1.X capable QEMU device I wanted to write a driver for fun and I used PCIem to forward the accesses to it).

cakehonolulu 3 hours ago | parent | prev [-]

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!