summaryrefslogtreecommitdiff
path: root/bsd-core
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2005-08-26 00:16:01 +0000
committerEric Anholt <anholt@freebsd.org>2005-08-26 00:16:01 +0000
commit55bea952b326b88f2fa6502321f605f96ee9be66 (patch)
tree9de73f0fa9527d8e3954808e7cb30493f166d1ac /bsd-core
parent9942cad1f6078c24bb69a126795635b2f34d65b5 (diff)
[1] Fix BSD DRM for the nonroot changes. [2] Don't attempt to acquire the
DMA lock in a non-DMA driver, as it will be uninitialized. Submitted by: [1] jkim (minor changes by me)
Diffstat (limited to 'bsd-core')
-rw-r--r--bsd-core/drmP.h8
-rw-r--r--bsd-core/drm_bufs.c58
-rw-r--r--bsd-core/drm_context.c5
-rw-r--r--bsd-core/drm_drv.c13
-rw-r--r--bsd-core/drm_fops.c7
-rw-r--r--bsd-core/drm_vm.c7
6 files changed, 81 insertions, 17 deletions
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h
index 7e16fe66..d5907355 100644
--- a/bsd-core/drmP.h
+++ b/bsd-core/drmP.h
@@ -229,7 +229,8 @@ enum {
int flags, DRM_STRUCTPROC *p, DRMFILE filp
#define PAGE_ALIGN(addr) round_page(addr)
-#define DRM_SUSER(p) suser(p)
+/* DRM_SUSER returns true if the user is superuser */
+#define DRM_SUSER(p) (suser(p) == 0)
#define DRM_AGP_FIND_DEVICE() agp_find_device()
#define DRM_MTRR_WC MDF_WRITECOMBINE
#define jiffies ticks
@@ -249,7 +250,8 @@ enum {
#define CDEV_MAJOR 34
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-#define DRM_SUSER(p) suser(p->p_ucred, &p->p_acflag)
+/* DRM_SUSER returns true if the user is superuser */
+#define DRM_SUSER(p) (suser(p->p_ucred, &p->p_acflag) == 0)
#define DRM_AGP_FIND_DEVICE() agp_find_device(0)
#define DRM_MTRR_WC MTRR_TYPE_WC
#define jiffies hardclock_ticks
@@ -524,6 +526,7 @@ typedef TAILQ_HEAD(drm_file_list, drm_file) drm_file_list_t;
struct drm_file {
TAILQ_ENTRY(drm_file) link;
int authenticated;
+ int master;
int minor;
pid_t pid;
uid_t uid;
@@ -585,6 +588,7 @@ typedef struct drm_agp_head {
typedef struct drm_sg_mem {
unsigned long handle;
+ void *virtual;
int pages;
dma_addr_t *busaddr;
drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */
diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c
index b00ecda2..5ce2d4de 100644
--- a/bsd-core/drm_bufs.c
+++ b/bsd-core/drm_bufs.c
@@ -113,11 +113,12 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
/* Check if this is just another version of a kernel-allocated map, and
* just hand that back if so.
*/
- if (type == _DRM_REGISTERS || type == _DRM_FRAME_BUFFER)
- {
+ if (type == _DRM_REGISTERS || type == _DRM_FRAME_BUFFER ||
+ type == _DRM_SHM) {
DRM_LOCK();
TAILQ_FOREACH(map, &dev->maplist, link) {
- if (map->type == type && map->offset == offset) {
+ if (map->type == type &&
+ (map->offset == offset || map->type == _DRM_SHM)) {
map->size = size;
DRM_DEBUG("Found kernel map %d\n", type);
goto done;
@@ -171,8 +172,25 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
}
break;
case _DRM_AGP:
- map->offset += dev->agp->base;
- map->mtrr = dev->agp->mtrr; /* for getmap */
+ {
+ drm_agp_mem_t *entry;
+ int valid = 0;
+
+ map->offset += dev->agp->base;
+ map->mtrr = dev->agp->mtrr; /* for getmap */
+ for (entry = dev->agp->memory; entry;
+ entry = entry->next)
+ if ((map->offset >= entry->bound) &&
+ (map->offset + map->size <=
+ entry->bound + entry->pages * PAGE_SIZE)) {
+ valid = 1;
+ break;
+ }
+ if (!valid) {
+ free(map, M_DRM);
+ return DRM_ERR(EACCES);
+ }
+ }
break;
case _DRM_SCATTER_GATHER:
if (!dev->sg) {
@@ -186,7 +204,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
0xfffffffful);
if (map->dmah == NULL) {
free(map, M_DRM);
- return ENOMEM;
+ return DRM_ERR(ENOMEM);
}
map->handle = map->dmah->vaddr;
map->offset = map->dmah->busaddr;
@@ -223,6 +241,9 @@ int drm_addmap_ioctl(DRM_IOCTL_ARGS)
DRM_COPY_FROM_USER_IOCTL(request, (drm_map_t *)data, sizeof(drm_map_t));
+ if (!DRM_SUSER(p) && request.type != _DRM_AGP)
+ return DRM_ERR(EACCES);
+
err = drm_addmap(dev, request.offset, request.size, request.type,
request.flags, &map);
if (err != 0)
@@ -342,6 +363,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
{
drm_device_dma_t *dma = dev->dma;
drm_buf_entry_t *entry;
+ drm_agp_mem_t *agp_entry;
drm_buf_t *buf;
unsigned long offset;
unsigned long agp_offset;
@@ -352,7 +374,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
int page_order;
int total;
int byte_count;
- int i;
+ int i, valid;
drm_buf_t **temp_buflist;
count = request->count;
@@ -375,6 +397,22 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
DRM_DEBUG( "page_order: %d\n", page_order );
DRM_DEBUG( "total: %d\n", total );
+ /* Make sure buffers are located in AGP memory that we own */
+ valid = 0;
+ for (agp_entry = dev->agp->memory; agp_entry;
+ agp_entry = agp_entry->next) {
+ if ((agp_offset >= agp_entry->bound) &&
+ (agp_offset + total * count <=
+ agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
+ valid = 1;
+ break;
+ }
+ }
+ if (!valid) {
+ DRM_DEBUG("zone invalid\n");
+ return DRM_ERR(EINVAL);
+ }
+
entry = &dma->bufs[order];
entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM,
@@ -742,6 +780,9 @@ int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
DRM_SPINLOCK(&dev->dma_lock);
+ if (!DRM_SUSER(DRM_CURPROC))
+ return DRM_ERR(EACCES);
+
if (request->count < 0 || request->count > 4096)
return DRM_ERR(EINVAL);
@@ -773,6 +814,9 @@ int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
DRM_SPINLOCK(&dev->dma_lock);
+ if (!DRM_SUSER(DRM_CURPROC))
+ return DRM_ERR(EACCES);
+
if (request->count < 0 || request->count > 4096)
return DRM_ERR(EINVAL);
diff --git a/bsd-core/drm_context.c b/bsd-core/drm_context.c
index 11d23c6f..8e009540 100644
--- a/bsd-core/drm_context.c
+++ b/bsd-core/drm_context.c
@@ -228,14 +228,17 @@ int drm_context_switch_complete(drm_device_t *dev, int new)
int drm_resctx(DRM_IOCTL_ARGS)
{
drm_ctx_res_t res;
+ drm_ctx_t ctx;
int i;
DRM_COPY_FROM_USER_IOCTL( res, (drm_ctx_res_t *)data, sizeof(res) );
if ( res.count >= DRM_RESERVED_CONTEXTS ) {
+ bzero(&ctx, sizeof(ctx));
for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
+ ctx.handle = i;
if ( DRM_COPY_TO_USER( &res.contexts[i],
- &i, sizeof(i) ) )
+ &ctx, sizeof(ctx) ) )
return DRM_ERR(EFAULT);
}
}
diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c
index d9784073..c4ee39cb 100644
--- a/bsd-core/drm_drv.c
+++ b/bsd-core/drm_drv.c
@@ -33,6 +33,7 @@
#include "drmP.h"
#include "drm.h"
+#include "drm_sarea.h"
int drm_debug_flag = 0;
@@ -357,10 +358,17 @@ drm_pci_id_list_t *drm_find_description(int vendor, int device,
static int drm_firstopen(drm_device_t *dev)
{
+ drm_local_map_t *map;
int i;
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+ /* prebuild the SAREA */
+ i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
+ _DRM_CONTAINS_LOCK, &map);
+ if (i != 0)
+ return i;
+
if (dev->driver.firstopen)
dev->driver.firstopen(dev);
@@ -388,7 +396,6 @@ static int drm_firstopen(drm_device_t *dev)
dev->magiclist[i].tail = NULL;
}
- dev->lock.hw_lock = NULL;
dev->lock.lock_queue = 0;
dev->irq_enabled = 0;
dev->context_flag = 0;
@@ -851,9 +858,9 @@ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
/* ioctl->master check should be against something in the filp set up
* for the first opener, but it doesn't matter yet.
*/
- if ((ioctl->root_only && DRM_SUSER(p)) ||
+ if ((ioctl->root_only && !DRM_SUSER(p)) ||
(ioctl->auth_needed && !priv->authenticated) ||
- (ioctl->master && !DRM_SUSER(p)))
+ (ioctl->master && !priv->master))
return EACCES;
if (is_driver_ioctl)
diff --git a/bsd-core/drm_fops.c b/bsd-core/drm_fops.c
index b15fd056..f5c9349b 100644
--- a/bsd-core/drm_fops.c
+++ b/bsd-core/drm_fops.c
@@ -88,7 +88,9 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
priv->refs = 1;
priv->minor = m;
priv->ioctl_count = 0;
- priv->authenticated = !DRM_SUSER(p);
+
+ /* for compatibility root is always authenticated */
+ priv->authenticated = DRM_SUSER(p);
if (dev->driver.open) {
retcode = dev->driver.open(dev, priv);
@@ -99,6 +101,9 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
}
}
+ /* first opener automatically becomes master */
+ priv->master = TAILQ_EMPTY(&dev->files);
+
TAILQ_INSERT_TAIL(&dev->files, priv, link);
}
DRM_UNLOCK();
diff --git a/bsd-core/drm_vm.c b/bsd-core/drm_vm.c
index 419b3cb1..05ac7b15 100644
--- a/bsd-core/drm_vm.c
+++ b/bsd-core/drm_vm.c
@@ -49,10 +49,11 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
if (!priv->authenticated)
return DRM_ERR(EACCES);
- DRM_SPINLOCK(&dev->dma_lock);
if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) {
drm_device_dma_t *dma = dev->dma;
+ DRM_SPINLOCK(&dev->dma_lock);
+
if (dma->pagelist != NULL) {
unsigned long page = offset >> PAGE_SHIFT;
unsigned long phys = dma->pagelist[page];
@@ -68,8 +69,8 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
DRM_SPINUNLOCK(&dev->dma_lock);
return -1;
}
+ DRM_SPINUNLOCK(&dev->dma_lock);
}
- DRM_SPINUNLOCK(&dev->dma_lock);
/* A sequential search of a linked list is
fine here because: 1) there will only be
@@ -89,7 +90,7 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
DRM_DEBUG("can't find map\n");
return -1;
}
- if (((map->flags&_DRM_RESTRICTED) && DRM_SUSER(DRM_CURPROC))) {
+ if (((map->flags&_DRM_RESTRICTED) && !DRM_SUSER(DRM_CURPROC))) {
DRM_UNLOCK();
DRM_DEBUG("restricted map\n");
return -1;