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

intel_global_state.c (6510B)


      1// SPDX-License-Identifier: MIT
      2/*
      3 * Copyright © 2020 Intel Corporation
      4 */
      5
      6#include <linux/string.h>
      7
      8#include "i915_drv.h"
      9#include "intel_atomic.h"
     10#include "intel_display_types.h"
     11#include "intel_global_state.h"
     12
     13static void __intel_atomic_global_state_free(struct kref *kref)
     14{
     15	struct intel_global_state *obj_state =
     16		container_of(kref, struct intel_global_state, ref);
     17	struct intel_global_obj *obj = obj_state->obj;
     18
     19	obj->funcs->atomic_destroy_state(obj, obj_state);
     20}
     21
     22static void intel_atomic_global_state_put(struct intel_global_state *obj_state)
     23{
     24	kref_put(&obj_state->ref, __intel_atomic_global_state_free);
     25}
     26
     27static struct intel_global_state *
     28intel_atomic_global_state_get(struct intel_global_state *obj_state)
     29{
     30	kref_get(&obj_state->ref);
     31
     32	return obj_state;
     33}
     34
     35void intel_atomic_global_obj_init(struct drm_i915_private *dev_priv,
     36				  struct intel_global_obj *obj,
     37				  struct intel_global_state *state,
     38				  const struct intel_global_state_funcs *funcs)
     39{
     40	memset(obj, 0, sizeof(*obj));
     41
     42	state->obj = obj;
     43
     44	kref_init(&state->ref);
     45
     46	obj->state = state;
     47	obj->funcs = funcs;
     48	list_add_tail(&obj->head, &dev_priv->global_obj_list);
     49}
     50
     51void intel_atomic_global_obj_cleanup(struct drm_i915_private *dev_priv)
     52{
     53	struct intel_global_obj *obj, *next;
     54
     55	list_for_each_entry_safe(obj, next, &dev_priv->global_obj_list, head) {
     56		list_del(&obj->head);
     57
     58		drm_WARN_ON(&dev_priv->drm, kref_read(&obj->state->ref) != 1);
     59		intel_atomic_global_state_put(obj->state);
     60	}
     61}
     62
     63static void assert_global_state_write_locked(struct drm_i915_private *dev_priv)
     64{
     65	struct intel_crtc *crtc;
     66
     67	for_each_intel_crtc(&dev_priv->drm, crtc)
     68		drm_modeset_lock_assert_held(&crtc->base.mutex);
     69}
     70
     71static bool modeset_lock_is_held(struct drm_modeset_acquire_ctx *ctx,
     72				 struct drm_modeset_lock *lock)
     73{
     74	struct drm_modeset_lock *l;
     75
     76	list_for_each_entry(l, &ctx->locked, head) {
     77		if (lock == l)
     78			return true;
     79	}
     80
     81	return false;
     82}
     83
     84static void assert_global_state_read_locked(struct intel_atomic_state *state)
     85{
     86	struct drm_modeset_acquire_ctx *ctx = state->base.acquire_ctx;
     87	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
     88	struct intel_crtc *crtc;
     89
     90	for_each_intel_crtc(&dev_priv->drm, crtc) {
     91		if (modeset_lock_is_held(ctx, &crtc->base.mutex))
     92			return;
     93	}
     94
     95	drm_WARN(&dev_priv->drm, 1, "Global state not read locked\n");
     96}
     97
     98struct intel_global_state *
     99intel_atomic_get_global_obj_state(struct intel_atomic_state *state,
    100				  struct intel_global_obj *obj)
    101{
    102	struct drm_i915_private *i915 = to_i915(state->base.dev);
    103	int index, num_objs, i;
    104	size_t size;
    105	struct __intel_global_objs_state *arr;
    106	struct intel_global_state *obj_state;
    107
    108	for (i = 0; i < state->num_global_objs; i++)
    109		if (obj == state->global_objs[i].ptr)
    110			return state->global_objs[i].state;
    111
    112	assert_global_state_read_locked(state);
    113
    114	num_objs = state->num_global_objs + 1;
    115	size = sizeof(*state->global_objs) * num_objs;
    116	arr = krealloc(state->global_objs, size, GFP_KERNEL);
    117	if (!arr)
    118		return ERR_PTR(-ENOMEM);
    119
    120	state->global_objs = arr;
    121	index = state->num_global_objs;
    122	memset(&state->global_objs[index], 0, sizeof(*state->global_objs));
    123
    124	obj_state = obj->funcs->atomic_duplicate_state(obj);
    125	if (!obj_state)
    126		return ERR_PTR(-ENOMEM);
    127
    128	obj_state->obj = obj;
    129	obj_state->changed = false;
    130
    131	kref_init(&obj_state->ref);
    132
    133	state->global_objs[index].state = obj_state;
    134	state->global_objs[index].old_state =
    135		intel_atomic_global_state_get(obj->state);
    136	state->global_objs[index].new_state = obj_state;
    137	state->global_objs[index].ptr = obj;
    138	obj_state->state = state;
    139
    140	state->num_global_objs = num_objs;
    141
    142	drm_dbg_atomic(&i915->drm, "Added new global object %p state %p to %p\n",
    143		       obj, obj_state, state);
    144
    145	return obj_state;
    146}
    147
    148struct intel_global_state *
    149intel_atomic_get_old_global_obj_state(struct intel_atomic_state *state,
    150				      struct intel_global_obj *obj)
    151{
    152	int i;
    153
    154	for (i = 0; i < state->num_global_objs; i++)
    155		if (obj == state->global_objs[i].ptr)
    156			return state->global_objs[i].old_state;
    157
    158	return NULL;
    159}
    160
    161struct intel_global_state *
    162intel_atomic_get_new_global_obj_state(struct intel_atomic_state *state,
    163				      struct intel_global_obj *obj)
    164{
    165	int i;
    166
    167	for (i = 0; i < state->num_global_objs; i++)
    168		if (obj == state->global_objs[i].ptr)
    169			return state->global_objs[i].new_state;
    170
    171	return NULL;
    172}
    173
    174void intel_atomic_swap_global_state(struct intel_atomic_state *state)
    175{
    176	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
    177	struct intel_global_state *old_obj_state, *new_obj_state;
    178	struct intel_global_obj *obj;
    179	int i;
    180
    181	for_each_oldnew_global_obj_in_state(state, obj, old_obj_state,
    182					    new_obj_state, i) {
    183		drm_WARN_ON(&dev_priv->drm, obj->state != old_obj_state);
    184
    185		/*
    186		 * If the new state wasn't modified (and properly
    187		 * locked for write access) we throw it away.
    188		 */
    189		if (!new_obj_state->changed)
    190			continue;
    191
    192		assert_global_state_write_locked(dev_priv);
    193
    194		old_obj_state->state = state;
    195		new_obj_state->state = NULL;
    196
    197		state->global_objs[i].state = old_obj_state;
    198
    199		intel_atomic_global_state_put(obj->state);
    200		obj->state = intel_atomic_global_state_get(new_obj_state);
    201	}
    202}
    203
    204void intel_atomic_clear_global_state(struct intel_atomic_state *state)
    205{
    206	int i;
    207
    208	for (i = 0; i < state->num_global_objs; i++) {
    209		intel_atomic_global_state_put(state->global_objs[i].old_state);
    210		intel_atomic_global_state_put(state->global_objs[i].new_state);
    211
    212		state->global_objs[i].ptr = NULL;
    213		state->global_objs[i].state = NULL;
    214		state->global_objs[i].old_state = NULL;
    215		state->global_objs[i].new_state = NULL;
    216	}
    217	state->num_global_objs = 0;
    218}
    219
    220int intel_atomic_lock_global_state(struct intel_global_state *obj_state)
    221{
    222	struct intel_atomic_state *state = obj_state->state;
    223	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
    224	struct intel_crtc *crtc;
    225
    226	for_each_intel_crtc(&dev_priv->drm, crtc) {
    227		int ret;
    228
    229		ret = drm_modeset_lock(&crtc->base.mutex,
    230				       state->base.acquire_ctx);
    231		if (ret)
    232			return ret;
    233	}
    234
    235	obj_state->changed = true;
    236
    237	return 0;
    238}
    239
    240int intel_atomic_serialize_global_state(struct intel_global_state *obj_state)
    241{
    242	struct intel_atomic_state *state = obj_state->state;
    243	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
    244	struct intel_crtc *crtc;
    245
    246	for_each_intel_crtc(&dev_priv->drm, crtc) {
    247		struct intel_crtc_state *crtc_state;
    248
    249		crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
    250		if (IS_ERR(crtc_state))
    251			return PTR_ERR(crtc_state);
    252	}
    253
    254	obj_state->changed = true;
    255
    256	return 0;
    257}