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