static int handle_page_fault(vm_t* vm, fault_t* fault) { struct device* d; /* See if the device is already in our address space */ d = vm_find_device_by_ipa(vm, fault_get_address(fault)); if (d != NULL) { if (d->devid == DEV_RAM) { DRAMFAULT("[%s] %s fault @ 0x%x from 0x%x\n", d->name, (fault_is_read(fault)) ? "read" : "write", fault_get_address(fault), fault_get_ctx(fault)->pc); } else { DDEVFAULT("[%s] %s fault @ 0x%x from 0x%x\n", d->name, (fault_is_read(fault)) ? "read" : "write", fault_get_address(fault), fault_get_ctx(fault)->pc); } return d->handle_page_fault(d, vm, fault); } else { #ifdef CONFIG_ONDEMAND_DEVICE_INSTALL uintptr_t addr = fault_get_address(fault) & ~0xfff; void* mapped; switch (addr) { case 0: printf("VM fault on IPA 0x%08x\n", 0); print_fault(fault); return -1; default: mapped = map_vm_device(vm, addr, addr, seL4_AllRights); if (mapped) { DVM("WARNING: Blindly mapped device @ 0x%x for PC 0x%x\n", fault_get_address(fault), fault_get_ctx(fault)->pc); restart_fault(fault); return 0; } mapped = map_vm_ram(vm, addr); if (mapped) { DVM("WARNING: Mapped RAM for device @ 0x%x for PC 0%x\n", fault_get_address(fault), fault_get_ctx(fault)->pc); restart_fault(fault); return 0; } DVM("Unhandled fault on address 0x%x\n", (uint32_t)addr); } #endif print_fault(fault); abandon_fault(fault); return -1; } }
/** * Parses a free instruction * * @param cmd String representing an allocation command in the program * @returns Status of read and execute */ static status_t parse_free(char* cmd) { assert(cmd != NULL); char var_name; int matched; var_t* var; // Read the command string errno = 0; matched = sscanf(cmd, "free(%c)", &var_name); // Check if sscanf was valid if (matched != 1 || errno != 0 || (var = get_var(var_name)) == NULL) return parse_error(cmd); // Ensure that the variable is in use if (!var->in_use) { print_fault(cmd, "Double free", ERROR); return DOUBLEFREE; } // Free variable buddy_free(var->mem); var->mem = NULL; var->in_use = false; return SUCCESS; }
/** Prototype: void slave_check_fault(uint8_t addr) Input: slave_addr: I2C address of slave Output: none Description: poll the I2C slave to see if any faults are occurring. if so, report Usage: slave_check_fault(USBA_ADDR); */ void slave_check_fault(uint8_t slave_addr) { //putstring0("slave_check_fault"); if (slave_addr == CHRGR_ADDR) { usb_chrgr_regs.REG09 = i2c_slave_read(CHRGR_ADDR, 0x09); // clear any existing fault usb_chrgr_regs.REG09 = i2c_slave_read(CHRGR_ADDR, 0x09); if (usb_chrgr_regs.REG09 != 0x00) // check for errors { print_fault(CHRGR_ADDR, 0x09, usb_chrgr_regs.REG09); } } else if (slave_addr == USBA_ADDR) { i2c_slave_command(USBA_ADDR, 0x10, 0x00); // clear any existing fault // usb_porta_regs.REG10 = i2c_slave_read(USBA_ADDR, 0x10); // __delay_ms(5); // give time for potential reset condition to occur // if (usb_porta_regs.REG10 & 0x20) // if device has been reset, reinitialize // usb_port_init(USBA_ADDR); usb_porta_regs.REG10 = i2c_slave_read(USBA_ADDR, 0x10); if (usb_porta_regs.REG10 != 0x00) // check for errors { print_fault(USBA_ADDR, 0x10, usb_porta_regs.REG10); clear_fault(USBA_ADDR); } } else if (slave_addr == USBB_ADDR) { i2c_slave_command(USBB_ADDR, 0x10, 0x00); // clear any existing fault // usb_portb_regs.REG10 = i2c_slave_read(USBB_ADDR, 0x10); // __delay_ms(5); // give time for potential reset condition to occur // if (usb_portb_regs.REG10 & 0x20) // if device has been reset, reinitialize // usb_port_init(USBB_ADDR); usb_portb_regs.REG10 = i2c_slave_read(USBB_ADDR, 0x10); if (usb_portb_regs.REG10 != 0x00) // check for errors { print_fault(USBB_ADDR, 0x10, usb_portb_regs.REG10); clear_fault(USBB_ADDR); } } return; }
/** * Parses an allocation instruction * * @param cmd String representing an allocation command in the program * @returns Status of read and execute */ static status_t parse_alloc(char* cmd) { assert(cmd != NULL); assert(cmd[0] != '\0'); char var_name; int size; char alter_size; int matched; errno = 0; matched = sscanf(cmd, "%c=alloc(%d%c)", &var_name, &size, &alter_size); // Error check sprintf if (matched == 3 && errno == 0) { // Check what the alter_size variable actually contains switch (alter_size) { case 'k': case 'K': size *= 1024; case ')': break; default: return parse_error(cmd); } } else { return parse_error(cmd); } // Resolve variable var_t* var = get_var(var_name); if (var == NULL) return parse_error(cmd); // Allocate variable var->mem = buddy_alloc(size); if (var->mem == NULL) { print_fault(cmd, "buddy_alloc returned NULL", WARNING); printf("Out of memory\n"); return OUTOFMEMORY; } var->in_use = true; return SUCCESS; }
static int get_kamcmd_list(int s) { struct binrpc_cmd cmd; int cookie; unsigned char reply_buf[MAX_REPLY_SIZE]; unsigned char* msg_body; struct binrpc_parse_ctx in_pkt; int ret; cmd.method="system.listMethods"; cmd.argc=0; cookie=gen_cookie(); if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){ if (ret==-1) goto error_send; else goto binrpc_err; } /* read reply */ memset(&in_pkt, 0, sizeof(in_pkt)); if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt, &msg_body))<0){ goto error; } switch(in_pkt.type){ case BINRPC_FAULT: if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){ goto error; } break; case BINRPC_REPL: rpc_no=100; /* default cmd list */ if ((rpc_array=parse_reply_body(&rpc_no, &in_pkt, msg_body, in_pkt.tlen))==0) goto error; break; default: fprintf(stderr, "ERROR: not a reply\n"); goto error; } return 0; binrpc_err: error_send: error: return -1; }
static int run_binrpc_cmd(int s, struct binrpc_cmd * cmd, char* fmt) { int cookie; unsigned char reply_buf[MAX_REPLY_SIZE]; unsigned char* msg_body; struct binrpc_parse_ctx in_pkt; int ret; cookie=gen_cookie(); if ((ret=send_binrpc_cmd(s, cmd, cookie))<0){ if (ret==-1) goto error_send; else goto binrpc_err; } /* read reply */ memset(&in_pkt, 0, sizeof(in_pkt)); if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt, &msg_body))<0){ switch(ret){ case -1: goto error_read; case -2: goto error_parse; case -3: goto error_cookie; case -4: goto error_toobig; } goto error; } switch(in_pkt.type){ case BINRPC_FAULT: if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){ goto error; } break; case BINRPC_REPL: if (print_body(&in_pkt, msg_body, in_pkt.tlen, fmt)<0){ goto error; } break; default: fprintf(stderr, "ERROR: not a reply\n"); goto error; } if (verbose) printf(".\n"); /* normal exit */ return 0; binrpc_err: fprintf(stderr, "ERROR while building the packet: %s\n", binrpc_error(ret)); goto error; error_parse: fprintf(stderr, "ERROR while parsing the reply: %s\n", binrpc_error(binrpc_errno)); goto error; error_cookie: fprintf(stderr, "ERROR: cookie does not match\n"); goto error; error_toobig: fprintf(stderr, "ERROR: reply too big\n"); goto error; error_send: fprintf(stderr, "ERROR: send packet failed: %s (%d)\n", strerror(errno), errno); goto error; error_read: fprintf(stderr, "ERROR: read reply failed: %s (%d)\n", strerror(errno), errno); goto error; error: return -1; }
/* retrieve the counters names and group list */ static int get_counters_list(int s) { struct binrpc_cmd cmd; int cookie; unsigned char reply_buf[MAX_REPLY_SIZE]; unsigned char* msg_body; struct binrpc_parse_ctx in_pkt; struct cnt_var_grp* grp; struct cnt_var_grp* last_grp; str grp_name; str var_name; int r; int ret; cmd.method="cnt.grps_list"; cmd.argc=0; if (!is_rpc_cmd(cmd.method)) goto error; cookie=gen_cookie(); if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){ if (ret==-1) goto error_send; else goto binrpc_err; } /* read reply */ memset(&in_pkt, 0, sizeof(in_pkt)); if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt, &msg_body))<0){ goto error; } switch(in_pkt.type){ case BINRPC_FAULT: if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){ goto error; } break; case BINRPC_REPL: cnt_grps_no=20; /* default counter list */ if ((cnt_grps_array=parse_reply_body(&cnt_grps_no, &in_pkt, msg_body, in_pkt.tlen))==0) goto error; break; default: fprintf(stderr, "ERROR: not a reply\n"); goto error; } /* get the config groups */ last_grp=0; for (r=0; r<cnt_grps_no; r++){ grp_name.s=0; grp_name.len=0; if (cnt_grps_array[r].type!=BINRPC_T_STR) continue; grp_name=cnt_grps_array[r].u.strval; /* check for duplicates */ for (grp=cnt_grp_lst; grp; grp=grp->next){ if (grp->grp_name.len==grp_name.len && memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){ break; /* found */ } } if (grp==0){ /* not found => create a new one */ grp=malloc(sizeof(*grp)); if (grp==0) goto error_mem; memset(grp, 0, sizeof(*grp)); grp->grp_name=grp_name; if (last_grp){ last_grp->next=grp; last_grp=grp; }else{ cnt_grp_lst=grp; last_grp=cnt_grp_lst; } } } /* gets vars per group */ for (grp=cnt_grp_lst; grp; grp=grp->next){ cmd.method="cnt.var_list"; cmd.argv[0].type=BINRPC_T_STR; cmd.argv[0].u.strval=grp->grp_name; cmd.argc=1; if (!is_rpc_cmd(cmd.method)) goto error; cookie=gen_cookie(); if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){ if (ret==-1) goto error_send; else goto binrpc_err; } /* read reply */ memset(&in_pkt, 0, sizeof(in_pkt)); if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt, &msg_body))<0){ goto error; } switch(in_pkt.type){ case BINRPC_FAULT: if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){ goto error; } break; case BINRPC_REPL: grp->cnt_vars_no=100; /* default counter list */ if ((grp->cnt_vars_array=parse_reply_body(&grp->cnt_vars_no, &in_pkt, msg_body, in_pkt.tlen))==0) goto error; break; default: fprintf(stderr, "ERROR: not a reply\n"); goto error; } grp->var_no = 0; grp->var_names=malloc(sizeof(str)*grp->cnt_vars_no); if (grp->var_names==0) goto error_mem; memset(grp->var_names, 0, sizeof(str)*grp->cnt_vars_no); for (r=0; r<grp->cnt_vars_no; r++) { if (grp->cnt_vars_array[r].type!=BINRPC_T_STR) continue; var_name=grp->cnt_vars_array[r].u.strval; grp->var_names[grp->var_no] = var_name; grp->var_no++; } } return 0; binrpc_err: error_send: error: error_mem: return -1; }
/* retrieve the cfg vars and group list */ static int get_cfgvars_list(int s) { struct binrpc_cmd cmd; int cookie; unsigned char reply_buf[MAX_REPLY_SIZE]; unsigned char* msg_body; struct binrpc_parse_ctx in_pkt; struct cfg_var_grp* grp; struct cfg_var_grp* last_grp; char* p; char* end; str grp_name; str var_name; int r; int ret; cmd.method="cfg.list"; cmd.argc=0; if (!is_rpc_cmd(cmd.method)) goto error; cookie=gen_cookie(); if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){ if (ret==-1) goto error_send; else goto binrpc_err; } /* read reply */ memset(&in_pkt, 0, sizeof(in_pkt)); if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt, &msg_body))<0){ goto error; } switch(in_pkt.type){ case BINRPC_FAULT: if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){ goto error; } break; case BINRPC_REPL: cfg_vars_no=100; /* default cmd list */ if ((cfg_vars_array=parse_reply_body(&cfg_vars_no, &in_pkt, msg_body, in_pkt.tlen))==0) goto error; break; default: fprintf(stderr, "ERROR: not a reply\n"); goto error; } /* get the config groups */ last_grp=0; for (r=0; r<cfg_vars_no; r++){ grp_name.s=0; grp_name.len=0; if (cfg_vars_array[r].type!=BINRPC_T_STR) continue; grp_name.s=cfg_vars_array[r].u.strval.s; end=cfg_vars_array[r].u.strval.len+grp_name.s; /* parse <grp>: <var_name>*/ for (p=grp_name.s; p<end; p++){ if (*p==':'){ grp_name.len=(int)(long)(p-grp_name.s); break; } } for (grp=cfg_grp_lst; grp; grp=grp->next){ if (grp->grp_name.len==grp_name.len && memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){ break; /* found */ } } if (grp==0){ /* not found => create a new one */ grp=malloc(sizeof(*grp)); if (grp==0) goto error_mem; memset(grp, 0, sizeof(*grp)); grp->grp_name=grp_name; if (last_grp){ last_grp->next=grp; last_grp=grp; }else{ cfg_grp_lst=grp; last_grp=cfg_grp_lst; } } grp->var_no++; } /* alloc the var arrays per group */ for (grp=cfg_grp_lst; grp; grp=grp->next){ grp->var_names=malloc(sizeof(str)*grp->var_no); if (grp->var_names==0) goto error_mem; memset(grp->var_names, 0, sizeof(str)*grp->var_no); grp->var_no=0; } /* reparse to get the var names per group */ for (r=0; r<cfg_vars_no; r++){ grp_name.s=0; grp_name.len=0; var_name.s=0; var_name.len=0; if (cfg_vars_array[r].type!=BINRPC_T_STR) continue; grp_name.s=cfg_vars_array[r].u.strval.s; end=cfg_vars_array[r].u.strval.len+grp_name.s; /* parse <grp>: <var_name>*/ for (p=grp_name.s; p<end; p++){ if (*p==':'){ grp_name.len=(int)(long)(p-grp_name.s); p++; for (; p<end && *p==' '; p++); var_name.s=p; var_name.len=(int)(long)(end-p); if (var_name.len==0) break; for (grp=cfg_grp_lst; grp; grp=grp->next){ if (grp->grp_name.len==grp_name.len && memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){ /* add var */ grp->var_names[grp->var_no]=var_name; grp->var_no++; } } break; } } } return 0; binrpc_err: error_send: error: error_mem: return -1; }
/** * Throw a parsing error * * @param cmd A string representing the faulting command * @return Returns BADINPUT status */ static status_t parse_error(const char* cmd) { print_fault(cmd, "Failed to parse command", ERROR); return BADINPUT; }