2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu>
11 * Copyright (c) 2009, Chang Seok Bae <jhuell@gmail.com>
12 * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org>
13 * All rights reserved.
15 * Author: Lei Xia <lxia@northwestern.edu>
16 * Chang Seok Bae <jhuell@gmail.com>
18 * This is free software. You are permitted to use,
19 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
26 #include <devices/vpci.h>
27 #include <palacios/vmm.h>
28 #include <palacios/vmm_types.h>
29 #include <palacios/vmm_io.h>
30 #include <palacios/vmm_string.h>
31 #include <palacios/vmm_intr.h>
34 // TODO: Add Debugging directives to Makefiles
38 #define PrintDebug(fmt, args...)
41 #define NUM_DEVICES 255
46 struct pci_device * device_list[NUM_DEVICES];
47 struct pci_bus * next;
48 struct vm_device * vm_dev;
53 uint32_t config_address; //current value of corresponding to configure port
54 struct pci_bus * bus_list[NUM_BUS];
60 int (*port_read)(ushort_t port, void * dst, uint_t length, struct vm_device * vdev);
61 int (*port_write)(ushort_t port, void * src, uint_t length, struct vm_device * vdev);
66 struct pci_device * get_device (struct vm_device * vmdev, uchar_t bus_no, uchar_t devfn_no)
68 struct pci_device * dev = NULL;
69 struct pci_bus * bus = NULL;
70 struct pci_internal * pci_state = NULL;
72 if ((bus_no >= NUM_BUS) || (devfn_no >= NUM_DEVICES)) {
76 pci_state = (struct pci_internal *)vmdev->private_data;
77 bus = pci_state->bus_list[bus_no];
80 dev = bus->device_list[devfn_no];
88 // TODO: Should this be static? If not it should be v3_pci_...
89 int pci_hook_ports(struct pci_device * dev,
92 port_read_fn * port_reads[],
93 port_write_fn * port_writes[]) {
94 struct pci_ioregion * ioreg = NULL;
96 ioreg = dev->ioregion[reg_num];
99 PrintError("No Device registered at ioregion %d\n", reg_num);
103 if (ioreg->size != num_ports) {
104 // TODO: What does this error mean?
105 PrintError("IO registration size mismatch\n");
109 ioreg->port_reads = port_reads;
110 ioreg->port_writes = port_writes;
116 // TODO: should return 'int' to indicate success or error?
117 // TODO: add error checking
118 static inline void hook_ioregion(struct pci_device * dev, struct pci_ioregion * ioreg) {
121 if (ioreg->addr == -1) {
122 // TODO: Is this an error?
126 if (ioreg->type != PCI_ADDRESS_SPACE_IO) {
127 // TODO: is this an error?
131 for (i = 0; i < ioreg->size; i++) {
132 if ( (ioreg->port_reads[i]) ||
133 (ioreg->port_writes[i]) ) {
134 v3_dev_hook_io(dev->bus->vm_dev, ioreg->addr + i, ioreg->port_reads[i], ioreg->port_writes[i]);
143 static uint32_t vpci_read_config(struct pci_device * pdev, uchar_t offset, int len) {
148 if (offset <= 0xfc) {
149 val = *(uint32_t *)(&(pdev->config) + offset);
152 // TODO: Shouldn't this break unconditionally?
154 if (offset <= 0xfe) {
155 val = *(uint16_t *)(&(pdev->config) + offset);
158 // TODO: Shouldn't this break unconditionally?
160 val = *(uint8_t *)(&(pdev->config) + offset);
170 // TODO: Should this return 'int'?
171 static void vpci_write_config(struct pci_device * dev, uchar_t offset, uint32_t val, int len) {
172 uchar_t * dev_config = NULL;
174 dev_config = (uchar_t *)&(dev->config);
175 dev_config += offset;
178 // TODO: cast 'val' instead of masking it
181 *dev_config = (val & 0xff);
184 *(uint16_t *)dev_config = (val & 0xffff);
187 *(uint32_t *)dev_config = val;
190 PrintDebug("pci_write_config: wrong length %d\n", len);
196 // TODO: If this is not static, it should be v3_pci_raise_irq
197 void vpci_raise_irq(struct pci_device * pdev, void * data) {
198 struct guest_info * vm = NULL;
201 vm = pdev->bus->vm_dev->vm;
202 irq_line = pdev->config.intr_line;
204 v3_raise_irq(vm, irq_line);
209 static void pci_write_config(struct pci_device *dev, uint32_t address, uint32_t val, int len)
211 int can_write, i, reg_num;
214 if(len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || //base address registers
215 (address >= 0x30 && address < 0x34))) { //expansion rom base address
217 struct pci_ioregion * ioregion;
218 if(address >= 0x30) {
219 reg_num = PCI_ROM_SLOT;
221 reg_num = ((address - 0x10) >>2);
224 ioregion = &dev->io_regions[reg_num];
226 if(ioregion->size == 0) {//default config
229 for (i=0;i<len;i++) {
230 switch(*(uint8_t *)(&(dev->config)+0x0e)) {
275 *(uint32_t *)(&(dev->config)+addr) = val;
277 if(++addr > 0xff) break;
284 if(reg_num== PCI_ROM_SLOT) {
285 val &= (~(ioregion->size -1 )) | 1;
287 val &= ~(ioregion->size -1);
288 val |= ioregion->type;
291 //pci_update_mappings();
297 /* -1 for dev_num means auto assign */
298 // TODO: Should be v3_pci_register_device
300 pci_register_device(struct pci_bus * bus, const char * name,
301 int instance_size, int dev_num,
302 uint32_t (*config_read)(struct pci_device * pci_dev, uchar_t addr, int len),
303 void (*config_write)(struct pci_device * pci_dev, uchar_t addr, uint32_t val, int len)) {
305 struct pci_device * pci_dev = NULL;
310 for (dev_num = 0; dev_num < 256; dev_num++) {
311 if (!bus->device_list[dev_num]) {
322 pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
324 if (pci_dev == NULL) {
329 pci_dev->dev_num = dev_num;
330 pci_dev->irqline = -1;
332 strcpy(pci_dev->name, name);
334 if (config_read != NULL) {
335 pci_dev->ops.config_read = config_read;
337 pci_dev->ops.config_read = &vpci_read_config;
340 if (config_write != NULL) {
341 pci_dev->ops.config_write = config_write;
343 pci_dev->ops.config_write = &vpci_write_config;
347 pci_dev->ops.raise_irq = &vpci_raise_irq;
349 for (i = 0; i < PCI_IO_REGIONS; i++) {
350 pci_dev->ioregion[i] = NULL;
353 //config space initiate
355 bus->device_list[dev_num] = pci_dev;
361 static void init_fake_device(struct pci_internal * pci_state) {
362 //maybe need table to map device, but just
363 //bus_num=0, dev_num=0
366 struct pci_device *fake_device;
369 fake_device = pci_register_device(pci_state->bus_list[0],
370 "fake ide", sizeof(struct pci_device),
383 fake_device->config.vendor_id = 0x8086;
384 fake_device->config.device_id = 0x1222;
385 fake_device->config.command = 0x0;
386 fake_device->config.status = 0x0;
387 fake_device->config.revision = 0x07;
388 fake_device->config.class_code[0] = 0x1;
389 fake_device->config.class_code[1] = 0x1;
390 fake_device->config.class_code[2] = 0x1;
391 fake_device->config.header_type = 0x0;
394 fake_device->config.BAR[0] = 0x1F0;
395 fake_device->config.BAR[1] = 0;
396 fake_device->config.BAR[2] = 0;
397 fake_device->config.BAR[3] = 0;
398 fake_device->config.BAR[4] = 0;
399 fake_device->config.BAR[5] = 0;
403 //need to register io regions
405 pci_state->bus_list[0]->device_list[0] = fake_device;
406 fake_device->bus = pci_state->bus_list[0];
407 fake_device->next = NULL;
415 /* if region_num == -1, assign automatically
417 //TODO: Should be v3_pci_register...
419 pci_register_io_region(struct pci_device * pci_dev, int region_num,
420 uint32_t size, int type,
421 pci_mapioregion_fn * map_func) {
423 struct pci_ioregion * region = NULL;
425 if (region_num < 0) {
426 for (region_num = 0; region_num < 256; region_num++) {
427 if (pci_dev->ioregion[region_num] == NULL) {
438 if (pci_dev->ioregion[region_num] != NULL) {
442 region = (struct pci_ioregion *)V3_Malloc(sizeof(struct pci_ioregion));
443 if (region == NULL) {
448 region->reg_num = region_num;
450 region->mapped_size = -1;
452 region->map_func = map_func;
453 region->port_reads = NULL;
454 region->port_writes = NULL;
456 pci_dev->ioregion[region_num] = region;
466 vpci_addrport_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
468 struct pci_internal *pci_state = (struct pci_internal *)dev->private_data;
470 uchar_t * addr = NULL;
473 start = port - PCI_CONFIG_ADDRESS;
475 if ((length + start) > 4) {
476 //cross port boundary, is memory mapped IO style
480 addr = (uchar_t *)&(pci_state->config_address);
483 memcpy(dst, addr, length); //be careful, PCI is little endian
485 PrintDebug("PCI Address: reading %d bytes from port %x: 0x", length, port);
486 for (i = (length - 1); i >= 0; i--) {
487 PrintDebug("%.2x", ((uchar_t*)dst)[i]);
496 vpci_addrport_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
497 struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;
499 uchar_t * addr = NULL;
502 start = port - PCI_CONFIG_ADDRESS;
504 if ((length + start) > 4){
505 //cross port boundary, is memory mapped IO style
509 addr = (uchar_t *)&(pci_state->config_address);
511 memcpy(addr, src, length); //be careful, PCI is little endian
513 PrintDebug("PCI Address: writing %d bytes to port %x: 0x", length, port);
515 for (i = (length - 1); i >= 0; i--) {
516 PrintDebug("%.2x", ((uchar_t*)src)[i]);
525 vpci_dataport_read(ushort_t port, void * dst, uint_t length, struct vm_device * vmdev) {
527 decode address of config_address
528 bus num = config_address[23:16]
529 device num = config_address[15:11]
530 func num = config_address[10:08]
531 reg num = config_address[07:02]
534 struct pci_internal * pci_state = NULL;
535 struct pci_device * pci_dev = NULL;
539 uint32_t address = 0;
544 PrintDebug("Read more than 4 bytes from port 0x%x\n", (int)port);
548 pci_state = (struct pci_internal *)vmdev->private_data;
550 address = pci_state->config_address;
551 offset = address & 0xff;
552 devfn = (address >> 8) & 0xff;
553 bus_num = (address >> 16) & 0xff;
555 pci_dev = get_device(vmdev, bus_num, devfn);
557 if (pci_dev == NULL) {
561 val = pci_dev->ops.config_read(pci_dev, offset, length);
564 memcpy(dst, &val, length);
566 PrintDebug("PCI Data: reading %d bytes from port %x: 0x", length, port);
568 for (i = (length - 1); i >= 0; i--) {
569 PrintDebug("%.2x", ((uchar_t*)dst)[i]);
577 vpci_dataport_write(ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
578 struct pci_internal * pci_state = NULL;
580 uint32_t address = 0;
581 struct pci_device * pdev = NULL;
582 // TODO: Why are these 'char', but the read variables 'int'
589 PrintDebug("Write more than 4 bytes to port 0x%x\n", (int)port);
593 pci_state = (struct pci_internal *)vmdev->private_data;
595 address = pci_state->config_address;
596 offset = address & 0xff;
597 devfn = (address >> 8) & 0xff;
598 bus = (address >> 16) & 0xff;
600 pdev = get_device(vmdev, bus, devfn);
603 // not sure what to do here, just ignore it
608 memcpy(&val, src, length);
610 pdev->ops.config_write(pdev, offset, val, length);
612 PrintDebug("PCI Data: writing %d bytes to port %x: 0x", length, port);
614 for (i = (length - 1); i >= 0; i--) {
615 PrintDebug("%.2x", ((uchar_t*)src)[i]);
624 static void init_pci_bus(struct pci_internal * pci_state) {
626 struct pci_bus * first_bus = NULL;
628 first_bus = (struct pci_bus *)V3_Malloc(sizeof(struct pci_bus));
630 first_bus->bus_num = 0; //?? not sure
632 for (i = 0; i < NUM_DEVICES; i++) {
633 first_bus->device_list[i] = NULL;
636 first_bus->next = NULL;
638 pci_state->num_buses = 1;
639 pci_state->bus_list[0] = first_bus;
641 for (i = 1; i < NUM_BUS; i++) {
642 pci_state->bus_list[i] = NULL;
647 static void init_pci_internal(struct pci_internal * pci_state) {
648 pci_state->config_address = 0x00; //Not sure????
649 init_pci_bus(pci_state);
653 static int vpci_set_defaults(struct vm_device * dev) {
654 PrintDebug("vpci: set defaults\n");
659 static int vpci_reset_device(struct vm_device * dev) {
660 PrintDebug("vpci: reset device\n");
662 vpci_set_defaults(dev);
668 static int vpci_start_device(struct vm_device * dev) {
669 PrintDebug("vpci: start device\n");
674 // TODO: This should be static
675 int vpci_stop_device(struct vm_device * dev) {
676 PrintDebug("vpci: stop device\n");
680 // TODO: this should be static?
681 int vpci_init_device(struct vm_device * dev) {
682 struct pci_internal *pci_state = NULL;
685 PrintDebug("vpci: init_device\n");
687 pci_state = (struct pci_internal *)dev->private_data;
689 init_pci_internal(pci_state);
691 init_fake_device(pci_state); //Chang
693 for (i = 0; i < 4; i++){
694 v3_dev_hook_io(dev, PCI_CONFIG_ADDRESS + i, &vpci_addrport_read, &vpci_addrport_write);
695 v3_dev_hook_io(dev, PCI_CONFIG_DATA + i, &vpci_dataport_read, &vpci_dataport_write);
701 // TODO: This should be static
702 int vpci_deinit_device(struct vm_device * dev) {
705 for (i = 0; i < 4; i++){
706 v3_dev_unhook_io(dev, PCI_CONFIG_ADDRESS + i);
707 v3_dev_unhook_io(dev, PCI_CONFIG_DATA + i);
710 vpci_reset_device(dev);
714 static struct vm_device_ops dev_ops = {
715 .init = vpci_init_device,
716 .deinit = vpci_deinit_device,
717 .reset = vpci_reset_device,
718 .start = vpci_start_device,
719 .stop = vpci_stop_device,
722 struct vm_device * v3_create_vpci() {
723 struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
725 PrintDebug("PCI internal at %p\n",(void *)pci_state);
727 struct vm_device * device = v3_create_device("PCI", &dev_ops, pci_state);