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(¤t_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(¤t_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