1 Preamble
<to be filled in>

2 Introduction

2.1 AGP Support

	Currently the standard Linux kernel does not provide support for AGP.
This includes both initializing the AGP point-to-point connection, and
providing a mechanism for allocating AGP memory.  There is however a simple
module that was written for the MGA-GLX project which provide a base level
of functionality to a user process.  This module has some severe limitations
for use in an environment where there are multiple direct clients.  The goal
of this project is to produce a module which provides a framework which
works well for multiple direct clients and approaches the security issue.

2.2 Limitations of the Current AGP module

	The current agp module was designed with a single client in mind
(the Xserver.)  It has been extended since its original inception to allow
for multiple user space programs to open its device file.  It does not
however address the requirements of security (every program must run with
the privileges of the /dev/gart file.)  This is typically the root user.  The
first program to open the /dev/gart device becomes the owner and  each
subsequent open is only allowed to mmap and query the device information.
This implementation is too simple for secure use of the agp module inside
the dri infrastructure.
	The current agp module also has a very simplistic view of agp
memory.  The current module views all memory allocations on the page
granular level.  While one can allocate multiple pages at once, they are not
grouped into any manageable unit.  This makes the memory management code for
the GART much more complex, and has problems with flexibility.  The current
module also must do a complete cache flush whenever a group of entries are
written to the table.  While some degree of cache flushing is necessary,
there are distinct ways in which this can be optimized.  Cache flushing on
SMP systems is particularly expensive, requiring approax 35 milliseconds.
For performance reasons it needs to be optimized as much as possible.
	The current agp module also provides no way for the kernel module to
limit the amount of agp memory allocated by the user process.  This is a
very big issue when a client is misbehaved.  A misbehaving client could
possibly create conditions where the system is unusable.  There must be some
way to limit the amount of system memory committed to agp memory in a
production agp driver.  Otherwise the agp module becomes a security concern.
	The current agp module has a simplistic framework for providing
driver support for devices that are not similar to the 440LX chipset.  To
provide support for the i810 device there was alot of work that was required
to 'hack' in support.  The hooks for device specific code are not general
enough to support such devices.  This framework needs to be extended and
generalized in a production driver.  Otherwise maintaining these drivers
might become difficult.
	The current agp module has no kernel level interface.  Since the drm
is controlling the resources allocated for each client, it is important that
a production level driver have the ability to be accessed from kernel space.
	There are some very important cases that the current agp module does
not manage in an intelligent way.  For a production level agp module these
must be addressed.

2.3 Requirements for a production level agp module

	For Precision Insight to provide a production level agp driver each
of the above items must be addressed.  These archetechtural limitations
would make using agp memory in the dri framework difficult.  Here is a list
of these limitations in order of importance.

2.3.1 Allow intelligent use of the agp module by multiple clients

2.3.2 Improve the security of the module as a whole
	a. Provide pid based authentication of each client.  The kernel has
an ioctl which informs it of which pid's are allowed to use the agp module.
This requires that there is some sort of controlling process.  To do this
another ioctl is provided which allows a program which is either uid or
setuid root to become the controlling process.
	b. Allow the kernel to be the controlling process.
	
2.3.3 Limit the amount of memory allowed for allocation
	This is provided by interpolating known 'good' limits of allowable
agp memory.  The amount of pages locked down by the kernel is not allowed to
be larger then this calculated value.  The value (-ENOMEM) is returned by
the module in this condition.

2.3.4 Provide a kernel level interface
	Each of the backend functions of the ioctl interface are planned to
be exported so a kernel based driver like the drm can utilize the agp
module.  Since all of the authentication occurs within the fops of the agp
module, this allows the drm to impose its own security model on the use of
agp.

2.3.5 Improve driver interface
	Provide an easy to extend archetechture for writing drivers.  Create
hooks for areas which the Athlon and i810 require.  Also provide a device
private area.

2.3.6 Improve the way a client would view agp memory
	a. Each client should be able to be limited in the amount of agp
memory it actually sees.  The dri client should be allowed to map only
portions of agp memory.  This allows the each client to have separate
sections of agp memory, and not have to worry about it being 'used' by other
clients.
	b. The controlling process should be able to allocate agp memory in
'hunks' which can be viewed as a unit.  This simplifies the code for managing
the memory in user space, while adding some complexity to the kernel code.
It also allows for optimizations to be made on cache flushing.
	c. Eventually the agp driver should provide a mechanism for allowing
agp memory to be swapped out through the vm subsystem of the kernel.  This
will allow clients to actually use more texture space then is actually
available.  While this is not an absolute requirement for the first release,
it would be a nice addition.  This optimization is there to address the
problem of clients having to keep vm copies of their textures in user space.

3.1 DRI support for the new kernel implementation

	Once a driver meeting the above specifications is written, the
mechanism of the above driver needs to be wrapped by the DRI.  There are two
approaches to this problem.  One is to provide a wrapper in the Xserver, and
the other is to wrap the driver in the drm kernel module.

