diff mbox

[v3,5/6] drm/i915: Introduce 'priority offset' for GPU contexts (v2)

Message ID 20180306234700.6562-6-matthew.d.roper@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Matt Roper March 6, 2018, 11:46 p.m. UTC
There are cases where a system integrator may wish to raise/lower the
priority of GPU workloads being submitted by specific OS process(es),
independently of how the software self-classifies its own priority.
Exposing "priority offset" as an i915-specific cgroup parameter will
enable such system-level configuration.

Normally GPU contexts start with a priority value of 0
(I915_CONTEXT_DEFAULT_PRIORITY) and then may be adjusted up/down from
there via other mechanisms.  We'd like to provide a system-level input
to the priority decision that will be taken into consideration, even
when userspace later attempts to set an absolute priority value via
I915_CONTEXT_PARAM_PRIORITY.  The priority offset introduced here
provides a base value that will always be added to (or subtracted from)
the software's self-assigned priority value.

This patch makes priority offset a cgroup-specific value; contexts will
be created with a priority offset based on the cgroup membership of the
process creating the context at the time the context is created.  Note
that priority offset is assigned at context creation time; migrating a
process to a different cgroup or changing the offset associated with a
cgroup will only affect new context creation and will not alter the
behavior of existing contexts previously created by the process.

v2:
 - Rebase onto new cgroup_priv API
 - Use current instead of drm_file->pid to determine which process to
   lookup priority for. (Chris)
 - Don't forget to subtract priority offset in context_getparam ioctl to
   make it match setparam behavior. (Chris)

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
 drivers/gpu/drm/i915/i915_cgroup.c      | 47 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h         | 15 ++++++-----
 drivers/gpu/drm/i915/i915_gem_context.c |  7 ++---
 drivers/gpu/drm/i915/i915_gem_context.h |  9 +++++++
 include/uapi/drm/i915_drm.h             |  1 +
 5 files changed, 69 insertions(+), 10 deletions(-)

Comments

Chris Wilson March 8, 2018, 11:32 a.m. UTC | #1
Quoting Matt Roper (2018-03-06 23:46:59)
> There are cases where a system integrator may wish to raise/lower the
> priority of GPU workloads being submitted by specific OS process(es),
> independently of how the software self-classifies its own priority.
> Exposing "priority offset" as an i915-specific cgroup parameter will
> enable such system-level configuration.
> 
> Normally GPU contexts start with a priority value of 0
> (I915_CONTEXT_DEFAULT_PRIORITY) and then may be adjusted up/down from
> there via other mechanisms.  We'd like to provide a system-level input
> to the priority decision that will be taken into consideration, even
> when userspace later attempts to set an absolute priority value via
> I915_CONTEXT_PARAM_PRIORITY.  The priority offset introduced here
> provides a base value that will always be added to (or subtracted from)
> the software's self-assigned priority value.
> 
> This patch makes priority offset a cgroup-specific value; contexts will
> be created with a priority offset based on the cgroup membership of the
> process creating the context at the time the context is created.  Note
> that priority offset is assigned at context creation time; migrating a
> process to a different cgroup or changing the offset associated with a
> cgroup will only affect new context creation and will not alter the
> behavior of existing contexts previously created by the process.
> 
> v2:
>  - Rebase onto new cgroup_priv API
>  - Use current instead of drm_file->pid to determine which process to
>    lookup priority for. (Chris)
>  - Don't forget to subtract priority offset in context_getparam ioctl to
>    make it match setparam behavior. (Chris)
> 
> Signed-off-by: Matt Roper <matthew.d.roper@intel.com>

For ctx->priority/ctx->priority_offset
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

At the end of the day, everything that is modifiable by context is going
to want cgroup constraint, but like priority_offset each will require
some thought as to how to express the constraint.

