1 /*
2 * memshrtool.c
3 *
4 * Copyright 2011 GridCentric Inc. (Adin Scannell, Andres Lagar-Cavilla)
5 */
6
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <errno.h>
11 #include <string.h>
12 #include <sys/mman.h>
13
14 #define XC_WANT_COMPAT_MAP_FOREIGN_API
15 #include "xenctrl.h"
16
usage(const char * prog)17 static int usage(const char* prog)
18 {
19 printf("usage: %s <command> [args...]\n", prog);
20 printf("where <command> may be:\n");
21 printf(" info - Display total sharing info.\n");
22 printf(" enable - Enable sharing on a domain.\n");
23 printf(" disable - Disable sharing on a domain.\n");
24 printf(" nominate <domid> <gfn> - Nominate a page for sharing.\n");
25 printf(" share <domid> <gfn> <handle> <source> <source-gfn> <source-handle>\n");
26 printf(" - Share two pages.\n");
27 printf(" range <source-domid> <destination-domid> <first-gfn> <last-gfn>\n");
28 printf(" - Share pages between domains in a range.\n");
29 printf(" unshare <domid> <gfn> - Unshare a page by grabbing a writable map.\n");
30 printf(" add-to-physmap <domid> <gfn> <source> <source-gfn> <source-handle>\n");
31 printf(" - Populate a page in a domain with a shared page.\n");
32 printf(" debug-gfn <domid> <gfn> - Debug a particular domain and gfn.\n");
33 printf(" audit - Audit the sharing subsytem in Xen.\n");
34 return 1;
35 }
36
37 #define R(f) do { \
38 int rc = f; \
39 if ( rc < 0 ) { \
40 printf("error executing %s: %s\n", #f, \
41 ((errno * -1) == XENMEM_SHARING_OP_S_HANDLE_INVALID) ? \
42 "problem with client handle" :\
43 ((errno * -1) == XENMEM_SHARING_OP_C_HANDLE_INVALID) ? \
44 "problem with source handle" : strerror(errno)); \
45 return rc; \
46 } \
47 } while(0)
48
main(int argc,const char ** argv)49 int main(int argc, const char** argv)
50 {
51 const char* cmd = NULL;
52 xc_interface *xch = xc_interface_open(0, 0, 0);
53
54 if( argc < 2 )
55 return usage(argv[0]);
56
57 cmd = argv[1];
58
59 if( !strcasecmp(cmd, "info") )
60 {
61 long rc;
62 if( argc != 2 )
63 return usage(argv[0]);
64
65 rc = xc_sharing_freed_pages(xch);
66 if ( rc < 0 )
67 return 1;
68
69 printf("used = %ld\n", rc);
70 rc = xc_sharing_used_frames(xch);
71 if ( rc < 0 )
72 return 1;
73 printf("freed = %ld\n", rc);
74 }
75 else if( !strcasecmp(cmd, "enable") )
76 {
77 domid_t domid;
78
79 if( argc != 3 )
80 return usage(argv[0]);
81
82 domid = strtol(argv[2], NULL, 0);
83 R(xc_memshr_control(xch, domid, 1));
84 }
85 else if( !strcasecmp(cmd, "disable") )
86 {
87 domid_t domid;
88
89 if( argc != 3 )
90 return usage(argv[0]);
91
92 domid = strtol(argv[2], NULL, 0);
93 R(xc_memshr_control(xch, domid, 0));
94 }
95 else if( !strcasecmp(cmd, "nominate") )
96 {
97 domid_t domid;
98 unsigned long gfn;
99 uint64_t handle;
100
101 if( argc != 4 )
102 return usage(argv[0]);
103
104 domid = strtol(argv[2], NULL, 0);
105 gfn = strtol(argv[3], NULL, 0);
106 R(xc_memshr_nominate_gfn(xch, domid, gfn, &handle));
107 printf("handle = 0x%08llx\n", (unsigned long long) handle);
108 }
109 else if( !strcasecmp(cmd, "share") )
110 {
111 domid_t domid;
112 unsigned long gfn;
113 uint64_t handle;
114 domid_t source_domid;
115 unsigned long source_gfn;
116 uint64_t source_handle;
117
118 if( argc != 8 )
119 return usage(argv[0]);
120
121 domid = strtol(argv[2], NULL, 0);
122 gfn = strtol(argv[3], NULL, 0);
123 handle = strtol(argv[4], NULL, 0);
124 source_domid = strtol(argv[5], NULL, 0);
125 source_gfn = strtol(argv[6], NULL, 0);
126 source_handle = strtol(argv[7], NULL, 0);
127 R(xc_memshr_share_gfns(xch, source_domid, source_gfn, source_handle, domid, gfn, handle));
128 }
129 else if( !strcasecmp(cmd, "unshare") )
130 {
131 domid_t domid;
132 unsigned long gfn;
133 void *map;
134
135 if( argc != 4 )
136 return usage(argv[0]);
137
138 domid = strtol(argv[2], NULL, 0);
139 gfn = strtol(argv[3], NULL, 0);
140 map = xc_map_foreign_range(xch, domid, 4096, PROT_WRITE, gfn);
141 if( map )
142 munmap(map, 4096);
143 R((int)!map);
144 }
145 else if( !strcasecmp(cmd, "add-to-physmap") )
146 {
147 domid_t domid;
148 unsigned long gfn;
149 domid_t source_domid;
150 unsigned long source_gfn;
151 uint64_t source_handle;
152
153 if( argc != 7 )
154 return usage(argv[0]);
155
156 domid = strtol(argv[2], NULL, 0);
157 gfn = strtol(argv[3], NULL, 0);
158 source_domid = strtol(argv[4], NULL, 0);
159 source_gfn = strtol(argv[5], NULL, 0);
160 source_handle = strtol(argv[6], NULL, 0);
161 R(xc_memshr_add_to_physmap(xch, source_domid, source_gfn, source_handle, domid, gfn));
162 }
163 else if( !strcasecmp(cmd, "debug-gfn") )
164 {
165 domid_t domid;
166 unsigned long gfn;
167
168 if( argc != 4 )
169 return usage(argv[0]);
170
171 domid = strtol(argv[2], NULL, 0);
172 gfn = strtol(argv[3], NULL, 0);
173 R(xc_memshr_debug_gfn(xch, domid, gfn));
174 }
175 else if( !strcasecmp(cmd, "audit") )
176 {
177 int rc = xc_memshr_audit(xch);
178 if ( rc < 0 )
179 {
180 printf("error executing xc_memshr_audit: %s\n", strerror(errno));
181 return rc;
182 }
183 printf("Audit returned %d errors.\n", rc);
184 }
185 else if( !strcasecmp(cmd, "range") )
186 {
187 domid_t sdomid, cdomid;
188 int rc;
189 uint64_t first_gfn, last_gfn;
190
191 if ( argc != 6 )
192 return usage(argv[0]);
193
194 sdomid = strtol(argv[2], NULL, 0);
195 cdomid = strtol(argv[3], NULL, 0);
196 first_gfn = strtoul(argv[4], NULL, 0);
197 last_gfn = strtoul(argv[5], NULL, 0);
198
199 rc = xc_memshr_range_share(xch, sdomid, cdomid, first_gfn, last_gfn);
200 if ( rc < 0 )
201 {
202 printf("error executing xc_memshr_range_share: %s\n", strerror(errno));
203 return rc;
204 }
205 }
206 return 0;
207 }
208