0001
0002
0003
0004
0005
0006 #include <linux/kernel.h>
0007 #include <linux/moduleparam.h>
0008 #include <linux/slab.h>
0009 #include <linux/string.h>
0010
0011 #include "i915_driver.h"
0012 #include "i915_drv.h"
0013 #include "i915_mitigations.h"
0014
0015 static unsigned long mitigations __read_mostly = ~0UL;
0016
0017 enum {
0018 CLEAR_RESIDUALS = 0,
0019 };
0020
0021 static const char * const names[] = {
0022 [CLEAR_RESIDUALS] = "residuals",
0023 };
0024
0025 bool i915_mitigate_clear_residuals(void)
0026 {
0027 return READ_ONCE(mitigations) & BIT(CLEAR_RESIDUALS);
0028 }
0029
0030 static int mitigations_set(const char *val, const struct kernel_param *kp)
0031 {
0032 unsigned long new = ~0UL;
0033 char *str, *sep, *tok;
0034 bool first = true;
0035 int err = 0;
0036
0037 BUILD_BUG_ON(ARRAY_SIZE(names) >= BITS_PER_TYPE(mitigations));
0038
0039 str = kstrdup(val, GFP_KERNEL);
0040 if (!str)
0041 return -ENOMEM;
0042
0043 for (sep = str; (tok = strsep(&sep, ","));) {
0044 bool enable = true;
0045 int i;
0046
0047
0048 tok = strim(tok);
0049
0050 if (first) {
0051 first = false;
0052
0053 if (!strcmp(tok, "auto"))
0054 continue;
0055
0056 new = 0;
0057 if (!strcmp(tok, "off"))
0058 continue;
0059 }
0060
0061 if (*tok == '!') {
0062 enable = !enable;
0063 tok++;
0064 }
0065
0066 if (!strncmp(tok, "no", 2)) {
0067 enable = !enable;
0068 tok += 2;
0069 }
0070
0071 if (*tok == '\0')
0072 continue;
0073
0074 for (i = 0; i < ARRAY_SIZE(names); i++) {
0075 if (!strcmp(tok, names[i])) {
0076 if (enable)
0077 new |= BIT(i);
0078 else
0079 new &= ~BIT(i);
0080 break;
0081 }
0082 }
0083 if (i == ARRAY_SIZE(names)) {
0084 pr_err("Bad \"%s.mitigations=%s\", '%s' is unknown\n",
0085 DRIVER_NAME, val, tok);
0086 err = -EINVAL;
0087 break;
0088 }
0089 }
0090 kfree(str);
0091 if (err)
0092 return err;
0093
0094 WRITE_ONCE(mitigations, new);
0095 return 0;
0096 }
0097
0098 static int mitigations_get(char *buffer, const struct kernel_param *kp)
0099 {
0100 unsigned long local = READ_ONCE(mitigations);
0101 int count, i;
0102 bool enable;
0103
0104 if (!local)
0105 return scnprintf(buffer, PAGE_SIZE, "%s\n", "off");
0106
0107 if (local & BIT(BITS_PER_LONG - 1)) {
0108 count = scnprintf(buffer, PAGE_SIZE, "%s,", "auto");
0109 enable = false;
0110 } else {
0111 enable = true;
0112 count = 0;
0113 }
0114
0115 for (i = 0; i < ARRAY_SIZE(names); i++) {
0116 if ((local & BIT(i)) != enable)
0117 continue;
0118
0119 count += scnprintf(buffer + count, PAGE_SIZE - count,
0120 "%s%s,", enable ? "" : "!", names[i]);
0121 }
0122
0123 buffer[count - 1] = '\n';
0124 return count;
0125 }
0126
0127 static const struct kernel_param_ops ops = {
0128 .set = mitigations_set,
0129 .get = mitigations_get,
0130 };
0131
0132 module_param_cb_unsafe(mitigations, &ops, NULL, 0600);
0133 MODULE_PARM_DESC(mitigations,
0134 "Selectively enable security mitigations for all Intel® GPUs in the system.\n"
0135 "\n"
0136 " auto -- enables all mitigations required for the platform [default]\n"
0137 " off -- disables all mitigations\n"
0138 "\n"
0139 "Individual mitigations can be enabled by passing a comma-separated string,\n"
0140 "e.g. mitigations=residuals to enable only clearing residuals or\n"
0141 "mitigations=auto,noresiduals to disable only the clear residual mitigation.\n"
0142 "Either '!' or 'no' may be used to switch from enabling the mitigation to\n"
0143 "disabling it.\n"
0144 "\n"
0145 "Active mitigations for Ivybridge, Baytrail, Haswell:\n"
0146 " residuals -- clear all thread-local registers between contexts"
0147 );