Interesting conundrum, and still we want a consistent interface for all
the gpus on a system.
-Chris
Chris Wilson March 8, 2018, 1:11 p.m. UTC | #2
Quoting Chris Wilson (2018-03-08 11:32:04)
> Quoting Matt Roper (2018-03-06 23:46:59)
> > There are cases where a system integrator may wish to raise/lower the
> > priority of GPU workloads being submitted by specific OS process(es),
> > independently of how the software self-classifies its own priority.
> > Exposing "priority offset" as an i915-specific cgroup parameter will
> > enable such system-level configuration.
> > 
> > Normally GPU contexts start with a priority value of 0
> > (I915_CONTEXT_DEFAULT_PRIORITY) and then may be adjusted up/down from
> > there via other mechanisms.  We'd like to provide a system-level input
> > to the priority decision that will be taken into consideration, even
> > when userspace later attempts to set an absolute priority value via
> > I915_CONTEXT_PARAM_PRIORITY.  The priority offset introduced here
> > provides a base value that will always be added to (or subtracted from)
> > the software's self-assigned priority value.
> > 
> > This patch makes priority offset a cgroup-specific value; contexts will
> > be created with a priority offset based on the cgroup membership of the
> > process creating the context at the time the context is created.  Note
> > that priority offset is assigned at context creation time; migrating a
> > process to a different cgroup or changing the offset associated with a
> > cgroup will only affect new context creation and will not alter the
> > behavior of existing contexts previously created by the process.
> > 
> > v2:
> >  - Rebase onto new cgroup_priv API
> >  - Use current instead of drm_file->pid to determine which process to
> >    lookup priority for. (Chris)
> >  - Don't forget to subtract priority offset in context_getparam ioctl to
> >    make it match setparam behavior. (Chris)
> > 
> > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> 
> For ctx->priority/ctx->priority_offset
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

As a reminder, we do have the question of how to bound ctx->priority +
ctx->priority_offset. Currently, outside of the user range is privileged
space reserved for the kernel (both above and below). Now we can move
those even further to accommodate multiple non-overlapping cgroups.
We also have the presumption that only privileged processes can raise a
priority, but I presume the cgroup property itself is protected.
-Chris
Matt Roper March 8, 2018, 6:22 p.m. UTC | #3
On Thu, Mar 08, 2018 at 01:11:33PM +0000, Chris Wilson wrote:
> Quoting Chris Wilson (2018-03-08 11:32:04)
> > Quoting Matt Roper (2018-03-06 23:46:59)
> > > There are cases where a system integrator may wish to raise/lower the
> > > priority of GPU workloads being submitted by specific OS process(es),
> > > independently of how the software self-classifies its own priority.
> > > Exposing "priority offset" as an i915-specific cgroup parameter will
> > > enable such system-level configuration.
> > > 
> > > Normally GPU contexts start with a priority value of 0
> > > (I915_CONTEXT_DEFAULT_PRIORITY) and then may be adjusted up/down from
> > > there via other mechanisms.  We'd like to provide a system-level input
> > > to the priority decision that will be taken into consideration, even
> > > when userspace later attempts to set an absolute priority value via
> > > I915_CONTEXT_PARAM_PRIORITY.  The priority offset introduced here
> > > provides a base value that will always be added to (or subtracted from)
> > > the software's self-assigned priority value.
> > > 
> > > This patch makes priority offset a cgroup-specific value; contexts will
> > > be created with a priority offset based on the cgroup membership of the
> > > process creating the context at the time the context is created.  Note
> > > that priority offset is assigned at context creation time; migrating a
> > > process to a different cgroup or changing the offset associated with a
> > > cgroup will only affect new context creation and will not alter the
> > > behavior of existing contexts previously created by the process.
> > > 
> > > v2:
> > >  - Rebase onto new cgroup_priv API
> > >  - Use current instead of drm_file->pid to determine which process to
> > >    lookup priority for. (Chris)
> > >  - Don't forget to subtract priority offset in context_getparam ioctl to
> > >    make it match setparam behavior. (Chris)
> > > 
> > > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> > 
> > For ctx->priority/ctx->priority_offset
> > Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> 
> As a reminder, we do have the question of how to bound ctx->priority +
> ctx->priority_offset. Currently, outside of the user range is privileged
> space reserved for the kernel (both above and below). Now we can move
> those even further to accommodate multiple non-overlapping cgroups.

