1e555d299SFrançois Tigeot /* 2e555d299SFrançois Tigeot * Copyright © 2011-2012 Intel Corporation 3e555d299SFrançois Tigeot * 4e555d299SFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 5e555d299SFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 6e555d299SFrançois Tigeot * to deal in the Software without restriction, including without limitation 7e555d299SFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8e555d299SFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 9e555d299SFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 10e555d299SFrançois Tigeot * 11e555d299SFrançois Tigeot * The above copyright notice and this permission notice (including the next 12e555d299SFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 13e555d299SFrançois Tigeot * Software. 14e555d299SFrançois Tigeot * 15e555d299SFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16e555d299SFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17e555d299SFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18e555d299SFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19e555d299SFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20e555d299SFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21e555d299SFrançois Tigeot * IN THE SOFTWARE. 22e555d299SFrançois Tigeot * 23e555d299SFrançois Tigeot * Authors: 24e555d299SFrançois Tigeot * Ben Widawsky <ben@bwidawsk.net> 25e555d299SFrançois Tigeot * 26e555d299SFrançois Tigeot */ 27e555d299SFrançois Tigeot 28e555d299SFrançois Tigeot /* 29e555d299SFrançois Tigeot * This file implements HW context support. On gen5+ a HW context consists of an 30e555d299SFrançois Tigeot * opaque GPU object which is referenced at times of context saves and restores. 31e555d299SFrançois Tigeot * With RC6 enabled, the context is also referenced as the GPU enters and exists 32e555d299SFrançois Tigeot * from RC6 (GPU has it's own internal power context, except on gen5). Though 33e555d299SFrançois Tigeot * something like a context does exist for the media ring, the code only 34e555d299SFrançois Tigeot * supports contexts for the render ring. 35e555d299SFrançois Tigeot * 36e555d299SFrançois Tigeot * In software, there is a distinction between contexts created by the user, 37e555d299SFrançois Tigeot * and the default HW context. The default HW context is used by GPU clients 38e555d299SFrançois Tigeot * that do not request setup of their own hardware context. The default 39e555d299SFrançois Tigeot * context's state is never restored to help prevent programming errors. This 40e555d299SFrançois Tigeot * would happen if a client ran and piggy-backed off another clients GPU state. 41e555d299SFrançois Tigeot * The default context only exists to give the GPU some offset to load as the 42e555d299SFrançois Tigeot * current to invoke a save of the context we actually care about. In fact, the 43e555d299SFrançois Tigeot * code could likely be constructed, albeit in a more complicated fashion, to 44e555d299SFrançois Tigeot * never use the default context, though that limits the driver's ability to 45e555d299SFrançois Tigeot * swap out, and/or destroy other contexts. 46e555d299SFrançois Tigeot * 47e555d299SFrançois Tigeot * All other contexts are created as a request by the GPU client. These contexts 48e555d299SFrançois Tigeot * store GPU state, and thus allow GPU clients to not re-emit state (and 49e555d299SFrançois Tigeot * potentially query certain state) at any time. The kernel driver makes 50e555d299SFrançois Tigeot * certain that the appropriate commands are inserted. 51e555d299SFrançois Tigeot * 52e555d299SFrançois Tigeot * The context life cycle is semi-complicated in that context BOs may live 53e555d299SFrançois Tigeot * longer than the context itself because of the way the hardware, and object 54e555d299SFrançois Tigeot * tracking works. Below is a very crude representation of the state machine 55e555d299SFrançois Tigeot * describing the context life. 56e555d299SFrançois Tigeot * refcount pincount active 57e555d299SFrançois Tigeot * S0: initial state 0 0 0 58e555d299SFrançois Tigeot * S1: context created 1 0 0 59e555d299SFrançois Tigeot * S2: context is currently running 2 1 X 60e555d299SFrançois Tigeot * S3: GPU referenced, but not current 2 0 1 61e555d299SFrançois Tigeot * S4: context is current, but destroyed 1 1 0 62e555d299SFrançois Tigeot * S5: like S3, but destroyed 1 0 1 63e555d299SFrançois Tigeot * 64e555d299SFrançois Tigeot * The most common (but not all) transitions: 65e555d299SFrançois Tigeot * S0->S1: client creates a context 66e555d299SFrançois Tigeot * S1->S2: client submits execbuf with context 67e555d299SFrançois Tigeot * S2->S3: other clients submits execbuf with context 68e555d299SFrançois Tigeot * S3->S1: context object was retired 69e555d299SFrançois Tigeot * S3->S2: clients submits another execbuf 70e555d299SFrançois Tigeot * S2->S4: context destroy called with current context 71e555d299SFrançois Tigeot * S3->S5->S0: destroy path 72e555d299SFrançois Tigeot * S4->S5->S0: destroy path on current context 73e555d299SFrançois Tigeot * 74e555d299SFrançois Tigeot * There are two confusing terms used above: 75e555d299SFrançois Tigeot * The "current context" means the context which is currently running on the 76*9edbd4a0SFrançois Tigeot * GPU. The GPU has loaded its state already and has stored away the gtt 77e555d299SFrançois Tigeot * offset of the BO. The GPU is not actively referencing the data at this 78e555d299SFrançois Tigeot * offset, but it will on the next context switch. The only way to avoid this 79e555d299SFrançois Tigeot * is to do a GPU reset. 80e555d299SFrançois Tigeot * 81e555d299SFrançois Tigeot * An "active context' is one which was previously the "current context" and is 82e555d299SFrançois Tigeot * on the active list waiting for the next context switch to occur. Until this 83e555d299SFrançois Tigeot * happens, the object must remain at the same gtt offset. It is therefore 84e555d299SFrançois Tigeot * possible to destroy a context, but it is still active. 85e555d299SFrançois Tigeot * 86e555d299SFrançois Tigeot */ 87e555d299SFrançois Tigeot 88e555d299SFrançois Tigeot #include <drm/drmP.h> 89e555d299SFrançois Tigeot #include <drm/i915_drm.h> 90e555d299SFrançois Tigeot #include "i915_drv.h" 91e555d299SFrançois Tigeot 92e555d299SFrançois Tigeot /* This is a HW constraint. The value below is the largest known requirement 93e555d299SFrançois Tigeot * I've seen in a spec to date, and that was a workaround for a non-shipping 94e555d299SFrançois Tigeot * part. It should be safe to decrease this, but it's more future proof as is. 95e555d299SFrançois Tigeot */ 96e555d299SFrançois Tigeot #define CONTEXT_ALIGN (64<<10) 97e555d299SFrançois Tigeot 98e555d299SFrançois Tigeot static struct i915_hw_context * 99e555d299SFrançois Tigeot i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); 100e555d299SFrançois Tigeot static int do_switch(struct i915_hw_context *to); 101e555d299SFrançois Tigeot 102e555d299SFrançois Tigeot static int get_context_size(struct drm_device *dev) 103e555d299SFrançois Tigeot { 104e555d299SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 105e555d299SFrançois Tigeot int ret; 106e555d299SFrançois Tigeot u32 reg; 107e555d299SFrançois Tigeot 108e555d299SFrançois Tigeot switch (INTEL_INFO(dev)->gen) { 109e555d299SFrançois Tigeot case 6: 110e555d299SFrançois Tigeot reg = I915_READ(CXT_SIZE); 111e555d299SFrançois Tigeot ret = GEN6_CXT_TOTAL_SIZE(reg) * 64; 112e555d299SFrançois Tigeot break; 113e555d299SFrançois Tigeot case 7: 114e555d299SFrançois Tigeot reg = I915_READ(GEN7_CXT_SIZE); 115e555d299SFrançois Tigeot if (IS_HASWELL(dev)) 1165d0b1887SFrançois Tigeot ret = HSW_CXT_TOTAL_SIZE; 117e555d299SFrançois Tigeot else 118e555d299SFrançois Tigeot ret = GEN7_CXT_TOTAL_SIZE(reg) * 64; 119e555d299SFrançois Tigeot break; 120*9edbd4a0SFrançois Tigeot case 8: 121*9edbd4a0SFrançois Tigeot ret = GEN8_CXT_TOTAL_SIZE; 122*9edbd4a0SFrançois Tigeot break; 123e555d299SFrançois Tigeot default: 124e555d299SFrançois Tigeot BUG(); 125e555d299SFrançois Tigeot } 126e555d299SFrançois Tigeot 127e555d299SFrançois Tigeot return ret; 128e555d299SFrançois Tigeot } 129e555d299SFrançois Tigeot 1305d0b1887SFrançois Tigeot void i915_gem_context_free(struct kref *ctx_ref) 131e555d299SFrançois Tigeot { 1325d0b1887SFrançois Tigeot struct i915_hw_context *ctx = container_of(ctx_ref, 1335d0b1887SFrançois Tigeot typeof(*ctx), ref); 134e555d299SFrançois Tigeot 135*9edbd4a0SFrançois Tigeot list_del(&ctx->link); 136e555d299SFrançois Tigeot drm_gem_object_unreference(&ctx->obj->base); 137158486a6SFrançois Tigeot kfree(ctx); 138e555d299SFrançois Tigeot } 139e555d299SFrançois Tigeot 140e555d299SFrançois Tigeot static struct i915_hw_context * 141e555d299SFrançois Tigeot create_hw_context(struct drm_device *dev, 142e555d299SFrançois Tigeot struct drm_i915_file_private *file_priv) 143e555d299SFrançois Tigeot { 144e555d299SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 145e555d299SFrançois Tigeot struct i915_hw_context *ctx; 1469f0f5970SFrançois Tigeot int ret; 147e555d299SFrançois Tigeot 148159fc1d7SFrançois Tigeot ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 149e555d299SFrançois Tigeot if (ctx == NULL) 150e555d299SFrançois Tigeot return ERR_PTR(-ENOMEM); 151e555d299SFrançois Tigeot 1525d0b1887SFrançois Tigeot kref_init(&ctx->ref); 153e555d299SFrançois Tigeot ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); 154*9edbd4a0SFrançois Tigeot INIT_LIST_HEAD(&ctx->link); 155e555d299SFrançois Tigeot if (ctx->obj == NULL) { 156158486a6SFrançois Tigeot kfree(ctx); 157e555d299SFrançois Tigeot DRM_DEBUG_DRIVER("Context object allocated failed\n"); 158e555d299SFrançois Tigeot return ERR_PTR(-ENOMEM); 159e555d299SFrançois Tigeot } 160e555d299SFrançois Tigeot 161e555d299SFrançois Tigeot if (INTEL_INFO(dev)->gen >= 7) { 162e555d299SFrançois Tigeot ret = i915_gem_object_set_cache_level(ctx->obj, 163*9edbd4a0SFrançois Tigeot I915_CACHE_L3_LLC); 1645d0b1887SFrançois Tigeot /* Failure shouldn't ever happen this early */ 1655d0b1887SFrançois Tigeot if (WARN_ON(ret)) 166e555d299SFrançois Tigeot goto err_out; 167e555d299SFrançois Tigeot } 168e555d299SFrançois Tigeot 169e555d299SFrançois Tigeot /* The ring associated with the context object is handled by the normal 170e555d299SFrançois Tigeot * object tracking code. We give an initial ring value simple to pass an 171e555d299SFrançois Tigeot * assertion in the context switch code. 172e555d299SFrançois Tigeot */ 173e555d299SFrançois Tigeot ctx->ring = &dev_priv->ring[RCS]; 174*9edbd4a0SFrançois Tigeot list_add_tail(&ctx->link, &dev_priv->context_list); 175e555d299SFrançois Tigeot 176e555d299SFrançois Tigeot /* Default context will never have a file_priv */ 177e555d299SFrançois Tigeot if (file_priv == NULL) 178e555d299SFrançois Tigeot return ctx; 179e555d299SFrançois Tigeot 1809f0f5970SFrançois Tigeot ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID + 1, 0, 1819f0f5970SFrançois Tigeot GFP_KERNEL); 1829f0f5970SFrançois Tigeot if (ret < 0) 183e555d299SFrançois Tigeot goto err_out; 1845d0b1887SFrançois Tigeot 1855d0b1887SFrançois Tigeot ctx->file_priv = file_priv; 1869f0f5970SFrançois Tigeot ctx->id = ret; 187*9edbd4a0SFrançois Tigeot /* NB: Mark all slices as needing a remap so that when the context first 188*9edbd4a0SFrançois Tigeot * loads it will restore whatever remap state already exists. If there 189*9edbd4a0SFrançois Tigeot * is no remap info, it will be a NOP. */ 190*9edbd4a0SFrançois Tigeot ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1; 191e555d299SFrançois Tigeot 192e555d299SFrançois Tigeot return ctx; 193e555d299SFrançois Tigeot 194e555d299SFrançois Tigeot err_out: 1955d0b1887SFrançois Tigeot i915_gem_context_unreference(ctx); 196e555d299SFrançois Tigeot return ERR_PTR(ret); 197e555d299SFrançois Tigeot } 198e555d299SFrançois Tigeot 199e555d299SFrançois Tigeot static inline bool is_default_context(struct i915_hw_context *ctx) 200e555d299SFrançois Tigeot { 201e555d299SFrançois Tigeot return (ctx == ctx->ring->default_context); 202e555d299SFrançois Tigeot } 203e555d299SFrançois Tigeot 204e555d299SFrançois Tigeot /** 205e555d299SFrançois Tigeot * The default context needs to exist per ring that uses contexts. It stores the 206e555d299SFrançois Tigeot * context state of the GPU for applications that don't utilize HW contexts, as 207e555d299SFrançois Tigeot * well as an idle case. 208e555d299SFrançois Tigeot */ 209e555d299SFrançois Tigeot static int create_default_context(struct drm_i915_private *dev_priv) 210e555d299SFrançois Tigeot { 211e555d299SFrançois Tigeot struct i915_hw_context *ctx; 212e555d299SFrançois Tigeot int ret; 213e555d299SFrançois Tigeot 214*9edbd4a0SFrançois Tigeot BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); 215e555d299SFrançois Tigeot 216e555d299SFrançois Tigeot ctx = create_hw_context(dev_priv->dev, NULL); 217e555d299SFrançois Tigeot if (IS_ERR(ctx)) 218e555d299SFrançois Tigeot return PTR_ERR(ctx); 219e555d299SFrançois Tigeot 220e555d299SFrançois Tigeot /* We may need to do things with the shrinker which require us to 221e555d299SFrançois Tigeot * immediately switch back to the default context. This can cause a 222e555d299SFrançois Tigeot * problem as pinning the default context also requires GTT space which 223e555d299SFrançois Tigeot * may not be available. To avoid this we always pin the 224e555d299SFrançois Tigeot * default context. 225e555d299SFrançois Tigeot */ 226*9edbd4a0SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(ctx->obj, CONTEXT_ALIGN, false, false); 2275d0b1887SFrançois Tigeot if (ret) { 2285d0b1887SFrançois Tigeot DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret); 229e555d299SFrançois Tigeot goto err_destroy; 2305d0b1887SFrançois Tigeot } 231e555d299SFrançois Tigeot 232e555d299SFrançois Tigeot ret = do_switch(ctx); 2335d0b1887SFrançois Tigeot if (ret) { 2345d0b1887SFrançois Tigeot DRM_DEBUG_DRIVER("Switch failed %d\n", ret); 235e555d299SFrançois Tigeot goto err_unpin; 2365d0b1887SFrançois Tigeot } 237e555d299SFrançois Tigeot 238*9edbd4a0SFrançois Tigeot dev_priv->ring[RCS].default_context = ctx; 239*9edbd4a0SFrançois Tigeot 240e555d299SFrançois Tigeot DRM_DEBUG_DRIVER("Default HW context loaded\n"); 241e555d299SFrançois Tigeot return 0; 242e555d299SFrançois Tigeot 243e555d299SFrançois Tigeot err_unpin: 244e555d299SFrançois Tigeot i915_gem_object_unpin(ctx->obj); 245e555d299SFrançois Tigeot err_destroy: 2465d0b1887SFrançois Tigeot i915_gem_context_unreference(ctx); 247e555d299SFrançois Tigeot return ret; 248e555d299SFrançois Tigeot } 249e555d299SFrançois Tigeot 250*9edbd4a0SFrançois Tigeot int i915_gem_context_init(struct drm_device *dev) 251e555d299SFrançois Tigeot { 252e555d299SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 253*9edbd4a0SFrançois Tigeot int ret; 254e555d299SFrançois Tigeot 255*9edbd4a0SFrançois Tigeot if (!HAS_HW_CONTEXTS(dev)) 256*9edbd4a0SFrançois Tigeot return 0; 257e555d299SFrançois Tigeot 258e555d299SFrançois Tigeot /* If called from reset, or thaw... we've been here already */ 259*9edbd4a0SFrançois Tigeot if (dev_priv->ring[RCS].default_context) 260*9edbd4a0SFrançois Tigeot return 0; 261e555d299SFrançois Tigeot 262a2fdbec6SFrançois Tigeot dev_priv->hw_context_size = round_up(get_context_size(dev), 4096); 263e555d299SFrançois Tigeot 264a2fdbec6SFrançois Tigeot if (dev_priv->hw_context_size > (1<<20)) { 2655d0b1887SFrançois Tigeot DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n"); 266*9edbd4a0SFrançois Tigeot return -E2BIG; 267e555d299SFrançois Tigeot } 268e555d299SFrançois Tigeot 269*9edbd4a0SFrançois Tigeot ret = create_default_context(dev_priv); 270*9edbd4a0SFrançois Tigeot if (ret) { 271*9edbd4a0SFrançois Tigeot DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %d\n", 272*9edbd4a0SFrançois Tigeot ret); 273*9edbd4a0SFrançois Tigeot return ret; 274e555d299SFrançois Tigeot } 275e555d299SFrançois Tigeot 276e555d299SFrançois Tigeot DRM_DEBUG_DRIVER("HW context support initialized\n"); 277*9edbd4a0SFrançois Tigeot return 0; 278e555d299SFrançois Tigeot } 279e555d299SFrançois Tigeot 280e555d299SFrançois Tigeot void i915_gem_context_fini(struct drm_device *dev) 281e555d299SFrançois Tigeot { 282e555d299SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 2835d0b1887SFrançois Tigeot struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context; 284e555d299SFrançois Tigeot 285*9edbd4a0SFrançois Tigeot if (!HAS_HW_CONTEXTS(dev)) 286e555d299SFrançois Tigeot return; 287e555d299SFrançois Tigeot 288e555d299SFrançois Tigeot /* The only known way to stop the gpu from accessing the hw context is 289e555d299SFrançois Tigeot * to reset it. Do this as the very last operation to avoid confusing 290e555d299SFrançois Tigeot * other code, leading to spurious errors. */ 291e555d299SFrançois Tigeot intel_gpu_reset(dev); 292e555d299SFrançois Tigeot 2935d0b1887SFrançois Tigeot /* When default context is created and switched to, base object refcount 2945d0b1887SFrançois Tigeot * will be 2 (+1 from object creation and +1 from do_switch()). 2955d0b1887SFrançois Tigeot * i915_gem_context_fini() will be called after gpu_idle() has switched 2965d0b1887SFrançois Tigeot * to default context. So we need to unreference the base object once 2975d0b1887SFrançois Tigeot * to offset the do_switch part, so that i915_gem_context_unreference() 2985d0b1887SFrançois Tigeot * can then free the base object correctly. */ 299*9edbd4a0SFrançois Tigeot WARN_ON(!dev_priv->ring[RCS].last_context); 300*9edbd4a0SFrançois Tigeot if (dev_priv->ring[RCS].last_context == dctx) { 301*9edbd4a0SFrançois Tigeot /* Fake switch to NULL context */ 302*9edbd4a0SFrançois Tigeot WARN_ON(dctx->obj->active); 303*9edbd4a0SFrançois Tigeot i915_gem_object_unpin(dctx->obj); 3045d0b1887SFrançois Tigeot i915_gem_context_unreference(dctx); 305e555d299SFrançois Tigeot } 306e555d299SFrançois Tigeot 307*9edbd4a0SFrançois Tigeot i915_gem_object_unpin(dctx->obj); 308*9edbd4a0SFrançois Tigeot i915_gem_context_unreference(dctx); 309*9edbd4a0SFrançois Tigeot dev_priv->ring[RCS].default_context = NULL; 310*9edbd4a0SFrançois Tigeot dev_priv->ring[RCS].last_context = NULL; 311*9edbd4a0SFrançois Tigeot } 312*9edbd4a0SFrançois Tigeot 313e555d299SFrançois Tigeot static int context_idr_cleanup(int id, void *p, void *data) 314e555d299SFrançois Tigeot { 315e555d299SFrançois Tigeot struct i915_hw_context *ctx = p; 316e555d299SFrançois Tigeot 317e555d299SFrançois Tigeot BUG_ON(id == DEFAULT_CONTEXT_ID); 318e555d299SFrançois Tigeot 3195d0b1887SFrançois Tigeot i915_gem_context_unreference(ctx); 320e555d299SFrançois Tigeot return 0; 321e555d299SFrançois Tigeot } 322e555d299SFrançois Tigeot 3235d0b1887SFrançois Tigeot struct i915_ctx_hang_stats * 324*9edbd4a0SFrançois Tigeot i915_gem_context_get_hang_stats(struct drm_device *dev, 3255d0b1887SFrançois Tigeot struct drm_file *file, 3265d0b1887SFrançois Tigeot u32 id) 3275d0b1887SFrançois Tigeot { 3285d0b1887SFrançois Tigeot struct drm_i915_file_private *file_priv = file->driver_priv; 329*9edbd4a0SFrançois Tigeot struct i915_hw_context *ctx; 3305d0b1887SFrançois Tigeot 3315d0b1887SFrançois Tigeot if (id == DEFAULT_CONTEXT_ID) 3325d0b1887SFrançois Tigeot return &file_priv->hang_stats; 3335d0b1887SFrançois Tigeot 334*9edbd4a0SFrançois Tigeot if (!HAS_HW_CONTEXTS(dev)) 3355d0b1887SFrançois Tigeot return ERR_PTR(-ENOENT); 3365d0b1887SFrançois Tigeot 337*9edbd4a0SFrançois Tigeot ctx = i915_gem_context_get(file->driver_priv, id); 338*9edbd4a0SFrançois Tigeot if (ctx == NULL) 339*9edbd4a0SFrançois Tigeot return ERR_PTR(-ENOENT); 340*9edbd4a0SFrançois Tigeot 341*9edbd4a0SFrançois Tigeot return &ctx->hang_stats; 3425d0b1887SFrançois Tigeot } 3435d0b1887SFrançois Tigeot 344e555d299SFrançois Tigeot void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) 345e555d299SFrançois Tigeot { 346e555d299SFrançois Tigeot struct drm_i915_file_private *file_priv = file->driver_priv; 347e555d299SFrançois Tigeot 348e555d299SFrançois Tigeot idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); 349e555d299SFrançois Tigeot idr_destroy(&file_priv->context_idr); 350e555d299SFrançois Tigeot } 351e555d299SFrançois Tigeot 352e555d299SFrançois Tigeot static struct i915_hw_context * 353e555d299SFrançois Tigeot i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) 354e555d299SFrançois Tigeot { 355e555d299SFrançois Tigeot return (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); 356e555d299SFrançois Tigeot } 357e555d299SFrançois Tigeot 358e555d299SFrançois Tigeot static inline int 359e555d299SFrançois Tigeot mi_set_context(struct intel_ring_buffer *ring, 360e555d299SFrançois Tigeot struct i915_hw_context *new_context, 361e555d299SFrançois Tigeot u32 hw_flags) 362e555d299SFrançois Tigeot { 363e555d299SFrançois Tigeot int ret; 364e555d299SFrançois Tigeot 365e555d299SFrançois Tigeot /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB 366e555d299SFrançois Tigeot * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value 367e555d299SFrançois Tigeot * explicitly, so we rely on the value at ring init, stored in 368e555d299SFrançois Tigeot * itlb_before_ctx_switch. 369e555d299SFrançois Tigeot */ 370e555d299SFrançois Tigeot if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) { 371e555d299SFrançois Tigeot ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0); 372e555d299SFrançois Tigeot if (ret) 373e555d299SFrançois Tigeot return ret; 374e555d299SFrançois Tigeot } 375e555d299SFrançois Tigeot 376e555d299SFrançois Tigeot ret = intel_ring_begin(ring, 6); 377e555d299SFrançois Tigeot if (ret) 378e555d299SFrançois Tigeot return ret; 379e555d299SFrançois Tigeot 3805d0b1887SFrançois Tigeot /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw */ 381e555d299SFrançois Tigeot if (IS_GEN7(ring->dev)) 382e555d299SFrançois Tigeot intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); 383e555d299SFrançois Tigeot else 384e555d299SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 385e555d299SFrançois Tigeot 386e555d299SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 387e555d299SFrançois Tigeot intel_ring_emit(ring, MI_SET_CONTEXT); 388*9edbd4a0SFrançois Tigeot intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->obj) | 389e555d299SFrançois Tigeot MI_MM_SPACE_GTT | 390e555d299SFrançois Tigeot MI_SAVE_EXT_STATE_EN | 391e555d299SFrançois Tigeot MI_RESTORE_EXT_STATE_EN | 392e555d299SFrançois Tigeot hw_flags); 393e555d299SFrançois Tigeot /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */ 394e555d299SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 395e555d299SFrançois Tigeot 396e555d299SFrançois Tigeot if (IS_GEN7(ring->dev)) 397e555d299SFrançois Tigeot intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); 398e555d299SFrançois Tigeot else 399e555d299SFrançois Tigeot intel_ring_emit(ring, MI_NOOP); 400e555d299SFrançois Tigeot 401e555d299SFrançois Tigeot intel_ring_advance(ring); 402e555d299SFrançois Tigeot 403e555d299SFrançois Tigeot return ret; 404e555d299SFrançois Tigeot } 405e555d299SFrançois Tigeot 406e555d299SFrançois Tigeot static int do_switch(struct i915_hw_context *to) 407e555d299SFrançois Tigeot { 408e555d299SFrançois Tigeot struct intel_ring_buffer *ring = to->ring; 4095d0b1887SFrançois Tigeot struct i915_hw_context *from = ring->last_context; 410e555d299SFrançois Tigeot u32 hw_flags = 0; 411*9edbd4a0SFrançois Tigeot int ret, i; 412e555d299SFrançois Tigeot 4135d0b1887SFrançois Tigeot BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0); 414e555d299SFrançois Tigeot 415*9edbd4a0SFrançois Tigeot if (from == to && !to->remap_slice) 416e555d299SFrançois Tigeot return 0; 417e555d299SFrançois Tigeot 418*9edbd4a0SFrançois Tigeot ret = i915_gem_obj_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false); 419e555d299SFrançois Tigeot if (ret) 420e555d299SFrançois Tigeot return ret; 421e555d299SFrançois Tigeot 422*9edbd4a0SFrançois Tigeot /* 423*9edbd4a0SFrançois Tigeot * Pin can switch back to the default context if we end up calling into 424*9edbd4a0SFrançois Tigeot * evict_everything - as a last ditch gtt defrag effort that also 425*9edbd4a0SFrançois Tigeot * switches to the default context. Hence we need to reload from here. 426*9edbd4a0SFrançois Tigeot */ 427*9edbd4a0SFrançois Tigeot from = ring->last_context; 428*9edbd4a0SFrançois Tigeot 429*9edbd4a0SFrançois Tigeot /* 430*9edbd4a0SFrançois Tigeot * Clear this page out of any CPU caches for coherent swap-in/out. Note 431e555d299SFrançois Tigeot * that thanks to write = false in this call and us not setting any gpu 432e555d299SFrançois Tigeot * write domains when putting a context object onto the active list 433e555d299SFrançois Tigeot * (when switching away from it), this won't block. 434*9edbd4a0SFrançois Tigeot * 435*9edbd4a0SFrançois Tigeot * XXX: We need a real interface to do this instead of trickery. 436*9edbd4a0SFrançois Tigeot */ 437e555d299SFrançois Tigeot ret = i915_gem_object_set_to_gtt_domain(to->obj, false); 438e555d299SFrançois Tigeot if (ret) { 439e555d299SFrançois Tigeot i915_gem_object_unpin(to->obj); 440e555d299SFrançois Tigeot return ret; 441e555d299SFrançois Tigeot } 442e555d299SFrançois Tigeot 443e555d299SFrançois Tigeot if (!to->obj->has_global_gtt_mapping) 444e555d299SFrançois Tigeot i915_gem_gtt_bind_object(to->obj, to->obj->cache_level); 445e555d299SFrançois Tigeot 446e555d299SFrançois Tigeot if (!to->is_initialized || is_default_context(to)) 447e555d299SFrançois Tigeot hw_flags |= MI_RESTORE_INHIBIT; 448e555d299SFrançois Tigeot 449e555d299SFrançois Tigeot ret = mi_set_context(ring, to, hw_flags); 450e555d299SFrançois Tigeot if (ret) { 451e555d299SFrançois Tigeot i915_gem_object_unpin(to->obj); 452e555d299SFrançois Tigeot return ret; 453e555d299SFrançois Tigeot } 454e555d299SFrançois Tigeot 455*9edbd4a0SFrançois Tigeot for (i = 0; i < MAX_L3_SLICES; i++) { 456*9edbd4a0SFrançois Tigeot if (!(to->remap_slice & (1<<i))) 457*9edbd4a0SFrançois Tigeot continue; 458*9edbd4a0SFrançois Tigeot 459*9edbd4a0SFrançois Tigeot ret = i915_gem_l3_remap(ring, i); 460*9edbd4a0SFrançois Tigeot /* If it failed, try again next round */ 461*9edbd4a0SFrançois Tigeot if (ret) 462*9edbd4a0SFrançois Tigeot DRM_DEBUG_DRIVER("L3 remapping failed\n"); 463*9edbd4a0SFrançois Tigeot else 464*9edbd4a0SFrançois Tigeot to->remap_slice &= ~(1<<i); 465*9edbd4a0SFrançois Tigeot } 466*9edbd4a0SFrançois Tigeot 467e555d299SFrançois Tigeot /* The backing object for the context is done after switching to the 468e555d299SFrançois Tigeot * *next* context. Therefore we cannot retire the previous context until 469e555d299SFrançois Tigeot * the next context has already started running. In fact, the below code 470e555d299SFrançois Tigeot * is a bit suboptimal because the retiring can occur simply after the 471e555d299SFrançois Tigeot * MI_SET_CONTEXT instead of when the next seqno has completed. 472e555d299SFrançois Tigeot */ 4735d0b1887SFrançois Tigeot if (from != NULL) { 4745d0b1887SFrançois Tigeot from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; 475*9edbd4a0SFrançois Tigeot i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->obj), ring); 476e555d299SFrançois Tigeot /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the 477e555d299SFrançois Tigeot * whole damn pipeline, we don't need to explicitly mark the 478e555d299SFrançois Tigeot * object dirty. The only exception is that the context must be 479e555d299SFrançois Tigeot * correct in case the object gets swapped out. Ideally we'd be 480e555d299SFrançois Tigeot * able to defer doing this until we know the object would be 481e555d299SFrançois Tigeot * swapped, but there is no way to do that yet. 482e555d299SFrançois Tigeot */ 4835d0b1887SFrançois Tigeot from->obj->dirty = 1; 4845d0b1887SFrançois Tigeot BUG_ON(from->obj->ring != ring); 485e555d299SFrançois Tigeot 486*9edbd4a0SFrançois Tigeot /* obj is kept alive until the next request by its active ref */ 4875d0b1887SFrançois Tigeot i915_gem_object_unpin(from->obj); 4885d0b1887SFrançois Tigeot i915_gem_context_unreference(from); 4895d0b1887SFrançois Tigeot } 4905d0b1887SFrançois Tigeot 4915d0b1887SFrançois Tigeot i915_gem_context_reference(to); 4925d0b1887SFrançois Tigeot ring->last_context = to; 493e555d299SFrançois Tigeot to->is_initialized = true; 494e555d299SFrançois Tigeot 495e555d299SFrançois Tigeot return 0; 496e555d299SFrançois Tigeot } 497e555d299SFrançois Tigeot 498e555d299SFrançois Tigeot /** 499e555d299SFrançois Tigeot * i915_switch_context() - perform a GPU context switch. 500e555d299SFrançois Tigeot * @ring: ring for which we'll execute the context switch 501e555d299SFrançois Tigeot * @file_priv: file_priv associated with the context, may be NULL 502e555d299SFrançois Tigeot * @id: context id number 503e555d299SFrançois Tigeot * 504e555d299SFrançois Tigeot * The context life cycle is simple. The context refcount is incremented and 505e555d299SFrançois Tigeot * decremented by 1 and create and destroy. If the context is in use by the GPU, 506e555d299SFrançois Tigeot * it will have a refoucnt > 1. This allows us to destroy the context abstract 507e555d299SFrançois Tigeot * object while letting the normal object tracking destroy the backing BO. 508e555d299SFrançois Tigeot */ 509e555d299SFrançois Tigeot int i915_switch_context(struct intel_ring_buffer *ring, 510e555d299SFrançois Tigeot struct drm_file *file, 511e555d299SFrançois Tigeot int to_id) 512e555d299SFrançois Tigeot { 513e555d299SFrançois Tigeot struct drm_i915_private *dev_priv = ring->dev->dev_private; 514e555d299SFrançois Tigeot struct i915_hw_context *to; 515e555d299SFrançois Tigeot 516*9edbd4a0SFrançois Tigeot if (!HAS_HW_CONTEXTS(ring->dev)) 517e555d299SFrançois Tigeot return 0; 518e555d299SFrançois Tigeot 5195d0b1887SFrançois Tigeot WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); 5205d0b1887SFrançois Tigeot 521e555d299SFrançois Tigeot if (ring != &dev_priv->ring[RCS]) 522e555d299SFrançois Tigeot return 0; 523e555d299SFrançois Tigeot 524e555d299SFrançois Tigeot if (to_id == DEFAULT_CONTEXT_ID) { 525e555d299SFrançois Tigeot to = ring->default_context; 526e555d299SFrançois Tigeot } else { 527e555d299SFrançois Tigeot if (file == NULL) 528e555d299SFrançois Tigeot return -EINVAL; 529e555d299SFrançois Tigeot 530e555d299SFrançois Tigeot to = i915_gem_context_get(file->driver_priv, to_id); 531e555d299SFrançois Tigeot if (to == NULL) 532e555d299SFrançois Tigeot return -ENOENT; 533e555d299SFrançois Tigeot } 534e555d299SFrançois Tigeot 535e555d299SFrançois Tigeot return do_switch(to); 536e555d299SFrançois Tigeot } 537e555d299SFrançois Tigeot 538e555d299SFrançois Tigeot int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, 539e555d299SFrançois Tigeot struct drm_file *file) 540e555d299SFrançois Tigeot { 541e555d299SFrançois Tigeot struct drm_i915_gem_context_create *args = data; 542e555d299SFrançois Tigeot struct drm_i915_file_private *file_priv = file->driver_priv; 543e555d299SFrançois Tigeot struct i915_hw_context *ctx; 544e555d299SFrançois Tigeot int ret; 545e555d299SFrançois Tigeot 546e555d299SFrançois Tigeot if (!(dev->driver->driver_features & DRIVER_GEM)) 547e555d299SFrançois Tigeot return -ENODEV; 548e555d299SFrançois Tigeot 549*9edbd4a0SFrançois Tigeot if (!HAS_HW_CONTEXTS(dev)) 550e555d299SFrançois Tigeot return -ENODEV; 551e555d299SFrançois Tigeot 552e555d299SFrançois Tigeot ret = i915_mutex_lock_interruptible(dev); 553e555d299SFrançois Tigeot if (ret) 554e555d299SFrançois Tigeot return ret; 555e555d299SFrançois Tigeot 556e555d299SFrançois Tigeot ctx = create_hw_context(dev, file_priv); 557a2fdbec6SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 558e555d299SFrançois Tigeot if (IS_ERR(ctx)) 559e555d299SFrançois Tigeot return PTR_ERR(ctx); 560e555d299SFrançois Tigeot 561e555d299SFrançois Tigeot args->ctx_id = ctx->id; 562e555d299SFrançois Tigeot DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id); 563e555d299SFrançois Tigeot 564e555d299SFrançois Tigeot return 0; 565e555d299SFrançois Tigeot } 566e555d299SFrançois Tigeot 567e555d299SFrançois Tigeot int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, 568e555d299SFrançois Tigeot struct drm_file *file) 569e555d299SFrançois Tigeot { 570e555d299SFrançois Tigeot struct drm_i915_gem_context_destroy *args = data; 571e555d299SFrançois Tigeot struct drm_i915_file_private *file_priv = file->driver_priv; 572e555d299SFrançois Tigeot struct i915_hw_context *ctx; 573e555d299SFrançois Tigeot int ret; 574e555d299SFrançois Tigeot 575e555d299SFrançois Tigeot if (!(dev->driver->driver_features & DRIVER_GEM)) 576e555d299SFrançois Tigeot return -ENODEV; 577e555d299SFrançois Tigeot 578e555d299SFrançois Tigeot ret = i915_mutex_lock_interruptible(dev); 579e555d299SFrançois Tigeot if (ret) 580e555d299SFrançois Tigeot return ret; 581e555d299SFrançois Tigeot 582e555d299SFrançois Tigeot ctx = i915_gem_context_get(file_priv, args->ctx_id); 583e555d299SFrançois Tigeot if (!ctx) { 584a2fdbec6SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 585e555d299SFrançois Tigeot return -ENOENT; 586e555d299SFrançois Tigeot } 587e555d299SFrançois Tigeot 5885d0b1887SFrançois Tigeot idr_remove(&ctx->file_priv->context_idr, ctx->id); 5895d0b1887SFrançois Tigeot i915_gem_context_unreference(ctx); 590a2fdbec6SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 591e555d299SFrançois Tigeot 592e555d299SFrançois Tigeot DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id); 593e555d299SFrançois Tigeot return 0; 594e555d299SFrançois Tigeot } 595