static int mips_sys_munmap_impl(struct mips_ctx_t *ctx) { struct mips_regs_t *regs = ctx->regs; struct mem_t *mem = ctx->mem; unsigned int addr; unsigned int size; unsigned int size_aligned; /* Arguments */ addr = regs->regs_R[4]; size = regs->regs_R[5]; mips_sys_debug(" addr=0x%x, size=0x%x\n", addr, size); /* Restrictions */ if (addr & (MEM_PAGE_SIZE - 1)) fatal("%s: address not aligned", __FUNCTION__); /* Unmap */ size_aligned = ROUND_UP(size, MEM_PAGE_SIZE); mem_unmap(mem, addr, size_aligned); /* Return */ return 0; }
static int mips_sys_brk_impl(struct mips_ctx_t *ctx) { struct mips_regs_t *regs = ctx->regs; struct mem_t *mem = ctx->mem; unsigned int old_heap_break; unsigned int new_heap_break; unsigned int size; unsigned int old_heap_break_aligned; unsigned int new_heap_break_aligned; /* Arguments */ new_heap_break = regs->regs_R[4]; old_heap_break = mem->heap_break; mips_sys_debug(" newbrk=0x%x (previous brk was 0x%x)\n", new_heap_break, old_heap_break); /* Align */ new_heap_break_aligned = ROUND_UP(new_heap_break, MEM_PAGE_SIZE); old_heap_break_aligned = ROUND_UP(old_heap_break, MEM_PAGE_SIZE); /* If argument is zero, the system call is used to * obtain the current top of the heap. */ if (!new_heap_break) return old_heap_break; /* If the heap is increased: if some page in the way is * allocated, do nothing and return old heap top. Otherwise, * allocate pages and return new heap top. */ if (new_heap_break > old_heap_break) { size = new_heap_break_aligned - old_heap_break_aligned; if (size) { if (mem_map_space(mem, old_heap_break_aligned, size) != old_heap_break_aligned) fatal("%s: out of memory", __FUNCTION__); mem_map(mem, old_heap_break_aligned, size, mem_access_read | mem_access_write); } mem->heap_break = new_heap_break; mips_sys_debug(" heap grows %u bytes\n", new_heap_break - old_heap_break); return new_heap_break; } /* Always allow to shrink the heap. */ if (new_heap_break < old_heap_break) { size = old_heap_break_aligned - new_heap_break_aligned; if (size) mem_unmap(mem, new_heap_break_aligned, size); mem->heap_break = new_heap_break; mips_sys_debug(" heap shrinks %u bytes\n", old_heap_break - new_heap_break); return new_heap_break; } /* Heap stays the same */ return 0; }
/* Return from a signal handler */ void arm_signal_handler_return(struct arm_ctx_t *ctx) { /* Change context status */ if (!arm_ctx_get_status(ctx, arm_ctx_handler)) fatal("%s: not handling a signal", __FUNCTION__); arm_ctx_clear_status(ctx, arm_ctx_handler); /* Free signal frame */ mem_unmap(ctx->mem, ctx->signal_mask_table->pretcode, MEM_PAGE_SIZE); arm_sys_debug(" signal handler return code at 0x%x deallocated\n", ctx->signal_mask_table->pretcode); /* Restore saved register file and free backup */ arm_regs_copy(ctx->regs, ctx->signal_mask_table->regs); arm_regs_free(ctx->signal_mask_table->regs); }
/* ------------------------------------------------------------------------*//** * @FUNCTION main * @BRIEF main entry point * @RETURNS 0 on success * OMAPCONF_ERR_CPU * OMAPCONF_ERR_ARG * OMAPCONF_ERR_REG_ACCESS * @param[in, out] argc: shell input argument number * @param[in, out] argv: shell input argument(s) * @DESCRIPTION main entry point *//*------------------------------------------------------------------------ */ int main(int argc, char *argv[]) { int ret; struct sigaction act; unsigned int start, end, time, delay; double sampling_rate; char *prefix; char *cfgfile; int c; cpu_found = 0; ret = 0; /* Register signal handler in order to catch incorrect memory access. */ act.sa_sigaction = &main_sigbus_handler; act.sa_flags = SA_SIGINFO; sigaction(SIGBUS, &act, NULL); /* Some of the omapconf functions do not support DEVICE OFF Mode, * so by default acquire a wakelock if OS is Android. */ if (os_is_android()) wakelock_acquire(); /* To be case-insensitive, lowercase all arguments */ main_arguments_lowercase(argc, argv); /* Scan user arguments for options */ argc--; argv++; ret = main_options_scan(&argc, &argv); if (ret < 0) goto main_exit; if (!cpu_is_forced()) { /* Detect CPU if not user-enforced */ ret = cpu_detect(); switch (ret) { case 0: cpu_found = 1; break; case OMAPCONF_ERR_REG_ACCESS: omapconf_revision_show(stdout); printf("'/dev/mem' could not be opened.\n"); printf( "Privileged access required to run omapconf.\n\n"); ret = OMAPCONF_ERR_REG_ACCESS; goto main_exit; case OMAPCONF_ERR_CPU: printf( "Warning: chip not recognized, running in safe mode (only platform-generic functions allowed).\n\n"); break; case OMAPCONF_ERR_UNEXPECTED: default: omapconf_revision_show(stdout); printf("Unexpected error, sorry ... (%d)\n\n", ret); ret = OMAPCONF_ERR_UNEXPECTED; goto main_exit; } } if (argc == 0) { help(HELP_USAGE); ret = OMAPCONF_ERR_ARG; goto main_exit; } /* Platform-generic functions, no need to detect cpu */ if (strcmp(argv[0], "--help") == 0) { omapconf_revision_show(stdout); help(HELP_ALL); ret = 0; goto main_exit; } else if (strcmp(argv[0], "--version") == 0) { omapconf_revision_show(stdout); ret = 0; goto main_exit; } else if (strcmp(argv[0], "--cpuinfo") == 0) { omapconf_revision_show(stdout); chips_info_show(stdout, 1); ret = 0; goto main_exit; } else if (strcmp(argv[0], "--buildinfo") == 0) { omapconf_revision_show(stdout); release_info_show(stdout); ret = 0; goto main_exit; } else if (strcmp(argv[0], "read") == 0) { if ((argc >= 2) && (strcmp(argv[1], "audioic") == 0)) { goto main_platform_specific; } else if ((argc >= 2) && (strcmp(argv[1], "i2c") == 0)) { if (argc < 5) { ret = err_arg_missing_msg_show(HELP_I2C_RW); goto main_exit; } else if (argc == 5) { ret = main_i2c_read(argc, argv); goto main_exit; } else { ret = err_arg_too_many_msg_show(HELP_I2C_RW); goto main_exit; } } if (argc == 2) { ret = main_readreg(uppercase(argv[1]), "hex"); goto main_exit; } else if (argc == 3) { ret = main_readreg(uppercase(argv[1]), lowercase(argv[2])); goto main_exit; } else { ret = err_arg_too_many_msg_show(HELP_RW); goto main_exit; } } else if (strcmp(argv[0], "write") == 0) { if ((argc >= 2) && (strcmp(argv[1], "audioic") == 0)) { goto main_platform_specific; } else if ((argc >= 2) && (strcmp(argv[1], "i2c") == 0)) { if (argc < 6) { ret = err_arg_missing_msg_show(HELP_I2C_RW); goto main_exit; } else if (argc == 6) { ret = main_i2c_write(argc, argv); goto main_exit; } else { ret = err_arg_too_many_msg_show(HELP_I2C_RW); goto main_exit; } } if (argc < 3) { ret = err_arg_missing_msg_show(HELP_RW); goto main_exit; } else if (argc == 3) { ret = main_writereg(uppercase(argv[1]), uppercase(argv[2])); goto main_exit; } else { ret = err_arg_too_many_msg_show(HELP_RW); goto main_exit; } } else if (strcmp(argv[0], "clear") == 0) { if ((argc >= 2) && (strcmp(argv[1], "bit") == 0)) { ret = main_clearbit(argc, argv); goto main_exit; } } else if (strcmp(argv[0], "set") == 0) { if ((argc >= 2) && (strcmp(argv[1], "bit") == 0)) { ret = main_setbit(argc, argv); goto main_exit; } } else if (strcmp(argv[0], "i2c") == 0) { if ((argc != 5) && (argc != 6)) { help(HELP_I2C_RW); ret = OMAPCONF_ERR_ARG; goto main_exit; } if (strcmp(argv[1], "read") == 0) { ret = main_i2c_read(argc, argv); goto main_exit; } else if (strcmp(argv[1], "write") == 0) { ret = main_i2c_write(argc, argv); goto main_exit; } else { ret = err_arg_msg_show(HELP_I2C_RW); goto main_exit; } } else if ((strcmp(argv[0], "dump") == 0) && (argc == 3) && (sscanf(argv[1], "0x%08x", &start) == 1) && (sscanf(argv[2], "0x%08x", &end) == 1)) { ret = mem_address_range_dump(start, end); goto main_exit; } else if ((argc >= 3) && (strcmp(argv[0], "trace") == 0) && (strcmp(argv[1], "perf") == 0) && (strcmp(argv[2], "setup") == 0)) { if (argc == 3) ret = trace_perf_setup( (char *) trace_perf_default_cfgfile); else ret = trace_perf_setup(argv[3]); goto main_exit; } else if ((argc >= 2) && (strcmp(argv[0], "trace") == 0) && (strcmp(argv[1], "perf") == 0)) { time = TRACE_PERF_DEFAULT_CAPTURE_TIME; delay = TRACE_PERF_DEFAULT_DELAY_TIME; sampling_rate = TRACE_PERF_DEFAULT_SAMPLING_RATE; prefix = NULL; cfgfile = (char *) trace_perf_default_cfgfile; omapconf_revision_show(stdout); chips_info_show(stdout, 0); release_info_show(stdout); if (argc == 2) { time = TRACE_PERF_DEFAULT_CAPTURE_TIME; delay = TRACE_PERF_DEFAULT_DELAY_TIME; sampling_rate = TRACE_PERF_DEFAULT_SAMPLING_RATE; prefix = NULL; cfgfile = (char *) trace_perf_default_cfgfile; } else if (argc == 3) { ret = sscanf(argv[2], "%u", &time); if (ret != 1) { help(HELP_TRACE); ret = OMAPCONF_ERR_ARG; goto main_exit; } } else { while ((c = getopt(argc, argv, "d:t:s:p:c:")) != -1) { switch (c) { case 'd': /* delay time */ ret = sscanf(optarg, "%u", &delay); if (ret != 1) { ret = err_arg_msg_show( HELP_TRACE); goto main_exit; } break; case 't': /* capture time */ ret = sscanf(optarg, "%u", &time); if (ret != 1) { ret = err_arg_msg_show( HELP_TRACE); goto main_exit; } break; case 's': /* sampling rate */ ret = sscanf(optarg, "%lf", &sampling_rate); if (ret != 1) { ret = err_arg_msg_show( HELP_TRACE); goto main_exit; } break; case 'p': /* file prefix */ prefix = optarg; break; case 'c': /* configuration file */ cfgfile = optarg; break; default: ret = err_arg_msg_show(HELP_TRACE); goto main_exit; } } } if (cpu_is_omap44xx()) main44xx_init(); else if (cpu_is_omap54xx()) dpll54xx_init(); ret = trace_perf_capture(cfgfile, prefix, sampling_rate, time, delay); goto main_exit; } /* Platform-specific functions */ main_platform_specific: if (cpu_found) { omapconf_revision_show(stdout); chips_info_show(stdout, 0); release_info_show(stdout); if (cpu_is_omap44xx()) { ret = main44xx(argc, argv); goto main_exit; } else if (cpu_is_omap54xx()) { ret = main54xx(argc, argv); goto main_exit; } else if (cpu_is_dra7xx()) { ret = main_dra7xx(argc, argv); goto main_exit; } else { printf("Unsupported chip, sorry ...\n\n"); ret = OMAPCONF_ERR_CPU; goto main_exit; } } else { printf("Function disabled in safe mode, sorry ...\n\n"); ret = OMAPCONF_ERR_NOT_AVAILABLE; goto main_exit; } main_exit: if (os_is_android()) wakelock_release(); /* Unmap last mapped memory page */ mem_unmap(); /* Deinitializations */ if (cpu_get() != OMAP_MAX) { opp_deinit(); voltdm_deinit(); temp_sensor_deinit(); module_deinit(); powerdm_deinit(); clockdm_deinit(); } return ret; }
static int mips_sys_mmap(struct mips_ctx_t *ctx, unsigned int addr, unsigned int len, int prot, int flags, int guest_fd, int offset) { struct mem_t *mem = ctx->mem; unsigned int len_aligned; int perm; int host_fd; struct mips_file_desc_t *desc; /* Check that protection flags match in guest and host */ assert(PROT_READ == 1); assert(PROT_WRITE == 2); assert(PROT_EXEC == 4); /* Check that mapping flags match */ assert(MAP_SHARED == 0x01); assert(MAP_PRIVATE == 0x02); assert(MAP_FIXED == 0x10); assert(MAP_ANONYMOUS == 0x20); /* Translate file descriptor */ desc = mips_file_desc_table_entry_get(ctx->file_desc_table, guest_fd); host_fd = desc ? desc->host_fd : -1; if (guest_fd > 0 && host_fd < 0) fatal("%s: invalid guest descriptor", __FUNCTION__); /* Permissions */ perm = mem_access_init; perm |= prot & PROT_READ ? mem_access_read : 0; perm |= prot & PROT_WRITE ? mem_access_write : 0; perm |= prot & PROT_EXEC ? mem_access_exec : 0; /* Flag MAP_ANONYMOUS. * If it is set, the 'fd' parameter is ignored. */ if (flags & MAP_ANONYMOUS) host_fd = -1; /* 'addr' and 'offset' must be aligned to page size boundaries. * 'len' is rounded up to page boundary. */ if (offset & ~MEM_PAGE_MASK) fatal("%s: unaligned offset", __FUNCTION__); if (addr & ~MEM_PAGE_MASK) fatal("%s: unaligned address", __FUNCTION__); len_aligned = ROUND_UP(len, MEM_PAGE_SIZE); /* Find region for allocation */ if (flags & MAP_FIXED) { /* If MAP_FIXED is set, the 'addr' parameter must be obeyed, and is not just a * hint for a possible base address of the allocated range. */ if (!addr) fatal("%s: no start specified for fixed mapping", __FUNCTION__); /* Any allocated page in the range specified by 'addr' and 'len' * must be discarded. */ mem_unmap(mem, addr, len_aligned); } else { if (!addr || mem_map_space_down(mem, addr, len_aligned) != addr) addr = SYS_MMAP_BASE_ADDRESS; addr = mem_map_space_down(mem, addr, len_aligned); if (addr == -1) fatal("%s: out of guest memory", __FUNCTION__); } /* Allocation of memory */ mem_map(mem, addr, len_aligned, perm); /* Host mapping */ if (host_fd >= 0) { char buf[MEM_PAGE_SIZE]; unsigned int last_pos; unsigned int curr_addr; int size; int count; /* Save previous position */ last_pos = lseek(host_fd, 0, SEEK_CUR); lseek(host_fd, offset, SEEK_SET); /* Read pages */ assert(len_aligned % MEM_PAGE_SIZE == 0); assert(addr % MEM_PAGE_SIZE == 0); curr_addr = addr; for (size = len_aligned; size > 0; size -= MEM_PAGE_SIZE) { memset(buf, 0, MEM_PAGE_SIZE); count = read(host_fd, buf, MEM_PAGE_SIZE); if (count) mem_access(mem, curr_addr, MEM_PAGE_SIZE, buf, mem_access_init); curr_addr += MEM_PAGE_SIZE; } /* Return file to last position */ lseek(host_fd, last_pos, SEEK_SET); } /* Return mapped address */ return addr; }