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