Yep, I mentioned this as an open question in the series coverletter.

My understanding is that today we limit userspace-assigned priorities to
[1023,1023] and that the kernel can use the userspace range plus -1024
(for the kernel idle context), 1024 (for boosting contexts the display
is waiting on), and INT_MAX (for the preempt context).  Are there any
other special values we use today that I'm overlooking?

I think we have the following options with how to proceed:

 * Option 1:  Silently limit (priority+priority offset) to the existing
   [-1023,1023] range.  That means that if, for example, a user context
   had a priority offset of 600 and tried to manually boost its context
   priority to 600, it would simply be treated as a 1023 for scheduling
   purposes.  This approach is simple, but doesn't allow us to force
   contexts in different cgroups into non-overlapping priority ranges
   (i.e., lowest possible priority in one cgroup is still higher than
   the highest possible priority in another cgroup).  It also isn't
   possible to define a class of applications as "more important than
   display" via cgroup, which I think might be useful in some cases.

 * Option 2:  Allow priority offset to be set in a much larger range
   (e.g., [SHRT_MIN+1023,SHRT_MAX-1023]).  This allows cgroups to have
   effective priority ranges that don't overlap.  cgroup ranges can also
   be intentionally set above I915_PRIORITY_DISPLAY to allow us to
   define classes of applications whose work is more important than
   maintaining a stable framerate on the display.  We'd also probably
   need to shift the kernel idle context down to something like INT_MIN
   instead of using -1024.

 * Option 3: No limits, leave behavior as it stands now in this patch
   series (unrestricted range).  If you're privileged enough to define
   the cgroup settings for a system and you decide to shoot yourself in
   the foot by setting them to nonsense values, that's your own fault.

Thoughts?  Any other options to consider?

> We also have the presumption that only privileged processes can raise a
> priority, but I presume the cgroup property itself is protected.
> -Chris

The way the code is written write now, anyone who has write access to
the cgroup itself (i.e., can migrate processes into/out of the cgroup)
is allowed to adjust the i915-specific cgroup settings.  So this depends
on how the cgroups-v2 filesystem was initially mounted and/or how the
filesystem permissions were adjusted after the fact; the details may
vary from system to system depending on the policy decisions of the
system integrator / system administrator.  But I think an off-the-shelf
Linux distro will only give the system administrator sufficient
permissions to adjust cgroups (if it even mounts the cgroups-v2
filesystem in the first place), so anyone else that winds up with those
privileges has had them intentionally delegated.


