static int annotate_release(struct inode *inode, struct file *file)
{
	int cpu = 0;

	/* synchronize between cores */
	spin_lock(&annotate_lock);

	if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
		uint32_t pid = current->pid;

		gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu());
		gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
		/* time */
		gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0);
		/* size */
		gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0);
	}

	/* Check and commit; commit is set to occur once buffer is 3/4 full */
	buffer_check(cpu, ANNOTATE_BUF, gator_get_time());

	spin_unlock(&annotate_lock);

	return 0;
}
Exemple #2
0
static void ebs_overflow_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
#endif
{
	unsigned int value, delta, cpu = smp_processor_id(), buftype = EVENT_BUF;

	if (event != per_cpu(pevent, cpu))
		return;

	if (buffer_check_space(cpu, buftype, 5 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
		value = local64_read(&event->count);
		delta = value - per_cpu(prev_value, cpu);
		per_cpu(prev_value, cpu) = value;

		// Counters header
		gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COUNTERS);     // type
		gator_buffer_write_packed_int64(cpu, buftype, gator_get_time());   // time

		// Output counter
		gator_buffer_write_packed_int(cpu, buftype, 2);                    // length
		gator_buffer_write_packed_int(cpu, buftype, per_cpu(key, cpu));    // key
		gator_buffer_write_packed_int(cpu, buftype, delta);                // delta

		// End Counters, length of zero
		gator_buffer_write_packed_int(cpu, buftype, 0);
	}

	// Output backtrace
	if (buffer_check_space(cpu, buftype, gator_backtrace_depth * 2 * MAXSIZE_PACK32))
		gator_add_sample(cpu, buftype, regs);

	// Check and commit; commit is set to occur once buffer is 3/4 full
	buffer_check(cpu, buftype);
}
static void marshal_cookie(int cookie, const char *text)
{
	int cpu = get_physical_cpu();
	/* buffer_check_space already called by marshal_cookie_header */
	gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE);
	gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
	gator_buffer_write_string(cpu, NAME_BUF, text);
	buffer_check(cpu, NAME_BUF, gator_get_time());
}
Exemple #4
0
static irqreturn_t armv7_pmnc_interrupt(int irq, void *arg)
{
	unsigned int cnt, cpu = smp_processor_id(), buftype = EVENT_BUF;
	struct pt_regs * const regs = get_irq_regs();
	u32 flags;

	// Stop irq generation
	armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);

	// Get and reset overflow status flags
	flags = armv7_pmnc_reset_interrupt();

	// Counters header
	gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COUNTERS);      // type
	gator_buffer_write_packed_int64(cpu, buftype, gator_get_time());    // time
	
	// Cycle counter
	if (flags & (1 << 31)) {
		int value = armv7_ccnt_read(pmnc_count[CCNT]);                  // overrun
		gator_buffer_write_packed_int(cpu, buftype, 2);                 // length
		gator_buffer_write_packed_int(cpu, buftype, pmnc_key[CCNT]);    // key
		gator_buffer_write_packed_int(cpu, buftype, value);             // value
	}

	// PMNC counters
	for (cnt = CNT0; cnt < CNTMAX; cnt++) {
		 if (flags & (1 << (cnt - CNT0))) {
			int value = armv7_cntn_read(cnt, pmnc_count[cnt]);          // overrun
			gator_buffer_write_packed_int(cpu, buftype, 2);             // length
			gator_buffer_write_packed_int(cpu, buftype, pmnc_key[cnt]); // key
			gator_buffer_write_packed_int(cpu, buftype, value);         // value
		 }
	}

	// End Counters, length of zero
	gator_buffer_write_packed_int(cpu, buftype, 0);

	// Output backtrace
	gator_add_sample(cpu, buftype, regs);

	// Check and commit; commit is set to occur once buffer is 3/4 full
	event_buffer_check(cpu);

	// Allow irq generation
	armv7_pmnc_write(armv7_pmnc_read() | PMNC_E);

	return IRQ_HANDLED;
}
static void marshal_core_name(const int core, const int cpuid, const char *name)
{
	int cpu = get_physical_cpu();
	unsigned long flags;

	local_irq_save(flags);
	if (buffer_check_space(cpu, SUMMARY_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) {
		gator_buffer_write_packed_int(cpu, SUMMARY_BUF, MESSAGE_CORE_NAME);
		gator_buffer_write_packed_int(cpu, SUMMARY_BUF, core);
		gator_buffer_write_packed_int(cpu, SUMMARY_BUF, cpuid);
		gator_buffer_write_string(cpu, SUMMARY_BUF, name);
	}
	/* Commit core names now so that they can show up in live */
	local_irq_restore(flags);
	gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time());
}
static void marshal_thread_name(int pid, char *name)
{
	unsigned long flags, cpu;
	u64 time;

	local_irq_save(flags);
	cpu = get_physical_cpu();
	time = gator_get_time();
	if (buffer_check_space(cpu, NAME_BUF, TASK_COMM_LEN + 3 * MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
		gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_THREAD_NAME);
		gator_buffer_write_packed_int64(cpu, NAME_BUF, time);
		gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
		gator_buffer_write_string(cpu, NAME_BUF, name);
	}
	local_irq_restore(flags);
	buffer_check(cpu, NAME_BUF, time);
}
static void marshal_idle(int core, int state)
{
	unsigned long flags, cpu;
	u64 time;

	local_irq_save(flags);
	cpu = get_physical_cpu();
	time = gator_get_time();
	if (buffer_check_space(cpu, IDLE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
		gator_buffer_write_packed_int(cpu, IDLE_BUF, state);
		gator_buffer_write_packed_int64(cpu, IDLE_BUF, time);
		gator_buffer_write_packed_int(cpu, IDLE_BUF, core);
	}
	local_irq_restore(flags);
	/* Check and commit; commit is set to occur once buffer is 3/4 full */
	buffer_check(cpu, IDLE_BUF, time);
}
static void marshal_summary(long long timestamp, long long uptime, long long monotonic_delta, const char *uname)
{
	unsigned long flags;
	int cpu = 0;
	char buf[32];

	local_irq_save(flags);
	gator_buffer_write_packed_int(cpu, SUMMARY_BUF, MESSAGE_SUMMARY);
	gator_buffer_write_string(cpu, SUMMARY_BUF, NEWLINE_CANARY);
	gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, timestamp);
	gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, uptime);
	gator_buffer_write_packed_int64(cpu, SUMMARY_BUF, monotonic_delta);
	gator_buffer_write_string(cpu, SUMMARY_BUF, "uname");
	gator_buffer_write_string(cpu, SUMMARY_BUF, uname);
	gator_buffer_write_string(cpu, SUMMARY_BUF, "PAGESIZE");
	snprintf(buf, sizeof(buf), "%lu", PAGE_SIZE);
	gator_buffer_write_string(cpu, SUMMARY_BUF, buf);
