libpciaccess on GNU/Hurd

Adam Jackson ajax at nwnk.net
Wed Nov 7 20:09:58 UTC 2018


On Wed, 2018-11-07 at 18:27 +0100, Samuel Thibault wrote:
> Adam Jackson, le mer. 07 nov. 2018 12:04:52 -0500, a ecrit:
> > On Mon, 2018-11-05 at 22:56 +1100, Damien Zammit wrote:
> > 
> > > I wish to propose an additional api call to libpciaccess.
> > > Before I submit a patch, I wish to get some feedback from the devs.
> > > 
> > > In GNU/Hurd currently, applications use the x86 backend from
> > > libpciaccess. This poses concurrency issues when multiple applications
> > > run at the same time accessing pci.
> > > Thus we want to make libpciaccess do operations through an arbiter.
> > > The pci arbiter would use libpciaccess to access the x86 methods, but
> > > then we wish to make applications use the hurd method on top of that.
> > 
> > What I'd do instead is make a kernel service for this and have the Hurd
> > backend call that,
> 
> Why would it _need_ to be a kernel service?

Because the kernel is the one thing in a position to enforce access
exclusion. If you try to implement this with a userspace arbiter then
all you need to do to break it is run an old version of libpciaccess.

> > The 'x86' backend is fundamentally broken (as you've noticed)
> 
> How do you see it broken? (considering that the concurrent access issue
> is solved by moving it to a central place)

1) PCI configuration space access isn't atomic. You write to 0xCF8,
then read/write 0xCFC. Process A writes CF8, process B writes CF8,
process A reads/writes to the device process B was trying to access.
Note that either of these processes can be device drivers, so a not-
even-malicious userspace process can confuse unrelated drivers. We hit
this kind of thing in Linux long ago, to the extent that starting X
would reprogram your IDE controller and halt further disk access, which
is why it moved config space access to sysfs so the kernel could
enforce mutual exclusion.

I'll assume that the design you're contemplating has a pci arbiter
server handling the actual port I/O, and that for normal processes
inl/outl would trap and relay the command to the arbiter. If that was
all you did that would still not be safe, because the x86 backend still
encodes config space access as two port operations, translated into two
calls to the server. You would need to make the arbiter cache the last
value written (by every client) to CF8 and re-emit it before any access
to CFC.

2) No support for multiple PCI domains, because the CF8/CFC access
method doesn't have any way to encode a domain.

3) No support for things that aren't x86. Not a concern for Hurd,
perhaps, but if that's a thing you ever want maybe solve it portably up
front.

- ajax



More information about the xorg-devel mailing list