Matt
Chris Wilson March 8, 2018, 6:48 p.m. UTC | #4
Quoting Matt Roper (2018-03-08 18:22:06)
> On Thu, Mar 08, 2018 at 01:11:33PM +0000, Chris Wilson wrote:
> > Quoting Chris Wilson (2018-03-08 11:32:04)
> > > Quoting Matt Roper (2018-03-06 23:46:59)
> > > > There are cases where a system integrator may wish to raise/lower the
> > > > priority of GPU workloads being submitted by specific OS process(es),
> > > > independently of how the software self-classifies its own priority.
> > > > Exposing "priority offset" as an i915-specific cgroup parameter will
> > > > enable such system-level configuration.
> > > > 
> > > > Normally GPU contexts start with a priority value of 0
> > > > (I915_CONTEXT_DEFAULT_PRIORITY) and then may be adjusted up/down from
> > > > there via other mechanisms.  We'd like to provide a system-level input
> > > > to the priority decision that will be taken into consideration, even
> > > > when userspace later attempts to set an absolute priority value via
> > > > I915_CONTEXT_PARAM_PRIORITY.  The priority offset introduced here
> > > > provides a base value that will always be added to (or subtracted from)
> > > > the software's self-assigned priority value.
> > > > 
> > > > This patch makes priority offset a cgroup-specific value; contexts will
> > > > be created with a priority offset based on the cgroup membership of the
> > > > process creating the context at the time the context is created.  Note
> > > > that priority offset is assigned at context creation time; migrating a
> > > > process to a different cgroup or changing the offset associated with a
> > > > cgroup will only affect new context creation and will not alter the
> > > > behavior of existing contexts previously created by the process.
> > > > 
> > > > v2:
> > > >  - Rebase onto new cgroup_priv API
> > > >  - Use current instead of drm_file->pid to determine which process to
> > > >    lookup priority for. (Chris)
> > > >  - Don't forget to subtract priority offset in context_getparam ioctl to
> > > >    make it match setparam behavior. (Chris)
> > > > 
> > > > Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> > > 
> > > For ctx->priority/ctx->priority_offset
> > > Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> > 
> > As a reminder, we do have the question of how to bound ctx->priority +
> > ctx->priority_offset. Currently, outside of the user range is privileged
> > space reserved for the kernel (both above and below). Now we can move
> > those even further to accommodate multiple non-overlapping cgroups.
> 
> Yep, I mentioned this as an open question in the series coverletter.
> 
> My understanding is that today we limit userspace-assigned priorities to
> [1023,1023] and that the kernel can use the userspace range plus -1024
> (for the kernel idle context), 1024 (for boosting contexts the display
> is waiting on), and INT_MAX (for the preempt context).  Are there any
> other special values we use today that I'm overlooking?
> 
> I think we have the following options with how to proceed:
> 
>  * Option 1:  Silently limit (priority+priority offset) to the existing
>    [-1023,1023] range.  That means that if, for example, a user context
>    had a priority offset of 600 and tried to manually boost its context
>    priority to 600, it would simply be treated as a 1023 for scheduling
>    purposes.  This approach is simple, but doesn't allow us to force
>    contexts in different cgroups into non-overlapping priority ranges
>    (i.e., lowest possible priority in one cgroup is still higher than
>    the highest possible priority in another cgroup).  It also isn't
>    possible to define a class of applications as "more important than
>    display" via cgroup, which I think might be useful in some cases.

Agreed, non-overlapping seems to be a useful property (apply the usual
disclaimer for the rudimentary scheduler).

>  * Option 2:  Allow priority offset to be set in a much larger range
>    (e.g., [SHRT_MIN+1023,SHRT_MAX-1023]).  This allows cgroups to have
>    effective priority ranges that don't overlap.  cgroup ranges can also
>    be intentionally set above I915_PRIORITY_DISPLAY to allow us to
>    define classes of applications whose work is more important than
>    maintaining a stable framerate on the display.  We'd also probably
>    need to shift the kernel idle context down to something like INT_MIN
>    instead of using -1024.

INT_MIN+1 just to be awkward. (INT_MIN is I915_PRIORITY_INVALID.)

Something to bear in mind is that I want to reserve the low 8 bits of
ctx->priority for internal use (heuristic adjustments by the scheduler).
Can shrink that to say 3 bits in the current scheme.

3bits for internal adjustment
20bits for user priority.
8bits for cgroup offset.
signbit.

Nothing prohibits us from moving to 64b if required. But 32b should be
enough range for plenty of clients and cgroups, imo. Reducing cgroup
offset to 6 bits would be nice :)

>  * Option 3: No limits, leave behavior as it stands now in this patch
>    series (unrestricted range).  If you're privileged enough to define
>    the cgroup settings for a system and you decide to shoot yourself in
>    the foot by setting them to nonsense values, that's your own fault.

Overflow have a habit of catching us out, so I'd like to rule that out.
And once we define a suitable range, it's hard to reduce it without
userspace noticing and screaming regression.

> Thoughts?  Any other options to consider?

