110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/**
210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @file daemon/opd_trans.c
310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * Processing the sample buffer
410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @remark Copyright 2002 OProfile authors
610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @remark Read the file COPYING
710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @author John Levon
910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @author Philippe Elie
1010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * Modified by Aravind Menon for Xen
1110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * These modifications are:
1210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * Copyright (C) 2005 Hewlett-Packard Co.
1310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
1410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * Modified by Maynard Johnson <maynardj@us.ibm.com>
1510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * These modifications are:
1610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * (C) Copyright IBM Corporation 2007
1710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
1810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "opd_trans.h"
2010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "opd_kernel.h"
2110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "opd_sfile.h"
2210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "opd_anon.h"
2310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "opd_stats.h"
2410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "opd_printf.h"
2510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "opd_interface.h"
2610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <limits.h>
2810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <string.h>
2910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <stdlib.h>
3010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <stdint.h>
3110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <stdio.h>
3210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <errno.h>
3310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectextern size_t kernel_pointer_size;
3510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid clear_trans_last(struct transient * trans)
3810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
3910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->last = NULL;
4010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->last_anon = NULL;
4110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
4210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
4310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
4410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid clear_trans_current(struct transient * trans)
4510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
4610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->current = NULL;
4710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->anon = NULL;
4810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
4910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectuint64_t pop_buffer_value(struct transient * trans)
5210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
5310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	uint64_t val;
5410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!trans->remaining) {
5610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		fprintf(stderr, "BUG: popping empty buffer !\n");
5710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		abort();
5810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
5910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
6010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (kernel_pointer_size == 4) {
6110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		uint32_t const * lbuf = (void const *)trans->buffer;
6210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		val = *lbuf;
6310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	} else {
6410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		uint64_t const * lbuf = (void const *)trans->buffer;
6510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		val = *lbuf;
6610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
6710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
6810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->remaining--;
6910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->buffer += kernel_pointer_size;
7010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return val;
7110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
7210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
7310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
7410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectint enough_remaining(struct transient * trans, size_t size)
7510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
7610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (trans->remaining >= size)
7710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return 1;
7810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
7910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	verbprintf(vmisc, "Dangling ESCAPE_CODE.\n");
8010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	opd_stats[OPD_DANGLING_CODE]++;
8110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return 0;
8210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
8310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
8410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
8510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void opd_put_sample(struct transient * trans, unsigned long long pc)
8610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
8710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	unsigned long long event;
8810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
8910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!enough_remaining(trans, 1)) {
9010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		trans->remaining = 0;
9110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
9210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
9310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
9410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	event = pop_buffer_value(trans);
9510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
9610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (trans->tracing != TRACING_ON)
9710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		trans->event = event;
9810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
9910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->pc = pc;
10010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
10110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* sfile can change at each sample for kernel */
10210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (trans->in_kernel != 0)
10310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		clear_trans_current(trans);
10410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
10510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!trans->in_kernel && trans->cookie == NO_COOKIE)
10610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		trans->anon = find_anon_mapping(trans);
10710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
10810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* get the current sfile if needed */
10910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!trans->current)
11010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		trans->current = sfile_find(trans);
11110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
11210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/*
11310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * can happen if kernel sample falls through the cracks, or if
11410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * it's a sample from an anon region we couldn't find
11510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 */
11610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!trans->current)
11710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		goto out;
11810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
11910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* FIXME: this logic is perhaps too harsh? */
12010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (trans->current->ignored || (trans->last && trans->last->ignored))
12110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		goto out;
12210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
12310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* log the sample or arc */
12410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	sfile_log_sample(trans);
12510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
12610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectout:
12710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* switch to trace mode */
12810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (trans->tracing == TRACING_START)
12910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		trans->tracing = TRACING_ON;
13010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
13110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	update_trans_last(trans);
13210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
13310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
13410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
13510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void code_unknown(struct transient * trans __attribute__((unused)))
13610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
13710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	fprintf(stderr, "Unknown code !\n");
13810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	abort();
13910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
14010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void code_ctx_switch(struct transient * trans)
14310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
14410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	clear_trans_current(trans);
14510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
14610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!enough_remaining(trans, 5)) {
14710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		trans->remaining = 0;
14810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
14910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
15010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
15110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->tid = pop_buffer_value(trans);
15210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->app_cookie = pop_buffer_value(trans);
15310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* must be ESCAPE_CODE, CTX_TGID_CODE, tgid. Like this
15410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * because tgid was added later in a compatible manner.
15510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 */
15610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	pop_buffer_value(trans);
15710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	pop_buffer_value(trans);
15810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->tgid = pop_buffer_value(trans);
15910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
16010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (vmisc) {
16110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		char const * app = find_cookie(trans->app_cookie);
16210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		printf("CTX_SWITCH to tid %lu, tgid %lu, cookie %llx(%s)\n",
16310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		       (unsigned long)trans->tid, (unsigned long)trans->tgid,
16410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		       trans->app_cookie, app ? app : "none");
16510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
16610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
16710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
16810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
16910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void code_cpu_switch(struct transient * trans)
17010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
17110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	clear_trans_current(trans);
17210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
17310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!enough_remaining(trans, 1)) {
17410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		trans->remaining = 0;
17510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
17610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
17710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
17810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->cpu = pop_buffer_value(trans);
17910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	verbprintf(vmisc, "CPU_SWITCH to %lu\n", trans->cpu);
18010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
18110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
18210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
18310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void code_cookie_switch(struct transient * trans)
18410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
18510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	clear_trans_current(trans);
18610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
18710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!enough_remaining(trans, 1)) {
18810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		trans->remaining = 0;
18910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
19010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
19110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
19210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->cookie = pop_buffer_value(trans);
19310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
19410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (vmisc) {
19510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		char const * name = verbose_cookie(trans->cookie);
19610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		verbprintf(vmisc, "COOKIE_SWITCH to cookie %s(%llx)\n",
1975a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng			   name, trans->cookie);
19810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
19910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
20010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
20110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
20210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void code_kernel_enter(struct transient * trans)
20310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
20410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	verbprintf(vmisc, "KERNEL_ENTER_SWITCH to kernel\n");
20510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->in_kernel = 1;
20610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	clear_trans_current(trans);
20710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* subtlety: we must keep trans->cookie cached,
20810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * even though it's meaningless for the kernel -
20910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * we won't necessarily get a cookie switch on
21010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * kernel exit. See comments in opd_sfile.c
21110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 */
21210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
21310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
21410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
21510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void code_user_enter(struct transient * trans)
21610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
21710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	verbprintf(vmisc, "USER_ENTER_SWITCH to user-space\n");
21810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->in_kernel = 0;
21910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	clear_trans_current(trans);
22010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	clear_trans_last(trans);
22110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
22210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
22310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
22410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void code_module_loaded(struct transient * trans __attribute__((unused)))
22510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
22610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	verbprintf(vmodule, "MODULE_LOADED_CODE\n");
22710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	opd_reread_module_info();
22810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	clear_trans_current(trans);
22910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	clear_trans_last(trans);
23010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
23110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
23210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
23310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/*
23410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * This also implicitly signals the end of the previous
23510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * trace, so we never explicitly set TRACING_OFF when
23610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * processing a buffer.
23710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
23810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void code_trace_begin(struct transient * trans)
23910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
24010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	verbprintf(varcs, "TRACE_BEGIN\n");
24110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->tracing = TRACING_START;
24210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
24310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
24410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void code_xen_enter(struct transient * trans)
24510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
24610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	verbprintf(vmisc, "XEN_ENTER_SWITCH to xen\n");
24710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->in_kernel = 1;
24810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	trans->current = NULL;
2495a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	/* subtlety: we must keep trans->cookie cached, even though it's
2505a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	 * meaningless for Xen - we won't necessarily get a cookie switch
2515a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	 * on Xen exit. See comments in opd_sfile.c. It seems that we can
2525a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	 * get away with in_kernel = 1 as long as we supply the correct
2535a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	 * Xen image, and its address range in startup find_kernel_image
25410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * is modified to look in the Xen image also
25510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 */
25610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
25710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
25810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectextern void code_spu_profiling(struct transient * trans);
25910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectextern void code_spu_ctx_switch(struct transient * trans);
26010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2615a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Chengextern void code_ibs_fetch_sample(struct transient * trans);
2625a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Chengextern void code_ibs_op_sample(struct transient * trans);
2635a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng
26410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projecthandler_t handlers[LAST_CODE + 1] = {
26510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_unknown,
26610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_ctx_switch,
26710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_cpu_switch,
26810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_cookie_switch,
26910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_kernel_enter,
2705a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	&code_user_enter,
27110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_module_loaded,
27210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* tgid handled differently */
27310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_unknown,
27410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_trace_begin,
27510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_unknown,
2765a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	&code_xen_enter,
27710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#if defined(__powerpc__)
27810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_spu_profiling,
27910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_spu_ctx_switch,
2805a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng#else
28110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	&code_unknown,
2825a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	&code_unknown,
2835a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng#endif
2845a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	&code_ibs_fetch_sample,
2855a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	&code_ibs_op_sample,
28610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project};
28710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
28810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectextern void (*special_processor)(struct transient *);
28910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
29010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectvoid opd_process_samples(char const * buffer, size_t count)
29110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
29210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	struct transient trans = {
29310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.buffer = buffer,
29410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.remaining = count,
29510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.tracing = TRACING_OFF,
29610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.current = NULL,
29710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.last = NULL,
29810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.cookie = INVALID_COOKIE,
29910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.app_cookie = INVALID_COOKIE,
30010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.anon = NULL,
30110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.last_anon = NULL,
30210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.pc = 0,
30310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.last_pc = 0,
30410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.event = 0,
30510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.in_kernel = -1,
30610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.cpu = -1,
30710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.tid = -1,
30810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		.embedded_offset = UNUSED_EMBEDDED_OFFSET,
3095a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng		.tgid = -1,
3105a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng		.ext = NULL
31110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	};
31210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
31310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* FIXME: was uint64_t but it can't compile on alpha where uint64_t
31410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * is an unsigned long and below the printf("..." %llu\n", code)
31510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 * generate a warning, this look like a stopper to use c98 types :/
31610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	 */
31710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	unsigned long long code;
31810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
31910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (special_processor) {
32010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		special_processor(&trans);
32110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return;
32210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
32310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
32410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	while (trans.remaining) {
32510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		code = pop_buffer_value(&trans);
32610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
32710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (!is_escape_code(code)) {
32810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			opd_put_sample(&trans, code);
32910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			continue;
33010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
33110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
33210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (!trans.remaining) {
33310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			verbprintf(vmisc, "Dangling ESCAPE_CODE.\n");
33410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			opd_stats[OPD_DANGLING_CODE]++;
33510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			break;
33610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
33710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
33810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		// started with ESCAPE_CODE, next is type
33910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		code = pop_buffer_value(&trans);
34010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
34110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (code >= LAST_CODE) {
34210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			fprintf(stderr, "Unknown code %llu\n", code);
34310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			abort();
34410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
34510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
34610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		handlers[code](&trans);
34710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
34810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
349