1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright © 2012 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker *
4*d83cc019SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker *
11*d83cc019SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker * Software.
14*d83cc019SAndroid Build Coastguard Worker *
15*d83cc019SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker *
23*d83cc019SAndroid Build Coastguard Worker * Authors:
24*d83cc019SAndroid Build Coastguard Worker * Ben Widawsky <[email protected]>
25*d83cc019SAndroid Build Coastguard Worker *
26*d83cc019SAndroid Build Coastguard Worker */
27*d83cc019SAndroid Build Coastguard Worker
28*d83cc019SAndroid Build Coastguard Worker #include <sys/types.h>
29*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
30*d83cc019SAndroid Build Coastguard Worker #include <assert.h>
31*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
32*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
33*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
34*d83cc019SAndroid Build Coastguard Worker #include <string.h>
35*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
36*d83cc019SAndroid Build Coastguard Worker #include <getopt.h>
37*d83cc019SAndroid Build Coastguard Worker #include "intel_chipset.h"
38*d83cc019SAndroid Build Coastguard Worker #include "intel_io.h"
39*d83cc019SAndroid Build Coastguard Worker #include "igt_sysfs.h"
40*d83cc019SAndroid Build Coastguard Worker #include "drmtest.h"
41*d83cc019SAndroid Build Coastguard Worker #include "config.h"
42*d83cc019SAndroid Build Coastguard Worker #include <libudev.h>
43*d83cc019SAndroid Build Coastguard Worker #include <syslog.h>
44*d83cc019SAndroid Build Coastguard Worker #include "intel_l3_parity.h"
45*d83cc019SAndroid Build Coastguard Worker
46*d83cc019SAndroid Build Coastguard Worker static unsigned int devid;
47*d83cc019SAndroid Build Coastguard Worker /* L3 size is always a function of banks. The number of banks cannot be
48*d83cc019SAndroid Build Coastguard Worker * determined by number of slices however */
num_banks(void)49*d83cc019SAndroid Build Coastguard Worker static inline int num_banks(void) {
50*d83cc019SAndroid Build Coastguard Worker switch (intel_gt(devid)) {
51*d83cc019SAndroid Build Coastguard Worker case 2: return 8;
52*d83cc019SAndroid Build Coastguard Worker case 1: return 4;
53*d83cc019SAndroid Build Coastguard Worker default: return 2;
54*d83cc019SAndroid Build Coastguard Worker }
55*d83cc019SAndroid Build Coastguard Worker }
56*d83cc019SAndroid Build Coastguard Worker #define NUM_SUBBANKS 8
57*d83cc019SAndroid Build Coastguard Worker #define BYTES_PER_BANK (128 << 10)
58*d83cc019SAndroid Build Coastguard Worker /* Each row addresses [up to] 4b. This multiplied by the number of subbanks
59*d83cc019SAndroid Build Coastguard Worker * will give the L3 size per bank.
60*d83cc019SAndroid Build Coastguard Worker * TODO: Row size is fixed on IVB, and variable on HSW.*/
61*d83cc019SAndroid Build Coastguard Worker #define MAX_ROW (1<<12)
62*d83cc019SAndroid Build Coastguard Worker #define MAX_BANKS_PER_SLICE 4
63*d83cc019SAndroid Build Coastguard Worker #define NUM_REGS (MAX_BANKS_PER_SLICE * NUM_SUBBANKS)
64*d83cc019SAndroid Build Coastguard Worker #define MAX_SLICES (intel_gt(devid) > 1 ? 2 : 1)
65*d83cc019SAndroid Build Coastguard Worker #define REAL_MAX_SLICES 2
66*d83cc019SAndroid Build Coastguard Worker /* TODO support SLM config */
67*d83cc019SAndroid Build Coastguard Worker #define L3_SIZE ((MAX_ROW * 4) * NUM_SUBBANKS * num_banks())
68*d83cc019SAndroid Build Coastguard Worker
69*d83cc019SAndroid Build Coastguard Worker struct __attribute__ ((__packed__)) l3_log_register {
70*d83cc019SAndroid Build Coastguard Worker uint32_t row0_enable : 1;
71*d83cc019SAndroid Build Coastguard Worker uint32_t rsvd2 : 4;
72*d83cc019SAndroid Build Coastguard Worker uint32_t row0 : 11;
73*d83cc019SAndroid Build Coastguard Worker uint32_t row1_enable : 1;
74*d83cc019SAndroid Build Coastguard Worker uint32_t rsvd1 : 4;
75*d83cc019SAndroid Build Coastguard Worker uint32_t row1 : 11;
76*d83cc019SAndroid Build Coastguard Worker } l3logs[REAL_MAX_SLICES][MAX_BANKS_PER_SLICE][NUM_SUBBANKS];
77*d83cc019SAndroid Build Coastguard Worker
78*d83cc019SAndroid Build Coastguard Worker static int which_slice = -1;
79*d83cc019SAndroid Build Coastguard Worker #define for_each_slice(__i) \
80*d83cc019SAndroid Build Coastguard Worker for ((__i) = (which_slice == -1) ? 0 : which_slice; \
81*d83cc019SAndroid Build Coastguard Worker (__i) < ((which_slice == -1) ? MAX_SLICES : (which_slice + 1)); \
82*d83cc019SAndroid Build Coastguard Worker (__i)++)
83*d83cc019SAndroid Build Coastguard Worker
decode_dft(uint32_t dft)84*d83cc019SAndroid Build Coastguard Worker static void decode_dft(uint32_t dft)
85*d83cc019SAndroid Build Coastguard Worker {
86*d83cc019SAndroid Build Coastguard Worker if (IS_IVYBRIDGE(devid) || !(dft & 1)) {
87*d83cc019SAndroid Build Coastguard Worker printf("Error injection disabled\n");
88*d83cc019SAndroid Build Coastguard Worker return;
89*d83cc019SAndroid Build Coastguard Worker }
90*d83cc019SAndroid Build Coastguard Worker printf("Error injection enabled\n");
91*d83cc019SAndroid Build Coastguard Worker printf(" Hang = %s\n", (dft >> 28) & 0x1 ? "yes" : "no");
92*d83cc019SAndroid Build Coastguard Worker printf(" Row = %d\n", (dft >> 7) & 0x7ff);
93*d83cc019SAndroid Build Coastguard Worker printf(" Bank = %d\n", (dft >> 2) & 0x3);
94*d83cc019SAndroid Build Coastguard Worker printf(" Subbank = %d\n", (dft >> 4) & 0x7);
95*d83cc019SAndroid Build Coastguard Worker printf(" Slice = %d\n", (dft >> 1) & 0x1);
96*d83cc019SAndroid Build Coastguard Worker }
97*d83cc019SAndroid Build Coastguard Worker
dumpit(int slice)98*d83cc019SAndroid Build Coastguard Worker static void dumpit(int slice)
99*d83cc019SAndroid Build Coastguard Worker {
100*d83cc019SAndroid Build Coastguard Worker int i, j;
101*d83cc019SAndroid Build Coastguard Worker
102*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < MAX_BANKS_PER_SLICE; i++) {
103*d83cc019SAndroid Build Coastguard Worker for (j = 0; j < NUM_SUBBANKS; j++) {
104*d83cc019SAndroid Build Coastguard Worker struct l3_log_register *reg = &l3logs[slice][i][j];
105*d83cc019SAndroid Build Coastguard Worker
106*d83cc019SAndroid Build Coastguard Worker if (reg->row0_enable)
107*d83cc019SAndroid Build Coastguard Worker printf("Slice %d, Row %d, Bank %d, Subbank %d is disabled\n",
108*d83cc019SAndroid Build Coastguard Worker slice, reg->row0, i, j);
109*d83cc019SAndroid Build Coastguard Worker if (reg->row1_enable)
110*d83cc019SAndroid Build Coastguard Worker printf("Slice %d, Row %d, Bank %d, Subbank %d is disabled\n",
111*d83cc019SAndroid Build Coastguard Worker slice, reg->row1, i, j);
112*d83cc019SAndroid Build Coastguard Worker }
113*d83cc019SAndroid Build Coastguard Worker }
114*d83cc019SAndroid Build Coastguard Worker }
115*d83cc019SAndroid Build Coastguard Worker
disable_rbs(int row,int bank,int sbank,int slice)116*d83cc019SAndroid Build Coastguard Worker static int disable_rbs(int row, int bank, int sbank, int slice)
117*d83cc019SAndroid Build Coastguard Worker {
118*d83cc019SAndroid Build Coastguard Worker struct l3_log_register *reg = &l3logs[slice][bank][sbank];
119*d83cc019SAndroid Build Coastguard Worker
120*d83cc019SAndroid Build Coastguard Worker // can't map more than 2 rows
121*d83cc019SAndroid Build Coastguard Worker if (reg->row0_enable && reg->row1_enable)
122*d83cc019SAndroid Build Coastguard Worker return -1;
123*d83cc019SAndroid Build Coastguard Worker
124*d83cc019SAndroid Build Coastguard Worker // can't remap the same row twice
125*d83cc019SAndroid Build Coastguard Worker if ((reg->row0_enable && reg->row0 == row) ||
126*d83cc019SAndroid Build Coastguard Worker (reg->row1_enable && reg->row1 == row)) {
127*d83cc019SAndroid Build Coastguard Worker return -1;
128*d83cc019SAndroid Build Coastguard Worker }
129*d83cc019SAndroid Build Coastguard Worker
130*d83cc019SAndroid Build Coastguard Worker if (reg->row0_enable) {
131*d83cc019SAndroid Build Coastguard Worker reg->row1 = row;
132*d83cc019SAndroid Build Coastguard Worker reg->row1_enable = 1;
133*d83cc019SAndroid Build Coastguard Worker } else {
134*d83cc019SAndroid Build Coastguard Worker reg->row0 = row;
135*d83cc019SAndroid Build Coastguard Worker reg->row0_enable = 1;
136*d83cc019SAndroid Build Coastguard Worker }
137*d83cc019SAndroid Build Coastguard Worker
138*d83cc019SAndroid Build Coastguard Worker return 0;
139*d83cc019SAndroid Build Coastguard Worker }
140*d83cc019SAndroid Build Coastguard Worker
enables_rbs(int row,int bank,int sbank,int slice)141*d83cc019SAndroid Build Coastguard Worker static void enables_rbs(int row, int bank, int sbank, int slice)
142*d83cc019SAndroid Build Coastguard Worker {
143*d83cc019SAndroid Build Coastguard Worker struct l3_log_register *reg = &l3logs[slice][bank][sbank];
144*d83cc019SAndroid Build Coastguard Worker
145*d83cc019SAndroid Build Coastguard Worker if (!reg->row0_enable && !reg->row1_enable)
146*d83cc019SAndroid Build Coastguard Worker return;
147*d83cc019SAndroid Build Coastguard Worker
148*d83cc019SAndroid Build Coastguard Worker if (reg->row1_enable && reg->row1 == row)
149*d83cc019SAndroid Build Coastguard Worker reg->row1_enable = 0;
150*d83cc019SAndroid Build Coastguard Worker else if (reg->row0_enable && reg->row0 == row)
151*d83cc019SAndroid Build Coastguard Worker reg->row0_enable = 0;
152*d83cc019SAndroid Build Coastguard Worker }
153*d83cc019SAndroid Build Coastguard Worker
usage(const char * name)154*d83cc019SAndroid Build Coastguard Worker static void usage(const char *name)
155*d83cc019SAndroid Build Coastguard Worker {
156*d83cc019SAndroid Build Coastguard Worker printf("usage: %s [OPTIONS] [ACTION]\n"
157*d83cc019SAndroid Build Coastguard Worker "Operate on the i915 L3 GPU cache (should be run as root)\n\n"
158*d83cc019SAndroid Build Coastguard Worker " OPTIONS:\n"
159*d83cc019SAndroid Build Coastguard Worker " -r, --row=[row] The row to act upon (default 0)\n"
160*d83cc019SAndroid Build Coastguard Worker " -b, --bank=[bank] The bank to act upon (default 0)\n"
161*d83cc019SAndroid Build Coastguard Worker " -s, --subbank=[subbank] The subbank to act upon (default 0)\n"
162*d83cc019SAndroid Build Coastguard Worker " -w, --slice=[slice] Which slice to act on (default: -1 [all])\n"
163*d83cc019SAndroid Build Coastguard Worker " , --daemon Run the listener (-L) as a daemon\n"
164*d83cc019SAndroid Build Coastguard Worker " ACTIONS (only 1 may be specified at a time):\n"
165*d83cc019SAndroid Build Coastguard Worker " -h, --help Display this help\n"
166*d83cc019SAndroid Build Coastguard Worker " -H, --hw-info Display the current L3 properties\n"
167*d83cc019SAndroid Build Coastguard Worker " -l, --list List the current L3 logs\n"
168*d83cc019SAndroid Build Coastguard Worker " -a, --clear-all Clear all disabled rows\n"
169*d83cc019SAndroid Build Coastguard Worker " -e, --enable Enable row, bank, subbank (undo -d)\n"
170*d83cc019SAndroid Build Coastguard Worker " -d, --disable=<row,bank,subbank> Disable row, bank, subbank (inline arguments are deprecated. Please use -r, -b, -s instead\n"
171*d83cc019SAndroid Build Coastguard Worker " -i, --inject [HSW only] Cause hardware to inject a row errors\n"
172*d83cc019SAndroid Build Coastguard Worker " -u, --uninject [HSW only] Turn off hardware error injectection (undo -i)\n"
173*d83cc019SAndroid Build Coastguard Worker " -L, --listen Listen for uevent errors\n",
174*d83cc019SAndroid Build Coastguard Worker name);
175*d83cc019SAndroid Build Coastguard Worker }
176*d83cc019SAndroid Build Coastguard Worker
main(int argc,char * argv[])177*d83cc019SAndroid Build Coastguard Worker int main(int argc, char *argv[])
178*d83cc019SAndroid Build Coastguard Worker {
179*d83cc019SAndroid Build Coastguard Worker const char *path[REAL_MAX_SLICES] = {"l3_parity", "l3_parity_slice_1"};
180*d83cc019SAndroid Build Coastguard Worker int row = 0, bank = 0, sbank = 0;
181*d83cc019SAndroid Build Coastguard Worker int fd[REAL_MAX_SLICES] = {0}, ret, i;
182*d83cc019SAndroid Build Coastguard Worker int action = '0';
183*d83cc019SAndroid Build Coastguard Worker int daemonize = 0;
184*d83cc019SAndroid Build Coastguard Worker int device, dir;
185*d83cc019SAndroid Build Coastguard Worker uint32_t dft;
186*d83cc019SAndroid Build Coastguard Worker
187*d83cc019SAndroid Build Coastguard Worker device = drm_open_driver(DRIVER_INTEL);
188*d83cc019SAndroid Build Coastguard Worker devid = intel_get_drm_devid(device);
189*d83cc019SAndroid Build Coastguard Worker if (intel_gen(devid) < 7 || IS_VALLEYVIEW(devid))
190*d83cc019SAndroid Build Coastguard Worker exit(77);
191*d83cc019SAndroid Build Coastguard Worker
192*d83cc019SAndroid Build Coastguard Worker assert(intel_register_access_init(intel_get_pci_device(), 0, device) == 0);
193*d83cc019SAndroid Build Coastguard Worker
194*d83cc019SAndroid Build Coastguard Worker dir = igt_sysfs_open(device);
195*d83cc019SAndroid Build Coastguard Worker
196*d83cc019SAndroid Build Coastguard Worker for_each_slice(i) {
197*d83cc019SAndroid Build Coastguard Worker fd[i] = openat(dir, path[i], O_RDWR);
198*d83cc019SAndroid Build Coastguard Worker if (fd[i] < 0) {
199*d83cc019SAndroid Build Coastguard Worker if (i == 0) /* at least one slice must be supported */
200*d83cc019SAndroid Build Coastguard Worker exit(77);
201*d83cc019SAndroid Build Coastguard Worker continue;
202*d83cc019SAndroid Build Coastguard Worker }
203*d83cc019SAndroid Build Coastguard Worker
204*d83cc019SAndroid Build Coastguard Worker if (read(fd[i], l3logs[i], NUM_REGS * sizeof(uint32_t)) < 0) {
205*d83cc019SAndroid Build Coastguard Worker perror(path[i]);
206*d83cc019SAndroid Build Coastguard Worker exit(77);
207*d83cc019SAndroid Build Coastguard Worker }
208*d83cc019SAndroid Build Coastguard Worker assert(lseek(fd[i], 0, SEEK_SET) == 0);
209*d83cc019SAndroid Build Coastguard Worker }
210*d83cc019SAndroid Build Coastguard Worker
211*d83cc019SAndroid Build Coastguard Worker close(dir);
212*d83cc019SAndroid Build Coastguard Worker
213*d83cc019SAndroid Build Coastguard Worker /* NB: It is potentially unsafe to read this register if the kernel is
214*d83cc019SAndroid Build Coastguard Worker * actively using this register range, or we're running multiple
215*d83cc019SAndroid Build Coastguard Worker * instances of this tool. Since neither of those cases should occur
216*d83cc019SAndroid Build Coastguard Worker * (and the tool should be root only) we can safely ignore this for
217*d83cc019SAndroid Build Coastguard Worker * now. Just be aware of this if for some reason a hang is reported
218*d83cc019SAndroid Build Coastguard Worker * when using this tool.
219*d83cc019SAndroid Build Coastguard Worker */
220*d83cc019SAndroid Build Coastguard Worker dft = intel_register_read(0xb038);
221*d83cc019SAndroid Build Coastguard Worker
222*d83cc019SAndroid Build Coastguard Worker while (1) {
223*d83cc019SAndroid Build Coastguard Worker int c, option_index = 0;
224*d83cc019SAndroid Build Coastguard Worker struct option long_options[] = {
225*d83cc019SAndroid Build Coastguard Worker { "help", no_argument, 0, 'h' },
226*d83cc019SAndroid Build Coastguard Worker { "list", no_argument, 0, 'l' },
227*d83cc019SAndroid Build Coastguard Worker { "clear-all", no_argument, 0, 'a' },
228*d83cc019SAndroid Build Coastguard Worker { "enable", no_argument, 0, 'e' },
229*d83cc019SAndroid Build Coastguard Worker { "disable", optional_argument, 0, 'd' },
230*d83cc019SAndroid Build Coastguard Worker { "inject", no_argument, 0, 'i' },
231*d83cc019SAndroid Build Coastguard Worker { "uninject", no_argument, 0, 'u' },
232*d83cc019SAndroid Build Coastguard Worker { "hw-info", no_argument, 0, 'H' },
233*d83cc019SAndroid Build Coastguard Worker { "listen", no_argument, 0, 'L' },
234*d83cc019SAndroid Build Coastguard Worker { "row", required_argument, 0, 'r' },
235*d83cc019SAndroid Build Coastguard Worker { "bank", required_argument, 0, 'b' },
236*d83cc019SAndroid Build Coastguard Worker { "subbank", required_argument, 0, 's' },
237*d83cc019SAndroid Build Coastguard Worker { "slice", required_argument, 0, 'w' },
238*d83cc019SAndroid Build Coastguard Worker { "daemon", no_argument, &daemonize, 1 },
239*d83cc019SAndroid Build Coastguard Worker {0, 0, 0, 0}
240*d83cc019SAndroid Build Coastguard Worker };
241*d83cc019SAndroid Build Coastguard Worker
242*d83cc019SAndroid Build Coastguard Worker c = getopt_long(argc, argv, "hHr:b:s:w:aled::iuL", long_options,
243*d83cc019SAndroid Build Coastguard Worker &option_index);
244*d83cc019SAndroid Build Coastguard Worker if (c == -1)
245*d83cc019SAndroid Build Coastguard Worker break;
246*d83cc019SAndroid Build Coastguard Worker
247*d83cc019SAndroid Build Coastguard Worker if (c == 0)
248*d83cc019SAndroid Build Coastguard Worker continue;
249*d83cc019SAndroid Build Coastguard Worker
250*d83cc019SAndroid Build Coastguard Worker switch (c) {
251*d83cc019SAndroid Build Coastguard Worker case '?':
252*d83cc019SAndroid Build Coastguard Worker case 'h':
253*d83cc019SAndroid Build Coastguard Worker usage(argv[0]);
254*d83cc019SAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
255*d83cc019SAndroid Build Coastguard Worker case 'H':
256*d83cc019SAndroid Build Coastguard Worker printf("Number of slices: %d\n", MAX_SLICES);
257*d83cc019SAndroid Build Coastguard Worker printf("Number of banks: %d\n", num_banks());
258*d83cc019SAndroid Build Coastguard Worker printf("Subbanks per bank: %d\n", NUM_SUBBANKS);
259*d83cc019SAndroid Build Coastguard Worker printf("Max L3 size: %dK\n", L3_SIZE >> 10);
260*d83cc019SAndroid Build Coastguard Worker printf("Has error injection: %s\n", IS_HASWELL(devid) ? "yes" : "no");
261*d83cc019SAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
262*d83cc019SAndroid Build Coastguard Worker case 'r':
263*d83cc019SAndroid Build Coastguard Worker row = atoi(optarg);
264*d83cc019SAndroid Build Coastguard Worker if (row >= MAX_ROW)
265*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
266*d83cc019SAndroid Build Coastguard Worker break;
267*d83cc019SAndroid Build Coastguard Worker case 'b':
268*d83cc019SAndroid Build Coastguard Worker bank = atoi(optarg);
269*d83cc019SAndroid Build Coastguard Worker if (bank >= num_banks() || bank >= MAX_BANKS_PER_SLICE)
270*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
271*d83cc019SAndroid Build Coastguard Worker break;
272*d83cc019SAndroid Build Coastguard Worker case 's':
273*d83cc019SAndroid Build Coastguard Worker sbank = atoi(optarg);
274*d83cc019SAndroid Build Coastguard Worker if (sbank >= NUM_SUBBANKS)
275*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
276*d83cc019SAndroid Build Coastguard Worker break;
277*d83cc019SAndroid Build Coastguard Worker case 'w':
278*d83cc019SAndroid Build Coastguard Worker which_slice = atoi(optarg);
279*d83cc019SAndroid Build Coastguard Worker if (which_slice >= MAX_SLICES)
280*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
281*d83cc019SAndroid Build Coastguard Worker break;
282*d83cc019SAndroid Build Coastguard Worker case 'i':
283*d83cc019SAndroid Build Coastguard Worker case 'u':
284*d83cc019SAndroid Build Coastguard Worker if (!IS_HASWELL(devid)) {
285*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Error injection supported on HSW+ only\n");
286*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
287*d83cc019SAndroid Build Coastguard Worker }
288*d83cc019SAndroid Build Coastguard Worker case 'd':
289*d83cc019SAndroid Build Coastguard Worker if (optarg) {
290*d83cc019SAndroid Build Coastguard Worker ret = sscanf(optarg, "%d,%d,%d", &row, &bank, &sbank);
291*d83cc019SAndroid Build Coastguard Worker if (ret != 3)
292*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
293*d83cc019SAndroid Build Coastguard Worker }
294*d83cc019SAndroid Build Coastguard Worker case 'a':
295*d83cc019SAndroid Build Coastguard Worker case 'l':
296*d83cc019SAndroid Build Coastguard Worker case 'e':
297*d83cc019SAndroid Build Coastguard Worker case 'L':
298*d83cc019SAndroid Build Coastguard Worker if (action != '0') {
299*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Only one action may be specified\n");
300*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
301*d83cc019SAndroid Build Coastguard Worker }
302*d83cc019SAndroid Build Coastguard Worker action = c;
303*d83cc019SAndroid Build Coastguard Worker break;
304*d83cc019SAndroid Build Coastguard Worker default:
305*d83cc019SAndroid Build Coastguard Worker abort();
306*d83cc019SAndroid Build Coastguard Worker }
307*d83cc019SAndroid Build Coastguard Worker }
308*d83cc019SAndroid Build Coastguard Worker
309*d83cc019SAndroid Build Coastguard Worker if (action == 'i') {
310*d83cc019SAndroid Build Coastguard Worker if (((dft >> 1) & 1) != which_slice) {
311*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "DFT register already has slice %d enabled, and we don't support multiple slices. Try modifying -w; but sometimes the register sticks in the wrong way\n", (dft >> 1) & 1);
312*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
313*d83cc019SAndroid Build Coastguard Worker }
314*d83cc019SAndroid Build Coastguard Worker
315*d83cc019SAndroid Build Coastguard Worker if (which_slice == -1) {
316*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "Cannot inject errors to multiple slices (modify -w)\n");
317*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
318*d83cc019SAndroid Build Coastguard Worker }
319*d83cc019SAndroid Build Coastguard Worker if (dft & 1 && ((dft >> 1) && 1) == which_slice)
320*d83cc019SAndroid Build Coastguard Worker printf("warning: overwriting existing injections. This is very dangerous.\n");
321*d83cc019SAndroid Build Coastguard Worker }
322*d83cc019SAndroid Build Coastguard Worker
323*d83cc019SAndroid Build Coastguard Worker /* Daemon doesn't work like the other commands */
324*d83cc019SAndroid Build Coastguard Worker if (action == 'L') {
325*d83cc019SAndroid Build Coastguard Worker struct l3_parity par;
326*d83cc019SAndroid Build Coastguard Worker struct l3_location loc;
327*d83cc019SAndroid Build Coastguard Worker if (daemonize) {
328*d83cc019SAndroid Build Coastguard Worker assert(daemon(0, 0) == 0);
329*d83cc019SAndroid Build Coastguard Worker openlog(argv[0], LOG_CONS | LOG_PID, LOG_USER);
330*d83cc019SAndroid Build Coastguard Worker }
331*d83cc019SAndroid Build Coastguard Worker memset(&par, 0, sizeof(par));
332*d83cc019SAndroid Build Coastguard Worker assert(l3_uevent_setup(&par) == 0);
333*d83cc019SAndroid Build Coastguard Worker assert(l3_listen(&par, daemonize == 1, &loc) == 0);
334*d83cc019SAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
335*d83cc019SAndroid Build Coastguard Worker }
336*d83cc019SAndroid Build Coastguard Worker
337*d83cc019SAndroid Build Coastguard Worker if (action == 'l')
338*d83cc019SAndroid Build Coastguard Worker decode_dft(dft);
339*d83cc019SAndroid Build Coastguard Worker
340*d83cc019SAndroid Build Coastguard Worker /* Per slice operations */
341*d83cc019SAndroid Build Coastguard Worker for_each_slice(i) {
342*d83cc019SAndroid Build Coastguard Worker if (fd[i] < 0)
343*d83cc019SAndroid Build Coastguard Worker continue;
344*d83cc019SAndroid Build Coastguard Worker
345*d83cc019SAndroid Build Coastguard Worker switch (action) {
346*d83cc019SAndroid Build Coastguard Worker case 'l':
347*d83cc019SAndroid Build Coastguard Worker dumpit(i);
348*d83cc019SAndroid Build Coastguard Worker break;
349*d83cc019SAndroid Build Coastguard Worker case 'a':
350*d83cc019SAndroid Build Coastguard Worker memset(l3logs[i], 0, NUM_REGS * sizeof(struct l3_log_register));
351*d83cc019SAndroid Build Coastguard Worker break;
352*d83cc019SAndroid Build Coastguard Worker case 'e':
353*d83cc019SAndroid Build Coastguard Worker enables_rbs(row, bank, sbank, i);
354*d83cc019SAndroid Build Coastguard Worker break;
355*d83cc019SAndroid Build Coastguard Worker case 'd':
356*d83cc019SAndroid Build Coastguard Worker assert(disable_rbs(row, bank, sbank, i) == 0);
357*d83cc019SAndroid Build Coastguard Worker break;
358*d83cc019SAndroid Build Coastguard Worker case 'i':
359*d83cc019SAndroid Build Coastguard Worker if (bank == 3) {
360*d83cc019SAndroid Build Coastguard Worker fprintf(stderr, "The hardware does not support error inject on bank 3.\n");
361*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
362*d83cc019SAndroid Build Coastguard Worker }
363*d83cc019SAndroid Build Coastguard Worker dft |= row << 7;
364*d83cc019SAndroid Build Coastguard Worker dft |= sbank << 4;
365*d83cc019SAndroid Build Coastguard Worker dft |= bank << 2;
366*d83cc019SAndroid Build Coastguard Worker assert(i < 2);
367*d83cc019SAndroid Build Coastguard Worker dft |= i << 1; /* slice */
368*d83cc019SAndroid Build Coastguard Worker dft |= 1 << 0; /* enable */
369*d83cc019SAndroid Build Coastguard Worker intel_register_write(0xb038, dft);
370*d83cc019SAndroid Build Coastguard Worker break;
371*d83cc019SAndroid Build Coastguard Worker case 'u':
372*d83cc019SAndroid Build Coastguard Worker intel_register_write(0xb038, dft & ~(1<<0));
373*d83cc019SAndroid Build Coastguard Worker break;
374*d83cc019SAndroid Build Coastguard Worker case 'L':
375*d83cc019SAndroid Build Coastguard Worker break;
376*d83cc019SAndroid Build Coastguard Worker default:
377*d83cc019SAndroid Build Coastguard Worker abort();
378*d83cc019SAndroid Build Coastguard Worker }
379*d83cc019SAndroid Build Coastguard Worker }
380*d83cc019SAndroid Build Coastguard Worker
381*d83cc019SAndroid Build Coastguard Worker intel_register_access_fini();
382*d83cc019SAndroid Build Coastguard Worker if (action == 'l')
383*d83cc019SAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
384*d83cc019SAndroid Build Coastguard Worker
385*d83cc019SAndroid Build Coastguard Worker for_each_slice(i) {
386*d83cc019SAndroid Build Coastguard Worker if (fd[i] < 0)
387*d83cc019SAndroid Build Coastguard Worker continue;
388*d83cc019SAndroid Build Coastguard Worker
389*d83cc019SAndroid Build Coastguard Worker ret = write(fd[i], l3logs[i], NUM_REGS * sizeof(uint32_t));
390*d83cc019SAndroid Build Coastguard Worker if (ret == -1) {
391*d83cc019SAndroid Build Coastguard Worker perror("Writing sysfs");
392*d83cc019SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
393*d83cc019SAndroid Build Coastguard Worker }
394*d83cc019SAndroid Build Coastguard Worker close(fd[i]);
395*d83cc019SAndroid Build Coastguard Worker }
396*d83cc019SAndroid Build Coastguard Worker
397*d83cc019SAndroid Build Coastguard Worker
398*d83cc019SAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
399*d83cc019SAndroid Build Coastguard Worker }
400