Another option would be to say keep a plist for each cgroup and
round-robin between cgroups (or somesuch, or just a plist of cgroups to
keep things priority based). Down that road lies CFS with fairness inside
cgroups and between cgroups.

> > We also have the presumption that only privileged processes can raise a
> > priority, but I presume the cgroup property itself is protected.
> 
> The way the code is written write now, anyone who has write access to
> the cgroup itself (i.e., can migrate processes into/out of the cgroup)
> is allowed to adjust the i915-specific cgroup settings.  So this depends
> on how the cgroups-v2 filesystem was initially mounted and/or how the
> filesystem permissions were adjusted after the fact; the details may
> vary from system to system depending on the policy decisions of the
> system integrator / system administrator.  But I think an off-the-shelf
> Linux distro will only give the system administrator sufficient
> permissions to adjust cgroups (if it even mounts the cgroups-v2
> filesystem in the first place), so anyone else that winds up with those
> privileges has had them intentionally delegated.

Ok. I just worry about how easy it is to starve the system and
accidentally DoS oneself. :)
-Chris
Chris Wilson March 8, 2018, 6:55 p.m. UTC | #5
Quoting Chris Wilson (2018-03-08 18:48:51)
> Quoting Matt Roper (2018-03-08 18:22:06)
> >  * Option 2:  Allow priority offset to be set in a much larger range
> >    (e.g., [SHRT_MIN+1023,SHRT_MAX-1023]).  This allows cgroups to have
> >    effective priority ranges that don't overlap.  cgroup ranges can also
> >    be intentionally set above I915_PRIORITY_DISPLAY to allow us to
> >    define classes of applications whose work is more important than
> >    maintaining a stable framerate on the display.  We'd also probably
> >    need to shift the kernel idle context down to something like INT_MIN
> >    instead of using -1024.
> 
> INT_MIN+1 just to be awkward. (INT_MIN is I915_PRIORITY_INVALID.)
> 
> Something to bear in mind is that I want to reserve the low 8 bits of
> ctx->priority for internal use (heuristic adjustments by the scheduler).
> Can shrink that to say 3 bits in the current scheme.
> 
> 3bits for internal adjustment
> 20bits for user priority.
> 8bits for cgroup offset.
> signbit.
> 
> Nothing prohibits us from moving to 64b if required. But 32b should be
> enough range for plenty of clients and cgroups, imo. Reducing cgroup
> offset to 6 bits would be nice :)

Forgot to comment on the policy decision of I915_PRIORITY_DISPLAY.
It's naughty that it's a magic constant that isn't exposed to the
sysadmin, so I would still set it to the maximum priority possible under
the extended scheme (i.e. INT_MAX), but allow for it to be adjusted.
I915_SETPARAM *shivers* Maybe that's a topic for cgroup as well if we can
associate the pageflip with a process and find its interactivity settings.

Can I expose just about any random policy decision through cgroup?
-Chris
Matt Roper March 8, 2018, 7:31 p.m. UTC | #6
On Thu, Mar 08, 2018 at 06:55:34PM +0000, Chris Wilson wrote:
> Quoting Chris Wilson (2018-03-08 18:48:51)
> > Quoting Matt Roper (2018-03-08 18:22:06)
> > >  * Option 2:  Allow priority offset to be set in a much larger range
> > >    (e.g., [SHRT_MIN+1023,SHRT_MAX-1023]).  This allows cgroups to have
> > >    effective priority ranges that don't overlap.  cgroup ranges can also
> > >    be intentionally set above I915_PRIORITY_DISPLAY to allow us to
> > >    define classes of applications whose work is more important than
> > >    maintaining a stable framerate on the display.  We'd also probably
> > >    need to shift the kernel idle context down to something like INT_MIN
> > >    instead of using -1024.
> > 
> > INT_MIN+1 just to be awkward. (INT_MIN is I915_PRIORITY_INVALID.)
> > 
> > Something to bear in mind is that I want to reserve the low 8 bits of
> > ctx->priority for internal use (heuristic adjustments by the scheduler).
> > Can shrink that to say 3 bits in the current scheme.
> > 
> > 3bits for internal adjustment
> > 20bits for user priority.
> > 8bits for cgroup offset.
> > signbit.
> > 
> > Nothing prohibits us from moving to 64b if required. But 32b should be
> > enough range for plenty of clients and cgroups, imo. Reducing cgroup
> > offset to 6 bits would be nice :)
> 
> Forgot to comment on the policy decision of I915_PRIORITY_DISPLAY.
> It's naughty that it's a magic constant that isn't exposed to the
> sysadmin, so I would still set it to the maximum priority possible under
> the extended scheme (i.e. INT_MAX), but allow for it to be adjusted.
> I915_SETPARAM *shivers* Maybe that's a topic for cgroup as well if we can
> associate the pageflip with a process and find its interactivity settings.
> 
> Can I expose just about any random policy decision through cgroup?
> -Chris

