• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdlib.h>
2 
3 #include "trace-cmd-local.h"
4 #include "trace-local.h"
5 
6 /*
7  * Structure to hold the mapping between host and guest.
8  * @self - A pointer back to the guest's mapping (for the host copy to use)
9  * @host_handle - The handle for the host for this mapping.
10  * @guest_handle - The handle for the guest for this mapping.
11  * @guest_vcpu - The vCPU # for this mapping.
12  * @host_pid - The pid of the task on the host that runs when this vCPU executes.
13  * @private - Private data for applications to use.
14  */
15 struct tracecmd_cpu_map {
16 	struct tracecmd_cpu_map		*self;
17 	struct tracecmd_input		*host_handle;
18 	struct tracecmd_input		*guest_handle;
19 	int				guest_vcpu;
20 	int				host_pid;
21 	void				*private;
22 };
23 
cmp_map(const void * A,const void * B)24 static int cmp_map(const void *A, const void *B)
25 {
26 	const struct tracecmd_cpu_map *a = A;
27 	const struct tracecmd_cpu_map *b = B;
28 
29 	if (a->host_pid < b->host_pid)
30 		return -1;
31 	return a->host_pid > b->host_pid;
32 }
33 
tracecmd_map_vcpus(struct tracecmd_input ** handles,int nr_handles)34 int tracecmd_map_vcpus(struct tracecmd_input **handles, int nr_handles)
35 {
36 	struct tracecmd_input *host_handle = handles[0];
37 	unsigned long long traceid;
38 	struct tracecmd_cpu_map *vcpu_maps = NULL;
39 	struct tracecmd_cpu_map *gmap;
40 	struct tracecmd_cpu_map *map;
41 	const int *cpu_pids;
42 	const char *name;
43 	int nr_vcpu_maps = 0;
44 	int vcpu_count;
45 	int mappings = 0;
46 	int ret;
47 	int i, k;
48 
49 	/* handles[0] is the host handle, do for each guest handle */
50 	for (i = 1; i < nr_handles; i++) {
51 		traceid = tracecmd_get_traceid(handles[i]);
52 
53 		/*
54 		 * Retrieve the host mapping of the guest for this handle.
55 		 * cpu_pids is an array of pids that map 1-1 the host vcpus where
56 		 * cpu_pids[vCPU_num] = host_task_pid
57 		 */
58 		ret = tracecmd_get_guest_cpumap(host_handle, traceid,
59 						&name, &vcpu_count, &cpu_pids);
60 		if (ret)
61 			continue;
62 
63 		mappings++;
64 
65 		gmap = calloc(sizeof(*gmap), vcpu_count);
66 		if (!gmap)
67 			goto fail;
68 
69 		for (k = 0; k < vcpu_count; k++) {
70 			gmap[k].host_handle = handles[0];
71 			gmap[k].guest_handle = handles[i];
72 			gmap[k].guest_vcpu = k;
73 			gmap[k].host_pid = cpu_pids[k];
74 			gmap[k].self = &gmap[k];
75 		}
76 
77 		trace_set_guest_map(handles[i], gmap);
78 		trace_set_guest_map_cnt(handles[i], vcpu_count);
79 
80 		/* Update the host mapping of all guests to the host */
81 		map = realloc(vcpu_maps, sizeof(*map) * (nr_vcpu_maps + vcpu_count));
82 		if (!map)
83 			goto fail;
84 		memset(map + nr_vcpu_maps, 0, sizeof(*map) * (vcpu_count - nr_vcpu_maps));
85 
86 		vcpu_maps = map;
87 		map += nr_vcpu_maps;
88 		nr_vcpu_maps += vcpu_count;
89 
90 		for (k = 0; k < vcpu_count; k++)
91 			map[k] = gmap[k];
92 	}
93 	if (!vcpu_maps)
94 		return 0;
95 
96 	/* We want to do a binary search via host_pid to find these mappings */
97 	qsort(vcpu_maps, nr_vcpu_maps, sizeof(*map), cmp_map);
98 
99 	trace_set_guest_map(handles[0], vcpu_maps);
100 	trace_set_guest_map_cnt(handles[0], nr_vcpu_maps);
101 
102 	return mappings;
103 
104  fail:
105 	free(vcpu_maps);
106 	return -1;
107 }
108 
trace_guest_map_free(struct tracecmd_cpu_map * map)109 __hidden void trace_guest_map_free(struct tracecmd_cpu_map *map)
110 {
111 	free(map);
112 }
113 
tracecmd_map_find_by_host_pid(struct tracecmd_input * handle,int host_pid)114 struct tracecmd_cpu_map *tracecmd_map_find_by_host_pid(struct tracecmd_input *handle,
115 						       int host_pid)
116 {
117 	struct tracecmd_cpu_map *map;
118 	struct tracecmd_cpu_map key;
119 	int nr_maps;
120 
121 	map = trace_get_guest_map(handle);
122 	if (!map)
123 		return NULL;
124 
125 	/* The handle could be from the guest, get the host handle */
126 	handle = map->host_handle;
127 
128 	/* And again, get the mapping of the host, as it has all the mappings */
129 	map = trace_get_guest_map(handle);
130 	if (!map)
131 		return NULL;
132 
133 	nr_maps = trace_get_guest_map_cnt(handle);
134 
135 	key.host_pid = host_pid;
136 
137 	map = bsearch(&key, map, nr_maps, sizeof(*map), cmp_map);
138 
139 	return map ? map->self : NULL;
140 }
141 
tracecmd_map_set_private(struct tracecmd_cpu_map * map,void * priv)142 void tracecmd_map_set_private(struct tracecmd_cpu_map *map, void *priv)
143 {
144 	/* Only set the guest private */
145 	map = map->self;
146 	map->private = priv;
147 }
148 
tracecmd_map_get_private(struct tracecmd_cpu_map * map)149 void *tracecmd_map_get_private(struct tracecmd_cpu_map *map)
150 {
151 	/* Return the guest private */
152 	map = map->self;
153 	return map->private;
154 }
155 
tracecmd_map_get_guest(struct tracecmd_cpu_map * map)156 struct tracecmd_input *tracecmd_map_get_guest(struct tracecmd_cpu_map *map)
157 {
158 	return map->guest_handle;
159 }
160 
tracecmd_map_get_host_pid(struct tracecmd_cpu_map * map)161 int tracecmd_map_get_host_pid(struct tracecmd_cpu_map *map)
162 {
163 	return map->host_pid;
164 }
165 
tracecmd_get_cpu_map(struct tracecmd_input * handle,int cpu)166 struct tracecmd_cpu_map *tracecmd_get_cpu_map(struct tracecmd_input *handle, int cpu)
167 {
168 	struct tracecmd_cpu_map *map;
169 	int cnt;
170 
171 	map = trace_get_guest_map(handle);
172 	/* Make sure it's for the guest handle, as this could be a host handle */
173 	map = map->self;
174 	cnt = trace_get_guest_map_cnt(map->guest_handle);
175 	if (cnt <= cpu)
176 		return NULL;
177 
178 	return map + cpu;
179 }
180