예제 #1
0
파일: pl310.c 프로젝트: FrozenCow/FIRE-ICE
static int __maybe_unused l2x0_set_events(int *events, int size)
{
	if (!events || size == 0) {
		l2x0_ctx.l2x0_event_type = -1;
		l2x0_ctx.event_id = -1;
		return 0;
	}

	if (size != 1) {
		pr_err("Error: number of events more than one\n");
		return -ENOSPC;
	}

	switch (*events) {
	case QUADD_EVENT_TYPE_L2_DCACHE_READ_MISSES:
		l2x0_ctx.l2x0_event_type = QUADD_L2X0_TYPE_DATA_READ_MISSES;
		break;
	case QUADD_EVENT_TYPE_L2_DCACHE_WRITE_MISSES:
		l2x0_ctx.l2x0_event_type = QUADD_L2X0_TYPE_DATA_WRITE_MISSES;
		break;
	case QUADD_EVENT_TYPE_L2_ICACHE_MISSES:
		l2x0_ctx.l2x0_event_type = QUADD_L2X0_TYPE_INSTRUCTION_MISSES;
		break;
	default:
		pr_err("Error event: %s\n", quadd_get_event_str(*events));
		return 1;
	}
	l2x0_ctx.event_id = *events;

	pr_info("Event has been added: id/l2x0: %s/%#x\n",
		quadd_get_event_str(*events), l2x0_ctx.l2x0_event_type);
	return 0;
}
예제 #2
0
static int __init quadd_module_init(void)
{
	int i, nr_events, err;
	int *events;

	pr_info("Branch: %s\n", QUADD_MODULE_BRANCH);
	pr_info("Version: %s\n", QUADD_MODULE_VERSION);
	pr_info("Samples version: %d\n", QUADD_SAMPLES_VERSION);
	pr_info("IO version: %d\n", QUADD_IO_VERSION);

#ifdef QM_DEBUG_SAMPLES_ENABLE
	pr_info("############## DEBUG VERSION! ##############\n");
#endif

	atomic_set(&ctx.started, 0);
	atomic_set(&ctx.tegra_profiler_lock, 0);

	get_default_properties();

	ctx.pmu_info.active = 0;
	ctx.pl310_info.active = 0;

#ifdef CONFIG_ARM64
	ctx.pmu = quadd_armv8_pmu_init();
#else
	ctx.pmu = quadd_armv7_pmu_init();
#endif
	if (!ctx.pmu) {
		pr_err("PMU init failed\n");
		return -ENODEV;
	} else {
		events = ctx.pmu_info.supported_events;
		nr_events = ctx.pmu->get_supported_events(events,
							  QUADD_MAX_COUNTERS);
		ctx.pmu_info.nr_supported_events = nr_events;

		pr_debug("PMU: amount of events: %d\n", nr_events);

		for (i = 0; i < nr_events; i++)
			pr_debug("PMU event: %s\n",
				 quadd_get_event_str(events[i]));
	}

#ifdef CONFIG_CACHE_L2X0
	ctx.pl310 = quadd_l2x0_events_init();
#else
	ctx.pl310 = NULL;
#endif
	if (ctx.pl310) {
		events = ctx.pl310_info.supported_events;
		nr_events = ctx.pl310->get_supported_events(events,
							    QUADD_MAX_COUNTERS);
		ctx.pl310_info.nr_supported_events = nr_events;

		pr_info("pl310 success, amount of events: %d\n",
			nr_events);

		for (i = 0; i < nr_events; i++)
			pr_info("pl310 event: %s\n",
				quadd_get_event_str(events[i]));
	} else {
		pr_debug("PL310 not found\n");
	}

	ctx.hrt = quadd_hrt_init(&ctx);
	if (IS_ERR(ctx.hrt)) {
		pr_err("error: HRT init failed\n");
		return PTR_ERR(ctx.hrt);
	}

	err = quadd_power_clk_init(&ctx);
	if (err < 0) {
		pr_err("error: POWER CLK init failed\n");
		return err;
	}

	ctx.comm = quadd_comm_events_init(&control);
	if (IS_ERR(ctx.comm)) {
		pr_err("error: COMM init failed\n");
		return PTR_ERR(ctx.comm);
	}

	err = quadd_auth_init(&ctx);
	if (err < 0) {
		pr_err("error: auth failed\n");
		return err;
	}

	err = quadd_unwind_init();
	if (err < 0) {
		pr_err("error: EH unwinding init failed\n");
		return err;
	}

	get_capabilities(&ctx.cap);
	quadd_proc_init(&ctx);

	return 0;
}
예제 #3
0
static int __init quadd_module_init(void)
{
	int i, nr_events, err;
	int *events;

	pr_info("Branch: %s\n", QUADD_MODULE_BRANCH);
	pr_info("Version: %s\n", QUADD_MODULE_VERSION);
	pr_info("Samples version: %d\n", QUADD_SAMPLES_VERSION);
	pr_info("IO version: %d\n", QUADD_IO_VERSION);

#ifdef QM_DEBUG_SAMPLES_ENABLE
	pr_info("############## DEBUG VERSION! ##############\n");
#endif
	atomic_set(&ctx.started, 0);

	get_default_properties();

	ctx.pmu_info.active = 0;
	ctx.pl310_info.active = 0;

	ctx.pmu = quadd_armv7_pmu_init();
	if (!ctx.pmu) {
		pr_err("PMU init failed\n");
		return -ENODEV;
	} else {
		events = ctx.pmu_info.supported_events;
		nr_events = ctx.pmu->get_supported_events(events);
		ctx.pmu_info.nr_supported_events = nr_events;

		pr_info("PMU: amount of events: %d\n", nr_events);

		for (i = 0; i < nr_events; i++)
			pr_info("PMU event: %s\n",
				quadd_get_event_str(events[i]));
	}

	ctx.pl310 = quadd_l2x0_events_init();
	if (ctx.pl310) {
		events = ctx.pl310_info.supported_events;
		nr_events = ctx.pl310->get_supported_events(events);
		ctx.pl310_info.nr_supported_events = nr_events;

		pr_info("pl310 success, amount of events: %d\n",
			nr_events);

		for (i = 0; i < nr_events; i++)
			pr_info("pl310 event: %s\n",
				quadd_get_event_str(events[i]));
	} else {
		pr_info("PL310 not found\n");
	}

	ctx.hrt = quadd_hrt_init(&ctx);
	if (!ctx.hrt) {
		pr_err("error: HRT init failed\n");
		return -ENODEV;
	}

	ctx.mmap = quadd_mmap_init(&ctx);
	if (!ctx.mmap) {
		pr_err("error: MMAP init failed\n");
		return -ENODEV;
	}

	err = quadd_power_clk_init(&ctx);
	if (err < 0) {
		pr_err("error: POWER CLK init failed\n");
		return err;
	}

	ctx.comm = quadd_comm_events_init(&control);
	if (!ctx.comm) {
		pr_err("error: COMM init failed\n");
		return -ENODEV;
	}

	err = quadd_auth_init(&ctx);
	if (err < 0) {
		pr_err("error: auth failed\n");
		return err;
	}

	return 0;
}
예제 #4
0
static int
set_parameters(struct quadd_parameters *p, uid_t *debug_app_uid)
{
	int i, err, uid = 0;
	int pmu_events_id[QUADD_MAX_COUNTERS];
	int pl310_events_id;
	int nr_pmu = 0, nr_pl310 = 0;
	struct task_struct *task;
	unsigned int extra;
	u64 *low_addr_p;

	if (!validate_freq(p->freq)) {
		pr_err("%s: incorrect frequency: %u\n", __func__, p->freq);
		return -EINVAL;
	}

	ctx.param.freq = p->freq;
	ctx.param.ma_freq = p->ma_freq;
	ctx.param.backtrace = p->backtrace;
	ctx.param.use_freq = p->use_freq;
	ctx.param.system_wide = p->system_wide;
	ctx.param.power_rate_freq = p->power_rate_freq;
	ctx.param.debug_samples = p->debug_samples;

	for (i = 0; i < ARRAY_SIZE(p->reserved); i++)
		ctx.param.reserved[i] = p->reserved[i];

	/* Currently only one process */
	if (p->nr_pids != 1)
		return -EINVAL;

	p->package_name[sizeof(p->package_name) - 1] = '\0';

	rcu_read_lock();
	task = pid_task(find_vpid(p->pids[0]), PIDTYPE_PID);
	rcu_read_unlock();
	if (!task) {
		pr_err("Process not found: %u\n", p->pids[0]);
		return -ESRCH;
	}

	pr_info("owner/task uids: %u/%u\n", current_fsuid(), task_uid(task));
	if (!capable(CAP_SYS_ADMIN)) {
		if (current_fsuid() != task_uid(task)) {
			uid = quadd_auth_is_debuggable((char *)p->package_name);
			if (uid < 0) {
				pr_err("Error: QuadD security service\n");
				return uid;
			} else if (uid == 0) {
				pr_err("Error: app is not debuggable\n");
				return -EACCES;
			}

			*debug_app_uid = uid;
			pr_info("debug_app_uid: %u\n", uid);
		}
		ctx.collect_kernel_ips = 0;
	} else {
		ctx.collect_kernel_ips = 1;
	}

	for (i = 0; i < p->nr_pids; i++)
		ctx.param.pids[i] = p->pids[i];

	ctx.param.nr_pids = p->nr_pids;

	for (i = 0; i < p->nr_events; i++) {
		int event = p->events[i];

		if (ctx.pmu && ctx.pmu_info.nr_supported_events > 0
			&& is_event_supported(&ctx.pmu_info, event)) {
			pmu_events_id[nr_pmu++] = p->events[i];

			pr_info("PMU active event: %s\n",
				quadd_get_event_str(event));
		} else if (ctx.pl310 &&
			   ctx.pl310_info.nr_supported_events > 0 &&
			   is_event_supported(&ctx.pl310_info, event)) {
			pl310_events_id = p->events[i];

			pr_info("PL310 active event: %s\n",
				quadd_get_event_str(event));

			if (nr_pl310++ > 1) {
				pr_err("error: multiply pl310 events\n");
				return -EINVAL;
			}
		} else {
			pr_err("Bad event: %s\n",
			       quadd_get_event_str(event));
			return -EINVAL;
		}
	}

	if (ctx.pmu) {
		if (nr_pmu > 0) {
			err = ctx.pmu->set_events(pmu_events_id, nr_pmu);
			if (err) {
				pr_err("PMU set parameters: error\n");
				return err;
			}
			ctx.pmu_info.active = 1;
		} else {
			ctx.pmu_info.active = 0;
			ctx.pmu->set_events(NULL, 0);
		}
	}

	if (ctx.pl310) {
		if (nr_pl310 == 1) {
			err = ctx.pl310->set_events(&pl310_events_id, 1);
			if (err) {
				pr_info("pl310 set_parameters: error\n");
				return err;
			}
			ctx.pl310_info.active = 1;
		} else {
			ctx.pl310_info.active = 0;
			ctx.pl310->set_events(NULL, 0);
		}
	}

	extra = p->reserved[QUADD_PARAM_IDX_EXTRA];

	if (extra & QUADD_PARAM_EXTRA_BT_UNWIND_TABLES)
		pr_info("unwinding: exception-handling tables\n");

	if (extra & QUADD_PARAM_EXTRA_BT_FP)
		pr_info("unwinding: frame pointers\n");

	if (extra & QUADD_PARAM_EXTRA_BT_MIXED)
		pr_info("unwinding: mixed mode\n");

	low_addr_p = (u64 *)&p->reserved[QUADD_PARAM_IDX_BT_LOWER_BOUND];
	ctx.hrt->low_addr = (unsigned long)*low_addr_p;
	pr_info("bt lower bound: %#lx\n", ctx.hrt->low_addr);

	err = quadd_unwind_start(task);
	if (err)
		return err;

	pr_info("New parameters have been applied\n");

	return 0;
}
예제 #5
0
static int set_parameters(struct quadd_parameters *param, uid_t *debug_app_uid)
{
	int i, err;
	int pmu_events_id[QUADD_MAX_COUNTERS];
	int pl310_events_id;
	int nr_pmu = 0, nr_pl310 = 0;
	int uid = 0;
	struct task_struct *task;

	if (ctx.param.freq != 100 && ctx.param.freq != 1000 &&
	    ctx.param.freq != 10000)
		return -EINVAL;

	ctx.param.freq = param->freq;
	ctx.param.ma_freq = param->ma_freq;
	ctx.param.backtrace = param->backtrace;
	ctx.param.use_freq = param->use_freq;
	ctx.param.system_wide = param->system_wide;
	ctx.param.power_rate_freq = param->power_rate_freq;
	ctx.param.debug_samples = param->debug_samples;

	/* Currently only one process */
	if (param->nr_pids != 1)
		return -EINVAL;

	rcu_read_lock();
	task = pid_task(find_vpid(param->pids[0]), PIDTYPE_PID);
	rcu_read_unlock();
	if (!task) {
		pr_err("Process not found: %u\n", param->pids[0]);
		return -ESRCH;
	}

	pr_info("owner/task uids: %u/%u\n", current_fsuid(), task_uid(task));
	if (!capable(CAP_SYS_ADMIN)) {
		if (current_fsuid() != task_uid(task)) {
			uid = quadd_auth_check_debug_flag(param->package_name);
			if (uid < 0) {
				pr_err("Error: QuadD security service\n");
				return uid;
			} else if (uid == 0) {
				pr_err("Error: app is not debuggable\n");
				return -EACCES;
			}

			*debug_app_uid = uid;
			pr_info("debug_app_uid: %u\n", uid);
		}
		ctx.collect_kernel_ips = 0;
	} else {
		ctx.collect_kernel_ips = 1;
	}

	for (i = 0; i < param->nr_pids; i++)
		ctx.param.pids[i] = param->pids[i];

	ctx.param.nr_pids = param->nr_pids;

	for (i = 0; i < param->nr_events; i++) {
		int event = param->events[i];

		if (ctx.pmu && ctx.pmu_info.nr_supported_events > 0
			&& is_event_supported(&ctx.pmu_info, event)) {
			pmu_events_id[nr_pmu++] = param->events[i];

			pr_info("PMU active event: %s\n",
				quadd_get_event_str(event));
		} else if (ctx.pl310 &&
			   ctx.pl310_info.nr_supported_events > 0 &&
			   is_event_supported(&ctx.pl310_info, event)) {
			pl310_events_id = param->events[i];

			pr_info("PL310 active event: %s\n",
				quadd_get_event_str(event));

			if (nr_pl310++ > 1) {
				pr_err("error: multiply pl310 events\n");
				return -EINVAL;
			}
		} else {
			pr_err("Bad event: %s\n",
			       quadd_get_event_str(event));
			return -EINVAL;
		}
	}

	if (ctx.pmu) {
		if (nr_pmu > 0) {
			err = ctx.pmu->set_events(pmu_events_id, nr_pmu);
			if (err) {
				pr_err("PMU set parameters: error\n");
				return err;
			}
			ctx.pmu_info.active = 1;
		} else {
			ctx.pmu_info.active = 0;
			ctx.pmu->set_events(NULL, 0);
		}
	}

	if (ctx.pl310) {
		if (nr_pl310 == 1) {
			err = ctx.pl310->set_events(&pl310_events_id, 1);
			if (err) {
				pr_info("pl310 set_parameters: error\n");
				return err;
			}
			ctx.pl310_info.active = 1;
		} else {
			ctx.pl310_info.active = 0;
			ctx.pl310->set_events(NULL, 0);
		}
	}
	pr_info("New parameters have been applied\n");

	return 0;
}