Example #1
0
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;
}
Example #2
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;
}
Example #3
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);
}
Example #4
0
/* ------------------------------------------------------------------------*//**
 * @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;
}
Example #5
0
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;
}