xref: /aosp_15_r20/external/trace-cmd/tracecmd/trace-vm.c (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
1*58e6ee5fSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*58e6ee5fSAndroid Build Coastguard Worker /*
3*58e6ee5fSAndroid Build Coastguard Worker  * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]>
4*58e6ee5fSAndroid Build Coastguard Worker  * Copyright (C) 2020, VMware, Tzvetomir Stoyanov <[email protected]>
5*58e6ee5fSAndroid Build Coastguard Worker  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6*58e6ee5fSAndroid Build Coastguard Worker  */
7*58e6ee5fSAndroid Build Coastguard Worker #include <stdio.h>
8*58e6ee5fSAndroid Build Coastguard Worker #include <stdlib.h>
9*58e6ee5fSAndroid Build Coastguard Worker #include <sys/types.h>
10*58e6ee5fSAndroid Build Coastguard Worker #include <dirent.h>
11*58e6ee5fSAndroid Build Coastguard Worker #include <limits.h>
12*58e6ee5fSAndroid Build Coastguard Worker #include <unistd.h>
13*58e6ee5fSAndroid Build Coastguard Worker #include <errno.h>
14*58e6ee5fSAndroid Build Coastguard Worker 
15*58e6ee5fSAndroid Build Coastguard Worker #include "trace-local.h"
16*58e6ee5fSAndroid Build Coastguard Worker #include "trace-msg.h"
17*58e6ee5fSAndroid Build Coastguard Worker 
18*58e6ee5fSAndroid Build Coastguard Worker static struct trace_guest *guests;
19*58e6ee5fSAndroid Build Coastguard Worker static size_t guests_len;
20*58e6ee5fSAndroid Build Coastguard Worker 
get_guest_by_cid(unsigned int guest_cid)21*58e6ee5fSAndroid Build Coastguard Worker static struct trace_guest *get_guest_by_cid(unsigned int guest_cid)
22*58e6ee5fSAndroid Build Coastguard Worker {
23*58e6ee5fSAndroid Build Coastguard Worker 	int i;
24*58e6ee5fSAndroid Build Coastguard Worker 
25*58e6ee5fSAndroid Build Coastguard Worker 	if (!guests)
26*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
27*58e6ee5fSAndroid Build Coastguard Worker 
28*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < guests_len; i++)
29*58e6ee5fSAndroid Build Coastguard Worker 		if (guest_cid == guests[i].cid)
30*58e6ee5fSAndroid Build Coastguard Worker 			return guests + i;
31*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
32*58e6ee5fSAndroid Build Coastguard Worker }
33*58e6ee5fSAndroid Build Coastguard Worker 
get_guest_by_name(const char * name)34*58e6ee5fSAndroid Build Coastguard Worker static struct trace_guest *get_guest_by_name(const char *name)
35*58e6ee5fSAndroid Build Coastguard Worker {
36*58e6ee5fSAndroid Build Coastguard Worker 	int i;
37*58e6ee5fSAndroid Build Coastguard Worker 
38*58e6ee5fSAndroid Build Coastguard Worker 	if (!guests)
39*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
40*58e6ee5fSAndroid Build Coastguard Worker 
41*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < guests_len; i++)
42*58e6ee5fSAndroid Build Coastguard Worker 		if (strcmp(name, guests[i].name) == 0)
43*58e6ee5fSAndroid Build Coastguard Worker 			return guests + i;
44*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
45*58e6ee5fSAndroid Build Coastguard Worker }
46*58e6ee5fSAndroid Build Coastguard Worker 
trace_have_guests_pid(void)47*58e6ee5fSAndroid Build Coastguard Worker bool trace_have_guests_pid(void)
48*58e6ee5fSAndroid Build Coastguard Worker {
49*58e6ee5fSAndroid Build Coastguard Worker 	for (int i = 0; i < guests_len; i++) {
50*58e6ee5fSAndroid Build Coastguard Worker 		if (guests[i].pid < 0)
51*58e6ee5fSAndroid Build Coastguard Worker 			return false;
52*58e6ee5fSAndroid Build Coastguard Worker 	}
53*58e6ee5fSAndroid Build Coastguard Worker 
54*58e6ee5fSAndroid Build Coastguard Worker 	return true;
55*58e6ee5fSAndroid Build Coastguard Worker }
56*58e6ee5fSAndroid Build Coastguard Worker 
add_guest(unsigned int cid,const char * name)57*58e6ee5fSAndroid Build Coastguard Worker static struct trace_guest *add_guest(unsigned int cid, const char *name)
58*58e6ee5fSAndroid Build Coastguard Worker {
59*58e6ee5fSAndroid Build Coastguard Worker 	guests = realloc(guests, (guests_len + 1) * sizeof(*guests));
60*58e6ee5fSAndroid Build Coastguard Worker 	if (!guests)
61*58e6ee5fSAndroid Build Coastguard Worker 		die("allocating new guest");
62*58e6ee5fSAndroid Build Coastguard Worker 	memset(&guests[guests_len], 0, sizeof(struct trace_guest));
63*58e6ee5fSAndroid Build Coastguard Worker 	guests[guests_len].name = strdup(name);
64*58e6ee5fSAndroid Build Coastguard Worker 	if (!guests[guests_len].name)
65*58e6ee5fSAndroid Build Coastguard Worker 		die("allocating guest name");
66*58e6ee5fSAndroid Build Coastguard Worker 	guests[guests_len].cid = cid;
67*58e6ee5fSAndroid Build Coastguard Worker 	guests[guests_len].pid = -1;
68*58e6ee5fSAndroid Build Coastguard Worker 	guests_len++;
69*58e6ee5fSAndroid Build Coastguard Worker 
70*58e6ee5fSAndroid Build Coastguard Worker 	return &guests[guests_len - 1];
71*58e6ee5fSAndroid Build Coastguard Worker }
72*58e6ee5fSAndroid Build Coastguard Worker 
start_trace_connect(void)73*58e6ee5fSAndroid Build Coastguard Worker static struct tracefs_instance *start_trace_connect(void)
74*58e6ee5fSAndroid Build Coastguard Worker {
75*58e6ee5fSAndroid Build Coastguard Worker 	struct tracefs_instance *open_instance;
76*58e6ee5fSAndroid Build Coastguard Worker 
77*58e6ee5fSAndroid Build Coastguard Worker 	open_instance = tracefs_instance_create("vsock_find_pid");
78*58e6ee5fSAndroid Build Coastguard Worker 	if (!open_instance)
79*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
80*58e6ee5fSAndroid Build Coastguard Worker 
81*58e6ee5fSAndroid Build Coastguard Worker 	tracefs_event_enable(open_instance, "sched", "sched_waking");
82*58e6ee5fSAndroid Build Coastguard Worker 	tracefs_event_enable(open_instance, "kvm", "kvm_exit");
83*58e6ee5fSAndroid Build Coastguard Worker 	tracefs_trace_on(open_instance);
84*58e6ee5fSAndroid Build Coastguard Worker 	return open_instance;
85*58e6ee5fSAndroid Build Coastguard Worker }
86*58e6ee5fSAndroid Build Coastguard Worker 
87*58e6ee5fSAndroid Build Coastguard Worker struct pids {
88*58e6ee5fSAndroid Build Coastguard Worker 	struct pids		*next;
89*58e6ee5fSAndroid Build Coastguard Worker 	int			pid;
90*58e6ee5fSAndroid Build Coastguard Worker };
91*58e6ee5fSAndroid Build Coastguard Worker 
92*58e6ee5fSAndroid Build Coastguard Worker struct trace_fields {
93*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_event		*sched_waking;
94*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_event		*kvm_exit;
95*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field		*common_pid;
96*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field		*sched_next;
97*58e6ee5fSAndroid Build Coastguard Worker 	struct pids			*pids;
98*58e6ee5fSAndroid Build Coastguard Worker 	int				found_pid;
99*58e6ee5fSAndroid Build Coastguard Worker };
100*58e6ee5fSAndroid Build Coastguard Worker 
free_pids(struct pids * pids)101*58e6ee5fSAndroid Build Coastguard Worker static void free_pids(struct pids *pids)
102*58e6ee5fSAndroid Build Coastguard Worker {
103*58e6ee5fSAndroid Build Coastguard Worker 	struct pids *next;
104*58e6ee5fSAndroid Build Coastguard Worker 
105*58e6ee5fSAndroid Build Coastguard Worker 	while (pids) {
106*58e6ee5fSAndroid Build Coastguard Worker 		next = pids;
107*58e6ee5fSAndroid Build Coastguard Worker 		pids = pids->next;
108*58e6ee5fSAndroid Build Coastguard Worker 		free(next);
109*58e6ee5fSAndroid Build Coastguard Worker 	}
110*58e6ee5fSAndroid Build Coastguard Worker }
111*58e6ee5fSAndroid Build Coastguard Worker 
add_pid(struct pids ** pids,int pid)112*58e6ee5fSAndroid Build Coastguard Worker static void add_pid(struct pids **pids, int pid)
113*58e6ee5fSAndroid Build Coastguard Worker {
114*58e6ee5fSAndroid Build Coastguard Worker 	struct pids *new_pid;
115*58e6ee5fSAndroid Build Coastguard Worker 
116*58e6ee5fSAndroid Build Coastguard Worker 	new_pid = malloc(sizeof(*new_pid));
117*58e6ee5fSAndroid Build Coastguard Worker 	if (!new_pid)
118*58e6ee5fSAndroid Build Coastguard Worker 		return;
119*58e6ee5fSAndroid Build Coastguard Worker 
120*58e6ee5fSAndroid Build Coastguard Worker 	new_pid->pid = pid;
121*58e6ee5fSAndroid Build Coastguard Worker 	new_pid->next = *pids;
122*58e6ee5fSAndroid Build Coastguard Worker 	*pids = new_pid;
123*58e6ee5fSAndroid Build Coastguard Worker }
124*58e6ee5fSAndroid Build Coastguard Worker 
match_pid(struct pids * pids,int pid)125*58e6ee5fSAndroid Build Coastguard Worker static bool match_pid(struct pids *pids, int pid)
126*58e6ee5fSAndroid Build Coastguard Worker {
127*58e6ee5fSAndroid Build Coastguard Worker 	while (pids) {
128*58e6ee5fSAndroid Build Coastguard Worker 		if (pids->pid == pid)
129*58e6ee5fSAndroid Build Coastguard Worker 			return true;
130*58e6ee5fSAndroid Build Coastguard Worker 		pids = pids->next;
131*58e6ee5fSAndroid Build Coastguard Worker 	}
132*58e6ee5fSAndroid Build Coastguard Worker 	return false;
133*58e6ee5fSAndroid Build Coastguard Worker }
134*58e6ee5fSAndroid Build Coastguard Worker 
callback(struct tep_event * event,struct tep_record * record,int cpu,void * data)135*58e6ee5fSAndroid Build Coastguard Worker static int callback(struct tep_event *event, struct tep_record *record, int cpu,
136*58e6ee5fSAndroid Build Coastguard Worker 		    void *data)
137*58e6ee5fSAndroid Build Coastguard Worker {
138*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_fields *fields = data;
139*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *tep = event->tep;
140*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long val;
141*58e6ee5fSAndroid Build Coastguard Worker 	int flags;
142*58e6ee5fSAndroid Build Coastguard Worker 	int type;
143*58e6ee5fSAndroid Build Coastguard Worker 	int pid;
144*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
145*58e6ee5fSAndroid Build Coastguard Worker 
146*58e6ee5fSAndroid Build Coastguard Worker 	ret = tep_read_number_field(fields->common_pid, record->data, &val);
147*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
148*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
149*58e6ee5fSAndroid Build Coastguard Worker 
150*58e6ee5fSAndroid Build Coastguard Worker 	flags = tep_data_flags(tep, record);
151*58e6ee5fSAndroid Build Coastguard Worker 
152*58e6ee5fSAndroid Build Coastguard Worker 	/* Ignore events in interrupts */
153*58e6ee5fSAndroid Build Coastguard Worker 	if (flags & (TRACE_FLAG_HARDIRQ | TRACE_FLAG_SOFTIRQ))
154*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
155*58e6ee5fSAndroid Build Coastguard Worker 
156*58e6ee5fSAndroid Build Coastguard Worker 	/*
157*58e6ee5fSAndroid Build Coastguard Worker 	 * First make sure that this event comes from a PID from
158*58e6ee5fSAndroid Build Coastguard Worker 	 * this task (or a task woken by this task)
159*58e6ee5fSAndroid Build Coastguard Worker 	 */
160*58e6ee5fSAndroid Build Coastguard Worker 	pid = val;
161*58e6ee5fSAndroid Build Coastguard Worker 	if (!match_pid(fields->pids, pid))
162*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
163*58e6ee5fSAndroid Build Coastguard Worker 
164*58e6ee5fSAndroid Build Coastguard Worker 	type = tep_data_type(tep, record);
165*58e6ee5fSAndroid Build Coastguard Worker 
166*58e6ee5fSAndroid Build Coastguard Worker 	/*
167*58e6ee5fSAndroid Build Coastguard Worker 	 * If this event is a kvm_exit, we have our PID
168*58e6ee5fSAndroid Build Coastguard Worker 	 * and we can stop processing.
169*58e6ee5fSAndroid Build Coastguard Worker 	 */
170*58e6ee5fSAndroid Build Coastguard Worker 	if (type == fields->kvm_exit->id) {
171*58e6ee5fSAndroid Build Coastguard Worker 		fields->found_pid = pid;
172*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
173*58e6ee5fSAndroid Build Coastguard Worker 	}
174*58e6ee5fSAndroid Build Coastguard Worker 
175*58e6ee5fSAndroid Build Coastguard Worker 	if (type != fields->sched_waking->id)
176*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
177*58e6ee5fSAndroid Build Coastguard Worker 
178*58e6ee5fSAndroid Build Coastguard Worker 	ret = tep_read_number_field(fields->sched_next, record->data, &val);
179*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
180*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
181*58e6ee5fSAndroid Build Coastguard Worker 
182*58e6ee5fSAndroid Build Coastguard Worker 	/* This is a task woken by our task or a chain of wake ups */
183*58e6ee5fSAndroid Build Coastguard Worker 	add_pid(&fields->pids, (int)val);
184*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
185*58e6ee5fSAndroid Build Coastguard Worker }
186*58e6ee5fSAndroid Build Coastguard Worker 
find_tgid(int pid)187*58e6ee5fSAndroid Build Coastguard Worker static int find_tgid(int pid)
188*58e6ee5fSAndroid Build Coastguard Worker {
189*58e6ee5fSAndroid Build Coastguard Worker 	FILE *fp;
190*58e6ee5fSAndroid Build Coastguard Worker 	char *path;
191*58e6ee5fSAndroid Build Coastguard Worker 	char *buf = NULL;
192*58e6ee5fSAndroid Build Coastguard Worker 	char *save;
193*58e6ee5fSAndroid Build Coastguard Worker 	size_t l = 0;
194*58e6ee5fSAndroid Build Coastguard Worker 	int tgid = -1;
195*58e6ee5fSAndroid Build Coastguard Worker 
196*58e6ee5fSAndroid Build Coastguard Worker 	if (asprintf(&path, "/proc/%d/status", pid) < 0)
197*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
198*58e6ee5fSAndroid Build Coastguard Worker 
199*58e6ee5fSAndroid Build Coastguard Worker 	fp = fopen(path, "r");
200*58e6ee5fSAndroid Build Coastguard Worker 	free(path);
201*58e6ee5fSAndroid Build Coastguard Worker 	if (!fp)
202*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
203*58e6ee5fSAndroid Build Coastguard Worker 
204*58e6ee5fSAndroid Build Coastguard Worker 	while (getline(&buf, &l, fp) > 0) {
205*58e6ee5fSAndroid Build Coastguard Worker 		char *tok;
206*58e6ee5fSAndroid Build Coastguard Worker 
207*58e6ee5fSAndroid Build Coastguard Worker 		if (strncmp(buf, "Tgid:", 5) != 0)
208*58e6ee5fSAndroid Build Coastguard Worker 			continue;
209*58e6ee5fSAndroid Build Coastguard Worker 		tok = strtok_r(buf, ":", &save);
210*58e6ee5fSAndroid Build Coastguard Worker 		if (!tok)
211*58e6ee5fSAndroid Build Coastguard Worker 			continue;
212*58e6ee5fSAndroid Build Coastguard Worker 		tok = strtok_r(NULL, ":", &save);
213*58e6ee5fSAndroid Build Coastguard Worker 		if (!tok)
214*58e6ee5fSAndroid Build Coastguard Worker 			continue;
215*58e6ee5fSAndroid Build Coastguard Worker 		while (isspace(*tok))
216*58e6ee5fSAndroid Build Coastguard Worker 			tok++;
217*58e6ee5fSAndroid Build Coastguard Worker 		tgid = strtol(tok, NULL, 0);
218*58e6ee5fSAndroid Build Coastguard Worker 		break;
219*58e6ee5fSAndroid Build Coastguard Worker 	}
220*58e6ee5fSAndroid Build Coastguard Worker 	free(buf);
221*58e6ee5fSAndroid Build Coastguard Worker 	fclose(fp);
222*58e6ee5fSAndroid Build Coastguard Worker 
223*58e6ee5fSAndroid Build Coastguard Worker 	return tgid;
224*58e6ee5fSAndroid Build Coastguard Worker }
225*58e6ee5fSAndroid Build Coastguard Worker 
stop_trace_connect(struct tracefs_instance * open_instance)226*58e6ee5fSAndroid Build Coastguard Worker static int stop_trace_connect(struct tracefs_instance *open_instance)
227*58e6ee5fSAndroid Build Coastguard Worker {
228*58e6ee5fSAndroid Build Coastguard Worker 	const char *systems[] = { "kvm", "sched", NULL};
229*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *tep;
230*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_fields trace_fields;
231*58e6ee5fSAndroid Build Coastguard Worker 	int tgid = -1;
232*58e6ee5fSAndroid Build Coastguard Worker 
233*58e6ee5fSAndroid Build Coastguard Worker 	if (!open_instance)
234*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
235*58e6ee5fSAndroid Build Coastguard Worker 
236*58e6ee5fSAndroid Build Coastguard Worker 	/* The connection is finished, stop tracing, we have what we want */
237*58e6ee5fSAndroid Build Coastguard Worker 	tracefs_trace_off(open_instance);
238*58e6ee5fSAndroid Build Coastguard Worker 	tracefs_event_disable(open_instance, NULL, NULL);
239*58e6ee5fSAndroid Build Coastguard Worker 
240*58e6ee5fSAndroid Build Coastguard Worker 	tep = tracefs_local_events_system(NULL, systems);
241*58e6ee5fSAndroid Build Coastguard Worker 
242*58e6ee5fSAndroid Build Coastguard Worker 	trace_fields.sched_waking = tep_find_event_by_name(tep, "sched", "sched_waking");
243*58e6ee5fSAndroid Build Coastguard Worker 	if (!trace_fields.sched_waking)
244*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
245*58e6ee5fSAndroid Build Coastguard Worker 	trace_fields.kvm_exit = tep_find_event_by_name(tep, "kvm", "kvm_exit");
246*58e6ee5fSAndroid Build Coastguard Worker 	if (!trace_fields.kvm_exit)
247*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
248*58e6ee5fSAndroid Build Coastguard Worker 	trace_fields.common_pid = tep_find_common_field(trace_fields.sched_waking,
249*58e6ee5fSAndroid Build Coastguard Worker 							"common_pid");
250*58e6ee5fSAndroid Build Coastguard Worker 	if (!trace_fields.common_pid)
251*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
252*58e6ee5fSAndroid Build Coastguard Worker 	trace_fields.sched_next = tep_find_any_field(trace_fields.sched_waking,
253*58e6ee5fSAndroid Build Coastguard Worker 							"pid");
254*58e6ee5fSAndroid Build Coastguard Worker 	if (!trace_fields.sched_next)
255*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
256*58e6ee5fSAndroid Build Coastguard Worker 
257*58e6ee5fSAndroid Build Coastguard Worker 	trace_fields.found_pid = -1;
258*58e6ee5fSAndroid Build Coastguard Worker 	trace_fields.pids = NULL;
259*58e6ee5fSAndroid Build Coastguard Worker 	add_pid(&trace_fields.pids, getpid());
260*58e6ee5fSAndroid Build Coastguard Worker 	tracefs_iterate_raw_events(tep, open_instance, NULL, 0, callback, &trace_fields);
261*58e6ee5fSAndroid Build Coastguard Worker 	free_pids(trace_fields.pids);
262*58e6ee5fSAndroid Build Coastguard Worker  out:
263*58e6ee5fSAndroid Build Coastguard Worker 	tracefs_instance_destroy(open_instance);
264*58e6ee5fSAndroid Build Coastguard Worker 	tracefs_instance_free(open_instance);
265*58e6ee5fSAndroid Build Coastguard Worker 
266*58e6ee5fSAndroid Build Coastguard Worker 	if (trace_fields.found_pid > 0)
267*58e6ee5fSAndroid Build Coastguard Worker 		tgid = find_tgid(trace_fields.found_pid);
268*58e6ee5fSAndroid Build Coastguard Worker 
269*58e6ee5fSAndroid Build Coastguard Worker 	return tgid;
270*58e6ee5fSAndroid Build Coastguard Worker }
271*58e6ee5fSAndroid Build Coastguard Worker 
272*58e6ee5fSAndroid Build Coastguard Worker /*
273*58e6ee5fSAndroid Build Coastguard Worker  * In order to find the guest that is associated to the given cid,
274*58e6ee5fSAndroid Build Coastguard Worker  * trace the sched_waking and kvm_exit events, connect to the cid
275*58e6ee5fSAndroid Build Coastguard Worker  * (doesn't matter what port, use -1 to not connect to anything)
276*58e6ee5fSAndroid Build Coastguard Worker  * and find what task gets woken up from this code and calls kvm_exit,
277*58e6ee5fSAndroid Build Coastguard Worker  * then that is the task that is running the guest.
278*58e6ee5fSAndroid Build Coastguard Worker  * Then look at the /proc/<guest-pid>/status file to find the task group
279*58e6ee5fSAndroid Build Coastguard Worker  * id (Tgid), and this is the PID of the task running all the threads.
280*58e6ee5fSAndroid Build Coastguard Worker  */
find_pid_by_cid(struct trace_guest * guest)281*58e6ee5fSAndroid Build Coastguard Worker static void find_pid_by_cid(struct trace_guest *guest)
282*58e6ee5fSAndroid Build Coastguard Worker {
283*58e6ee5fSAndroid Build Coastguard Worker 	struct tracefs_instance *instance;
284*58e6ee5fSAndroid Build Coastguard Worker 	int fd;
285*58e6ee5fSAndroid Build Coastguard Worker 
286*58e6ee5fSAndroid Build Coastguard Worker 	instance = start_trace_connect();
287*58e6ee5fSAndroid Build Coastguard Worker 	fd = trace_vsock_open(guest->cid, -1);
288*58e6ee5fSAndroid Build Coastguard Worker 	guest->pid = stop_trace_connect(instance);
289*58e6ee5fSAndroid Build Coastguard Worker 	/* Just in case! */
290*58e6ee5fSAndroid Build Coastguard Worker 	if (fd >= 0)
291*58e6ee5fSAndroid Build Coastguard Worker 		close(fd);
292*58e6ee5fSAndroid Build Coastguard Worker }
293*58e6ee5fSAndroid Build Coastguard Worker 
trace_get_guest(unsigned int cid,const char * name)294*58e6ee5fSAndroid Build Coastguard Worker struct trace_guest *trace_get_guest(unsigned int cid, const char *name)
295*58e6ee5fSAndroid Build Coastguard Worker {
296*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_guest *guest = NULL;
297*58e6ee5fSAndroid Build Coastguard Worker 
298*58e6ee5fSAndroid Build Coastguard Worker 	if (name) {
299*58e6ee5fSAndroid Build Coastguard Worker 		guest = get_guest_by_name(name);
300*58e6ee5fSAndroid Build Coastguard Worker 		if (guest)
301*58e6ee5fSAndroid Build Coastguard Worker 			return guest;
302*58e6ee5fSAndroid Build Coastguard Worker 	}
303*58e6ee5fSAndroid Build Coastguard Worker 
304*58e6ee5fSAndroid Build Coastguard Worker 	if (cid > 0) {
305*58e6ee5fSAndroid Build Coastguard Worker 		guest = get_guest_by_cid(cid);
306*58e6ee5fSAndroid Build Coastguard Worker 		if (!guest && name) {
307*58e6ee5fSAndroid Build Coastguard Worker 			guest = add_guest(cid, name);
308*58e6ee5fSAndroid Build Coastguard Worker 			if (guest)
309*58e6ee5fSAndroid Build Coastguard Worker 				find_pid_by_cid(guest);
310*58e6ee5fSAndroid Build Coastguard Worker 		}
311*58e6ee5fSAndroid Build Coastguard Worker 	}
312*58e6ee5fSAndroid Build Coastguard Worker 	return guest;
313*58e6ee5fSAndroid Build Coastguard Worker }
314*58e6ee5fSAndroid Build Coastguard Worker 
315*58e6ee5fSAndroid Build Coastguard Worker #define VM_CID_CMD	"virsh dumpxml"
316*58e6ee5fSAndroid Build Coastguard Worker #define VM_CID_LINE	"<cid auto="
317*58e6ee5fSAndroid Build Coastguard Worker #define VM_CID_ID	"address='"
read_guest_cid(char * name)318*58e6ee5fSAndroid Build Coastguard Worker static void read_guest_cid(char *name)
319*58e6ee5fSAndroid Build Coastguard Worker {
320*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_guest *guest;
321*58e6ee5fSAndroid Build Coastguard Worker 	char *cmd = NULL;
322*58e6ee5fSAndroid Build Coastguard Worker 	char line[512];
323*58e6ee5fSAndroid Build Coastguard Worker 	char *cid;
324*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int cid_id = 0;
325*58e6ee5fSAndroid Build Coastguard Worker 	FILE *f;
326*58e6ee5fSAndroid Build Coastguard Worker 
327*58e6ee5fSAndroid Build Coastguard Worker 	asprintf(&cmd, "%s %s", VM_CID_CMD, name);
328*58e6ee5fSAndroid Build Coastguard Worker 	f = popen(cmd, "r");
329*58e6ee5fSAndroid Build Coastguard Worker 	free(cmd);
330*58e6ee5fSAndroid Build Coastguard Worker 	if (f == NULL)
331*58e6ee5fSAndroid Build Coastguard Worker 		return;
332*58e6ee5fSAndroid Build Coastguard Worker 
333*58e6ee5fSAndroid Build Coastguard Worker 	while (fgets(line, sizeof(line), f) != NULL) {
334*58e6ee5fSAndroid Build Coastguard Worker 		if (!strstr(line, VM_CID_LINE))
335*58e6ee5fSAndroid Build Coastguard Worker 			continue;
336*58e6ee5fSAndroid Build Coastguard Worker 		cid = strstr(line, VM_CID_ID);
337*58e6ee5fSAndroid Build Coastguard Worker 		if (!cid)
338*58e6ee5fSAndroid Build Coastguard Worker 			continue;
339*58e6ee5fSAndroid Build Coastguard Worker 		cid_id = strtol(cid + strlen(VM_CID_ID), NULL, 10);
340*58e6ee5fSAndroid Build Coastguard Worker 		if ((cid_id == INT_MIN || cid_id == INT_MAX) && errno == ERANGE)
341*58e6ee5fSAndroid Build Coastguard Worker 			continue;
342*58e6ee5fSAndroid Build Coastguard Worker 		guest = add_guest(cid_id, name);
343*58e6ee5fSAndroid Build Coastguard Worker 		if (guest)
344*58e6ee5fSAndroid Build Coastguard Worker 			find_pid_by_cid(guest);
345*58e6ee5fSAndroid Build Coastguard Worker 		break;
346*58e6ee5fSAndroid Build Coastguard Worker 	}
347*58e6ee5fSAndroid Build Coastguard Worker 
348*58e6ee5fSAndroid Build Coastguard Worker 	/* close */
349*58e6ee5fSAndroid Build Coastguard Worker 	pclose(f);
350*58e6ee5fSAndroid Build Coastguard Worker }
351*58e6ee5fSAndroid Build Coastguard Worker 
352*58e6ee5fSAndroid Build Coastguard Worker #define VM_NAME_CMD	"virsh list --name"
read_qemu_guests(void)353*58e6ee5fSAndroid Build Coastguard Worker void read_qemu_guests(void)
354*58e6ee5fSAndroid Build Coastguard Worker {
355*58e6ee5fSAndroid Build Coastguard Worker 	char name[256];
356*58e6ee5fSAndroid Build Coastguard Worker 	FILE *f;
357*58e6ee5fSAndroid Build Coastguard Worker 
358*58e6ee5fSAndroid Build Coastguard Worker 	f = popen(VM_NAME_CMD, "r");
359*58e6ee5fSAndroid Build Coastguard Worker 	if (f == NULL)
360*58e6ee5fSAndroid Build Coastguard Worker 		return;
361*58e6ee5fSAndroid Build Coastguard Worker 
362*58e6ee5fSAndroid Build Coastguard Worker 	while (fgets(name, sizeof(name), f) != NULL) {
363*58e6ee5fSAndroid Build Coastguard Worker 		if (name[0] == '\n')
364*58e6ee5fSAndroid Build Coastguard Worker 			continue;
365*58e6ee5fSAndroid Build Coastguard Worker 		if (name[strlen(name) - 1] == '\n')
366*58e6ee5fSAndroid Build Coastguard Worker 			name[strlen(name) - 1] = '\0';
367*58e6ee5fSAndroid Build Coastguard Worker 		read_guest_cid(name);
368*58e6ee5fSAndroid Build Coastguard Worker 	}
369*58e6ee5fSAndroid Build Coastguard Worker 
370*58e6ee5fSAndroid Build Coastguard Worker 	/* close */
371*58e6ee5fSAndroid Build Coastguard Worker 	pclose(f);
372*58e6ee5fSAndroid Build Coastguard Worker }
373*58e6ee5fSAndroid Build Coastguard Worker 
get_guest_vcpu_pid(unsigned int guest_cid,unsigned int guest_vcpu)374*58e6ee5fSAndroid Build Coastguard Worker int get_guest_vcpu_pid(unsigned int guest_cid, unsigned int guest_vcpu)
375*58e6ee5fSAndroid Build Coastguard Worker {
376*58e6ee5fSAndroid Build Coastguard Worker 	int i;
377*58e6ee5fSAndroid Build Coastguard Worker 
378*58e6ee5fSAndroid Build Coastguard Worker 	if (!guests)
379*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
380*58e6ee5fSAndroid Build Coastguard Worker 
381*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < guests_len; i++) {
382*58e6ee5fSAndroid Build Coastguard Worker 		if (guests[i].cpu_pid < 0 || guest_vcpu >= guests[i].cpu_max)
383*58e6ee5fSAndroid Build Coastguard Worker 			continue;
384*58e6ee5fSAndroid Build Coastguard Worker 		if (guest_cid == guests[i].cid)
385*58e6ee5fSAndroid Build Coastguard Worker 			return guests[i].cpu_pid[guest_vcpu];
386*58e6ee5fSAndroid Build Coastguard Worker 	}
387*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
388*58e6ee5fSAndroid Build Coastguard Worker }
389