xref: /OK3568_Linux_fs/kernel/Documentation/ia64/err_inject.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun========================================
2*4882a593SmuzhiyunIPF Machine Check (MC) error inject tool
3*4882a593Smuzhiyun========================================
4*4882a593Smuzhiyun
5*4882a593SmuzhiyunIPF Machine Check (MC) error inject tool is used to inject MC
6*4882a593Smuzhiyunerrors from Linux. The tool is a test bed for IPF MC work flow including
7*4882a593Smuzhiyunhardware correctable error handling, OS recoverable error handling, MC
8*4882a593Smuzhiyunevent logging, etc.
9*4882a593Smuzhiyun
10*4882a593SmuzhiyunThe tool includes two parts: a kernel driver and a user application
11*4882a593Smuzhiyunsample. The driver provides interface to PAL to inject error
12*4882a593Smuzhiyunand query error injection capabilities. The driver code is in
13*4882a593Smuzhiyunarch/ia64/kernel/err_inject.c. The application sample (shown below)
14*4882a593Smuzhiyunprovides a combination of various errors and calls the driver's interface
15*4882a593Smuzhiyun(sysfs interface) to inject errors or query error injection capabilities.
16*4882a593Smuzhiyun
17*4882a593SmuzhiyunThe tool can be used to test Intel IPF machine MC handling capabilities.
18*4882a593SmuzhiyunIt's especially useful for people who can not access hardware MC injection
19*4882a593Smuzhiyuntool to inject error. It's also very useful to integrate with other
20*4882a593Smuzhiyunsoftware test suits to do stressful testing on IPF.
21*4882a593Smuzhiyun
22*4882a593SmuzhiyunBelow is a sample application as part of the whole tool. The sample
23*4882a593Smuzhiyuncan be used as a working test tool. Or it can be expanded to include
24*4882a593Smuzhiyunmore features. It also can be a integrated into a library or other user
25*4882a593Smuzhiyunapplication to have more thorough test.
26*4882a593Smuzhiyun
27*4882a593SmuzhiyunThe sample application takes err.conf as error configuration input. GCC
28*4882a593Smuzhiyuncompiles the code. After you install err_inject driver, you can run
29*4882a593Smuzhiyunthis sample application to inject errors.
30*4882a593Smuzhiyun
31*4882a593SmuzhiyunErrata: Itanium 2 Processors Specification Update lists some errata against
32*4882a593Smuzhiyunthe pal_mc_error_inject PAL procedure. The following err.conf has been tested
33*4882a593Smuzhiyunon latest Montecito PAL.
34*4882a593Smuzhiyun
35*4882a593Smuzhiyunerr.conf::
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun  #This is configuration file for err_inject_tool.
38*4882a593Smuzhiyun  #The format of the each line is:
39*4882a593Smuzhiyun  #cpu, loop, interval, err_type_info, err_struct_info, err_data_buffer
40*4882a593Smuzhiyun  #where
41*4882a593Smuzhiyun  #	cpu: logical cpu number the error will be inject in.
42*4882a593Smuzhiyun  #	loop: times the error will be injected.
43*4882a593Smuzhiyun  #	interval: In second. every so often one error is injected.
44*4882a593Smuzhiyun  #	err_type_info, err_struct_info: PAL parameters.
45*4882a593Smuzhiyun  #
46*4882a593Smuzhiyun  #Note: All values are hex w/o or w/ 0x prefix.
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun  #On cpu2, inject only total 0x10 errors, interval 5 seconds
50*4882a593Smuzhiyun  #corrected, data cache, hier-2, physical addr(assigned by tool code).
51*4882a593Smuzhiyun  #working on Montecito latest PAL.
52*4882a593Smuzhiyun  2, 10, 5, 4101, 95
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun  #On cpu4, inject and consume total 0x10 errors, interval 5 seconds
55*4882a593Smuzhiyun  #corrected, data cache, hier-2, physical addr(assigned by tool code).
56*4882a593Smuzhiyun  #working on Montecito latest PAL.
57*4882a593Smuzhiyun  4, 10, 5, 4109, 95
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun  #On cpu15, inject and consume total 0x10 errors, interval 5 seconds
60*4882a593Smuzhiyun  #recoverable, DTR0, hier-2.
61*4882a593Smuzhiyun  #working on Montecito latest PAL.
62*4882a593Smuzhiyun  0xf, 0x10, 5, 4249, 15
63*4882a593Smuzhiyun
64*4882a593SmuzhiyunThe sample application source code:
65*4882a593Smuzhiyun
66*4882a593Smuzhiyunerr_injection_tool.c::
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun  /*
69*4882a593Smuzhiyun   * This program is free software; you can redistribute it and/or modify
70*4882a593Smuzhiyun   * it under the terms of the GNU General Public License as published by
71*4882a593Smuzhiyun   * the Free Software Foundation; either version 2 of the License, or
72*4882a593Smuzhiyun   * (at your option) any later version.
73*4882a593Smuzhiyun   *
74*4882a593Smuzhiyun   * This program is distributed in the hope that it will be useful, but
75*4882a593Smuzhiyun   * WITHOUT ANY WARRANTY; without even the implied warranty of
76*4882a593Smuzhiyun   * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
77*4882a593Smuzhiyun   * NON INFRINGEMENT.  See the GNU General Public License for more
78*4882a593Smuzhiyun   * details.
79*4882a593Smuzhiyun   *
80*4882a593Smuzhiyun   * You should have received a copy of the GNU General Public License
81*4882a593Smuzhiyun   * along with this program; if not, write to the Free Software
82*4882a593Smuzhiyun   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
83*4882a593Smuzhiyun   *
84*4882a593Smuzhiyun   * Copyright (C) 2006 Intel Co
85*4882a593Smuzhiyun   *	Fenghua Yu <fenghua.yu@intel.com>
86*4882a593Smuzhiyun   *
87*4882a593Smuzhiyun   */
88*4882a593Smuzhiyun  #include <sys/types.h>
89*4882a593Smuzhiyun  #include <sys/stat.h>
90*4882a593Smuzhiyun  #include <fcntl.h>
91*4882a593Smuzhiyun  #include <stdio.h>
92*4882a593Smuzhiyun  #include <sched.h>
93*4882a593Smuzhiyun  #include <unistd.h>
94*4882a593Smuzhiyun  #include <stdlib.h>
95*4882a593Smuzhiyun  #include <stdarg.h>
96*4882a593Smuzhiyun  #include <string.h>
97*4882a593Smuzhiyun  #include <errno.h>
98*4882a593Smuzhiyun  #include <time.h>
99*4882a593Smuzhiyun  #include <sys/ipc.h>
100*4882a593Smuzhiyun  #include <sys/sem.h>
101*4882a593Smuzhiyun  #include <sys/wait.h>
102*4882a593Smuzhiyun  #include <sys/mman.h>
103*4882a593Smuzhiyun  #include <sys/shm.h>
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun  #define MAX_FN_SIZE 		256
106*4882a593Smuzhiyun  #define MAX_BUF_SIZE 		256
107*4882a593Smuzhiyun  #define DATA_BUF_SIZE 		256
108*4882a593Smuzhiyun  #define NR_CPUS 		512
109*4882a593Smuzhiyun  #define MAX_TASK_NUM		2048
110*4882a593Smuzhiyun  #define MIN_INTERVAL		5	// seconds
111*4882a593Smuzhiyun  #define	ERR_DATA_BUFFER_SIZE 	3	// Three 8-byte.
112*4882a593Smuzhiyun  #define PARA_FIELD_NUM		5
113*4882a593Smuzhiyun  #define MASK_SIZE		(NR_CPUS/64)
114*4882a593Smuzhiyun  #define PATH_FORMAT "/sys/devices/system/cpu/cpu%d/err_inject/"
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun  int sched_setaffinity(pid_t pid, unsigned int len, unsigned long *mask);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun  int verbose;
119*4882a593Smuzhiyun  #define vbprintf if (verbose) printf
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun  int log_info(int cpu, const char *fmt, ...)
122*4882a593Smuzhiyun  {
123*4882a593Smuzhiyun	FILE *log;
124*4882a593Smuzhiyun	char fn[MAX_FN_SIZE];
125*4882a593Smuzhiyun	char buf[MAX_BUF_SIZE];
126*4882a593Smuzhiyun	va_list args;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun	sprintf(fn, "%d.log", cpu);
129*4882a593Smuzhiyun	log=fopen(fn, "a+");
130*4882a593Smuzhiyun	if (log==NULL) {
131*4882a593Smuzhiyun		perror("Error open:");
132*4882a593Smuzhiyun		return -1;
133*4882a593Smuzhiyun	}
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun	va_start(args, fmt);
136*4882a593Smuzhiyun	vprintf(fmt, args);
137*4882a593Smuzhiyun	memset(buf, 0, MAX_BUF_SIZE);
138*4882a593Smuzhiyun	vsprintf(buf, fmt, args);
139*4882a593Smuzhiyun	va_end(args);
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun	fwrite(buf, sizeof(buf), 1, log);
142*4882a593Smuzhiyun	fclose(log);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun	return 0;
145*4882a593Smuzhiyun  }
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun  typedef unsigned long u64;
148*4882a593Smuzhiyun  typedef unsigned int  u32;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun  typedef union err_type_info_u {
151*4882a593Smuzhiyun	struct {
152*4882a593Smuzhiyun		u64	mode		: 3,	/* 0-2 */
153*4882a593Smuzhiyun			err_inj		: 3,	/* 3-5 */
154*4882a593Smuzhiyun			err_sev		: 2,	/* 6-7 */
155*4882a593Smuzhiyun			err_struct	: 5,	/* 8-12 */
156*4882a593Smuzhiyun			struct_hier	: 3,	/* 13-15 */
157*4882a593Smuzhiyun			reserved	: 48;	/* 16-63 */
158*4882a593Smuzhiyun	} err_type_info_u;
159*4882a593Smuzhiyun	u64	err_type_info;
160*4882a593Smuzhiyun  } err_type_info_t;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun  typedef union err_struct_info_u {
163*4882a593Smuzhiyun	struct {
164*4882a593Smuzhiyun		u64	siv		: 1,	/* 0	 */
165*4882a593Smuzhiyun			c_t		: 2,	/* 1-2	 */
166*4882a593Smuzhiyun			cl_p		: 3,	/* 3-5	 */
167*4882a593Smuzhiyun			cl_id		: 3,	/* 6-8	 */
168*4882a593Smuzhiyun			cl_dp		: 1,	/* 9	 */
169*4882a593Smuzhiyun			reserved1	: 22,	/* 10-31 */
170*4882a593Smuzhiyun			tiv		: 1,	/* 32	 */
171*4882a593Smuzhiyun			trigger		: 4,	/* 33-36 */
172*4882a593Smuzhiyun			trigger_pl 	: 3,	/* 37-39 */
173*4882a593Smuzhiyun			reserved2 	: 24;	/* 40-63 */
174*4882a593Smuzhiyun	} err_struct_info_cache;
175*4882a593Smuzhiyun	struct {
176*4882a593Smuzhiyun		u64	siv		: 1,	/* 0	 */
177*4882a593Smuzhiyun			tt		: 2,	/* 1-2	 */
178*4882a593Smuzhiyun			tc_tr		: 2,	/* 3-4	 */
179*4882a593Smuzhiyun			tr_slot		: 8,	/* 5-12	 */
180*4882a593Smuzhiyun			reserved1	: 19,	/* 13-31 */
181*4882a593Smuzhiyun			tiv		: 1,	/* 32	 */
182*4882a593Smuzhiyun			trigger		: 4,	/* 33-36 */
183*4882a593Smuzhiyun			trigger_pl 	: 3,	/* 37-39 */
184*4882a593Smuzhiyun			reserved2 	: 24;	/* 40-63 */
185*4882a593Smuzhiyun	} err_struct_info_tlb;
186*4882a593Smuzhiyun	struct {
187*4882a593Smuzhiyun		u64	siv		: 1,	/* 0	 */
188*4882a593Smuzhiyun			regfile_id	: 4,	/* 1-4	 */
189*4882a593Smuzhiyun			reg_num		: 7,	/* 5-11	 */
190*4882a593Smuzhiyun			reserved1	: 20,	/* 12-31 */
191*4882a593Smuzhiyun			tiv		: 1,	/* 32	 */
192*4882a593Smuzhiyun			trigger		: 4,	/* 33-36 */
193*4882a593Smuzhiyun			trigger_pl 	: 3,	/* 37-39 */
194*4882a593Smuzhiyun			reserved2 	: 24;	/* 40-63 */
195*4882a593Smuzhiyun	} err_struct_info_register;
196*4882a593Smuzhiyun	struct {
197*4882a593Smuzhiyun		u64	reserved;
198*4882a593Smuzhiyun	} err_struct_info_bus_processor_interconnect;
199*4882a593Smuzhiyun	u64	err_struct_info;
200*4882a593Smuzhiyun  } err_struct_info_t;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun  typedef union err_data_buffer_u {
203*4882a593Smuzhiyun	struct {
204*4882a593Smuzhiyun		u64	trigger_addr;		/* 0-63		*/
205*4882a593Smuzhiyun		u64	inj_addr;		/* 64-127 	*/
206*4882a593Smuzhiyun		u64	way		: 5,	/* 128-132	*/
207*4882a593Smuzhiyun			index		: 20,	/* 133-152	*/
208*4882a593Smuzhiyun					: 39;	/* 153-191	*/
209*4882a593Smuzhiyun	} err_data_buffer_cache;
210*4882a593Smuzhiyun	struct {
211*4882a593Smuzhiyun		u64	trigger_addr;		/* 0-63		*/
212*4882a593Smuzhiyun		u64	inj_addr;		/* 64-127 	*/
213*4882a593Smuzhiyun		u64	way		: 5,	/* 128-132	*/
214*4882a593Smuzhiyun			index		: 20,	/* 133-152	*/
215*4882a593Smuzhiyun			reserved	: 39;	/* 153-191	*/
216*4882a593Smuzhiyun	} err_data_buffer_tlb;
217*4882a593Smuzhiyun	struct {
218*4882a593Smuzhiyun		u64	trigger_addr;		/* 0-63		*/
219*4882a593Smuzhiyun	} err_data_buffer_register;
220*4882a593Smuzhiyun	struct {
221*4882a593Smuzhiyun		u64	reserved;		/* 0-63		*/
222*4882a593Smuzhiyun	} err_data_buffer_bus_processor_interconnect;
223*4882a593Smuzhiyun	u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
224*4882a593Smuzhiyun  } err_data_buffer_t;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun  typedef union capabilities_u {
227*4882a593Smuzhiyun	struct {
228*4882a593Smuzhiyun		u64	i		: 1,
229*4882a593Smuzhiyun			d		: 1,
230*4882a593Smuzhiyun			rv		: 1,
231*4882a593Smuzhiyun			tag		: 1,
232*4882a593Smuzhiyun			data		: 1,
233*4882a593Smuzhiyun			mesi		: 1,
234*4882a593Smuzhiyun			dp		: 1,
235*4882a593Smuzhiyun			reserved1	: 3,
236*4882a593Smuzhiyun			pa		: 1,
237*4882a593Smuzhiyun			va		: 1,
238*4882a593Smuzhiyun			wi		: 1,
239*4882a593Smuzhiyun			reserved2	: 20,
240*4882a593Smuzhiyun			trigger		: 1,
241*4882a593Smuzhiyun			trigger_pl	: 1,
242*4882a593Smuzhiyun			reserved3	: 30;
243*4882a593Smuzhiyun	} capabilities_cache;
244*4882a593Smuzhiyun	struct {
245*4882a593Smuzhiyun		u64	d		: 1,
246*4882a593Smuzhiyun			i		: 1,
247*4882a593Smuzhiyun			rv		: 1,
248*4882a593Smuzhiyun			tc		: 1,
249*4882a593Smuzhiyun			tr		: 1,
250*4882a593Smuzhiyun			reserved1	: 27,
251*4882a593Smuzhiyun			trigger		: 1,
252*4882a593Smuzhiyun			trigger_pl	: 1,
253*4882a593Smuzhiyun			reserved2	: 30;
254*4882a593Smuzhiyun	} capabilities_tlb;
255*4882a593Smuzhiyun	struct {
256*4882a593Smuzhiyun		u64	gr_b0		: 1,
257*4882a593Smuzhiyun			gr_b1		: 1,
258*4882a593Smuzhiyun			fr		: 1,
259*4882a593Smuzhiyun			br		: 1,
260*4882a593Smuzhiyun			pr		: 1,
261*4882a593Smuzhiyun			ar		: 1,
262*4882a593Smuzhiyun			cr		: 1,
263*4882a593Smuzhiyun			rr		: 1,
264*4882a593Smuzhiyun			pkr		: 1,
265*4882a593Smuzhiyun			dbr		: 1,
266*4882a593Smuzhiyun			ibr		: 1,
267*4882a593Smuzhiyun			pmc		: 1,
268*4882a593Smuzhiyun			pmd		: 1,
269*4882a593Smuzhiyun			reserved1	: 3,
270*4882a593Smuzhiyun			regnum		: 1,
271*4882a593Smuzhiyun			reserved2	: 15,
272*4882a593Smuzhiyun			trigger		: 1,
273*4882a593Smuzhiyun			trigger_pl	: 1,
274*4882a593Smuzhiyun			reserved3	: 30;
275*4882a593Smuzhiyun	} capabilities_register;
276*4882a593Smuzhiyun	struct {
277*4882a593Smuzhiyun		u64	reserved;
278*4882a593Smuzhiyun	} capabilities_bus_processor_interconnect;
279*4882a593Smuzhiyun  } capabilities_t;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun  typedef struct resources_s {
282*4882a593Smuzhiyun	u64	ibr0		: 1,
283*4882a593Smuzhiyun		ibr2		: 1,
284*4882a593Smuzhiyun		ibr4		: 1,
285*4882a593Smuzhiyun		ibr6		: 1,
286*4882a593Smuzhiyun		dbr0		: 1,
287*4882a593Smuzhiyun		dbr2		: 1,
288*4882a593Smuzhiyun		dbr4		: 1,
289*4882a593Smuzhiyun		dbr6		: 1,
290*4882a593Smuzhiyun		reserved	: 48;
291*4882a593Smuzhiyun  } resources_t;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun  long get_page_size(void)
295*4882a593Smuzhiyun  {
296*4882a593Smuzhiyun	long page_size=sysconf(_SC_PAGESIZE);
297*4882a593Smuzhiyun	return page_size;
298*4882a593Smuzhiyun  }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun  #define PAGE_SIZE (get_page_size()==-1?0x4000:get_page_size())
301*4882a593Smuzhiyun  #define SHM_SIZE (2*PAGE_SIZE*NR_CPUS)
302*4882a593Smuzhiyun  #define SHM_VA 0x2000000100000000
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun  int shmid;
305*4882a593Smuzhiyun  void *shmaddr;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun  int create_shm(void)
308*4882a593Smuzhiyun  {
309*4882a593Smuzhiyun	key_t key;
310*4882a593Smuzhiyun	char fn[MAX_FN_SIZE];
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun	/* cpu0 is always existing */
313*4882a593Smuzhiyun	sprintf(fn, PATH_FORMAT, 0);
314*4882a593Smuzhiyun	if ((key = ftok(fn, 's')) == -1) {
315*4882a593Smuzhiyun		perror("ftok");
316*4882a593Smuzhiyun		return -1;
317*4882a593Smuzhiyun	}
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun	shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT);
320*4882a593Smuzhiyun	if (shmid == -1) {
321*4882a593Smuzhiyun		if (errno==EEXIST) {
322*4882a593Smuzhiyun			shmid = shmget(key, SHM_SIZE, 0);
323*4882a593Smuzhiyun			if (shmid == -1) {
324*4882a593Smuzhiyun				perror("shmget");
325*4882a593Smuzhiyun				return -1;
326*4882a593Smuzhiyun			}
327*4882a593Smuzhiyun		}
328*4882a593Smuzhiyun		else {
329*4882a593Smuzhiyun			perror("shmget");
330*4882a593Smuzhiyun			return -1;
331*4882a593Smuzhiyun		}
332*4882a593Smuzhiyun	}
333*4882a593Smuzhiyun	vbprintf("shmid=%d", shmid);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun	/* connect to the segment: */
336*4882a593Smuzhiyun	shmaddr = shmat(shmid, (void *)SHM_VA, 0);
337*4882a593Smuzhiyun	if (shmaddr == (void*)-1) {
338*4882a593Smuzhiyun		perror("shmat");
339*4882a593Smuzhiyun		return -1;
340*4882a593Smuzhiyun	}
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun	memset(shmaddr, 0, SHM_SIZE);
343*4882a593Smuzhiyun	mlock(shmaddr, SHM_SIZE);
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun	return 0;
346*4882a593Smuzhiyun  }
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun  int free_shm()
349*4882a593Smuzhiyun  {
350*4882a593Smuzhiyun	munlock(shmaddr, SHM_SIZE);
351*4882a593Smuzhiyun          shmdt(shmaddr);
352*4882a593Smuzhiyun	semctl(shmid, 0, IPC_RMID);
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun	return 0;
355*4882a593Smuzhiyun  }
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun  #ifdef _SEM_SEMUN_UNDEFINED
358*4882a593Smuzhiyun  union semun
359*4882a593Smuzhiyun  {
360*4882a593Smuzhiyun	int val;
361*4882a593Smuzhiyun	struct semid_ds *buf;
362*4882a593Smuzhiyun	unsigned short int *array;
363*4882a593Smuzhiyun	struct seminfo *__buf;
364*4882a593Smuzhiyun  };
365*4882a593Smuzhiyun  #endif
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun  u32 mode=1; /* 1: physical mode; 2: virtual mode. */
368*4882a593Smuzhiyun  int one_lock=1;
369*4882a593Smuzhiyun  key_t key[NR_CPUS];
370*4882a593Smuzhiyun  int semid[NR_CPUS];
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun  int create_sem(int cpu)
373*4882a593Smuzhiyun  {
374*4882a593Smuzhiyun	union semun arg;
375*4882a593Smuzhiyun	char fn[MAX_FN_SIZE];
376*4882a593Smuzhiyun	int sid;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun	sprintf(fn, PATH_FORMAT, cpu);
379*4882a593Smuzhiyun	sprintf(fn, "%s/%s", fn, "err_type_info");
380*4882a593Smuzhiyun	if ((key[cpu] = ftok(fn, 'e')) == -1) {
381*4882a593Smuzhiyun		perror("ftok");
382*4882a593Smuzhiyun		return -1;
383*4882a593Smuzhiyun	}
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun	if (semid[cpu]!=0)
386*4882a593Smuzhiyun		return 0;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun	/* clear old semaphore */
389*4882a593Smuzhiyun	if ((sid = semget(key[cpu], 1, 0)) != -1)
390*4882a593Smuzhiyun		semctl(sid, 0, IPC_RMID);
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun	/* get one semaphore */
393*4882a593Smuzhiyun	if ((semid[cpu] = semget(key[cpu], 1, IPC_CREAT | IPC_EXCL)) == -1) {
394*4882a593Smuzhiyun		perror("semget");
395*4882a593Smuzhiyun		printf("Please remove semaphore with key=0x%lx, then run the tool.\n",
396*4882a593Smuzhiyun			(u64)key[cpu]);
397*4882a593Smuzhiyun		return -1;
398*4882a593Smuzhiyun	}
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun	vbprintf("semid[%d]=0x%lx, key[%d]=%lx\n",cpu,(u64)semid[cpu],cpu,
401*4882a593Smuzhiyun		(u64)key[cpu]);
402*4882a593Smuzhiyun	/* initialize the semaphore to 1: */
403*4882a593Smuzhiyun	arg.val = 1;
404*4882a593Smuzhiyun	if (semctl(semid[cpu], 0, SETVAL, arg) == -1) {
405*4882a593Smuzhiyun		perror("semctl");
406*4882a593Smuzhiyun		return -1;
407*4882a593Smuzhiyun	}
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun	return 0;
410*4882a593Smuzhiyun  }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun  static int lock(int cpu)
413*4882a593Smuzhiyun  {
414*4882a593Smuzhiyun	struct sembuf lock;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun	lock.sem_num = cpu;
417*4882a593Smuzhiyun	lock.sem_op = 1;
418*4882a593Smuzhiyun	semop(semid[cpu], &lock, 1);
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun          return 0;
421*4882a593Smuzhiyun  }
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun  static int unlock(int cpu)
424*4882a593Smuzhiyun  {
425*4882a593Smuzhiyun	struct sembuf unlock;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun	unlock.sem_num = cpu;
428*4882a593Smuzhiyun	unlock.sem_op = -1;
429*4882a593Smuzhiyun	semop(semid[cpu], &unlock, 1);
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun          return 0;
432*4882a593Smuzhiyun  }
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun  void free_sem(int cpu)
435*4882a593Smuzhiyun  {
436*4882a593Smuzhiyun	semctl(semid[cpu], 0, IPC_RMID);
437*4882a593Smuzhiyun  }
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun  int wr_multi(char *fn, unsigned long *data, int size)
440*4882a593Smuzhiyun  {
441*4882a593Smuzhiyun	int fd;
442*4882a593Smuzhiyun	char buf[MAX_BUF_SIZE];
443*4882a593Smuzhiyun	int ret;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun	if (size==1)
446*4882a593Smuzhiyun		sprintf(buf, "%lx", *data);
447*4882a593Smuzhiyun	else if (size==3)
448*4882a593Smuzhiyun		sprintf(buf, "%lx,%lx,%lx", data[0], data[1], data[2]);
449*4882a593Smuzhiyun	else {
450*4882a593Smuzhiyun		fprintf(stderr,"write to file with wrong size!\n");
451*4882a593Smuzhiyun		return -1;
452*4882a593Smuzhiyun	}
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun	fd=open(fn, O_RDWR);
455*4882a593Smuzhiyun	if (!fd) {
456*4882a593Smuzhiyun		perror("Error:");
457*4882a593Smuzhiyun		return -1;
458*4882a593Smuzhiyun	}
459*4882a593Smuzhiyun	ret=write(fd, buf, sizeof(buf));
460*4882a593Smuzhiyun	close(fd);
461*4882a593Smuzhiyun	return ret;
462*4882a593Smuzhiyun  }
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun  int wr(char *fn, unsigned long data)
465*4882a593Smuzhiyun  {
466*4882a593Smuzhiyun	return wr_multi(fn, &data, 1);
467*4882a593Smuzhiyun  }
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun  int rd(char *fn, unsigned long *data)
470*4882a593Smuzhiyun  {
471*4882a593Smuzhiyun	int fd;
472*4882a593Smuzhiyun	char buf[MAX_BUF_SIZE];
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun	fd=open(fn, O_RDONLY);
475*4882a593Smuzhiyun	if (fd<0) {
476*4882a593Smuzhiyun		perror("Error:");
477*4882a593Smuzhiyun		return -1;
478*4882a593Smuzhiyun	}
479*4882a593Smuzhiyun	read(fd, buf, MAX_BUF_SIZE);
480*4882a593Smuzhiyun	*data=strtoul(buf, NULL, 16);
481*4882a593Smuzhiyun	close(fd);
482*4882a593Smuzhiyun	return 0;
483*4882a593Smuzhiyun  }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun  int rd_status(char *path, int *status)
486*4882a593Smuzhiyun  {
487*4882a593Smuzhiyun	char fn[MAX_FN_SIZE];
488*4882a593Smuzhiyun	sprintf(fn, "%s/status", path);
489*4882a593Smuzhiyun	if (rd(fn, (u64*)status)<0) {
490*4882a593Smuzhiyun		perror("status reading error.\n");
491*4882a593Smuzhiyun		return -1;
492*4882a593Smuzhiyun	}
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun	return 0;
495*4882a593Smuzhiyun  }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun  int rd_capabilities(char *path, u64 *capabilities)
498*4882a593Smuzhiyun  {
499*4882a593Smuzhiyun	char fn[MAX_FN_SIZE];
500*4882a593Smuzhiyun	sprintf(fn, "%s/capabilities", path);
501*4882a593Smuzhiyun	if (rd(fn, capabilities)<0) {
502*4882a593Smuzhiyun		perror("capabilities reading error.\n");
503*4882a593Smuzhiyun		return -1;
504*4882a593Smuzhiyun	}
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun	return 0;
507*4882a593Smuzhiyun  }
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun  int rd_all(char *path)
510*4882a593Smuzhiyun  {
511*4882a593Smuzhiyun	unsigned long err_type_info, err_struct_info, err_data_buffer;
512*4882a593Smuzhiyun	int status;
513*4882a593Smuzhiyun	unsigned long capabilities, resources;
514*4882a593Smuzhiyun	char fn[MAX_FN_SIZE];
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun	sprintf(fn, "%s/err_type_info", path);
517*4882a593Smuzhiyun	if (rd(fn, &err_type_info)<0) {
518*4882a593Smuzhiyun		perror("err_type_info reading error.\n");
519*4882a593Smuzhiyun		return -1;
520*4882a593Smuzhiyun	}
521*4882a593Smuzhiyun	printf("err_type_info=%lx\n", err_type_info);
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun	sprintf(fn, "%s/err_struct_info", path);
524*4882a593Smuzhiyun	if (rd(fn, &err_struct_info)<0) {
525*4882a593Smuzhiyun		perror("err_struct_info reading error.\n");
526*4882a593Smuzhiyun		return -1;
527*4882a593Smuzhiyun	}
528*4882a593Smuzhiyun	printf("err_struct_info=%lx\n", err_struct_info);
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun	sprintf(fn, "%s/err_data_buffer", path);
531*4882a593Smuzhiyun	if (rd(fn, &err_data_buffer)<0) {
532*4882a593Smuzhiyun		perror("err_data_buffer reading error.\n");
533*4882a593Smuzhiyun		return -1;
534*4882a593Smuzhiyun	}
535*4882a593Smuzhiyun	printf("err_data_buffer=%lx\n", err_data_buffer);
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun	sprintf(fn, "%s/status", path);
538*4882a593Smuzhiyun	if (rd("status", (u64*)&status)<0) {
539*4882a593Smuzhiyun		perror("status reading error.\n");
540*4882a593Smuzhiyun		return -1;
541*4882a593Smuzhiyun	}
542*4882a593Smuzhiyun	printf("status=%d\n", status);
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun	sprintf(fn, "%s/capabilities", path);
545*4882a593Smuzhiyun	if (rd(fn,&capabilities)<0) {
546*4882a593Smuzhiyun		perror("capabilities reading error.\n");
547*4882a593Smuzhiyun		return -1;
548*4882a593Smuzhiyun	}
549*4882a593Smuzhiyun	printf("capabilities=%lx\n", capabilities);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun	sprintf(fn, "%s/resources", path);
552*4882a593Smuzhiyun	if (rd(fn, &resources)<0) {
553*4882a593Smuzhiyun		perror("resources reading error.\n");
554*4882a593Smuzhiyun		return -1;
555*4882a593Smuzhiyun	}
556*4882a593Smuzhiyun	printf("resources=%lx\n", resources);
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun	return 0;
559*4882a593Smuzhiyun  }
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun  int query_capabilities(char *path, err_type_info_t err_type_info,
562*4882a593Smuzhiyun			u64 *capabilities)
563*4882a593Smuzhiyun  {
564*4882a593Smuzhiyun	char fn[MAX_FN_SIZE];
565*4882a593Smuzhiyun	err_struct_info_t err_struct_info;
566*4882a593Smuzhiyun	err_data_buffer_t err_data_buffer;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun	err_struct_info.err_struct_info=0;
569*4882a593Smuzhiyun	memset(err_data_buffer.err_data_buffer, -1, ERR_DATA_BUFFER_SIZE*8);
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun	sprintf(fn, "%s/err_type_info", path);
572*4882a593Smuzhiyun	wr(fn, err_type_info.err_type_info);
573*4882a593Smuzhiyun	sprintf(fn, "%s/err_struct_info", path);
574*4882a593Smuzhiyun	wr(fn, 0x0);
575*4882a593Smuzhiyun	sprintf(fn, "%s/err_data_buffer", path);
576*4882a593Smuzhiyun	wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun	// Fire pal_mc_error_inject procedure.
579*4882a593Smuzhiyun	sprintf(fn, "%s/call_start", path);
580*4882a593Smuzhiyun	wr(fn, mode);
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun	if (rd_capabilities(path, capabilities)<0)
583*4882a593Smuzhiyun		return -1;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun	return 0;
586*4882a593Smuzhiyun  }
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun  int query_all_capabilities()
589*4882a593Smuzhiyun  {
590*4882a593Smuzhiyun	int status;
591*4882a593Smuzhiyun	err_type_info_t err_type_info;
592*4882a593Smuzhiyun	int err_sev, err_struct, struct_hier;
593*4882a593Smuzhiyun	int cap=0;
594*4882a593Smuzhiyun	u64 capabilities;
595*4882a593Smuzhiyun	char path[MAX_FN_SIZE];
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun	err_type_info.err_type_info=0;			// Initial
598*4882a593Smuzhiyun	err_type_info.err_type_info_u.mode=0;		// Query mode;
599*4882a593Smuzhiyun	err_type_info.err_type_info_u.err_inj=0;
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun	printf("All capabilities implemented in pal_mc_error_inject:\n");
602*4882a593Smuzhiyun	sprintf(path, PATH_FORMAT ,0);
603*4882a593Smuzhiyun	for (err_sev=0;err_sev<3;err_sev++)
604*4882a593Smuzhiyun		for (err_struct=0;err_struct<5;err_struct++)
605*4882a593Smuzhiyun			for (struct_hier=0;struct_hier<5;struct_hier++)
606*4882a593Smuzhiyun	{
607*4882a593Smuzhiyun		status=-1;
608*4882a593Smuzhiyun		capabilities=0;
609*4882a593Smuzhiyun		err_type_info.err_type_info_u.err_sev=err_sev;
610*4882a593Smuzhiyun		err_type_info.err_type_info_u.err_struct=err_struct;
611*4882a593Smuzhiyun		err_type_info.err_type_info_u.struct_hier=struct_hier;
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun		if (query_capabilities(path, err_type_info, &capabilities)<0)
614*4882a593Smuzhiyun			continue;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun		if (rd_status(path, &status)<0)
617*4882a593Smuzhiyun			continue;
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun		if (status==0) {
620*4882a593Smuzhiyun			cap=1;
621*4882a593Smuzhiyun			printf("For err_sev=%d, err_struct=%d, struct_hier=%d: ",
622*4882a593Smuzhiyun				err_sev, err_struct, struct_hier);
623*4882a593Smuzhiyun			printf("capabilities 0x%lx\n", capabilities);
624*4882a593Smuzhiyun		}
625*4882a593Smuzhiyun	}
626*4882a593Smuzhiyun	if (!cap) {
627*4882a593Smuzhiyun		printf("No capabilities supported.\n");
628*4882a593Smuzhiyun		return 0;
629*4882a593Smuzhiyun	}
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun	return 0;
632*4882a593Smuzhiyun  }
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun  int err_inject(int cpu, char *path, err_type_info_t err_type_info,
635*4882a593Smuzhiyun		err_struct_info_t err_struct_info,
636*4882a593Smuzhiyun		err_data_buffer_t err_data_buffer)
637*4882a593Smuzhiyun  {
638*4882a593Smuzhiyun	int status;
639*4882a593Smuzhiyun	char fn[MAX_FN_SIZE];
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun	log_info(cpu, "err_type_info=%lx, err_struct_info=%lx, ",
642*4882a593Smuzhiyun		err_type_info.err_type_info,
643*4882a593Smuzhiyun		err_struct_info.err_struct_info);
644*4882a593Smuzhiyun	log_info(cpu,"err_data_buffer=[%lx,%lx,%lx]\n",
645*4882a593Smuzhiyun		err_data_buffer.err_data_buffer[0],
646*4882a593Smuzhiyun		err_data_buffer.err_data_buffer[1],
647*4882a593Smuzhiyun		err_data_buffer.err_data_buffer[2]);
648*4882a593Smuzhiyun	sprintf(fn, "%s/err_type_info", path);
649*4882a593Smuzhiyun	wr(fn, err_type_info.err_type_info);
650*4882a593Smuzhiyun	sprintf(fn, "%s/err_struct_info", path);
651*4882a593Smuzhiyun	wr(fn, err_struct_info.err_struct_info);
652*4882a593Smuzhiyun	sprintf(fn, "%s/err_data_buffer", path);
653*4882a593Smuzhiyun	wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun	// Fire pal_mc_error_inject procedure.
656*4882a593Smuzhiyun	sprintf(fn, "%s/call_start", path);
657*4882a593Smuzhiyun	wr(fn,mode);
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun	if (rd_status(path, &status)<0) {
660*4882a593Smuzhiyun		vbprintf("fail: read status\n");
661*4882a593Smuzhiyun		return -100;
662*4882a593Smuzhiyun	}
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun	if (status!=0) {
665*4882a593Smuzhiyun		log_info(cpu, "fail: status=%d\n", status);
666*4882a593Smuzhiyun		return status;
667*4882a593Smuzhiyun	}
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun	return status;
670*4882a593Smuzhiyun  }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun  static int construct_data_buf(char *path, err_type_info_t err_type_info,
673*4882a593Smuzhiyun		err_struct_info_t err_struct_info,
674*4882a593Smuzhiyun		err_data_buffer_t *err_data_buffer,
675*4882a593Smuzhiyun		void *va1)
676*4882a593Smuzhiyun  {
677*4882a593Smuzhiyun	char fn[MAX_FN_SIZE];
678*4882a593Smuzhiyun	u64 virt_addr=0, phys_addr=0;
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun	vbprintf("va1=%lx\n", (u64)va1);
681*4882a593Smuzhiyun	memset(&err_data_buffer->err_data_buffer_cache, 0, ERR_DATA_BUFFER_SIZE*8);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun	switch (err_type_info.err_type_info_u.err_struct) {
684*4882a593Smuzhiyun		case 1: // Cache
685*4882a593Smuzhiyun			switch (err_struct_info.err_struct_info_cache.cl_id) {
686*4882a593Smuzhiyun				case 1: //Virtual addr
687*4882a593Smuzhiyun					err_data_buffer->err_data_buffer_cache.inj_addr=(u64)va1;
688*4882a593Smuzhiyun					break;
689*4882a593Smuzhiyun				case 2: //Phys addr
690*4882a593Smuzhiyun					sprintf(fn, "%s/virtual_to_phys", path);
691*4882a593Smuzhiyun					virt_addr=(u64)va1;
692*4882a593Smuzhiyun					if (wr(fn,virt_addr)<0)
693*4882a593Smuzhiyun						return -1;
694*4882a593Smuzhiyun					rd(fn, &phys_addr);
695*4882a593Smuzhiyun					err_data_buffer->err_data_buffer_cache.inj_addr=phys_addr;
696*4882a593Smuzhiyun					break;
697*4882a593Smuzhiyun				default:
698*4882a593Smuzhiyun					printf("Not supported cl_id\n");
699*4882a593Smuzhiyun					break;
700*4882a593Smuzhiyun			}
701*4882a593Smuzhiyun			break;
702*4882a593Smuzhiyun		case 2: //  TLB
703*4882a593Smuzhiyun			break;
704*4882a593Smuzhiyun		case 3: //  Register file
705*4882a593Smuzhiyun			break;
706*4882a593Smuzhiyun		case 4: //  Bus/system interconnect
707*4882a593Smuzhiyun		default:
708*4882a593Smuzhiyun			printf("Not supported err_struct\n");
709*4882a593Smuzhiyun			break;
710*4882a593Smuzhiyun	}
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun	return 0;
713*4882a593Smuzhiyun  }
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun  typedef struct {
716*4882a593Smuzhiyun	u64 cpu;
717*4882a593Smuzhiyun	u64 loop;
718*4882a593Smuzhiyun	u64 interval;
719*4882a593Smuzhiyun	u64 err_type_info;
720*4882a593Smuzhiyun	u64 err_struct_info;
721*4882a593Smuzhiyun	u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
722*4882a593Smuzhiyun  } parameters_t;
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun  parameters_t line_para;
725*4882a593Smuzhiyun  int para;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun  static int empty_data_buffer(u64 *err_data_buffer)
728*4882a593Smuzhiyun  {
729*4882a593Smuzhiyun	int empty=1;
730*4882a593Smuzhiyun	int i;
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun	for (i=0;i<ERR_DATA_BUFFER_SIZE; i++)
733*4882a593Smuzhiyun	   if (err_data_buffer[i]!=-1)
734*4882a593Smuzhiyun		empty=0;
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun	return empty;
737*4882a593Smuzhiyun  }
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun  int err_inj()
740*4882a593Smuzhiyun  {
741*4882a593Smuzhiyun	err_type_info_t err_type_info;
742*4882a593Smuzhiyun	err_struct_info_t err_struct_info;
743*4882a593Smuzhiyun	err_data_buffer_t err_data_buffer;
744*4882a593Smuzhiyun	int count;
745*4882a593Smuzhiyun	FILE *fp;
746*4882a593Smuzhiyun	unsigned long cpu, loop, interval, err_type_info_conf, err_struct_info_conf;
747*4882a593Smuzhiyun	u64 err_data_buffer_conf[ERR_DATA_BUFFER_SIZE];
748*4882a593Smuzhiyun	int num;
749*4882a593Smuzhiyun	int i;
750*4882a593Smuzhiyun	char path[MAX_FN_SIZE];
751*4882a593Smuzhiyun	parameters_t parameters[MAX_TASK_NUM]={};
752*4882a593Smuzhiyun	pid_t child_pid[MAX_TASK_NUM];
753*4882a593Smuzhiyun	time_t current_time;
754*4882a593Smuzhiyun	int status;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun	if (!para) {
757*4882a593Smuzhiyun	    fp=fopen("err.conf", "r");
758*4882a593Smuzhiyun	    if (fp==NULL) {
759*4882a593Smuzhiyun		perror("Error open err.conf");
760*4882a593Smuzhiyun		return -1;
761*4882a593Smuzhiyun	    }
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun	    num=0;
764*4882a593Smuzhiyun	    while (!feof(fp)) {
765*4882a593Smuzhiyun		char buf[256];
766*4882a593Smuzhiyun		memset(buf,0,256);
767*4882a593Smuzhiyun		fgets(buf, 256, fp);
768*4882a593Smuzhiyun		count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
769*4882a593Smuzhiyun				&cpu, &loop, &interval,&err_type_info_conf,
770*4882a593Smuzhiyun				&err_struct_info_conf,
771*4882a593Smuzhiyun				&err_data_buffer_conf[0],
772*4882a593Smuzhiyun				&err_data_buffer_conf[1],
773*4882a593Smuzhiyun				&err_data_buffer_conf[2]);
774*4882a593Smuzhiyun		if (count!=PARA_FIELD_NUM+3) {
775*4882a593Smuzhiyun			err_data_buffer_conf[0]=-1;
776*4882a593Smuzhiyun			err_data_buffer_conf[1]=-1;
777*4882a593Smuzhiyun			err_data_buffer_conf[2]=-1;
778*4882a593Smuzhiyun			count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx\n",
779*4882a593Smuzhiyun				&cpu, &loop, &interval,&err_type_info_conf,
780*4882a593Smuzhiyun				&err_struct_info_conf);
781*4882a593Smuzhiyun			if (count!=PARA_FIELD_NUM)
782*4882a593Smuzhiyun				continue;
783*4882a593Smuzhiyun		}
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun		parameters[num].cpu=cpu;
786*4882a593Smuzhiyun		parameters[num].loop=loop;
787*4882a593Smuzhiyun		parameters[num].interval= interval>MIN_INTERVAL
788*4882a593Smuzhiyun					  ?interval:MIN_INTERVAL;
789*4882a593Smuzhiyun		parameters[num].err_type_info=err_type_info_conf;
790*4882a593Smuzhiyun		parameters[num].err_struct_info=err_struct_info_conf;
791*4882a593Smuzhiyun		memcpy(parameters[num++].err_data_buffer,
792*4882a593Smuzhiyun			err_data_buffer_conf,ERR_DATA_BUFFER_SIZE*8) ;
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun		if (num>=MAX_TASK_NUM)
795*4882a593Smuzhiyun			break;
796*4882a593Smuzhiyun	    }
797*4882a593Smuzhiyun	}
798*4882a593Smuzhiyun	else {
799*4882a593Smuzhiyun		parameters[0].cpu=line_para.cpu;
800*4882a593Smuzhiyun		parameters[0].loop=line_para.loop;
801*4882a593Smuzhiyun		parameters[0].interval= line_para.interval>MIN_INTERVAL
802*4882a593Smuzhiyun					  ?line_para.interval:MIN_INTERVAL;
803*4882a593Smuzhiyun		parameters[0].err_type_info=line_para.err_type_info;
804*4882a593Smuzhiyun		parameters[0].err_struct_info=line_para.err_struct_info;
805*4882a593Smuzhiyun		memcpy(parameters[0].err_data_buffer,
806*4882a593Smuzhiyun			line_para.err_data_buffer,ERR_DATA_BUFFER_SIZE*8) ;
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun		num=1;
809*4882a593Smuzhiyun	}
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun	/* Create semaphore: If one_lock, one semaphore for all processors.
812*4882a593Smuzhiyun	   Otherwise, one semaphore for each processor. */
813*4882a593Smuzhiyun	if (one_lock) {
814*4882a593Smuzhiyun		if (create_sem(0)) {
815*4882a593Smuzhiyun			printf("Can not create semaphore...exit\n");
816*4882a593Smuzhiyun			free_sem(0);
817*4882a593Smuzhiyun			return -1;
818*4882a593Smuzhiyun		}
819*4882a593Smuzhiyun	}
820*4882a593Smuzhiyun	else {
821*4882a593Smuzhiyun		for (i=0;i<num;i++) {
822*4882a593Smuzhiyun		   if (create_sem(parameters[i].cpu)) {
823*4882a593Smuzhiyun			printf("Can not create semaphore for cpu%d...exit\n",i);
824*4882a593Smuzhiyun			free_sem(parameters[num].cpu);
825*4882a593Smuzhiyun			return -1;
826*4882a593Smuzhiyun		   }
827*4882a593Smuzhiyun		}
828*4882a593Smuzhiyun	}
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun	/* Create a shm segment which will be used to inject/consume errors on.*/
831*4882a593Smuzhiyun	if (create_shm()==-1) {
832*4882a593Smuzhiyun		printf("Error to create shm...exit\n");
833*4882a593Smuzhiyun		return -1;
834*4882a593Smuzhiyun	}
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun	for (i=0;i<num;i++) {
837*4882a593Smuzhiyun		pid_t pid;
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun		current_time=time(NULL);
840*4882a593Smuzhiyun		log_info(parameters[i].cpu, "\nBegine at %s", ctime(&current_time));
841*4882a593Smuzhiyun		log_info(parameters[i].cpu, "Configurations:\n");
842*4882a593Smuzhiyun		log_info(parameters[i].cpu,"On cpu%ld: loop=%lx, interval=%lx(s)",
843*4882a593Smuzhiyun			parameters[i].cpu,
844*4882a593Smuzhiyun			parameters[i].loop,
845*4882a593Smuzhiyun			parameters[i].interval);
846*4882a593Smuzhiyun		log_info(parameters[i].cpu," err_type_info=%lx,err_struct_info=%lx\n",
847*4882a593Smuzhiyun			parameters[i].err_type_info,
848*4882a593Smuzhiyun			parameters[i].err_struct_info);
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun		sprintf(path, PATH_FORMAT, (int)parameters[i].cpu);
851*4882a593Smuzhiyun		err_type_info.err_type_info=parameters[i].err_type_info;
852*4882a593Smuzhiyun		err_struct_info.err_struct_info=parameters[i].err_struct_info;
853*4882a593Smuzhiyun		memcpy(err_data_buffer.err_data_buffer,
854*4882a593Smuzhiyun			parameters[i].err_data_buffer,
855*4882a593Smuzhiyun			ERR_DATA_BUFFER_SIZE*8);
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun		pid=fork();
858*4882a593Smuzhiyun		if (pid==0) {
859*4882a593Smuzhiyun			unsigned long mask[MASK_SIZE];
860*4882a593Smuzhiyun			int j, k;
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun			void *va1, *va2;
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun			/* Allocate two memory areas va1 and va2 in shm */
865*4882a593Smuzhiyun			va1=shmaddr+parameters[i].cpu*PAGE_SIZE;
866*4882a593Smuzhiyun			va2=shmaddr+parameters[i].cpu*PAGE_SIZE+PAGE_SIZE;
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun			vbprintf("va1=%lx, va2=%lx\n", (u64)va1, (u64)va2);
869*4882a593Smuzhiyun			memset(va1, 0x1, PAGE_SIZE);
870*4882a593Smuzhiyun			memset(va2, 0x2, PAGE_SIZE);
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun			if (empty_data_buffer(err_data_buffer.err_data_buffer))
873*4882a593Smuzhiyun				/* If not specified yet, construct data buffer
874*4882a593Smuzhiyun				 * with va1
875*4882a593Smuzhiyun				 */
876*4882a593Smuzhiyun				construct_data_buf(path, err_type_info,
877*4882a593Smuzhiyun					err_struct_info, &err_data_buffer,va1);
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun			for (j=0;j<MASK_SIZE;j++)
880*4882a593Smuzhiyun				mask[j]=0;
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun			cpu=parameters[i].cpu;
883*4882a593Smuzhiyun			k = cpu%64;
884*4882a593Smuzhiyun			j = cpu/64;
885*4882a593Smuzhiyun			mask[j] = 1UL << k;
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun			if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) {
888*4882a593Smuzhiyun				perror("Error sched_setaffinity:");
889*4882a593Smuzhiyun				return -1;
890*4882a593Smuzhiyun			}
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun			for (j=0; j<parameters[i].loop; j++) {
893*4882a593Smuzhiyun				log_info(parameters[i].cpu,"Injection ");
894*4882a593Smuzhiyun				log_info(parameters[i].cpu,"on cpu%ld: #%d/%ld ",
895*4882a593Smuzhiyun
896*4882a593Smuzhiyun					parameters[i].cpu,j+1, parameters[i].loop);
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun				/* Hold the lock */
899*4882a593Smuzhiyun				if (one_lock)
900*4882a593Smuzhiyun					lock(0);
901*4882a593Smuzhiyun				else
902*4882a593Smuzhiyun				/* Hold lock on this cpu */
903*4882a593Smuzhiyun					lock(parameters[i].cpu);
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun				if ((status=err_inject(parameters[i].cpu,
906*4882a593Smuzhiyun					   path, err_type_info,
907*4882a593Smuzhiyun					   err_struct_info, err_data_buffer))
908*4882a593Smuzhiyun					   ==0) {
909*4882a593Smuzhiyun					/* consume the error for "inject only"*/
910*4882a593Smuzhiyun					memcpy(va2, va1, PAGE_SIZE);
911*4882a593Smuzhiyun					memcpy(va1, va2, PAGE_SIZE);
912*4882a593Smuzhiyun					log_info(parameters[i].cpu,
913*4882a593Smuzhiyun						"successful\n");
914*4882a593Smuzhiyun				}
915*4882a593Smuzhiyun				else {
916*4882a593Smuzhiyun					log_info(parameters[i].cpu,"fail:");
917*4882a593Smuzhiyun					log_info(parameters[i].cpu,
918*4882a593Smuzhiyun						"status=%d\n", status);
919*4882a593Smuzhiyun					unlock(parameters[i].cpu);
920*4882a593Smuzhiyun					break;
921*4882a593Smuzhiyun				}
922*4882a593Smuzhiyun				if (one_lock)
923*4882a593Smuzhiyun				/* Release the lock */
924*4882a593Smuzhiyun					unlock(0);
925*4882a593Smuzhiyun				/* Release lock on this cpu */
926*4882a593Smuzhiyun				else
927*4882a593Smuzhiyun					unlock(parameters[i].cpu);
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun				if (j < parameters[i].loop-1)
930*4882a593Smuzhiyun					sleep(parameters[i].interval);
931*4882a593Smuzhiyun			}
932*4882a593Smuzhiyun			current_time=time(NULL);
933*4882a593Smuzhiyun			log_info(parameters[i].cpu, "Done at %s", ctime(&current_time));
934*4882a593Smuzhiyun			return 0;
935*4882a593Smuzhiyun		}
936*4882a593Smuzhiyun		else if (pid<0) {
937*4882a593Smuzhiyun			perror("Error fork:");
938*4882a593Smuzhiyun			continue;
939*4882a593Smuzhiyun		}
940*4882a593Smuzhiyun		child_pid[i]=pid;
941*4882a593Smuzhiyun	}
942*4882a593Smuzhiyun	for (i=0;i<num;i++)
943*4882a593Smuzhiyun		waitpid(child_pid[i], NULL, 0);
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun	if (one_lock)
946*4882a593Smuzhiyun		free_sem(0);
947*4882a593Smuzhiyun	else
948*4882a593Smuzhiyun		for (i=0;i<num;i++)
949*4882a593Smuzhiyun			free_sem(parameters[i].cpu);
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun	printf("All done.\n");
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun	return 0;
954*4882a593Smuzhiyun  }
955*4882a593Smuzhiyun
956*4882a593Smuzhiyun  void help()
957*4882a593Smuzhiyun  {
958*4882a593Smuzhiyun	printf("err_inject_tool:\n");
959*4882a593Smuzhiyun	printf("\t-q: query all capabilities. default: off\n");
960*4882a593Smuzhiyun	printf("\t-m: procedure mode. 1: physical 2: virtual. default: 1\n");
961*4882a593Smuzhiyun	printf("\t-i: inject errors. default: off\n");
962*4882a593Smuzhiyun	printf("\t-l: one lock per cpu. default: one lock for all\n");
963*4882a593Smuzhiyun	printf("\t-e: error parameters:\n");
964*4882a593Smuzhiyun	printf("\t\tcpu,loop,interval,err_type_info,err_struct_info[,err_data_buffer[0],err_data_buffer[1],err_data_buffer[2]]\n");
965*4882a593Smuzhiyun	printf("\t\t   cpu: logical cpu number the error will be inject in.\n");
966*4882a593Smuzhiyun	printf("\t\t   loop: times the error will be injected.\n");
967*4882a593Smuzhiyun	printf("\t\t   interval: In second. every so often one error is injected.\n");
968*4882a593Smuzhiyun	printf("\t\t   err_type_info, err_struct_info: PAL parameters.\n");
969*4882a593Smuzhiyun	printf("\t\t   err_data_buffer: PAL parameter. Optional. If not present,\n");
970*4882a593Smuzhiyun	printf("\t\t                    it's constructed by tool automatically. Be\n");
971*4882a593Smuzhiyun	printf("\t\t                    careful to provide err_data_buffer and make\n");
972*4882a593Smuzhiyun	printf("\t\t                    sure it's working with the environment.\n");
973*4882a593Smuzhiyun	printf("\t    Note:no space between error parameters.\n");
974*4882a593Smuzhiyun	printf("\t    default: Take error parameters from err.conf instead of command line.\n");
975*4882a593Smuzhiyun	printf("\t-v: verbose. default: off\n");
976*4882a593Smuzhiyun	printf("\t-h: help\n\n");
977*4882a593Smuzhiyun	printf("The tool will take err.conf file as ");
978*4882a593Smuzhiyun	printf("input to inject single or multiple errors ");
979*4882a593Smuzhiyun	printf("on one or multiple cpus in parallel.\n");
980*4882a593Smuzhiyun  }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun  int main(int argc, char **argv)
983*4882a593Smuzhiyun  {
984*4882a593Smuzhiyun	char c;
985*4882a593Smuzhiyun	int do_err_inj=0;
986*4882a593Smuzhiyun	int do_query_all=0;
987*4882a593Smuzhiyun	int count;
988*4882a593Smuzhiyun	u32 m;
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun	/* Default one lock for all cpu's */
991*4882a593Smuzhiyun	one_lock=1;
992*4882a593Smuzhiyun	while ((c = getopt(argc, argv, "m:iqvhle:")) != EOF)
993*4882a593Smuzhiyun		switch (c) {
994*4882a593Smuzhiyun			case 'm':	/* Procedure mode. 1: phys 2: virt */
995*4882a593Smuzhiyun				count=sscanf(optarg, "%x", &m);
996*4882a593Smuzhiyun				if (count!=1 || (m!=1 && m!=2)) {
997*4882a593Smuzhiyun					printf("Wrong mode number.\n");
998*4882a593Smuzhiyun					help();
999*4882a593Smuzhiyun					return -1;
1000*4882a593Smuzhiyun				}
1001*4882a593Smuzhiyun				mode=m;
1002*4882a593Smuzhiyun				break;
1003*4882a593Smuzhiyun			case 'i':	/* Inject errors */
1004*4882a593Smuzhiyun				do_err_inj=1;
1005*4882a593Smuzhiyun				break;
1006*4882a593Smuzhiyun			case 'q':	/* Query */
1007*4882a593Smuzhiyun				do_query_all=1;
1008*4882a593Smuzhiyun				break;
1009*4882a593Smuzhiyun			case 'v':	/* Verbose */
1010*4882a593Smuzhiyun				verbose=1;
1011*4882a593Smuzhiyun				break;
1012*4882a593Smuzhiyun			case 'l':	/* One lock per cpu */
1013*4882a593Smuzhiyun				one_lock=0;
1014*4882a593Smuzhiyun				break;
1015*4882a593Smuzhiyun			case 'e':	/* error arguments */
1016*4882a593Smuzhiyun				/* Take parameters:
1017*4882a593Smuzhiyun				 * #cpu, loop, interval, err_type_info, err_struct_info[, err_data_buffer]
1018*4882a593Smuzhiyun				 * err_data_buffer is optional. Recommend not to specify
1019*4882a593Smuzhiyun				 * err_data_buffer. Better to use tool to generate it.
1020*4882a593Smuzhiyun				 */
1021*4882a593Smuzhiyun				count=sscanf(optarg,
1022*4882a593Smuzhiyun					"%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
1023*4882a593Smuzhiyun					&line_para.cpu,
1024*4882a593Smuzhiyun					&line_para.loop,
1025*4882a593Smuzhiyun					&line_para.interval,
1026*4882a593Smuzhiyun					&line_para.err_type_info,
1027*4882a593Smuzhiyun					&line_para.err_struct_info,
1028*4882a593Smuzhiyun					&line_para.err_data_buffer[0],
1029*4882a593Smuzhiyun					&line_para.err_data_buffer[1],
1030*4882a593Smuzhiyun					&line_para.err_data_buffer[2]);
1031*4882a593Smuzhiyun				if (count!=PARA_FIELD_NUM+3) {
1032*4882a593Smuzhiyun				    line_para.err_data_buffer[0]=-1,
1033*4882a593Smuzhiyun				    line_para.err_data_buffer[1]=-1,
1034*4882a593Smuzhiyun				    line_para.err_data_buffer[2]=-1;
1035*4882a593Smuzhiyun				    count=sscanf(optarg, "%lx, %lx, %lx, %lx, %lx\n",
1036*4882a593Smuzhiyun						&line_para.cpu,
1037*4882a593Smuzhiyun						&line_para.loop,
1038*4882a593Smuzhiyun						&line_para.interval,
1039*4882a593Smuzhiyun						&line_para.err_type_info,
1040*4882a593Smuzhiyun						&line_para.err_struct_info);
1041*4882a593Smuzhiyun				    if (count!=PARA_FIELD_NUM) {
1042*4882a593Smuzhiyun					printf("Wrong error arguments.\n");
1043*4882a593Smuzhiyun					help();
1044*4882a593Smuzhiyun					return -1;
1045*4882a593Smuzhiyun				    }
1046*4882a593Smuzhiyun				}
1047*4882a593Smuzhiyun				para=1;
1048*4882a593Smuzhiyun				break;
1049*4882a593Smuzhiyun			continue;
1050*4882a593Smuzhiyun				break;
1051*4882a593Smuzhiyun			case 'h':
1052*4882a593Smuzhiyun				help();
1053*4882a593Smuzhiyun				return 0;
1054*4882a593Smuzhiyun			default:
1055*4882a593Smuzhiyun				break;
1056*4882a593Smuzhiyun		}
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun	if (do_query_all)
1059*4882a593Smuzhiyun		query_all_capabilities();
1060*4882a593Smuzhiyun	if (do_err_inj)
1061*4882a593Smuzhiyun		err_inj();
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun	if (!do_query_all &&  !do_err_inj)
1064*4882a593Smuzhiyun		help();
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun	return 0;
1067*4882a593Smuzhiyun  }
1068