return -EINVAL;
        }
        /* Copy in the exec list from userland */
-       exec_list = drm_calloc_large(sizeof(*exec_list), args->buffer_count);
-       object_list = drm_calloc_large(sizeof(*object_list), args->buffer_count);
+       exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
+       object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count);
        if (exec_list == NULL || object_list == NULL) {
                DRM_ERROR("Failed to allocate exec or object list "
                          "for %d buffers\n",
 
 
 static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
 {
+       if (size != 0 && nmemb > ULONG_MAX / size)
+               return NULL;
+
        if (size * nmemb <= PAGE_SIZE)
            return kcalloc(nmemb, size, GFP_KERNEL);
 
+       return __vmalloc(size * nmemb,
+                        GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+}
+
+/* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */
+static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size)
+{
        if (size != 0 && nmemb > ULONG_MAX / size)
                return NULL;
 
+       if (size * nmemb <= PAGE_SIZE)
+           return kmalloc(nmemb * size, GFP_KERNEL);
+
        return __vmalloc(size * nmemb,
-                        GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+                        GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
 }
 
 static __inline void drm_free_large(void *ptr)