Commit 54ba2f76 authored by Dave Airlie's avatar Dave Airlie

drm: bring bufs code from git tree.

This checks the AGP mappings are in a valid place and also fixes the size
check in the vm..
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent 5cc7f9ab
...@@ -57,7 +57,8 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev, ...@@ -57,7 +57,8 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
list_for_each(list, &dev->maplist->head) { list_for_each(list, &dev->maplist->head) {
drm_map_list_t *entry = list_entry(list, drm_map_list_t, head); drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
if (entry->map && map->type == entry->map->type && if (entry->map && map->type == entry->map->type &&
entry->map->offset == map->offset) { ((entry->map->offset == map->offset) ||
(map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
return entry; return entry;
} }
} }
...@@ -180,8 +181,20 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, ...@@ -180,8 +181,20 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
if (map->type == _DRM_REGISTERS) if (map->type == _DRM_REGISTERS)
map->handle = ioremap(map->offset, map->size); map->handle = ioremap(map->offset, map->size);
break; break;
case _DRM_SHM: case _DRM_SHM:
list = drm_find_matching_map(dev, map);
if (list != NULL) {
if(list->map->size != map->size) {
DRM_DEBUG("Matching maps of type %d with "
"mismatched sizes, (%ld vs %ld)\n",
map->type, map->size, list->map->size);
list->map->size = map->size;
}
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
*maplist = list;
return 0;
}
map->handle = vmalloc_user(map->size); map->handle = vmalloc_user(map->size);
DRM_DEBUG("%lu %d %p\n", DRM_DEBUG("%lu %d %p\n",
map->size, drm_order(map->size), map->handle); map->size, drm_order(map->size), map->handle);
...@@ -200,15 +213,45 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, ...@@ -200,15 +213,45 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */ dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */
} }
break; break;
case _DRM_AGP: case _DRM_AGP: {
if (drm_core_has_AGP(dev)) { drm_agp_mem_t *entry;
int valid = 0;
if (!drm_core_has_AGP(dev)) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
#ifdef __alpha__ #ifdef __alpha__
map->offset += dev->hose->mem_space->start; map->offset += dev->hose->mem_space->start;
#endif #endif
map->offset += dev->agp->base; /* Note: dev->agp->base may actually be 0 when the DRM
map->mtrr = dev->agp->agp_mtrr; /* for getmap */ * is not in control of AGP space. But if user space is
* it should already have added the AGP base itself.
*/
map->offset += dev->agp->base;
map->mtrr = dev->agp->agp_mtrr; /* for getmap */
/* This assumes the DRM is in total control of AGP space.
* It's not always the case as AGP can be in the control
* of user space (i.e. i810 driver). So this loop will get
* skipped and we double check that dev->agp->memory is
* actually set as well as being invalid before EPERM'ing
*/
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 (dev->agp->memory && !valid) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EPERM;
}
DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size);
break; break;
}
case _DRM_SCATTER_GATHER: case _DRM_SCATTER_GATHER:
if (!dev->sg) { if (!dev->sg) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
...@@ -267,7 +310,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, ...@@ -267,7 +310,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
*maplist = list; *maplist = list;
return 0; return 0;
} }
int drm_addmap(drm_device_t * dev, unsigned int offset, int drm_addmap(drm_device_t * dev, unsigned int offset,
unsigned int size, drm_map_type_t type, unsigned int size, drm_map_type_t type,
...@@ -519,6 +562,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -519,6 +562,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
{ {
drm_device_dma_t *dma = dev->dma; drm_device_dma_t *dma = dev->dma;
drm_buf_entry_t *entry; drm_buf_entry_t *entry;
drm_agp_mem_t *agp_entry;
drm_buf_t *buf; drm_buf_t *buf;
unsigned long offset; unsigned long offset;
unsigned long agp_offset; unsigned long agp_offset;
...@@ -529,7 +573,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -529,7 +573,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
int page_order; int page_order;
int total; int total;
int byte_count; int byte_count;
int i; int i, valid;
drm_buf_t **temp_buflist; drm_buf_t **temp_buflist;
if (!dma) if (!dma)
...@@ -560,6 +604,19 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -560,6 +604,19 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
if (dev->queue_count) if (dev->queue_count)
return -EBUSY; /* Not while in use */ return -EBUSY; /* Not while in use */
/* 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 (dev->agp->memory && !valid) {
DRM_DEBUG("zone invalid\n");
return -EINVAL;
}
spin_lock(&dev->count_lock); spin_lock(&dev->count_lock);
if (dev->buf_use) { if (dev->buf_use) {
spin_unlock(&dev->count_lock); spin_unlock(&dev->count_lock);
......
...@@ -589,7 +589,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -589,7 +589,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
return -EPERM; return -EPERM;
/* Check for valid size. */ /* Check for valid size. */
if (map->size != vma->vm_end - vma->vm_start) if (map->size < vma->vm_end - vma->vm_start)
return -EINVAL; return -EINVAL;
if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment