1 /*
2  * Copyright 2009-2017 Citrix Ltd and other contributors
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; version 2.1 only. with the special
7  * exception on linking described in file LICENSE.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  */
14 
15 #include <stdlib.h>
16 
17 #include <libxl.h>
18 #include <libxl_utils.h>
19 #include <libxlutil.h>
20 
21 #include "xl.h"
22 #include "xl_utils.h"
23 #include "xl_parse.h"
24 
pcilist(uint32_t domid)25 static void pcilist(uint32_t domid)
26 {
27     libxl_device_pci *pcidevs;
28     int num, i;
29 
30     pcidevs = libxl_device_pci_list(ctx, domid, &num);
31     if (pcidevs == NULL)
32         return;
33     printf("Vdev Device\n");
34     for (i = 0; i < num; i++) {
35         printf("%02x.%01x %04x:%02x:%02x.%01x\n",
36                (pcidevs[i].vdevfn >> 3) & 0x1f, pcidevs[i].vdevfn & 0x7,
37                pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
38         libxl_device_pci_dispose(&pcidevs[i]);
39     }
40     free(pcidevs);
41 }
42 
main_pcilist(int argc,char ** argv)43 int main_pcilist(int argc, char **argv)
44 {
45     uint32_t domid;
46     int opt;
47 
48     SWITCH_FOREACH_OPT(opt, "", NULL, "pci-list", 1) {
49         /* No options */
50     }
51 
52     domid = find_domain(argv[optind]);
53 
54     pcilist(domid);
55     return 0;
56 }
57 
pcidetach(uint32_t domid,const char * bdf,int force)58 static int pcidetach(uint32_t domid, const char *bdf, int force)
59 {
60     libxl_device_pci pcidev;
61     XLU_Config *config;
62     int r = 0;
63 
64     libxl_device_pci_init(&pcidev);
65 
66     config = xlu_cfg_init(stderr, "command line");
67     if (!config) { perror("xlu_cfg_inig"); exit(-1); }
68 
69     if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
70         fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
71         exit(2);
72     }
73     if (force) {
74         if (libxl_device_pci_destroy(ctx, domid, &pcidev, 0))
75             r = 1;
76     } else {
77         if (libxl_device_pci_remove(ctx, domid, &pcidev, 0))
78             r = 1;
79     }
80 
81     libxl_device_pci_dispose(&pcidev);
82     xlu_cfg_destroy(config);
83 
84     return r;
85 }
86 
main_pcidetach(int argc,char ** argv)87 int main_pcidetach(int argc, char **argv)
88 {
89     uint32_t domid;
90     int opt;
91     int force = 0;
92     const char *bdf = NULL;
93 
94     SWITCH_FOREACH_OPT(opt, "f", NULL, "pci-detach", 2) {
95     case 'f':
96         force = 1;
97         break;
98     }
99 
100     domid = find_domain(argv[optind]);
101     bdf = argv[optind + 1];
102 
103     if (pcidetach(domid, bdf, force))
104         return EXIT_FAILURE;
105 
106     return EXIT_SUCCESS;
107 }
108 
pciattach(uint32_t domid,const char * bdf,const char * vs)109 static int pciattach(uint32_t domid, const char *bdf, const char *vs)
110 {
111     libxl_device_pci pcidev;
112     XLU_Config *config;
113     int r = 0;
114 
115     libxl_device_pci_init(&pcidev);
116 
117     config = xlu_cfg_init(stderr, "command line");
118     if (!config) { perror("xlu_cfg_inig"); exit(-1); }
119 
120     if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
121         fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
122         exit(2);
123     }
124 
125     if (libxl_device_pci_add(ctx, domid, &pcidev, 0))
126         r = 1;
127 
128     libxl_device_pci_dispose(&pcidev);
129     xlu_cfg_destroy(config);
130 
131     return r;
132 }
133 
main_pciattach(int argc,char ** argv)134 int main_pciattach(int argc, char **argv)
135 {
136     uint32_t domid;
137     int opt;
138     const char *bdf = NULL, *vs = NULL;
139 
140     SWITCH_FOREACH_OPT(opt, "", NULL, "pci-attach", 2) {
141         /* No options */
142     }
143 
144     domid = find_domain(argv[optind]);
145     bdf = argv[optind + 1];
146 
147     if (optind + 1 < argc)
148         vs = argv[optind + 2];
149 
150     if (pciattach(domid, bdf, vs))
151         return EXIT_FAILURE;
152 
153     return EXIT_SUCCESS;
154 }
155 
pciassignable_list(void)156 static void pciassignable_list(void)
157 {
158     libxl_device_pci *pcidevs;
159     int num, i;
160 
161     pcidevs = libxl_device_pci_assignable_list(ctx, &num);
162 
163     if ( pcidevs == NULL )
164         return;
165     for (i = 0; i < num; i++) {
166         printf("%04x:%02x:%02x.%01x\n",
167                pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
168         libxl_device_pci_dispose(&pcidevs[i]);
169     }
170     free(pcidevs);
171 }
172 
main_pciassignable_list(int argc,char ** argv)173 int main_pciassignable_list(int argc, char **argv)
174 {
175     int opt;
176 
177     SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-list", 0) {
178         /* No options */
179     }
180 
181     pciassignable_list();
182     return 0;
183 }
184 
pciassignable_add(const char * bdf,int rebind)185 static int pciassignable_add(const char *bdf, int rebind)
186 {
187     libxl_device_pci pcidev;
188     XLU_Config *config;
189     int r = 0;
190 
191     libxl_device_pci_init(&pcidev);
192 
193     config = xlu_cfg_init(stderr, "command line");
194     if (!config) { perror("xlu_cfg_init"); exit(-1); }
195 
196     if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
197         fprintf(stderr, "pci-assignable-add: malformed BDF specification \"%s\"\n", bdf);
198         exit(2);
199     }
200 
201     if (libxl_device_pci_assignable_add(ctx, &pcidev, rebind))
202         r = 1;
203 
204     libxl_device_pci_dispose(&pcidev);
205     xlu_cfg_destroy(config);
206 
207     return r;
208 }
209 
main_pciassignable_add(int argc,char ** argv)210 int main_pciassignable_add(int argc, char **argv)
211 {
212     int opt;
213     const char *bdf = NULL;
214 
215     SWITCH_FOREACH_OPT(opt, "", NULL, "pci-assignable-add", 1) {
216         /* No options */
217     }
218 
219     bdf = argv[optind];
220 
221     if (pciassignable_add(bdf, 1))
222         return EXIT_FAILURE;
223 
224     return EXIT_SUCCESS;
225 }
226 
pciassignable_remove(const char * bdf,int rebind)227 static int pciassignable_remove(const char *bdf, int rebind)
228 {
229     libxl_device_pci pcidev;
230     XLU_Config *config;
231     int r = 0;
232 
233     libxl_device_pci_init(&pcidev);
234 
235     config = xlu_cfg_init(stderr, "command line");
236     if (!config) { perror("xlu_cfg_init"); exit(-1); }
237 
238     if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
239         fprintf(stderr, "pci-assignable-remove: malformed BDF specification \"%s\"\n", bdf);
240         exit(2);
241     }
242 
243     if (libxl_device_pci_assignable_remove(ctx, &pcidev, rebind))
244         r = 1;
245 
246     libxl_device_pci_dispose(&pcidev);
247     xlu_cfg_destroy(config);
248 
249     return r;
250 }
251 
main_pciassignable_remove(int argc,char ** argv)252 int main_pciassignable_remove(int argc, char **argv)
253 {
254     int opt;
255     const char *bdf = NULL;
256     int rebind = 0;
257 
258     SWITCH_FOREACH_OPT(opt, "r", NULL, "pci-assignable-remove", 1) {
259     case 'r':
260         rebind=1;
261         break;
262     }
263 
264     bdf = argv[optind];
265 
266     if (pciassignable_remove(bdf, rebind))
267         return EXIT_FAILURE;
268 
269     return EXIT_SUCCESS;
270 }
271 
272 /*
273  * Local variables:
274  * mode: C
275  * c-basic-offset: 4
276  * indent-tabs-mode: nil
277  * End:
278  */
279