148 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2021 Intel Corporation4 */5 6#include <linux/kernel.h>7#include <linux/moduleparam.h>8#include <linux/slab.h>9#include <linux/string.h>10 11#include "i915_driver.h"12#include "i915_drv.h"13#include "i915_mitigations.h"14 15static unsigned long mitigations __read_mostly = ~0UL;16 17enum {18 CLEAR_RESIDUALS = 0,19};20 21static const char * const names[] = {22 [CLEAR_RESIDUALS] = "residuals",23};24 25bool i915_mitigate_clear_residuals(void)26{27 return READ_ONCE(mitigations) & BIT(CLEAR_RESIDUALS);28}29 30static int mitigations_set(const char *val, const struct kernel_param *kp)31{32 unsigned long new = ~0UL;33 char *str, *sep, *tok;34 bool first = true;35 int err = 0;36 37 BUILD_BUG_ON(ARRAY_SIZE(names) >= BITS_PER_TYPE(mitigations));38 39 str = kstrdup(val, GFP_KERNEL);40 if (!str)41 return -ENOMEM;42 43 for (sep = str; (tok = strsep(&sep, ","));) {44 bool enable = true;45 int i;46 47 /* Be tolerant of leading/trailing whitespace */48 tok = strim(tok);49 50 if (first) {51 first = false;52 53 if (!strcmp(tok, "auto"))54 continue;55 56 new = 0;57 if (!strcmp(tok, "off"))58 continue;59 }60 61 if (*tok == '!') {62 enable = !enable;63 tok++;64 }65 66 if (!strncmp(tok, "no", 2)) {67 enable = !enable;68 tok += 2;69 }70 71 if (*tok == '\0')72 continue;73 74 for (i = 0; i < ARRAY_SIZE(names); i++) {75 if (!strcmp(tok, names[i])) {76 if (enable)77 new |= BIT(i);78 else79 new &= ~BIT(i);80 break;81 }82 }83 if (i == ARRAY_SIZE(names)) {84 pr_err("Bad \"%s.mitigations=%s\", '%s' is unknown\n",85 DRIVER_NAME, val, tok);86 err = -EINVAL;87 break;88 }89 }90 kfree(str);91 if (err)92 return err;93 94 WRITE_ONCE(mitigations, new);95 return 0;96}97 98static int mitigations_get(char *buffer, const struct kernel_param *kp)99{100 unsigned long local = READ_ONCE(mitigations);101 int count, i;102 bool enable;103 104 if (!local)105 return scnprintf(buffer, PAGE_SIZE, "%s\n", "off");106 107 if (local & BIT(BITS_PER_LONG - 1)) {108 count = scnprintf(buffer, PAGE_SIZE, "%s,", "auto");109 enable = false;110 } else {111 enable = true;112 count = 0;113 }114 115 for (i = 0; i < ARRAY_SIZE(names); i++) {116 if ((local & BIT(i)) != enable)117 continue;118 119 count += scnprintf(buffer + count, PAGE_SIZE - count,120 "%s%s,", enable ? "" : "!", names[i]);121 }122 123 buffer[count - 1] = '\n';124 return count;125}126 127static const struct kernel_param_ops ops = {128 .set = mitigations_set,129 .get = mitigations_get,130};131 132module_param_cb_unsafe(mitigations, &ops, NULL, 0600);133MODULE_PARM_DESC(mitigations,134"Selectively enable security mitigations for all Intel® GPUs in the system.\n"135"\n"136" auto -- enables all mitigations required for the platform [default]\n"137" off -- disables all mitigations\n"138"\n"139"Individual mitigations can be enabled by passing a comma-separated string,\n"140"e.g. mitigations=residuals to enable only clearing residuals or\n"141"mitigations=auto,noresiduals to disable only the clear residual mitigation.\n"142"Either '!' or 'no' may be used to switch from enabling the mitigation to\n"143"disabling it.\n"144"\n"145"Active mitigations for Ivybridge, Baytrail, Haswell:\n"146" residuals -- clear all thread-local registers between contexts"147);148