On Sun, Jun 13, 2004 at 08:47:37PM +0100, Matt Sealey wrote: > > Having a capable accelerated 2D and 3D architecture, something > like DirectFB but at more of a "core" and "commercial" level > would benefit everyone. Building a single DDX driver to > interface with this would simplify support for X - no drivers > in the X tree but one! "Console Framebuffers" could be built > on top of the same low-level graphics API. In the end losing > the 4-driver system for each card would both simplify and > optimise the Linux graphics experience. [..]
> We need a low-level "kernel" graphics API (much like Windows > has, although Windows favours microkernels with high-level > kernel functionality, rather than monolithic kernels with > user-level functionality.. the two philosophies are at odds) > which can perform and accelerate the expected functionality of > everything from router to PDA, past desktop to display of > remote-served apps. Careful. I think it is wise to consider the difference between what needs to be in the kernel, versus what is convenient to have an API for. For instance, it is possible to have a mode setting API without it being in the kernel -- just have a library that talks to a trusted userspace arbiter. Same for a 3D locking and command serialization. The only real difference between implementing such an API over a trusted userspace process or over kernel ioctls is that the userspace process might crash (and leave the system running, unlike a kernel crash) or be killed by the kernel; so you would need to plan for such a scenario and be able to recover from it. I don't particularly like the 1 driver to rule them all approach, especially if it's going in the kernel. I like the idea of nailing down exactly what resources the multiple drivers would be in competition for, and providing methods for permitted entities to cooperatively share those resources and to recover from failure. Putting everything in the kernel would enforce a lot of policy and doesn't guarantee it will all work right anyway. otoh, doing everything by disparate userland processes which each assume the hardware is their own doesn't work too well either, because graphics hardware has too much state. It seems like the sanest thing to do is to provide a userland server which maps the hardware and which graphical programs can talk to via a socket or library to get things done. That way all the policy ends up in userland, and all the server does regarding the kernel is to lock the hardware so i.e. two servers can't accidentally run at the same time. The problem with this approach is not only that the process could be killed, but what about scheduling? If I dispatch a command to it, what guarantees me that it gets done reasonably soon? Because of that it would probably have to run at realtime priority like jack does for audio processes. This still doesn't save you the overhead of a context switch compared to a uniform userspace driver, unfortunately. But you can use shared memory to e.g. dispatch big DMA lists or maintain a ring buffer. Like I said, this is also a cooperative approach. This has its advantages but its drawbacks as well. For instance, I ask the arbiter what the physical address of the framebuffer for the primary display is and to lock other people out from it. Its policy is to only give me the address if nobody else has said they are going to map the framebuffer directly. If someone else has already and it returns false, there is nothing to stop me from just finding the fb address and mapping it myself, possibly scrambling someone else's display or locking up the hardware. So the users of this arbiter need to not be hostile, which means there needs to be a security policy. I think the current DRM idea of having a device node for security would suffice for that security policy. Open /dev/display/*, then talk to the arbiter. If it believes you should get the access you want, it tells that to the kernel (via its own interface), then when you ioctl(.. MMAP_FB) the kernel can just look up whether or not the arbiter has granted your process access for that or not, and if so, mmap the framebuffer (or MMIO registers, or BIOS, or whatever) and give you a pointer. This way, direct hardware access need not be done as root (meaning less opportunity to abuse the system), but the user of the kernel API only gets access depending on the arbiter's policy, not policy embedded in the kernel. The great thing is that the arbiter's policy can be based on intimate knowledge of the hardware and arbitrarily complicated. For instance, it can know the state of the 3D engine while a game is running (via Mesa/DRI), and if another process (such as a XAA driver) requests an operation that is unsafe if the 3D engine is in a particular state, it can defer that until the time is right. Or maybe it knows that there must be a delay after a particular operation, so it defers any other accesses until then. This is stuff that is trivial to do in userspace compared to the kernel. One problem compared to a kernel approach I see is locking. If some process is waiting for a lock and its thread with the arbiter is sleeping, and the resource becomes free, how do I wake it up? Send it a signal? So the idea is that the kernel has nothing at all to do with graphics besides some security related stuff if necessary. Instead of a bunch of processes competing for the hardware without having knowledge of what the others are doing or what state the hardware is in, place a trusted userspace arbiter in control of access to the hardware. Root-owned processes could circumvent the arbiter, and individual processes are not obligated to share low-level resources (like FB or MMIO registers) if they are granted access, so it is a cooperative approach. But for normal processes using abstract resources, the arbiter can enforce whatever policy it feels like for a particular piece of hardware to ensure that it cannot be caused to fail by numerous processes competing for its resources. A library would be wrapped around the arbiter to make access to it transparent as well as provide mid level APIs for various common graphics tasks. Individual applications like Mesa would still have control over e.g. the structure of DMA buffers, and then they call a arbiter library function to dispatch a buffer, competely ignoring the state of the hardware because the arbiter is taking care of serialization and locking as well as checking the validity of the buffers if desired. I just mashed this down so its probably half baked. Any thoughts? -- Ryan Underwood, <[EMAIL PROTECTED]>
signature.asc
Description: Digital signature