📄 err_inject.txt
字号:
sprintf(fn, "%s/status", path); if (rd("status", (u64*)&status)<0) { perror("status reading error.\n"); return -1; } printf("status=%d\n", status); sprintf(fn, "%s/capabilities", path); if (rd(fn,&capabilities)<0) { perror("capabilities reading error.\n"); return -1; } printf("capabilities=%lx\n", capabilities); sprintf(fn, "%s/resources", path); if (rd(fn, &resources)<0) { perror("resources reading error.\n"); return -1; } printf("resources=%lx\n", resources); return 0;}int query_capabilities(char *path, err_type_info_t err_type_info, u64 *capabilities){ char fn[MAX_FN_SIZE]; err_struct_info_t err_struct_info; err_data_buffer_t err_data_buffer; err_struct_info.err_struct_info=0; memset(err_data_buffer.err_data_buffer, -1, ERR_DATA_BUFFER_SIZE*8); sprintf(fn, "%s/err_type_info", path); wr(fn, err_type_info.err_type_info); sprintf(fn, "%s/err_struct_info", path); wr(fn, 0x0); sprintf(fn, "%s/err_data_buffer", path); wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE); // Fire pal_mc_error_inject procedure. sprintf(fn, "%s/call_start", path); wr(fn, mode); if (rd_capabilities(path, capabilities)<0) return -1; return 0;}int query_all_capabilities(){ int status; err_type_info_t err_type_info; int err_sev, err_struct, struct_hier; int cap=0; u64 capabilities; char path[MAX_FN_SIZE]; err_type_info.err_type_info=0; // Initial err_type_info.err_type_info_u.mode=0; // Query mode; err_type_info.err_type_info_u.err_inj=0; printf("All capabilities implemented in pal_mc_error_inject:\n"); sprintf(path, PATH_FORMAT ,0); for (err_sev=0;err_sev<3;err_sev++) for (err_struct=0;err_struct<5;err_struct++) for (struct_hier=0;struct_hier<5;struct_hier++) { status=-1; capabilities=0; err_type_info.err_type_info_u.err_sev=err_sev; err_type_info.err_type_info_u.err_struct=err_struct; err_type_info.err_type_info_u.struct_hier=struct_hier; if (query_capabilities(path, err_type_info, &capabilities)<0) continue; if (rd_status(path, &status)<0) continue; if (status==0) { cap=1; printf("For err_sev=%d, err_struct=%d, struct_hier=%d: ", err_sev, err_struct, struct_hier); printf("capabilities 0x%lx\n", capabilities); } } if (!cap) { printf("No capabilities supported.\n"); return 0; } return 0;}int err_inject(int cpu, char *path, err_type_info_t err_type_info, err_struct_info_t err_struct_info, err_data_buffer_t err_data_buffer){ int status; char fn[MAX_FN_SIZE]; log_info(cpu, "err_type_info=%lx, err_struct_info=%lx, ", err_type_info.err_type_info, err_struct_info.err_struct_info); log_info(cpu,"err_data_buffer=[%lx,%lx,%lx]\n", err_data_buffer.err_data_buffer[0], err_data_buffer.err_data_buffer[1], err_data_buffer.err_data_buffer[2]); sprintf(fn, "%s/err_type_info", path); wr(fn, err_type_info.err_type_info); sprintf(fn, "%s/err_struct_info", path); wr(fn, err_struct_info.err_struct_info); sprintf(fn, "%s/err_data_buffer", path); wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE); // Fire pal_mc_error_inject procedure. sprintf(fn, "%s/call_start", path); wr(fn,mode); if (rd_status(path, &status)<0) { vbprintf("fail: read status\n"); return -100; } if (status!=0) { log_info(cpu, "fail: status=%d\n", status); return status; } return status;}static int construct_data_buf(char *path, err_type_info_t err_type_info, err_struct_info_t err_struct_info, err_data_buffer_t *err_data_buffer, void *va1){ char fn[MAX_FN_SIZE]; u64 virt_addr=0, phys_addr=0; vbprintf("va1=%lx\n", (u64)va1); memset(&err_data_buffer->err_data_buffer_cache, 0, ERR_DATA_BUFFER_SIZE*8); switch (err_type_info.err_type_info_u.err_struct) { case 1: // Cache switch (err_struct_info.err_struct_info_cache.cl_id) { case 1: //Virtual addr err_data_buffer->err_data_buffer_cache.inj_addr=(u64)va1; break; case 2: //Phys addr sprintf(fn, "%s/virtual_to_phys", path); virt_addr=(u64)va1; if (wr(fn,virt_addr)<0) return -1; rd(fn, &phys_addr); err_data_buffer->err_data_buffer_cache.inj_addr=phys_addr; break; default: printf("Not supported cl_id\n"); break; } break; case 2: // TLB break; case 3: // Register file break; case 4: // Bus/system interconnect default: printf("Not supported err_struct\n"); break; } return 0;}typedef struct { u64 cpu; u64 loop; u64 interval; u64 err_type_info; u64 err_struct_info; u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];} parameters_t;parameters_t line_para;int para;static int empty_data_buffer(u64 *err_data_buffer){ int empty=1; int i; for (i=0;i<ERR_DATA_BUFFER_SIZE; i++) if (err_data_buffer[i]!=-1) empty=0; return empty;}int err_inj(){ err_type_info_t err_type_info; err_struct_info_t err_struct_info; err_data_buffer_t err_data_buffer; int count; FILE *fp; unsigned long cpu, loop, interval, err_type_info_conf, err_struct_info_conf; u64 err_data_buffer_conf[ERR_DATA_BUFFER_SIZE]; int num; int i; char path[MAX_FN_SIZE]; parameters_t parameters[MAX_TASK_NUM]={}; pid_t child_pid[MAX_TASK_NUM]; time_t current_time; int status; if (!para) { fp=fopen("err.conf", "r"); if (fp==NULL) { perror("Error open err.conf"); return -1; } num=0; while (!feof(fp)) { char buf[256]; memset(buf,0,256); fgets(buf, 256, fp); count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n", &cpu, &loop, &interval,&err_type_info_conf, &err_struct_info_conf, &err_data_buffer_conf[0], &err_data_buffer_conf[1], &err_data_buffer_conf[2]); if (count!=PARA_FIELD_NUM+3) { err_data_buffer_conf[0]=-1; err_data_buffer_conf[1]=-1; err_data_buffer_conf[2]=-1; count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx\n", &cpu, &loop, &interval,&err_type_info_conf, &err_struct_info_conf); if (count!=PARA_FIELD_NUM) continue; } parameters[num].cpu=cpu; parameters[num].loop=loop; parameters[num].interval= interval>MIN_INTERVAL ?interval:MIN_INTERVAL; parameters[num].err_type_info=err_type_info_conf; parameters[num].err_struct_info=err_struct_info_conf; memcpy(parameters[num++].err_data_buffer, err_data_buffer_conf,ERR_DATA_BUFFER_SIZE*8) ; if (num>=MAX_TASK_NUM) break; } } else { parameters[0].cpu=line_para.cpu; parameters[0].loop=line_para.loop; parameters[0].interval= line_para.interval>MIN_INTERVAL ?line_para.interval:MIN_INTERVAL; parameters[0].err_type_info=line_para.err_type_info; parameters[0].err_struct_info=line_para.err_struct_info; memcpy(parameters[0].err_data_buffer, line_para.err_data_buffer,ERR_DATA_BUFFER_SIZE*8) ; num=1; } /* Create semaphore: If one_lock, one semaphore for all processors. Otherwise, one semaphore for each processor. */ if (one_lock) { if (create_sem(0)) { printf("Can not create semaphore...exit\n"); free_sem(0); return -1; } } else { for (i=0;i<num;i++) { if (create_sem(parameters[i].cpu)) { printf("Can not create semaphore for cpu%d...exit\n",i); free_sem(parameters[num].cpu); return -1; } } } /* Create a shm segment which will be used to inject/consume errors on.*/ if (create_shm()==-1) { printf("Error to create shm...exit\n"); return -1; } for (i=0;i<num;i++) { pid_t pid; current_time=time(NULL); log_info(parameters[i].cpu, "\nBegine at %s", ctime(¤t_time)); log_info(parameters[i].cpu, "Configurations:\n"); log_info(parameters[i].cpu,"On cpu%ld: loop=%lx, interval=%lx(s)", parameters[i].cpu, parameters[i].loop, parameters[i].interval); log_info(parameters[i].cpu," err_type_info=%lx,err_struct_info=%lx\n", parameters[i].err_type_info, parameters[i].err_struct_info); sprintf(path, PATH_FORMAT, (int)parameters[i].cpu); err_type_info.err_type_info=parameters[i].err_type_info; err_struct_info.err_struct_info=parameters[i].err_struct_info; memcpy(err_data_buffer.err_data_buffer, parameters[i].err_data_buffer, ERR_DATA_BUFFER_SIZE*8); pid=fork(); if (pid==0) { unsigned long mask[MASK_SIZE]; int j, k; void *va1, *va2; /* Allocate two memory areas va1 and va2 in shm */ va1=shmaddr+parameters[i].cpu*PAGE_SIZE; va2=shmaddr+parameters[i].cpu*PAGE_SIZE+PAGE_SIZE; vbprintf("va1=%lx, va2=%lx\n", (u64)va1, (u64)va2); memset(va1, 0x1, PAGE_SIZE); memset(va2, 0x2, PAGE_SIZE); if (empty_data_buffer(err_data_buffer.err_data_buffer)) /* If not specified yet, construct data buffer * with va1 */ construct_data_buf(path, err_type_info, err_struct_info, &err_data_buffer,va1); for (j=0;j<MASK_SIZE;j++) mask[j]=0; cpu=parameters[i].cpu; k = cpu%64; j = cpu/64; mask[j]=1<<k; if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) { perror("Error sched_setaffinity:"); return -1; } for (j=0; j<parameters[i].loop; j++) { log_info(parameters[i].cpu,"Injection "); log_info(parameters[i].cpu,"on cpu%ld: #%d/%ld ", parameters[i].cpu,j+1, parameters[i].loop); /* Hold the lock */ if (one_lock) lock(0); else /* Hold lock on this cpu */ lock(parameters[i].cpu); if ((status=err_inject(parameters[i].cpu, path, err_type_info, err_struct_info, err_data_buffer)) ==0) { /* consume the error for "inject only"*/ memcpy(va2, va1, PAGE_SIZE); memcpy(va1, va2, PAGE_SIZE); log_info(parameters[i].cpu, "successful\n"); } else { log_info(parameters[i].cpu,"fail:"); log_info(parameters[i].cpu, "status=%d\n", status); unlock(parameters[i].cpu); break; } if (one_lock) /* Release the lock */ unlock(0); /* Release lock on this cpu */ else unlock(parameters[i].cpu); if (j < parameters[i].loop-1) sleep(parameters[i].interval); } current_time=time(NULL); log_info(parameters[i].cpu, "Done at %s", ctime(¤t_time)); return 0; } else if (pid<0) { perror("Error fork:"); continue; } child_pid[i]=pid; } for (i=0;i<num;i++) waitpid(child_pid[i], NULL, 0); if (one_lock) free_sem(0); else for (i=0;i<num;i++) free_sem(parameters[i].cpu); printf("All done.\n"); return 0;}void help(){ printf("err_inject_tool:\n"); printf("\t-q: query all capabilities. default: off\n"); printf("\t-m: procedure mode. 1: physical 2: virtual. default: 1\n"); printf("\t-i: inject errors. default: off\n"); printf("\t-l: one lock per cpu. default: one lock for all\n"); printf("\t-e: error parameters:\n"); printf("\t\tcpu,loop,interval,err_type_info,err_struct_info[,err_data_buffer[0],err_data_buffer[1],err_data_buffer[2]]\n"); printf("\t\t cpu: logical cpu number the error will be inject in.\n"); printf("\t\t loop: times the error will be injected.\n"); printf("\t\t interval: In second. every so often one error is injected.\n"); printf("\t\t err_type_info, err_struct_info: PAL parameters.\n"); printf("\t\t err_data_buffer: PAL parameter. Optional. If not present,\n"); printf("\t\t it's constructed by tool automatically. Be\n"); printf("\t\t careful to provide err_data_buffer and make\n"); printf("\t\t sure it's working with the environment.\n"); printf("\t Note:no space between error parameters.\n"); printf("\t default: Take error parameters from err.conf instead of command line.\n"); printf("\t-v: verbose. default: off\n"); printf("\t-h: help\n\n"); printf("The tool will take err.conf file as "); printf("input to inject single or multiple errors "); printf("on one or multiple cpus in parallel.\n");}int main(int argc, char **argv){ char c; int do_err_inj=0; int do_query_all=0; int count; u32 m; /* Default one lock for all cpu's */ one_lock=1; while ((c = getopt(argc, argv, "m:iqvhle:")) != EOF) switch (c) { case 'm': /* Procedure mode. 1: phys 2: virt */ count=sscanf(optarg, "%x", &m); if (count!=1 || (m!=1 && m!=2)) { printf("Wrong mode number.\n"); help(); return -1; } mode=m; break; case 'i': /* Inject errors */ do_err_inj=1; break; case 'q': /* Query */ do_query_all=1; break; case 'v': /* Verbose */ verbose=1; break; case 'l': /* One lock per cpu */ one_lock=0; break; case 'e': /* error arguments */ /* Take parameters: * #cpu, loop, interval, err_type_info, err_struct_info[, err_data_buffer] * err_data_buffer is optional. Recommend not to specify * err_data_buffer. Better to use tool to generate it. */ count=sscanf(optarg, "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n", &line_para.cpu, &line_para.loop, &line_para.interval, &line_para.err_type_info, &line_para.err_struct_info, &line_para.err_data_buffer[0], &line_para.err_data_buffer[1], &line_para.err_data_buffer[2]); if (count!=PARA_FIELD_NUM+3) { line_para.err_data_buffer[0]=-1, line_para.err_data_buffer[1]=-1, line_para.err_data_buffer[2]=-1; count=sscanf(optarg, "%lx, %lx, %lx, %lx, %lx\n", &line_para.cpu, &line_para.loop, &line_para.interval, &line_para.err_type_info, &line_para.err_struct_info); if (count!=PARA_FIELD_NUM) { printf("Wrong error arguments.\n"); help(); return -1; } } para=1; break; continue; break; case 'h': help(); return 0; default: break; } if (do_query_all) query_all_capabilities(); if (do_err_inj) err_inj(); if (!do_query_all && !do_err_inj) help(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -