|
From: Sottek, M. J <mat...@in...> - 2001-11-20 19:48:49
|
>You don't intent to run X ontop of your fbdev, do you ?
>X uses the mmio & memory pointer to do its stuff, the same happens
>for other apps (all of them) that use the fbdev. Even the DRI/DRM
>stuff is mostly userspace, and the OpenGL access the board
>memory/mmio, trough the dma engine though.
Yes I am aware of how the X server works. You have misunderstood
the issues I want to resolve. see below...
BTW: The X server gets mmio access because it runs as root. The
DRM interfaces do not allow the userspace drivers to access anything
that is insecure, most mmio regions fall into the insecure category.
Also, the DRM does not have any driver private information visible
in public data structures. Only device independent information is
in public structures the rest are in structures that are privately
defined in both the kernel portion and the X server portion of the
driver.
>And getting all image stuff into the driver is nto the _right way_,
>at least that is what linus decreted as he boycotted every attemps
>to do so, and most people would agree with him, doing the minimal
>thing in the driver/kernel space and the rest in userpsace.
It isn't a user vs. kernel space issue. It is a public vs. private
data structure issue. Drivers have intimate knowledge of the hardware
regardless of if they reside in userspace or are part of the kernel.
Currently mmio and fb pointers are in a PUBLIC data structure, a data
structure that is defined for everyone using the fb interfaces, both
kernel side and user side. This is the wrong thing to do. The current
fb interfaces have traded away code separation in order to achieve
code reuse. This could have been done better without losing any
of the easy-to-implement code reuse features.
Let me offer some other ways:
#1 Nobody without intimate hardware knowledge should have access to
the mmio region. If they don't know how to use it, they have no reason
to touch it, right? So why put it in a user visible, public data
structure? It should be up to the kernel driver and the userspace
driver to work out a way of passing this information. A device private
ioctl is a way to go. Even a well defined get_driver_private() ioctl
is fine.
#2 What about frambuffer size/location pointers? This is the same issue,
but with far greater consequences. A user driver can obtain the physical
pointers through a driver private structure, but the var structure
currently has a kernel virtual address to the framebuffer! This allows
parts of the kernel outside the driver to write to the framebuffer!
(The logo code is an example) This is a real problem if for instance,
like the i810, you can make use of banked memory modes. In those modes
(The only ones available without programming the gart) there IS NO
framebuffer pointer/size combination that will work. You cannot write
to the framebuffer without intimate knowledge of the hardware.
If you give people easy access to pointers they WILL use them.
#3 Keep your code reuse. The fb drivers have three layers (at least)
the fb infrastructure, the hardware driver, and various subdrivers.
The struct display_switch is one set of subdrivers that are reused
for most drivers (and rightly so). However they obtain their driver
layer pointers from the fb infrastructure layer, skipping a layer of
separation. The logo code accesses pointers (that belong to the driver)
to go straight to hardware, again skipping a layer. Something like
this fixes up this problem.
struct display_switch {
(some function pointer *)setup;
(some function pointer *)putc;
...
void *priv;
}
struct generic_ds_priv {
u32 fb_base;
u32 fb_size;
u32 fb_pitch;
u32 *pseudo_palette;
...
}
Driver calls something like this:
my_fb_info.display_sw = create_generic_ds(base,size,pitch,depth);
The generic code keeps the "secret" pointers in a private data
structure. These pointers are provided directly from the driver layer.
Each display_switch function is passed the "void *priv" as an argument
which is then cast to the generic_sw_priv type. Drivers that don't use
the generic display_switch subdirver can create their own private
strictures to pass to the subdriver, or they can pass their whole
driver private structure.
Let me sum up the problem discussed here as I see it. The #1 rule
of driver writing is that only a driver should touch the hardware.
Anything that is device independent should go through a driver
interface to access the hardware. This interface could be in
userspace (i.e. OpenGL which then has a userspace hardware driver
that is allowed to access secure features of the hardware from
userspace) or in the kernel.
-Matt
|