| @@ -1957,207 +1957,14 @@ static int create_setparam(struct i915_user_extension __user *ext, void *data) · 1956 unmodified lines |
| 1957 | 1957 | return ctx_setparam(arg->fpriv, arg->ctx, &local.param); |
| 1958 | 1958 | } |
| 1959 | 1959 | |
| 1960 | | −static int clone_engines(struct i915_gem_context *dst, |
| 1961 | | − struct i915_gem_context *src) |
| 1960 | +static int invalid_ext(struct i915_user_extension __user *ext, void *data) |
| 1962 | 1961 | { |
| 1963 | | − struct i915_gem_engines *clone, *e; |
| 1964 | | − bool user_engines; |
| 1965 | | − unsigned long n; |
| 1966 | | − |
| 1967 | | − e = __context_engines_await(src, &user_engines); |
| 1968 | | − if (!e) |
| 1969 | | − return -ENOENT; |
| 1970 | | − |
| 1971 | | − clone = alloc_engines(e->num_engines); |
| 1972 | | − if (!clone) |
| 1973 | | − goto err_unlock; |
| 1974 | | − |
| 1975 | | − for (n = 0; n < e->num_engines; n++) { |
| 1976 | | − struct intel_engine_cs *engine; |
| 1977 | | − |
| 1978 | | − if (!e->engines[n]) { |
| 1979 | | − clone->engines[n] = NULL; |
| 1980 | | − continue; |
| 1981 | | − } |
| 1982 | | − engine = e->engines[n]->engine; |
| 1983 | | − |
| 1984 | | − /* |
| 1985 | | − * Virtual engines are singletons; they can only exist |
| 1986 | | − * inside a single context, because they embed their |
| 1987 | | − * HW context... As each virtual context implies a single |
| 1988 | | − * timeline (each engine can only dequeue a single request |
| 1989 | | − * at any time), it would be surprising for two contexts |
| 1990 | | − * to use the same engine. So let's create a copy of |
| 1991 | | − * the virtual engine instead. |
| 1992 | | − */ |
| 1993 | | − if (intel_engine_is_virtual(engine)) |
| 1994 | | − clone->engines[n] = |
| 1995 | | − intel_execlists_clone_virtual(engine); |
| 1996 | | − else |
| 1997 | | − clone->engines[n] = intel_context_create(engine); |
| 1998 | | − if (IS_ERR_OR_NULL(clone->engines[n])) { |
| 1999 | | − __free_engines(clone, n); |
| 2000 | | − goto err_unlock; |
| 2001 | | − } |
| 2002 | | − |
| 2003 | | − intel_context_set_gem(clone->engines[n], dst); |
| 2004 | | − } |
| 2005 | | − clone->num_engines = n; |
| 2006 | | − i915_sw_fence_complete(&e->fence); |
| 2007 | | − |
| 2008 | | − /* Serialised by constructor */ |
| 2009 | | − engines_idle_release(dst, rcu_replace_pointer(dst->engines, clone, 1)); |
| 2010 | | − if (user_engines) |
| 2011 | | − i915_gem_context_set_user_engines(dst); |
| 2012 | | − else |
| 2013 | | − i915_gem_context_clear_user_engines(dst); |
| 2014 | | − return 0; |
| 2015 | | − |
| 2016 | | −err_unlock: |
| 2017 | | − i915_sw_fence_complete(&e->fence); |
| 2018 | | − return -ENOMEM; |
| 2019 | | −} |
| 2020 | | − |
| 2021 | | −static int clone_flags(struct i915_gem_context *dst, |
| 2022 | | − struct i915_gem_context *src) |
| 2023 | | −{ |
| 2024 | | − dst->user_flags = src->user_flags; |
| 2025 | | − return 0; |
| 2026 | | −} |
| 2027 | | − |
| 2028 | | −static int clone_schedattr(struct i915_gem_context *dst, |
| 2029 | | − struct i915_gem_context *src) |
| 2030 | | −{ |
| 2031 | | − dst->sched = src->sched; |
| 2032 | | − return 0; |
| 2033 | | −} |
| 2034 | | − |
| 2035 | | −static int clone_sseu(struct i915_gem_context *dst, |
| 2036 | | − struct i915_gem_context *src) |
| 2037 | | −{ |
| 2038 | | − struct i915_gem_engines *e = i915_gem_context_lock_engines(src); |
| 2039 | | − struct i915_gem_engines *clone; |
| 2040 | | − unsigned long n; |
| 2041 | | − int err; |
| 2042 | | − |
| 2043 | | − /* no locking required; sole access under constructor*/ |
| 2044 | | − clone = __context_engines_static(dst); |
| 2045 | | − if (e->num_engines != clone->num_engines) { |
| 2046 | | − err = -EINVAL; |
| 2047 | | − goto unlock; |
| 2048 | | − } |
| 2049 | | − |
| 2050 | | − for (n = 0; n < e->num_engines; n++) { |
| 2051 | | − struct intel_context *ce = e->engines[n]; |
| 2052 | | − |
| 2053 | | − if (clone->engines[n]->engine->class != ce->engine->class) { |
| 2054 | | − /* Must have compatible engine maps! */ |
| 2055 | | − err = -EINVAL; |
| 2056 | | − goto unlock; |
| 2057 | | − } |
| 2058 | | − |
| 2059 | | − /* serialises with set_sseu */ |
| 2060 | | − err = intel_context_lock_pinned(ce); |
| 2061 | | − if (err) |
| 2062 | | − goto unlock; |
| 2063 | | − |
| 2064 | | − clone->engines[n]->sseu = ce->sseu; |
| 2065 | | − intel_context_unlock_pinned(ce); |
| 2066 | | − } |
| 2067 | | − |
| 2068 | | − err = 0; |
| 2069 | | −unlock: |
| 2070 | | − i915_gem_context_unlock_engines(src); |
| 2071 | | − return err; |
| 2072 | | −} |
| 2073 | | − |
| 2074 | | −static int clone_timeline(struct i915_gem_context *dst, |
| 2075 | | − struct i915_gem_context *src) |
| 2076 | | −{ |
| 2077 | | − if (src->timeline) |
| 2078 | | − __assign_timeline(dst, src->timeline); |
| 2079 | | − |
| 2080 | | − return 0; |
| 2081 | | −} |
| 2082 | | − |
| 2083 | | −static int clone_vm(struct i915_gem_context *dst, |
| 2084 | | − struct i915_gem_context *src) |
| 2085 | | −{ |
| 2086 | | − struct i915_address_space *vm; |
| 2087 | | − int err = 0; |
| 2088 | | − |
| 2089 | | − if (!rcu_access_pointer(src->vm)) |
| 2090 | | − return 0; |
| 2091 | | − |
| 2092 | | − rcu_read_lock(); |
| 2093 | | − vm = context_get_vm_rcu(src); |
| 2094 | | − rcu_read_unlock(); |
| 2095 | | − |
| 2096 | | − if (!mutex_lock_interruptible(&dst->mutex)) { |
| 2097 | | − __assign_ppgtt(dst, vm); |
| 2098 | | − mutex_unlock(&dst->mutex); |
| 2099 | | − } else { |
| 2100 | | − err = -EINTR; |
| 2101 | | − } |
| 2102 | | − |
| 2103 | | − i915_vm_put(vm); |
| 2104 | | − return err; |
| 2105 | | −} |
| 2106 | | − |
| 2107 | | −static int create_clone(struct i915_user_extension __user *ext, void *data) |
| 2108 | | −{ |
| 2109 | | − static int (* const fn[])(struct i915_gem_context *dst, |
| 2110 | | − struct i915_gem_context *src) = { |
| 2111 | | −#define MAP(x, y) [ilog2(I915_CONTEXT_CLONE_##x)] = y |
| 2112 | | − MAP(ENGINES, clone_engines), |
| 2113 | | − MAP(FLAGS, clone_flags), |
| 2114 | | − MAP(SCHEDATTR, clone_schedattr), |
| 2115 | | − MAP(SSEU, clone_sseu), |
| 2116 | | − MAP(TIMELINE, clone_timeline), |
| 2117 | | − MAP(VM, clone_vm), |
| 2118 | | −#undef MAP |
| 2119 | | − }; |
| 2120 | | − struct drm_i915_gem_context_create_ext_clone local; |
| 2121 | | − const struct create_ext *arg = data; |
| 2122 | | − struct i915_gem_context *dst = arg->ctx; |
| 2123 | | − struct i915_gem_context *src; |
| 2124 | | − int err, bit; |
| 2125 | | − |
| 2126 | | − if (copy_from_user(&local, ext, sizeof(local))) |
| 2127 | | − return -EFAULT; |
| 2128 | | − |
| 2129 | | − BUILD_BUG_ON(GENMASK(BITS_PER_TYPE(local.flags) - 1, ARRAY_SIZE(fn)) != |
| 2130 | | − I915_CONTEXT_CLONE_UNKNOWN); |
| 2131 | | − |
| 2132 | | − if (local.flags & I915_CONTEXT_CLONE_UNKNOWN) |
| 2133 | | − return -EINVAL; |
| 2134 | | − |
| 2135 | | − if (local.rsvd) |
| 2136 | | − return -EINVAL; |
| 2137 | | − |
| 2138 | | − rcu_read_lock(); |
| 2139 | | − src = __i915_gem_context_lookup_rcu(arg->fpriv, local.clone_id); |
| 2140 | | − rcu_read_unlock(); |
| 2141 | | − if (!src) |
| 2142 | | − return -ENOENT; |
| 2143 | | − |
| 2144 | | − GEM_BUG_ON(src == dst); |
| 2145 | | − |
| 2146 | | − for (bit = 0; bit < ARRAY_SIZE(fn); bit++) { |
| 2147 | | − if (!(local.flags & BIT(bit))) |
| 2148 | | − continue; |
| 2149 | | − |
| 2150 | | − err = fn[bit](dst, src); |
| 2151 | | − if (err) |
| 2152 | | − return err; |
| 2153 | | − } |
| 2154 | | − |
| 2155 | | − return 0; |
| 1962 | + return -EINVAL; |
| 2156 | 1963 | } |
| 2157 | 1964 | |
| 2158 | 1965 | static const i915_user_extension_fn create_extensions[] = { |
| 2159 | 1966 | [I915_CONTEXT_CREATE_EXT_SETPARAM] = create_setparam, |
| 2160 | | − [I915_CONTEXT_CREATE_EXT_CLONE] = create_clone, |
| 1967 | + [I915_CONTEXT_CREATE_EXT_CLONE] = invalid_ext, |
| 2161 | 1968 | }; |
| 2162 | 1969 | |
| 2163 | 1970 | static bool client_is_banned(struct drm_i915_file_private *file_priv) |