#if GATOR_IKS_SUPPORT
	gator_buffer_write_string(cpu, SUMMARY_BUF, "iks");
	gator_buffer_write_string(cpu, SUMMARY_BUF, "");
#endif
#ifdef CONFIG_PREEMPT_RTB
	gator_buffer_write_string(cpu, SUMMARY_BUF, "preempt_rtb");
	gator_buffer_write_string(cpu, SUMMARY_BUF, "");
#endif
#ifdef CONFIG_PREEMPT_RT_FULL
	gator_buffer_write_string(cpu, SUMMARY_BUF, "preempt_rt_full");
	gator_buffer_write_string(cpu, SUMMARY_BUF, "");
#endif
	/* Let Streamline know which GPU is used so that it can label the GPU Activity appropriately. This is a temporary fix, to be improved in a future release. */
#ifdef MALI_SUPPORT
	gator_buffer_write_string(cpu, SUMMARY_BUF, "mali_type");
#if (MALI_SUPPORT == MALI_4xx)
	gator_buffer_write_string(cpu, SUMMARY_BUF, "4xx");
#elif (MALI_SUPPORT == MALI_MIDGARD)
	gator_buffer_write_string(cpu, SUMMARY_BUF, "6xx");
#else
	gator_buffer_write_string(cpu, SUMMARY_BUF, "unknown");
