Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright © 2021 Intel Corporation
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         /* Be tolerant of leading/trailing whitespace */
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 );