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