#endif
#endif
	gator_buffer_write_string(cpu, SUMMARY_BUF, "");
	/* Commit the buffer now so it can be one of the first frames read by Streamline */
	local_irq_restore(flags);
	gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time());
}
static void __maybe_unused marshal_event_single64(int core, int key, long long value)
{
	unsigned long flags, cpu;
	u64 time;

	local_irq_save(flags);
	cpu = get_physical_cpu();
	time = gator_get_time();
	if (buffer_check_space(cpu, COUNTER_BUF, 2 * MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
		gator_buffer_write_packed_int64(cpu, COUNTER_BUF, time);
		gator_buffer_write_packed_int(cpu, COUNTER_BUF, core);
		gator_buffer_write_packed_int(cpu, COUNTER_BUF, key);
		gator_buffer_write_packed_int64(cpu, COUNTER_BUF, value);
	}
	local_irq_restore(flags);
	/* Check and commit; commit is set to occur once buffer is 3/4 full */
	buffer_check(cpu, COUNTER_BUF, time);
}
static void marshal_link(int cookie, int tgid, int pid)
{
	unsigned long cpu = get_physical_cpu(), flags;
	u64 time;

	local_irq_save(flags);
	time = gator_get_time();
	if (buffer_check_space(cpu, ACTIVITY_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, MESSAGE_LINK);
		gator_buffer_write_packed_int64(cpu, ACTIVITY_BUF, time);
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, cookie);
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, tgid);
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, pid);
	}
	local_irq_restore(flags);
	/* Check and commit; commit is set to occur once buffer is 3/4 full */
	buffer_check(cpu, ACTIVITY_BUF, time);
}
static void marshal_sched_trace_exit(int tgid, int pid)
{
	unsigned long cpu = get_physical_cpu(), flags;
	u64 time;

	if (!per_cpu(gator_buffer, cpu)[SCHED_TRACE_BUF])
		return;

	local_irq_save(flags);
	time = gator_get_time();
	if (buffer_check_space(cpu, SCHED_TRACE_BUF, MAXSIZE_PACK64 + 2 * MAXSIZE_PACK32)) {
		gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, MESSAGE_SCHED_EXIT);
		gator_buffer_write_packed_int64(cpu, SCHED_TRACE_BUF, time);
		gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid);
	}
	local_irq_restore(flags);
	/* Check and commit; commit is set to occur once buffer is 3/4 full */
	buffer_check(cpu, SCHED_TRACE_BUF, time);
}
Exemple #12
0
static void gator_event_sampling_online(void)
{
	int cpu = smp_processor_id(), buftype = EVENT_BUF;

	// read the counter and toss the invalid data, return zero instead
	struct perf_event * ev = per_cpu(pevent, cpu);
	if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
		ev->pmu->read(ev);
		per_cpu(prev_value, cpu) = local64_read(&ev->count);

		// Counters header
		gator_buffer_write_packed_int(cpu, buftype, MESSAGE_COUNTERS);     // type
		gator_buffer_write_packed_int64(cpu, buftype, gator_get_time());   // time

		// Output counter
		gator_buffer_write_packed_int(cpu, buftype, 2);                    // length
		gator_buffer_write_packed_int(cpu, buftype, per_cpu(key, cpu));    // key
		gator_buffer_write_packed_int(cpu, buftype, 0);                    // delta - zero for initialization

		// End Counters, length of zero
		gator_buffer_write_packed_int(cpu, buftype, 0);
	}
}
static void marshal_activity_switch(int core, int key, int activity, int pid, int state)
{
	unsigned long cpu = get_physical_cpu(), flags;
	u64 time;

	if (!per_cpu(gator_buffer, cpu)[ACTIVITY_BUF])
		return;

	local_irq_save(flags);
	time = gator_get_time();
	if (buffer_check_space(cpu, ACTIVITY_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, MESSAGE_SWITCH);
		gator_buffer_write_packed_int64(cpu, ACTIVITY_BUF, time);
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, core);
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, key);
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, activity);
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, pid);
		gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, state);
	}
	local_irq_restore(flags);
	/* Check and commit; commit is set to occur once buffer is 3/4 full */
	buffer_check(cpu, ACTIVITY_BUF, time);
}
static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count_orig, loff_t *offset)
{
	int pid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
	bool interrupt_context;

	if (*offset)
		return -EINVAL;

	interrupt_context = in_interrupt();
	/* Annotations are not supported in interrupt context, but may work
	 * if you comment out the the next four lines of code. By doing so,
	 * annotations in interrupt context can result in deadlocks and lost
	 * data.
	 */
	if (interrupt_context) {
		pr_warning("gator: Annotations are not supported in interrupt context. Edit gator_annotate.c in the gator driver to enable annotations in interrupt context.\n");
		return -EINVAL;
	}

 retry:
	/* synchronize between cores and with collect_annotations */
	spin_lock(&annotate_lock);

	if (!collect_annotations) {
		/* Not collecting annotations, tell the caller everything was written */
		size = count_orig;
		goto annotate_write_out;
	}

	/* Annotation only uses a single per-cpu buffer as the data must be in order to the engine */
	cpu = 0;

        if (current == NULL)
		pid = 0;
	else
		pid = current->pid;

	/* determine total size of the payload */
	header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64;
	available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size;
	size = count < available ? count : available;

	if (size <= 0) {
		/* Buffer is full, wait until space is available */
		spin_unlock(&annotate_lock);

		/* Drop the annotation as blocking is not allowed in interrupt context */
		if (interrupt_context)
			return -EINVAL;

		wait_event_interruptible(gator_annotate_wait, buffer_bytes_available(cpu, ANNOTATE_BUF) > header_size || !collect_annotations);

		/* Check to see if a signal is pending */
		if (signal_pending(current))
			return -EINTR;

		goto retry;
	}

	/* synchronize shared variables annotateBuf and annotatePos */
	if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
		u64 time = gator_get_time();

		gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu());
		gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
		gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, time);
		gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size);

		/* determine the sizes to capture, length1 + length2 will equal size */
		contiguous = contiguous_space_available(cpu, ANNOTATE_BUF);
		if (size < contiguous) {
			length1 = size;
			length2 = 0;
		} else {
			length1 = contiguous;
			length2 = size - contiguous;
		}

		if (annotate_copy(file, buf, length1) != 0) {
			size = -EINVAL;
			goto annotate_write_out;
		}

		if (length2 > 0 && annotate_copy(file, &buf[length1], length2) != 0) {
			size = -EINVAL;
			goto annotate_write_out;
		}

		/* Check and commit; commit is set to occur once buffer is 3/4 full */
		buffer_check(cpu, ANNOTATE_BUF, time);
	}

annotate_write_out:
	spin_unlock(&annotate_lock);

	/* return the number of bytes written */
	return size;
}