Commit f7452c7c authored by Chris Wilson's avatar Chris Wilson

drm/i915: Allow the sysadmin to override security mitigations

The clear-residuals mitigation is a relatively heavy hammer and under some
circumstances the user may wish to forgo the context isolation in order
to meet some performance requirement. Introduce a generic module
parameter to allow selectively enabling/disabling different mitigations.

To disable just the clear-residuals mitigation (on Ivybridge, Baytrail,
or Haswell) use the module parameter: i915.mitigations=auto,!residuals

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/1858
Fixes: 47f8253d ("drm/i915/gen7: Clear all EU/L3 residual contexts")
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Jon Bloomfield <jon.bloomfield@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: stable@vger.kernel.org # v5.7
Reviewed-by: default avatarJon Bloomfield <jon.bloomfield@intel.com>
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210111225220.3483-3-chris@chris-wilson.co.uk
parent 008ead6e
...@@ -38,6 +38,7 @@ i915-y += i915_drv.o \ ...@@ -38,6 +38,7 @@ i915-y += i915_drv.o \
i915_config.o \ i915_config.o \
i915_irq.o \ i915_irq.o \
i915_getparam.o \ i915_getparam.o \
i915_mitigations.o \
i915_params.o \ i915_params.o \
i915_pci.o \ i915_pci.o \
i915_scatterlist.o \ i915_scatterlist.o \
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "gen6_ppgtt.h" #include "gen6_ppgtt.h"
#include "gen7_renderclear.h" #include "gen7_renderclear.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_mitigations.h"
#include "intel_breadcrumbs.h" #include "intel_breadcrumbs.h"
#include "intel_context.h" #include "intel_context.h"
#include "intel_gt.h" #include "intel_gt.h"
...@@ -918,7 +919,8 @@ static int switch_context(struct i915_request *rq) ...@@ -918,7 +919,8 @@ static int switch_context(struct i915_request *rq)
GEM_BUG_ON(HAS_EXECLISTS(engine->i915)); GEM_BUG_ON(HAS_EXECLISTS(engine->i915));
if (engine->wa_ctx.vma && ce != engine->kernel_context) { if (engine->wa_ctx.vma && ce != engine->kernel_context) {
if (engine->wa_ctx.vma->private != ce) { if (engine->wa_ctx.vma->private != ce &&
i915_mitigate_clear_residuals()) {
ret = clear_residuals(rq); ret = clear_residuals(rq);
if (ret) if (ret)
return ret; return ret;
......
// SPDX-License-Identifier: MIT
/*
* Copyright © 2021 Intel Corporation
*/
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/string.h>
#include "i915_drv.h"
#include "i915_mitigations.h"
static unsigned long mitigations __read_mostly = ~0UL;
enum {
CLEAR_RESIDUALS = 0,
};
static const char * const names[] = {
[CLEAR_RESIDUALS] = "residuals",
};
bool i915_mitigate_clear_residuals(void)
{
return READ_ONCE(mitigations) & BIT(CLEAR_RESIDUALS);
}
static int mitigations_set(const char *val, const struct kernel_param *kp)
{
unsigned long new = ~0UL;
char *str, *sep, *tok;
bool first = true;
int err = 0;
BUILD_BUG_ON(ARRAY_SIZE(names) >= BITS_PER_TYPE(mitigations));
str = kstrdup(val, GFP_KERNEL);
if (!str)
return -ENOMEM;
for (sep = str; (tok = strsep(&sep, ","));) {
bool enable = true;
int i;
/* Be tolerant of leading/trailing whitespace */
tok = strim(tok);
if (first) {
first = false;
if (!strcmp(tok, "auto"))
continue;
new = 0;
if (!strcmp(tok, "off"))
continue;
}
if (*tok == '!') {
enable = !enable;
tok++;
}
if (!strncmp(tok, "no", 2)) {
enable = !enable;
tok += 2;
}
if (*tok == '\0')
continue;
for (i = 0; i < ARRAY_SIZE(names); i++) {
if (!strcmp(tok, names[i])) {
if (enable)
new |= BIT(i);
else
new &= ~BIT(i);
break;
}
}
if (i == ARRAY_SIZE(names)) {
pr_err("Bad \"%s.mitigations=%s\", '%s' is unknown\n",
DRIVER_NAME, val, tok);
err = -EINVAL;
break;
}
}
kfree(str);
if (err)
return err;
WRITE_ONCE(mitigations, new);
return 0;
}
static int mitigations_get(char *buffer, const struct kernel_param *kp)
{
unsigned long local = READ_ONCE(mitigations);
int count, i;
bool enable;
if (!local)
return scnprintf(buffer, PAGE_SIZE, "%s\n", "off");
if (local & BIT(BITS_PER_LONG - 1)) {
count = scnprintf(buffer, PAGE_SIZE, "%s,", "auto");
enable = false;
} else {
enable = true;
count = 0;
}
for (i = 0; i < ARRAY_SIZE(names); i++) {
if ((local & BIT(i)) != enable)
continue;
count += scnprintf(buffer + count, PAGE_SIZE - count,
"%s%s,", enable ? "" : "!", names[i]);
}
buffer[count - 1] = '\n';
return count;
}
static const struct kernel_param_ops ops = {
.set = mitigations_set,
.get = mitigations_get,
};
module_param_cb_unsafe(mitigations, &ops, NULL, 0600);
MODULE_PARM_DESC(mitigations,
"Selectively enable security mitigations for all Intel® GPUs in the system.\n"
"\n"
" auto -- enables all mitigations required for the platform [default]\n"
" off -- disables all mitigations\n"
"\n"
"Individual mitigations can be enabled by passing a comma-separated string,\n"
"e.g. mitigations=residuals to enable only clearing residuals or\n"
"mitigations=auto,noresiduals to disable only the clear residual mitigation.\n"
"Either '!' or 'no' may be used to switch from enabling the mitigation to\n"
"disabling it.\n"
"\n"
"Active mitigations for Ivybridge, Baytrail, Haswell:\n"
" residuals -- clear all thread-local registers between contexts"
);
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2021 Intel Corporation
*/
#ifndef __I915_MITIGATIONS_H__
#define __I915_MITIGATIONS_H__
#include <linux/types.h>
bool i915_mitigate_clear_residuals(void);
#endif /* __I915_MITIGATIONS_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment