debuggers.hg

view tools/ioemu/hw/pass-through.c @ 17984:b3d827e63a09

stubdom: PCI passthrough support via PV-PCI

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jul 02 13:54:20 2008 +0100 (2008-07-02)
parents 4afc6023e8ec
children 9cf72db44ee9
line source
1 /*
2 * Copyright (c) 2007, Neocleus Corporation.
3 * Copyright (c) 2007, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 * Alex Novik <alex@neocleus.com>
19 * Allen Kay <allen.m.kay@intel.com>
20 * Guy Zana <guy@neocleus.com>
21 *
22 * This file implements direct PCI assignment to a HVM guest
23 */
25 #include "vl.h"
26 #include "pass-through.h"
27 #include "pci/header.h"
28 #include "pci/pci.h"
29 #include "pt-msi.h"
31 extern FILE *logfile;
33 struct php_dev {
34 struct pt_dev *pt_dev;
35 uint8_t valid;
36 uint8_t r_bus;
37 uint8_t r_dev;
38 uint8_t r_func;
39 };
40 struct dpci_infos {
42 struct php_dev php_devs[PHP_SLOT_LEN];
44 PCIBus *e_bus;
45 struct pci_access *pci_access;
47 } dpci_infos;
49 static int token_value(char *token)
50 {
51 return strtol(token, NULL, 16);
52 }
54 static int next_bdf(char **str, int *seg, int *bus, int *dev, int *func)
55 {
56 char *token, *delim = ":.-";
58 if ( !(*str) ||
59 ( !strchr(*str, ':') && !strchr(*str, '.')) )
60 return 0;
62 token = strsep(str, delim);
63 *seg = token_value(token);
65 token = strsep(str, delim);
66 *bus = token_value(token);
68 token = strsep(str, delim);
69 *dev = token_value(token);
71 token = strsep(str, delim);
72 *func = token_value(token);
74 return 1;
75 }
77 /* Insert a new pass-through device into a specific pci slot.
78 * input dom:bus:dev.func@slot, chose free one if slot == 0
79 * return -1: required slot not available
80 * 0: no free hotplug slots, but normal slot should okay
81 * >0: the new hotplug slot
82 */
83 static int __insert_to_pci_slot(int bus, int dev, int func, int slot)
84 {
85 int i, php_slot;
87 /* preferred virt pci slot */
88 if ( slot >= PHP_SLOT_START && slot < PHP_SLOT_END )
89 {
90 php_slot = PCI_TO_PHP_SLOT(slot);
91 if ( !dpci_infos.php_devs[php_slot].valid )
92 {
93 goto found;
94 }
95 else
96 return -1;
97 }
99 if ( slot != 0 )
100 return -1;
102 /* slot == 0, pick up a free one */
103 for ( i = 0; i < PHP_SLOT_LEN; i++ )
104 {
105 if ( !dpci_infos.php_devs[i].valid )
106 {
107 php_slot = i;
108 goto found;
109 }
110 }
112 /* not found */
113 return 0;
115 found:
116 dpci_infos.php_devs[php_slot].valid = 1;
117 dpci_infos.php_devs[php_slot].r_bus = bus;
118 dpci_infos.php_devs[php_slot].r_dev = dev;
119 dpci_infos.php_devs[php_slot].r_func = func;
120 return PHP_TO_PCI_SLOT(php_slot);
121 }
123 /* Insert a new pass-through device into a specific pci slot.
124 * input dom:bus:dev.func@slot
125 */
126 int insert_to_pci_slot(char *bdf_slt)
127 {
128 int seg, bus, dev, func, slot;
129 char *bdf_str, *slt_str, *delim="@";
131 bdf_str = strsep(&bdf_slt, delim);
132 slt_str = bdf_slt;
133 slot = token_value(slt_str);
135 if ( !next_bdf(&bdf_str, &seg, &bus, &dev, &func))
136 {
137 return -1;
138 }
140 return __insert_to_pci_slot(bus, dev, func, slot);
142 }
144 /* Test if a pci slot has a device
145 * 1: present
146 * 0: not present
147 * -1: invalide pci slot input
148 */
149 int test_pci_slot(int slot)
150 {
151 int php_slot;
153 if ( slot < PHP_SLOT_START || slot >= PHP_SLOT_END )
154 return -1;
156 php_slot = PCI_TO_PHP_SLOT(slot);
157 if ( dpci_infos.php_devs[php_slot].valid )
158 return 1;
159 else
160 return 0;
161 }
163 /* find the pci slot for pass-through dev with specified BDF */
164 int bdf_to_slot(char *bdf_str)
165 {
166 int seg, bus, dev, func, i;
168 if ( !next_bdf(&bdf_str, &seg, &bus, &dev, &func))
169 {
170 return -1;
171 }
173 /* locate the virtual pci slot for this VTd device */
174 for ( i = 0; i < PHP_SLOT_LEN; i++ )
175 {
176 if ( dpci_infos.php_devs[i].valid &&
177 dpci_infos.php_devs[i].r_bus == bus &&
178 dpci_infos.php_devs[i].r_dev == dev &&
179 dpci_infos.php_devs[i].r_func == func )
180 {
181 return PHP_TO_PCI_SLOT(i);
182 }
183 }
185 return -1;
186 }
188 /* Being called each time a mmio region has been updated */
189 void pt_iomem_map(PCIDevice *d, int i, uint32_t e_phys, uint32_t e_size,
190 int type)
191 {
192 struct pt_dev *assigned_device = (struct pt_dev *)d;
193 uint32_t old_ebase = assigned_device->bases[i].e_physbase;
194 int first_map = ( assigned_device->bases[i].e_size == 0 );
195 int ret = 0;
197 assigned_device->bases[i].e_physbase = e_phys;
198 assigned_device->bases[i].e_size= e_size;
200 PT_LOG("e_phys=%08x maddr=%08x type=%d len=%08x index=%d\n",
201 e_phys, assigned_device->bases[i].access.maddr, type, e_size, i);
203 if ( e_size == 0 )
204 return;
206 if ( !first_map )
207 {
208 add_msix_mapping(assigned_device, i);
209 /* Remove old mapping */
210 ret = xc_domain_memory_mapping(xc_handle, domid,
211 old_ebase >> XC_PAGE_SHIFT,
212 assigned_device->bases[i].access.maddr >> XC_PAGE_SHIFT,
213 (e_size+XC_PAGE_SIZE-1) >> XC_PAGE_SHIFT,
214 DPCI_REMOVE_MAPPING);
215 if ( ret != 0 )
216 {
217 PT_LOG("Error: remove old mapping failed!\n");
218 return;
219 }
220 }
222 /* Create new mapping */
223 ret = xc_domain_memory_mapping(xc_handle, domid,
224 assigned_device->bases[i].e_physbase >> XC_PAGE_SHIFT,
225 assigned_device->bases[i].access.maddr >> XC_PAGE_SHIFT,
226 (e_size+XC_PAGE_SIZE-1) >> XC_PAGE_SHIFT,
227 DPCI_ADD_MAPPING);
228 if ( ret != 0 )
229 PT_LOG("Error: create new mapping failed!\n");
231 ret = remove_msix_mapping(assigned_device, i);
232 if ( ret != 0 )
233 PT_LOG("Error: remove MSX-X mmio mapping failed!\n");
234 }
236 /* Being called each time a pio region has been updated */
237 void pt_ioport_map(PCIDevice *d, int i,
238 uint32_t e_phys, uint32_t e_size, int type)
239 {
240 struct pt_dev *assigned_device = (struct pt_dev *)d;
241 uint32_t old_ebase = assigned_device->bases[i].e_physbase;
242 int first_map = ( assigned_device->bases[i].e_size == 0 );
243 int ret = 0;
245 assigned_device->bases[i].e_physbase = e_phys;
246 assigned_device->bases[i].e_size= e_size;
248 PT_LOG("e_phys=%04x pio_base=%04x len=%04x index=%d\n",
249 (uint16_t)e_phys, (uint16_t)assigned_device->bases[i].access.pio_base,
250 (uint16_t)e_size, i);
252 if ( e_size == 0 )
253 return;
255 if ( !first_map )
256 {
257 /* Remove old mapping */
258 ret = xc_domain_ioport_mapping(xc_handle, domid, old_ebase,
259 assigned_device->bases[i].access.pio_base, e_size,
260 DPCI_REMOVE_MAPPING);
261 if ( ret != 0 )
262 {
263 PT_LOG("Error: remove old mapping failed!\n");
264 return;
265 }
266 }
268 /* Create new mapping */
269 ret = xc_domain_ioport_mapping(xc_handle, domid, e_phys,
270 assigned_device->bases[i].access.pio_base, e_size,
271 DPCI_ADD_MAPPING);
272 if ( ret != 0 )
273 PT_LOG("Error: create new mapping failed!\n");
275 }
277 static void pt_pci_write_config(PCIDevice *d, uint32_t address, uint32_t val,
278 int len)
279 {
280 struct pt_dev *assigned_device = (struct pt_dev *)d;
281 struct pci_dev *pci_dev = assigned_device->pci_dev;
283 #ifdef PT_DEBUG_PCI_CONFIG_ACCESS
284 PT_LOG("(%x.%x): address=%04x val=0x%08x len=%d\n",
285 (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, val, len);
286 #endif
288 /* Pre-write hooking */
289 switch ( address ) {
290 case 0x0C ... 0x3F:
291 pci_default_write_config(d, address, val, len);
292 return;
293 }
295 if ( pt_msi_write(assigned_device, address, val, len) )
296 return;
298 if ( pt_msix_write(assigned_device, address, val, len) )
299 return;
301 /* PCI config pass-through */
302 if (address == 0x4) {
303 switch (len){
304 case 1:
305 pci_write_byte(pci_dev, address, val);
306 break;
307 case 2:
308 pci_write_word(pci_dev, address, val);
309 break;
310 case 4:
311 pci_write_long(pci_dev, address, val);
312 break;
313 }
314 }
316 if (address == 0x4) {
317 /* Post-write hooking */
318 pci_default_write_config(d, address, val, len);
319 }
320 }
322 static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t address, int len)
323 {
324 struct pt_dev *assigned_device = (struct pt_dev *)d;
325 struct pci_dev *pci_dev = assigned_device->pci_dev;
326 uint32_t val = 0xFF;
328 /* Pre-hooking */
329 switch ( address ) {
330 case 0x0C ... 0x3F:
331 val = pci_default_read_config(d, address, len);
332 goto exit;
333 }
335 switch ( len ) {
336 case 1:
337 val = pci_read_byte(pci_dev, address);
338 break;
339 case 2:
340 val = pci_read_word(pci_dev, address);
341 break;
342 case 4:
343 val = pci_read_long(pci_dev, address);
344 break;
345 }
347 pt_msi_read(assigned_device, address, len, &val);
348 pt_msix_read(assigned_device, address, len, &val);
349 exit:
351 #ifdef PT_DEBUG_PCI_CONFIG_ACCESS
352 PT_LOG("(%x.%x): address=%04x val=0x%08x len=%d\n",
353 (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, val, len);
354 #endif
356 return val;
357 }
359 static int pt_register_regions(struct pt_dev *assigned_device)
360 {
361 int i = 0;
362 uint32_t bar_data = 0;
363 struct pci_dev *pci_dev = assigned_device->pci_dev;
364 PCIDevice *d = &assigned_device->dev;
366 /* Register PIO/MMIO BARs */
367 for ( i = 0; i < PCI_BAR_ENTRIES; i++ )
368 {
369 if ( pci_dev->base_addr[i] )
370 {
371 assigned_device->bases[i].e_physbase = pci_dev->base_addr[i];
372 assigned_device->bases[i].access.u = pci_dev->base_addr[i];
374 /* Register current region */
375 bar_data = *((uint32_t*)(d->config + PCI_BASE_ADDRESS_0) + i);
376 if ( bar_data & PCI_ADDRESS_SPACE_IO )
377 pci_register_io_region((PCIDevice *)assigned_device, i,
378 (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_IO,
379 pt_ioport_map);
380 else if ( bar_data & PCI_ADDRESS_SPACE_MEM_PREFETCH )
381 pci_register_io_region((PCIDevice *)assigned_device, i,
382 (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM_PREFETCH,
383 pt_iomem_map);
384 else
385 pci_register_io_region((PCIDevice *)assigned_device, i,
386 (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM,
387 pt_iomem_map);
389 PT_LOG("IO region registered (size=0x%08x base_addr=0x%08x)\n",
390 (uint32_t)(pci_dev->size[i]),
391 (uint32_t)(pci_dev->base_addr[i]));
392 }
393 }
395 /* Register expansion ROM address */
396 if ( pci_dev->rom_base_addr && pci_dev->rom_size )
397 {
398 assigned_device->bases[PCI_ROM_SLOT].e_physbase =
399 pci_dev->rom_base_addr;
400 assigned_device->bases[PCI_ROM_SLOT].access.maddr =
401 pci_dev->rom_base_addr;
402 pci_register_io_region((PCIDevice *)assigned_device, PCI_ROM_SLOT,
403 pci_dev->rom_size, PCI_ADDRESS_SPACE_MEM_PREFETCH,
404 pt_iomem_map);
406 PT_LOG("Expansion ROM registered (size=0x%08x base_addr=0x%08x)\n",
407 (uint32_t)(pci_dev->rom_size), (uint32_t)(pci_dev->rom_base_addr));
408 }
410 return 0;
411 }
413 static int pt_unregister_regions(struct pt_dev *assigned_device)
414 {
415 int i, type, ret;
416 uint32_t e_size;
417 PCIDevice *d = (PCIDevice*)assigned_device;
419 for ( i = 0; i < PCI_NUM_REGIONS; i++ )
420 {
421 e_size = assigned_device->bases[i].e_size;
422 if ( e_size == 0 )
423 continue;
425 type = d->io_regions[i].type;
427 if ( type == PCI_ADDRESS_SPACE_MEM ||
428 type == PCI_ADDRESS_SPACE_MEM_PREFETCH )
429 {
430 ret = xc_domain_memory_mapping(xc_handle, domid,
431 assigned_device->bases[i].e_physbase >> XC_PAGE_SHIFT,
432 assigned_device->bases[i].access.maddr >> XC_PAGE_SHIFT,
433 (e_size+XC_PAGE_SIZE-1) >> XC_PAGE_SHIFT,
434 DPCI_REMOVE_MAPPING);
435 if ( ret != 0 )
436 {
437 PT_LOG("Error: remove old mem mapping failed!\n");
438 continue;
439 }
441 }
442 else if ( type == PCI_ADDRESS_SPACE_IO )
443 {
444 ret = xc_domain_ioport_mapping(xc_handle, domid,
445 assigned_device->bases[i].e_physbase,
446 assigned_device->bases[i].access.pio_base,
447 e_size,
448 DPCI_REMOVE_MAPPING);
449 if ( ret != 0 )
450 {
451 PT_LOG("Error: remove old io mapping failed!\n");
452 continue;
453 }
455 }
457 }
459 }
461 uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap)
462 {
463 int id;
464 int max_cap = 48;
465 int pos = PCI_CAPABILITY_LIST;
466 int status;
468 status = pci_read_byte(pci_dev, PCI_STATUS);
469 if ( (status & PCI_STATUS_CAP_LIST) == 0 )
470 return 0;
472 while ( max_cap-- )
473 {
474 pos = pci_read_byte(pci_dev, pos);
475 if ( pos < 0x40 )
476 break;
478 pos &= ~3;
479 id = pci_read_byte(pci_dev, pos + PCI_CAP_LIST_ID);
481 if ( id == 0xff )
482 break;
483 if ( id == cap )
484 return pos;
486 pos += PCI_CAP_LIST_NEXT;
487 }
488 return 0;
489 }
491 struct pt_dev * register_real_device(PCIBus *e_bus,
492 const char *e_dev_name, int e_devfn, uint8_t r_bus, uint8_t r_dev,
493 uint8_t r_func, uint32_t machine_irq, struct pci_access *pci_access)
494 {
495 int rc = -1, i, pos;
496 struct pt_dev *assigned_device = NULL;
497 struct pci_dev *pci_dev;
498 uint8_t e_device, e_intx;
499 struct pci_config_cf8 machine_bdf;
500 int free_pci_slot = -1;
502 PT_LOG("Assigning real physical device %02x:%02x.%x ...\n",
503 r_bus, r_dev, r_func);
505 /* Find real device structure */
506 for (pci_dev = pci_access->devices; pci_dev != NULL;
507 pci_dev = pci_dev->next)
508 {
509 if ((r_bus == pci_dev->bus) && (r_dev == pci_dev->dev)
510 && (r_func == pci_dev->func))
511 break;
512 }
513 if ( pci_dev == NULL )
514 {
515 PT_LOG("Error: couldn't locate device in libpci structures\n");
516 return NULL;
517 }
518 pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES);
520 if ( e_devfn == PT_VIRT_DEVFN_AUTO ) {
521 /*indicate a static assignment(not hotplug), so find a free PCI hot plug slot */
522 free_pci_slot = __insert_to_pci_slot(r_bus, r_dev, r_func, 0);
523 if ( free_pci_slot > 0 )
524 e_devfn = free_pci_slot << 3;
525 else
526 PT_LOG("Error: no free virtual PCI hot plug slot, thus no live migration.\n");
527 }
529 /* Register device */
530 assigned_device = (struct pt_dev *) pci_register_device(e_bus, e_dev_name,
531 sizeof(struct pt_dev), e_devfn,
532 pt_pci_read_config, pt_pci_write_config);
533 if ( assigned_device == NULL )
534 {
535 PT_LOG("Error: couldn't register real device\n");
536 return NULL;
537 }
539 if ( free_pci_slot > 0 )
540 dpci_infos.php_devs[PCI_TO_PHP_SLOT(free_pci_slot)].pt_dev = assigned_device;
542 assigned_device->pci_dev = pci_dev;
545 /* Assign device */
546 machine_bdf.reg = 0;
547 machine_bdf.bus = r_bus;
548 machine_bdf.dev = r_dev;
549 machine_bdf.func = r_func;
550 rc = xc_assign_device(xc_handle, domid, machine_bdf.value);
551 if ( rc < 0 )
552 PT_LOG("Error: xc_assign_device error %d\n", rc);
554 /* Initialize virtualized PCI configuration (Extended 256 Bytes) */
555 for ( i = 0; i < PCI_CONFIG_SIZE; i++ )
556 assigned_device->dev.config[i] = pci_read_byte(pci_dev, i);
558 if ( (pos = find_cap_offset(pci_dev, PCI_CAP_ID_MSI)) )
559 pt_msi_init(assigned_device, pos);
561 if ( (pos = find_cap_offset(pci_dev, PCI_CAP_ID_MSIX)) )
562 pt_msix_init(assigned_device, pos);
564 /* Handle real device's MMIO/PIO BARs */
565 pt_register_regions(assigned_device);
567 /* Bind interrupt */
568 e_device = (assigned_device->dev.devfn >> 3) & 0x1f;
569 e_intx = assigned_device->dev.config[0x3d]-1;
571 if ( PT_MACHINE_IRQ_AUTO == machine_irq )
572 {
573 int pirq = pci_dev->irq;
575 machine_irq = pci_dev->irq;
576 rc = xc_physdev_map_pirq(xc_handle, domid, MAP_PIRQ_TYPE_GSI,
577 machine_irq, &pirq);
579 if ( rc )
580 {
581 /* TBD: unregister device in case of an error */
582 PT_LOG("Error: Mapping irq failed, rc = %d\n", rc);
583 }
584 else
585 machine_irq = pirq;
586 }
588 /* bind machine_irq to device */
589 if ( 0 != machine_irq )
590 {
591 rc = xc_domain_bind_pt_pci_irq(xc_handle, domid, machine_irq, 0,
592 e_device, e_intx);
593 if ( rc < 0 )
594 {
595 /* TBD: unregister device in case of an error */
596 PT_LOG("Error: Binding of interrupt failed! rc=%d\n", rc);
597 }
598 }
599 else {
600 /* Disable PCI intx assertion (turn on bit10 of devctl) */
601 assigned_device->dev.config[0x05] |= 0x04;
602 pci_write_word(pci_dev, 0x04,
603 *(uint16_t *)(&assigned_device->dev.config[0x04]));
604 }
606 PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n",
607 r_bus, r_dev, r_func);
609 return assigned_device;
610 }
612 int unregister_real_device(int php_slot)
613 {
614 struct php_dev *php_dev;
615 struct pci_dev *pci_dev;
616 uint8_t e_device, e_intx;
617 struct pt_dev *assigned_device = NULL;
618 uint32_t machine_irq;
619 uint32_t bdf = 0;
620 int rc = -1;
622 if ( php_slot < 0 || php_slot >= PHP_SLOT_LEN )
623 return -1;
625 php_dev = &dpci_infos.php_devs[php_slot];
626 assigned_device = php_dev->pt_dev;
628 if ( !assigned_device || !php_dev->valid )
629 return -1;
631 pci_dev = assigned_device->pci_dev;
633 /* hide pci dev from qemu */
634 pci_hide_device((PCIDevice*)assigned_device);
636 /* Unbind interrupt */
637 e_device = (assigned_device->dev.devfn >> 3) & 0x1f;
638 e_intx = assigned_device->dev.config[0x3d]-1;
639 machine_irq = pci_dev->irq;
641 if ( machine_irq != 0 ) {
642 rc = xc_domain_unbind_pt_irq(xc_handle, domid, machine_irq, PT_IRQ_TYPE_PCI, 0,
643 e_device, e_intx, 0);
644 if ( rc < 0 )
645 {
646 /* TBD: unregister device in case of an error */
647 PT_LOG("Error: Unbinding of interrupt failed! rc=%d\n", rc);
648 }
649 }
651 /* unregister real device's MMIO/PIO BARs */
652 pt_unregister_regions(assigned_device);
654 /* deassign the dev to dom0 */
655 bdf |= (pci_dev->bus & 0xff) << 16;
656 bdf |= (pci_dev->dev & 0x1f) << 11;
657 bdf |= (pci_dev->func & 0x1f) << 8;
658 if ( (rc = xc_deassign_device(xc_handle, domid, bdf)) != 0)
659 PT_LOG("Error: Revoking the device failed! rc=%d\n", rc);
661 /* mark this slot as free */
662 php_dev->valid = 0;
663 php_dev->pt_dev = NULL;
664 qemu_free(assigned_device);
666 return 0;
667 }
669 int power_on_php_slot(int php_slot)
670 {
671 struct php_dev *php_dev = &dpci_infos.php_devs[php_slot];
672 int pci_slot = php_slot + PHP_SLOT_START;
673 struct pt_dev *pt_dev;
674 pt_dev =
675 register_real_device(dpci_infos.e_bus,
676 "DIRECT PCI",
677 pci_slot << 3,
678 php_dev->r_bus,
679 php_dev->r_dev,
680 php_dev->r_func,
681 PT_MACHINE_IRQ_AUTO,
682 dpci_infos.pci_access);
684 php_dev->pt_dev = pt_dev;
686 return 0;
688 }
690 int power_off_php_slot(int php_slot)
691 {
692 return unregister_real_device(php_slot);
693 }
695 int pt_init(PCIBus *e_bus, char *direct_pci)
696 {
697 int seg, b, d, f, php_slot = 0;
698 struct pt_dev *pt_dev;
699 struct pci_access *pci_access;
700 char *vslots;
701 char slot_str[8];
703 /* Initialize libpci */
704 pci_access = pci_alloc();
705 if ( pci_access == NULL )
706 {
707 PT_LOG("pci_access is NULL\n");
708 return -1;
709 }
710 pci_init(pci_access);
711 pci_scan_bus(pci_access);
713 memset(&dpci_infos, 0, sizeof(struct dpci_infos));
714 dpci_infos.pci_access = pci_access;
715 dpci_infos.e_bus = e_bus;
717 if ( strlen(direct_pci) == 0 ) {
718 return 0;
719 }
721 /* the virtual pci slots of all pass-through devs
722 * with hex format: xx;xx...;
723 */
724 vslots = qemu_mallocz ( strlen(direct_pci) / 3 );
726 /* Assign given devices to guest */
727 while ( next_bdf(&direct_pci, &seg, &b, &d, &f) )
728 {
729 /* Register real device with the emulated bus */
730 pt_dev = register_real_device(e_bus, "DIRECT PCI", PT_VIRT_DEVFN_AUTO,
731 b, d, f, PT_MACHINE_IRQ_AUTO, pci_access);
732 if ( pt_dev == NULL )
733 {
734 PT_LOG("Error: Registration failed (%02x:%02x.%x)\n", b, d, f);
735 return -1;
736 }
738 /* Record the virtual slot info */
739 if ( php_slot < PHP_SLOT_LEN &&
740 dpci_infos.php_devs[php_slot].pt_dev == pt_dev )
741 {
742 sprintf(slot_str, "0x%x;", PHP_TO_PCI_SLOT(php_slot));
743 }
744 else
745 sprintf(slot_str, "0x%x;", 0);
747 strcat(vslots, slot_str);
748 php_slot++;
749 }
751 /* Write virtual slots info to xenstore for Control panel use */
752 xenstore_write_vslots(vslots);
754 qemu_free(vslots);
756 /* Success */
757 return 0;
758 }