drm: add unified vma offset manager

If we want to map GPU memory into user-space, we need to linearize the
addresses to not confuse mm-core. Currently, GEM and TTM both implement
their own offset-managers to assign a pgoff to each object for user-space
CPU access. GEM uses a hash-table, TTM uses an rbtree.

This patch provides a unified implementation that can be used to replace
both. TTM allows partial mmaps with a given offset, so we cannot use
hashtables as the start address may not be known at mmap time. Hence, we
use the rbtree-implementation of TTM.

We could easily update drm_mm to use an rbtree instead of a linked list
for it's object list and thus drop the rbtree from the vma-manager.
However, this would slow down drm_mm object allocation for all other
use-cases (rbtree insertion) and add another 4-8 bytes to each mm node.
Hence, use the separate tree but allow for later migration.

This is a rewrite of the 2012-proposal by David Airlie <airlied@linux.ie>

v2:
 - fix Docbook integration
 - drop drm_mm_node_linked() and use drm_mm_node_allocated()
 - remove unjustified likely/unlikely usage (but keep for rbtree paths)
 - remove BUG_ON() as drm_mm already does that
 - clarify page-based vs. byte-based addresses
 - use drm_vma_node_reset() for initialization, too

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/gem: convert to new unified vma manager

Use the new vma manager instead of the old hashtable. Also convert all
drivers to use the new convenience helpers. This drops all the
(map_list.hash.key << PAGE_SHIFT) non-sense.

Locking and access-management is exactly the same as before with an
additional lock inside of the vma-manager, which strictly wouldn't be
needed for gem.

v2:
 - rebase on drm-next
 - init nodes via drm_vma_node_reset() in drm_gem.c
v3:
 - fix tegra

Cc: Inki Dae <inki.dae@samsung.com>
Cc: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/ttm: convert to unified vma offset manager

Use the new vma-manager infrastructure. This doesn't change any
implementation details as the vma-offset-manager is nearly copied 1-to-1
from TTM.

Even though the vma-manager uses its own locks, we still need bo->vm_lock
to prevent bos from being destroyed before we can get a reference during
lookup. However, this lock is not needed during vm-setup as we still
hold a reference there.

This also drops the addr_space_offset member as it is a copy of vm_start
in vma_node objects. Use the accessor functions instead.

Cc: Dave Airlie <airlied@redhat.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Cc: Martin Peres <martin.peres@labri.fr>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/vma: provide drm_vma_node_unmap() helper

Instead of unmapping the nodes in TTM and GEM users manually, we provide
a generic wrapper which does the correct thing for all vma-nodes.

v2: remove bdev->dev_mapping test in ttm_bo_unmap_virtual_unlocked() as
ttm_mem_io_free_vm() does nothing in that case (io_reserved_vm is 0).

Cc: Dave Airlie <airlied@redhat.com>
Cc: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/vma: add access management helpers

The VMA offset manager uses a device-global address-space, hence, any
user can currently map any offset-node they want. They only need to guess
the right offset. If we wanted per open-file offset spaces, we'd either
need VM_NONLINEAR mappings or multiple "struct address_space" trees. As
both doesn't really scale, we implement access management in the VMA
manager itself.

We use an rb-tree to store open-files for each VMA node. On each mmap
call, GEM, TTM or the drivers must check whether the current user is
allowed to map this file.

We add a separate lock for each node as there is no generic lock available
for the caller to protect the node easily.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/ast: implement mmap access managament

Correctly allow and revoke buffer access on each open/close via the new
VMA offset manager.

Cc: Dave Airlie <airlied@redhat.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/cirrus: implement mmap access managament

Correctly allow and revoke buffer access on each open/close via the new
VMA offset manager.

Cc: Dave Airlie <airlied@redhat.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/mgag200: implement mmap access managament

Correctly allow and revoke buffer access on each open/close via the new
VMA offset manager.

Cc: Dave Airlie <airlied@redhat.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/nouveau: implement mmap access managament

Correctly allow and revoke buffer access on each open/close via the new
VMA offset manager.

Cc: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/radeon: implement mmap access managament

Correctly allow and revoke buffer access on each open/close via the new
VMA offset manager.

Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/qxl: implement mmap access managament

Correctly allow and revoke buffer access on each open/close via the new
VMA offset manager.

Cc: Dave Airlie <airlied@redhat.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/vmwgfx: implement mmap access managament

Correctly allow and revoke buffer access on each open/close via the new
VMA offset manager.

Also remove unused vmw_user_dmabuf_reference() to prevent from using it
later without correctly adding mmap permissions.

Cc: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/ttm: prevent mmap access to unauthorized users

If a user does not have access to a given buffer, we must not allow them
to mmap it. Otherwise, users could "guess" the buffer offsets of other
users and get access to the buffer.

All TTM drivers already use the new VMA offset manager access management
so we can enable TTM mmap access management now.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/gem: implement mmap access management

Implement automatic access management for mmap offsets for all GEM
drivers. This prevents user-space applications from "guessing" GEM BO
offsets and accessing buffers which they don't own.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm: fix minor number range calculation

Currently, both ranges overlap. Fix the limits so both ranges are mutually
exclusive. Also use the occasion to convert whitespaces to tabs.

Cc: Martin Peres <martin.peres@labri.fr>
Cc: Kristian Høgsberg <krh@bitplanet.net>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm: implement render nodes

Render nodes provide an API for userspace to use non-privileged GPU
commands without any running DRM-Master. It is useful for offscreen
rendering, GPGPU clients, and normal render clients which do not perform
modesetting.

Compared to legacy clients, render clients no longer need any
authentication to perform client ioctls. Instead, user-space controls
render/client access to GPUs via filesystem access-modes on the
render-node. Once a render-node was opened, a client has full access to
the client/render operations on the GPU. However, no modesetting or ioctls
that affect global state are allowed on render nodes.

To prevent privilege-escalation, drivers must explicitly state that they
support render nodes. They must mark their render-only ioctls as
DRM_RENDER_ALLOW so render clients can use them. Furthermore, they must
support clients without any attached master.

If filesystem access-modes are not enough for fine-grained access control
to render nodes (very unlikely, considering the versaitlity of FS-ACLs),
you may still fall-back to fd-passing from server to client (which allows
arbitrary access-control). However, note that revoking access is
currently impossible and unlikely to get implemented.

Note: Render clients no longer have any associated DRM-Master as they are
supposed to be independent of any server state. DRM core highly depends on
file_priv->master to be non-NULL for modesetting/ctx/etc. commands.
Therefore, drivers must be very careful to not require DRM-Master if they
support DRIVER_RENDER.

Cc: Kristian Høgsberg <krh@bitplanet.net>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/mm: add "best_match" to drm_mm_insert_node()

Add a "best_match" argument similar to the drm_mm_search_*() helpers so we
can convert TTM to use them in follow up patches.

Also move the non-generic aliases to drm_mm.h header instead of keeping
them in the source file.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/ttm: replace drm_mm_pre_get() by direct alloc

Instead of calling drm_mm_pre_get() in a row, we now preallocate the node
and then use the atomic insertion functions. This has the exact same
semantics and there is no reason to use the racy pre-allocations.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/i915: pre-alloc instead of drm_mm search/get_block

i915 is the last user of the weird search+get_block drm_mm API. Convert it
to an explicit kmalloc()+insert_node().

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
drm/mm: remove unused API

These calls are no longer used. Remove them.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>