3.1.1 Wrapping the agp driver in the Xserver

	There are some limitations to this model of usage of the agp module.
The largest problem is that each dri client would be required to have adhere
to another security policy.  The modules design is such that the controlling
process (Xserver in this case), must know the pid of the process.  To learn
this in a secure way, the Xserver must check the permissions of the pipe
between it and the client.  While most modern Unix implementations have the
ability to do this, there is no standardized interface across them to
accomplish this task.  This would require OS dependent code for each port of
the dri.  This was a security model that was investigated for the dri, and
it was discarded.  If this is the route that the implementation takes, we do
lose some portability.
	There is also the issue that once advanced texture management is
implementated that the drm will be the only entity in the system that knows
when textures are resident.  Wrapping the agp module in the Xserver would
require that the Xserver do all the management of the textures in agp space.
This would require an extension to the signaling system used by the drm.
While using a signal is an option, there is the the problem of the
performance of such a method.

3.1.2 Wrapping the agp ioctl's inside the drm
	This is the preferred implementation of adding support to the DRI for
agp.  Such an interface allows the drm to implement its own security
mechanism for agp functionality.  However there are some open issues.
	a. Since the agp module fails to load if a supported agp device is
not found, there will probably have to be two builds of the drm.  One which
hooks out the agp ioctl's to the approiate kernel functions.  The other
which loads wrapper functions which return error conditions when these
ioctl's are used.  It might be possible to require that the device specific
module be loaded first, and have a callback to setup the dri for agp
support.  This issue needs to be discussed.
	b. Since it is possible that the agp module might not load, drivers
need to act reasonably well when agp support is not available.  Depending on
the device, this might become something that can not just be wrapped away by
the drm.  There might need to be information in a device specific area of the
of the shared memory segment to deal with agp.  Or possibly an ioctl to
query the state of agp.  Moving from agp to a mmio fifo might require quite
a different interface to be exported by the drm.  This needs to be discussed.

4. Ioctl interfaces
	Here is a low level description of the two ioctl interfaces.
	
4.1 Ioctl interface exported by the new agp module

	Here is a rough cut of what the agp drivers ioctl interface looks
like.  The formating needs some cleanup here.

#define AGPIOC_BASE         'A'

#define AGPIOC_INFO         _IOR (AGPIOC_BASE, 0,  agp_info *)
	This ioctl returns some information about the agp module.  It
returns the version of the agp module, the chipset type, agp mode currently
enabled, the bus address of the start of the aperture, and the size of the
aperture.

#define AGPIOC_ACQUIRE      _IO  (AGPIOC_BASE, 1)
	This ioctl makes the current process the controlling process.  It
sets up initial internal lists of clients, and a memory pool.  If the
current controller was previously a controller, it just uses the previously
allocated structures.  It would be nice to keep a per client list of mapped
ranges and map/remap them on acquire/release.  This however is not targeted
for the first production driver. 

#define AGPIOC_RELEASE      _IO  (AGPIOC_BASE, 2)
	This removes the current process from being the controlling process.
It does not free its lists and allocated agp memory, this is only done when
the device is closed by that controller.

#define AGPIOC_RESERVE      _IOW (AGPIOC_BASE, 3,  agp_reserve *)
	This ioctl sets up the restrictions on what can be mapped on a pid
basis.  It allows parceling of the agp space into smaller chunks then just
the whole aperture.

#define AGPIOC_ALLOCATE     _IORW(AGPIOC_BASE, 4,  agp_allocate *)
	Creates a block of agp memory of pg_count size.  It writes back a
key to user space to be used to manage this block.

#define AGPIOC_DEALLOCATE   _IOW (AGPIOC_BASE, 5,  agp_key_t)
	Frees a block of agp memory referenced by key.  If the block is
bound into the aperture, it is unbound.

#define AGPIOC_BIND         _IOW (AGPIOC_BASE, 6,  agp_bind *)
	Takes a block of agp memory and binds it to the agp aperture
starting at pg_start.  If any of these pages are already occupied in the
aperture, then (-EBUZY) is returned.

#define AGPIOC_UNBIND       _IOW (AGPIOC_BASE, 7,  agp_key_t)
	Removes a bound block of agp memory from the aperture.

#define AGPIOC_ALLOWSWAP    _IOW (AGPIOC_BASE, 8,  agp_key_t)
	For the first implementation, this will probably be a feature that
will not be implemented.  But it takes an unbound piece of memory and allows
to to again be managed by the vm subsystem.

#define AGPIOC_ADDCLIENT    _IOW (AGPIOC_BASE, 9,  pid_t)
	Adds the pid of client to an authorized list.  Clients can only use
the agp info ioctl, and the mmap file operation.

#define AGPIOC_REMOVECLIENT _IOW (AGPIOC_BASE. 10, pid_t)
	Removes a client from an authorized list.  After this ioctl has been
processed then the agp module disallows any activity from that client.  It
does not however remove the clients structures, or the current mmaps done by
the client.

4.2 Ioctl interface of exported by the drm
	(To be described)

5. Conclusions
