cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drm_mode_object.c (16946B)


      1/*
      2 * Copyright (c) 2016 Intel Corporation
      3 *
      4 * Permission to use, copy, modify, distribute, and sell this software and its
      5 * documentation for any purpose is hereby granted without fee, provided that
      6 * the above copyright notice appear in all copies and that both that copyright
      7 * notice and this permission notice appear in supporting documentation, and
      8 * that the name of the copyright holders not be used in advertising or
      9 * publicity pertaining to distribution of the software without specific,
     10 * written prior permission.  The copyright holders make no representations
     11 * about the suitability of this software for any purpose.  It is provided "as
     12 * is" without express or implied warranty.
     13 *
     14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20 * OF THIS SOFTWARE.
     21 */
     22
     23#include <linux/export.h>
     24#include <linux/uaccess.h>
     25
     26#include <drm/drm_atomic.h>
     27#include <drm/drm_drv.h>
     28#include <drm/drm_device.h>
     29#include <drm/drm_file.h>
     30#include <drm/drm_mode_object.h>
     31#include <drm/drm_print.h>
     32
     33#include "drm_crtc_internal.h"
     34
     35/*
     36 * Internal function to assign a slot in the object idr and optionally
     37 * register the object into the idr.
     38 */
     39int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
     40			  uint32_t obj_type, bool register_obj,
     41			  void (*obj_free_cb)(struct kref *kref))
     42{
     43	int ret;
     44
     45	WARN_ON(!dev->driver->load && dev->registered && !obj_free_cb);
     46
     47	mutex_lock(&dev->mode_config.idr_mutex);
     48	ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL,
     49			1, 0, GFP_KERNEL);
     50	if (ret >= 0) {
     51		/*
     52		 * Set up the object linking under the protection of the idr
     53		 * lock so that other users can't see inconsistent state.
     54		 */
     55		obj->id = ret;
     56		obj->type = obj_type;
     57		if (obj_free_cb) {
     58			obj->free_cb = obj_free_cb;
     59			kref_init(&obj->refcount);
     60		}
     61	}
     62	mutex_unlock(&dev->mode_config.idr_mutex);
     63
     64	return ret < 0 ? ret : 0;
     65}
     66
     67/**
     68 * drm_mode_object_add - allocate a new modeset identifier
     69 * @dev: DRM device
     70 * @obj: object pointer, used to generate unique ID
     71 * @obj_type: object type
     72 *
     73 * Create a unique identifier based on @ptr in @dev's identifier space.  Used
     74 * for tracking modes, CRTCs and connectors.
     75 *
     76 * Returns:
     77 * Zero on success, error code on failure.
     78 */
     79int drm_mode_object_add(struct drm_device *dev,
     80			struct drm_mode_object *obj, uint32_t obj_type)
     81{
     82	return __drm_mode_object_add(dev, obj, obj_type, true, NULL);
     83}
     84
     85void drm_mode_object_register(struct drm_device *dev,
     86			      struct drm_mode_object *obj)
     87{
     88	mutex_lock(&dev->mode_config.idr_mutex);
     89	idr_replace(&dev->mode_config.object_idr, obj, obj->id);
     90	mutex_unlock(&dev->mode_config.idr_mutex);
     91}
     92
     93/**
     94 * drm_mode_object_unregister - free a modeset identifier
     95 * @dev: DRM device
     96 * @object: object to free
     97 *
     98 * Free @id from @dev's unique identifier pool.
     99 * This function can be called multiple times, and guards against
    100 * multiple removals.
    101 * These modeset identifiers are _not_ reference counted. Hence don't use this
    102 * for reference counted modeset objects like framebuffers.
    103 */
    104void drm_mode_object_unregister(struct drm_device *dev,
    105				struct drm_mode_object *object)
    106{
    107	WARN_ON(!dev->driver->load && dev->registered && !object->free_cb);
    108
    109	mutex_lock(&dev->mode_config.idr_mutex);
    110	if (object->id) {
    111		idr_remove(&dev->mode_config.object_idr, object->id);
    112		object->id = 0;
    113	}
    114	mutex_unlock(&dev->mode_config.idr_mutex);
    115}
    116
    117/**
    118 * drm_mode_object_lease_required - check types which must be leased to be used
    119 * @type: type of object
    120 *
    121 * Returns whether the provided type of drm_mode_object must
    122 * be owned or leased to be used by a process.
    123 */
    124bool drm_mode_object_lease_required(uint32_t type)
    125{
    126	switch(type) {
    127	case DRM_MODE_OBJECT_CRTC:
    128	case DRM_MODE_OBJECT_CONNECTOR:
    129	case DRM_MODE_OBJECT_PLANE:
    130		return true;
    131	default:
    132		return false;
    133	}
    134}
    135
    136struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
    137					       struct drm_file *file_priv,
    138					       uint32_t id, uint32_t type)
    139{
    140	struct drm_mode_object *obj = NULL;
    141
    142	mutex_lock(&dev->mode_config.idr_mutex);
    143	obj = idr_find(&dev->mode_config.object_idr, id);
    144	if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
    145		obj = NULL;
    146	if (obj && obj->id != id)
    147		obj = NULL;
    148
    149	if (obj && drm_mode_object_lease_required(obj->type) &&
    150	    !_drm_lease_held(file_priv, obj->id))
    151		obj = NULL;
    152
    153	if (obj && obj->free_cb) {
    154		if (!kref_get_unless_zero(&obj->refcount))
    155			obj = NULL;
    156	}
    157	mutex_unlock(&dev->mode_config.idr_mutex);
    158
    159	return obj;
    160}
    161
    162/**
    163 * drm_mode_object_find - look up a drm object with static lifetime
    164 * @dev: drm device
    165 * @file_priv: drm file
    166 * @id: id of the mode object
    167 * @type: type of the mode object
    168 *
    169 * This function is used to look up a modeset object. It will acquire a
    170 * reference for reference counted objects. This reference must be dropped again
    171 * by callind drm_mode_object_put().
    172 */
    173struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
    174		struct drm_file *file_priv,
    175		uint32_t id, uint32_t type)
    176{
    177	struct drm_mode_object *obj = NULL;
    178
    179	obj = __drm_mode_object_find(dev, file_priv, id, type);
    180	return obj;
    181}
    182EXPORT_SYMBOL(drm_mode_object_find);
    183
    184/**
    185 * drm_mode_object_put - release a mode object reference
    186 * @obj: DRM mode object
    187 *
    188 * This function decrements the object's refcount if it is a refcounted modeset
    189 * object. It is a no-op on any other object. This is used to drop references
    190 * acquired with drm_mode_object_get().
    191 */
    192void drm_mode_object_put(struct drm_mode_object *obj)
    193{
    194	if (obj->free_cb) {
    195		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
    196		kref_put(&obj->refcount, obj->free_cb);
    197	}
    198}
    199EXPORT_SYMBOL(drm_mode_object_put);
    200
    201/**
    202 * drm_mode_object_get - acquire a mode object reference
    203 * @obj: DRM mode object
    204 *
    205 * This function increments the object's refcount if it is a refcounted modeset
    206 * object. It is a no-op on any other object. References should be dropped again
    207 * by calling drm_mode_object_put().
    208 */
    209void drm_mode_object_get(struct drm_mode_object *obj)
    210{
    211	if (obj->free_cb) {
    212		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
    213		kref_get(&obj->refcount);
    214	}
    215}
    216EXPORT_SYMBOL(drm_mode_object_get);
    217
    218/**
    219 * drm_object_attach_property - attach a property to a modeset object
    220 * @obj: drm modeset object
    221 * @property: property to attach
    222 * @init_val: initial value of the property
    223 *
    224 * This attaches the given property to the modeset object with the given initial
    225 * value. Currently this function cannot fail since the properties are stored in
    226 * a statically sized array.
    227 *
    228 * Note that all properties must be attached before the object itself is
    229 * registered and accessible from userspace.
    230 */
    231void drm_object_attach_property(struct drm_mode_object *obj,
    232				struct drm_property *property,
    233				uint64_t init_val)
    234{
    235	int count = obj->properties->count;
    236	struct drm_device *dev = property->dev;
    237
    238
    239	if (obj->type == DRM_MODE_OBJECT_CONNECTOR) {
    240		struct drm_connector *connector = obj_to_connector(obj);
    241
    242		WARN_ON(!dev->driver->load &&
    243			connector->registration_state == DRM_CONNECTOR_REGISTERED);
    244	} else {
    245		WARN_ON(!dev->driver->load && dev->registered);
    246	}
    247
    248	if (count == DRM_OBJECT_MAX_PROPERTY) {
    249		WARN(1, "Failed to attach object property (type: 0x%x). Please "
    250			"increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
    251			"you see this message on the same object type.\n",
    252			obj->type);
    253		return;
    254	}
    255
    256	obj->properties->properties[count] = property;
    257	obj->properties->values[count] = init_val;
    258	obj->properties->count++;
    259}
    260EXPORT_SYMBOL(drm_object_attach_property);
    261
    262/**
    263 * drm_object_property_set_value - set the value of a property
    264 * @obj: drm mode object to set property value for
    265 * @property: property to set
    266 * @val: value the property should be set to
    267 *
    268 * This function sets a given property on a given object. This function only
    269 * changes the software state of the property, it does not call into the
    270 * driver's ->set_property callback.
    271 *
    272 * Note that atomic drivers should not have any need to call this, the core will
    273 * ensure consistency of values reported back to userspace through the
    274 * appropriate ->atomic_get_property callback. Only legacy drivers should call
    275 * this function to update the tracked value (after clamping and other
    276 * restrictions have been applied).
    277 *
    278 * Returns:
    279 * Zero on success, error code on failure.
    280 */
    281int drm_object_property_set_value(struct drm_mode_object *obj,
    282				  struct drm_property *property, uint64_t val)
    283{
    284	int i;
    285
    286	WARN_ON(drm_drv_uses_atomic_modeset(property->dev) &&
    287		!(property->flags & DRM_MODE_PROP_IMMUTABLE));
    288
    289	for (i = 0; i < obj->properties->count; i++) {
    290		if (obj->properties->properties[i] == property) {
    291			obj->properties->values[i] = val;
    292			return 0;
    293		}
    294	}
    295
    296	return -EINVAL;
    297}
    298EXPORT_SYMBOL(drm_object_property_set_value);
    299
    300static int __drm_object_property_get_prop_value(struct drm_mode_object *obj,
    301						struct drm_property *property,
    302						uint64_t *val)
    303{
    304	int i;
    305
    306	for (i = 0; i < obj->properties->count; i++) {
    307		if (obj->properties->properties[i] == property) {
    308			*val = obj->properties->values[i];
    309			return 0;
    310		}
    311	}
    312
    313	return -EINVAL;
    314}
    315
    316static int __drm_object_property_get_value(struct drm_mode_object *obj,
    317					   struct drm_property *property,
    318					   uint64_t *val)
    319{
    320
    321	/* read-only properties bypass atomic mechanism and still store
    322	 * their value in obj->properties->values[].. mostly to avoid
    323	 * having to deal w/ EDID and similar props in atomic paths:
    324	 */
    325	if (drm_drv_uses_atomic_modeset(property->dev) &&
    326			!(property->flags & DRM_MODE_PROP_IMMUTABLE))
    327		return drm_atomic_get_property(obj, property, val);
    328
    329	return __drm_object_property_get_prop_value(obj, property, val);
    330}
    331
    332/**
    333 * drm_object_property_get_value - retrieve the value of a property
    334 * @obj: drm mode object to get property value from
    335 * @property: property to retrieve
    336 * @val: storage for the property value
    337 *
    338 * This function retrieves the softare state of the given property for the given
    339 * property. Since there is no driver callback to retrieve the current property
    340 * value this might be out of sync with the hardware, depending upon the driver
    341 * and property.
    342 *
    343 * Atomic drivers should never call this function directly, the core will read
    344 * out property values through the various ->atomic_get_property callbacks.
    345 *
    346 * Returns:
    347 * Zero on success, error code on failure.
    348 */
    349int drm_object_property_get_value(struct drm_mode_object *obj,
    350				  struct drm_property *property, uint64_t *val)
    351{
    352	WARN_ON(drm_drv_uses_atomic_modeset(property->dev));
    353
    354	return __drm_object_property_get_value(obj, property, val);
    355}
    356EXPORT_SYMBOL(drm_object_property_get_value);
    357
    358/**
    359 * drm_object_property_get_default_value - retrieve the default value of a
    360 * property when in atomic mode.
    361 * @obj: drm mode object to get property value from
    362 * @property: property to retrieve
    363 * @val: storage for the property value
    364 *
    365 * This function retrieves the default state of the given property as passed in
    366 * to drm_object_attach_property
    367 *
    368 * Only atomic drivers should call this function directly, as for non-atomic
    369 * drivers it will return the current value.
    370 *
    371 * Returns:
    372 * Zero on success, error code on failure.
    373 */
    374int drm_object_property_get_default_value(struct drm_mode_object *obj,
    375					  struct drm_property *property,
    376					  uint64_t *val)
    377{
    378	WARN_ON(!drm_drv_uses_atomic_modeset(property->dev));
    379
    380	return __drm_object_property_get_prop_value(obj, property, val);
    381}
    382EXPORT_SYMBOL(drm_object_property_get_default_value);
    383
    384/* helper for getconnector and getproperties ioctls */
    385int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
    386				   uint32_t __user *prop_ptr,
    387				   uint64_t __user *prop_values,
    388				   uint32_t *arg_count_props)
    389{
    390	int i, ret, count;
    391
    392	for (i = 0, count = 0; i < obj->properties->count; i++) {
    393		struct drm_property *prop = obj->properties->properties[i];
    394		uint64_t val;
    395
    396		if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
    397			continue;
    398
    399		if (*arg_count_props > count) {
    400			ret = __drm_object_property_get_value(obj, prop, &val);
    401			if (ret)
    402				return ret;
    403
    404			if (put_user(prop->base.id, prop_ptr + count))
    405				return -EFAULT;
    406
    407			if (put_user(val, prop_values + count))
    408				return -EFAULT;
    409		}
    410
    411		count++;
    412	}
    413	*arg_count_props = count;
    414
    415	return 0;
    416}
    417
    418/**
    419 * drm_mode_obj_get_properties_ioctl - get the current value of a object's property
    420 * @dev: DRM device
    421 * @data: ioctl data
    422 * @file_priv: DRM file info
    423 *
    424 * This function retrieves the current value for an object's property. Compared
    425 * to the connector specific ioctl this one is extended to also work on crtc and
    426 * plane objects.
    427 *
    428 * Called by the user via ioctl.
    429 *
    430 * Returns:
    431 * Zero on success, negative errno on failure.
    432 */
    433int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
    434				      struct drm_file *file_priv)
    435{
    436	struct drm_mode_obj_get_properties *arg = data;
    437	struct drm_mode_object *obj;
    438	struct drm_modeset_acquire_ctx ctx;
    439	int ret = 0;
    440
    441	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    442		return -EOPNOTSUPP;
    443
    444	DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
    445
    446	obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type);
    447	if (!obj) {
    448		ret = -ENOENT;
    449		goto out;
    450	}
    451	if (!obj->properties) {
    452		ret = -EINVAL;
    453		goto out_unref;
    454	}
    455
    456	ret = drm_mode_object_get_properties(obj, file_priv->atomic,
    457			(uint32_t __user *)(unsigned long)(arg->props_ptr),
    458			(uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
    459			&arg->count_props);
    460
    461out_unref:
    462	drm_mode_object_put(obj);
    463out:
    464	DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
    465	return ret;
    466}
    467
    468struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj,
    469					       uint32_t prop_id)
    470{
    471	int i;
    472
    473	for (i = 0; i < obj->properties->count; i++)
    474		if (obj->properties->properties[i]->base.id == prop_id)
    475			return obj->properties->properties[i];
    476
    477	return NULL;
    478}
    479
    480static int set_property_legacy(struct drm_mode_object *obj,
    481			       struct drm_property *prop,
    482			       uint64_t prop_value)
    483{
    484	struct drm_device *dev = prop->dev;
    485	struct drm_mode_object *ref;
    486	struct drm_modeset_acquire_ctx ctx;
    487	int ret = -EINVAL;
    488
    489	if (!drm_property_change_valid_get(prop, prop_value, &ref))
    490		return -EINVAL;
    491
    492	DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
    493	switch (obj->type) {
    494	case DRM_MODE_OBJECT_CONNECTOR:
    495		ret = drm_connector_set_obj_prop(obj, prop, prop_value);
    496		break;
    497	case DRM_MODE_OBJECT_CRTC:
    498		ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value);
    499		break;
    500	case DRM_MODE_OBJECT_PLANE:
    501		ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj),
    502						  prop, prop_value);
    503		break;
    504	}
    505	drm_property_change_valid_put(prop, ref);
    506	DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
    507
    508	return ret;
    509}
    510
    511static int set_property_atomic(struct drm_mode_object *obj,
    512			       struct drm_file *file_priv,
    513			       struct drm_property *prop,
    514			       uint64_t prop_value)
    515{
    516	struct drm_device *dev = prop->dev;
    517	struct drm_atomic_state *state;
    518	struct drm_modeset_acquire_ctx ctx;
    519	int ret;
    520
    521	state = drm_atomic_state_alloc(dev);
    522	if (!state)
    523		return -ENOMEM;
    524
    525	drm_modeset_acquire_init(&ctx, 0);
    526	state->acquire_ctx = &ctx;
    527
    528retry:
    529	if (prop == state->dev->mode_config.dpms_property) {
    530		if (obj->type != DRM_MODE_OBJECT_CONNECTOR) {
    531			ret = -EINVAL;
    532			goto out;
    533		}
    534
    535		ret = drm_atomic_connector_commit_dpms(state,
    536						       obj_to_connector(obj),
    537						       prop_value);
    538	} else {
    539		ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value);
    540		if (ret)
    541			goto out;
    542		ret = drm_atomic_commit(state);
    543	}
    544out:
    545	if (ret == -EDEADLK) {
    546		drm_atomic_state_clear(state);
    547		drm_modeset_backoff(&ctx);
    548		goto retry;
    549	}
    550
    551	drm_atomic_state_put(state);
    552
    553	drm_modeset_drop_locks(&ctx);
    554	drm_modeset_acquire_fini(&ctx);
    555
    556	return ret;
    557}
    558
    559int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
    560				    struct drm_file *file_priv)
    561{
    562	struct drm_mode_obj_set_property *arg = data;
    563	struct drm_mode_object *arg_obj;
    564	struct drm_property *property;
    565	int ret = -EINVAL;
    566
    567	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    568		return -EOPNOTSUPP;
    569
    570	arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type);
    571	if (!arg_obj)
    572		return -ENOENT;
    573
    574	if (!arg_obj->properties)
    575		goto out_unref;
    576
    577	property = drm_mode_obj_find_prop_id(arg_obj, arg->prop_id);
    578	if (!property)
    579		goto out_unref;
    580
    581	if (drm_drv_uses_atomic_modeset(property->dev))
    582		ret = set_property_atomic(arg_obj, file_priv, property, arg->value);
    583	else
    584		ret = set_property_legacy(arg_obj, property, arg->value);
    585
    586out_unref:
    587	drm_mode_object_put(arg_obj);
    588	return ret;
    589}