If the policy applies to a cgroup of processes, then we can deal with
pretty much any kind of policy as long as we stick to the driver ioctl
approach in this series.  E.g., we could add a cgroup setting "eligible
for display boost" so that only specific processes are eligible for a
display boost.

If we want to control a single overall system value (e.g., "set the
display boost fixed value") we could technically do that by having such
parameters set on the v2 hierarchy's root cgroup, but that seems a bit
counterintuitive and I'm not sure if there's a benefit to doing so.
Using a more general interface like I915_SETPARAM or sysfs or something
seems more appropriate in that case.


Matt
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_cgroup.c b/drivers/gpu/drm/i915/i915_cgroup.c
index 4a46cb167f53..6a28b1a23971 100644
--- a/drivers/gpu/drm/i915/i915_cgroup.c
+++ b/drivers/gpu/drm/i915/i915_cgroup.c
@@ -13,6 +13,8 @@  struct i915_cgroup_data {
 	struct cgroup_priv base;
 
 	struct list_head node;
+
+	int priority_offset;
 };
 
 static inline struct i915_cgroup_data *
@@ -117,8 +119,10 @@  i915_cgroup_setparam_ioctl(struct drm_device *dev,
 			   void *data,
 			   struct drm_file *file)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_cgroup_param *req = data;
 	struct cgroup *cgrp;
+	struct i915_cgroup_data *cgrpdata;
 	int ret;
 
 	/* We don't actually support any flags yet. */
@@ -154,7 +158,18 @@  i915_cgroup_setparam_ioctl(struct drm_device *dev,
 	if (ret)
 		goto out;
 
+	cgrpdata = get_or_create_cgroup_data(dev_priv, cgrp);
+	if (IS_ERR(cgrpdata)) {
+		ret = PTR_ERR(cgrpdata);
+		goto out;
+	}
+
 	switch (req->param) {
+	case I915_CGROUP_PARAM_PRIORITY_OFFSET:
+		DRM_DEBUG_DRIVER("Setting cgroup priority offset to %lld\n",
+				 req->value);
+		cgrpdata->priority_offset = req->value;
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Invalid cgroup parameter %lld\n", req->param);
 		ret = -EINVAL;
@@ -165,3 +180,35 @@  i915_cgroup_setparam_ioctl(struct drm_device *dev,
 
 	return ret;
 }
+
+/**
+ * i915_cgroup_get_prio_offset() - get prio offset for current proc's cgroup
+ * @dev_priv: drm device
+ * @file_priv: file handle for calling process
+ *
+ * RETURNS:
+ * Priority offset associated with the calling process' cgroup in the default
+ * (v2) hierarchy, otherwise 0 if no explicit priority has been assigned.
+ */
+int
+i915_cgroup_get_current_prio_offset(struct drm_i915_private *dev_priv)
+{
+       struct cgroup *cgrp;
+       struct cgroup_priv *cgrpdata;
+       int offset = 0;
+
+       cgrp = task_get_dfl_cgroup(current);
+       if (WARN_ON(!cgrp))
+               return 0;
+
+       mutex_lock(&cgrp->privdata_mutex);
+
+       cgrpdata = cgroup_priv_lookup(cgrp, dev_priv);
+       if (cgrpdata)
+	       offset = cgrp_to_i915(cgrpdata)->priority_offset;
+
+       mutex_unlock(&cgrp->privdata_mutex);
+       cgroup_put(cgrp);
+
+       return offset;
+}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7c38142ee009..51b80926d20c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2947,18 +2947,19 @@  void i915_cgroup_init(struct drm_i915_private *dev_priv);
 int i915_cgroup_setparam_ioctl(struct drm_device *dev, void *data,
 			       struct drm_file *file);
 void i915_cgroup_shutdown(struct drm_i915_private *dev_priv);
+int i915_cgroup_get_current_prio_offset(struct drm_i915_private *dev_priv);
 #else
-static inline int
-i915_cgroup_init(struct drm_i915_private *dev_priv)
+static inline void i915_cgroup_init(struct drm_i915_private *dev_priv) {}
+static inline void i915_cgroup_shutdown(struct drm_i915_private *dev_priv) {}
+static inline int i915_cgroup_setparam_ioctl(struct drm_device *dev, void *data,
+					     struct drm_file *file)
 {
-	return 0;
+	return -EINVAL;
 }
-static inline void i915_cgroup_shutdown(struct drm_i915_private *dev_priv) {}
 static inline int
-i915_cgroup_setparam_ioctl(struct drm_device *dev, void *data,
-			   struct drm_file *file)
+i915_cgroup_get_current_prio_offset(struct drm_i915_private *dev_priv)
 {
-	return -EINVAL;
+	return 0;
 }
 #endif
 
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index a73340ae9419..b29fbe0c776f 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -274,7 +274,8 @@  __create_hw_context(struct drm_i915_private *dev_priv,
 	kref_init(&ctx->ref);
 	list_add_tail(&ctx->link, &dev_priv->contexts.list);
 	ctx->i915 = dev_priv;
-	ctx->priority = I915_PRIORITY_NORMAL;
+	ctx->priority_offset = i915_cgroup_get_current_prio_offset(dev_priv);
+	ctx->priority = I915_PRIORITY_NORMAL + ctx->priority_offset;
 
 	INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
 	INIT_LIST_HEAD(&ctx->handles_list);
@@ -739,7 +740,7 @@  int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
 		args->value = i915_gem_context_is_bannable(ctx);
 		break;
 	case I915_CONTEXT_PARAM_PRIORITY:
-		args->value = ctx->priority;
+		args->value = ctx->priority - ctx->priority_offset;
 		break;
 	default:
 		ret = -EINVAL;
@@ -812,7 +813,7 @@  int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
 				 !capable(CAP_SYS_NICE))
 				ret = -EPERM;
 			else
-				ctx->priority = priority;
+				ctx->priority = priority + ctx->priority_offset;
 		}
 		break;
 
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h
index 7854262ddfd9..c3b4fb54fbb6 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -150,6 +150,15 @@  struct i915_gem_context {
 	 */
 	int priority;
 
+	/**
+	 * @priority_offset: priority offset
+	 *
+	 * A value, configured via cgroup, that sets the starting priority
+	 * of the context.  Any priority set explicitly via context parameter
+	 * will be added to the priority offset.
+	 */
+	int priority_offset;
+
 	/** ggtt_offset_bias: placement restriction for context objects */
 	u32 ggtt_offset_bias;
 
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index b6651b263838..5b67aaf8a1c0 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1624,6 +1624,7 @@  struct drm_i915_cgroup_param {
 	__s32 cgroup_fd;
 	__u32 flags;
 	__u64 param;
+#define I915_CGROUP_PARAM_PRIORITY_OFFSET	0x1
 	__s64 value;
 };