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;
179 *dev_config = (val & 0xff);
182 *(uint16_t *)dev_config = (val & 0xffff);
185 *(uint32_t *)dev_config = val;
188 PrintDebug("pci_write_config: wrong length %d\n", len);
194 // TODO: If this is not static, it should be v3_pci_raise_irq
195 void vpci_raise_irq(struct pci_device * pdev, void * data) {
196 struct guest_info * vm = NULL;
199 vm = pdev->bus->vm_dev->vm;
200 irq_line = pdev->config.intr_line;
202 v3_raise_irq(vm, irq_line);
207 static void pci_write_config(struct pci_device *dev, uint32_t address, uint32_t val, int len)
209 int can_write, i, reg_num;
212 if(len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || //base address registers
213 (address >= 0x30 && address < 0x34))) { //expansion rom base address
215 struct pci_ioregion * ioregion;
216 if(address >= 0x30) {
217 reg_num = PCI_ROM_SLOT;
219 reg_num = ((address - 0x10) >>2);
222 ioregion = &dev->io_regions[reg_num];
224 if(ioregion->size == 0) {//default config
227 for (i=0;i<len;i++) {
228 switch(*(uint8_t *)(&(dev->config)+0x0e)) {
273 *(uint32_t *)(&(dev->config)+addr) = val;
275 if(++addr > 0xff) break;
282 if(reg_num== PCI_ROM_SLOT) {
283 val &= (~(ioregion->size -1 )) | 1;
285 val &= ~(ioregion->size -1);
286 val |= ioregion->type;
289 //pci_update_mappings();
295 /* -1 for dev_num means auto assign */
296 // TODO: Should be v3_pci_register_device
298 pci_register_device(struct pci_bus * bus, const char * name,
299 int instance_size, int dev_num,
300 uint32_t (*config_read)(struct pci_device * pci_dev, uchar_t addr, int len),
301 void (*config_write)(struct pci_device * pci_dev, uchar_t addr, uint32_t val, int len)) {
303 struct pci_device * pci_dev = NULL;
308 for (dev_num = 0; dev_num < 256; dev_num++) {
309 if (!bus->device_list[dev_num]) {
320 pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
322 if (pci_dev == NULL) {
327 pci_dev->dev_num = dev_num;
328 pci_dev->irqline = -1;
330 strcpy(pci_dev->name, name);
332 if (config_read != NULL) {
333 pci_dev->ops.config_read = config_read;
335 pci_dev->ops.config_read = &vpci_read_config;
338 if (config_write != NULL) {
339 pci_dev->ops.config_write = config_write;
341 pci_dev->ops.config_write = &vpci_write_config;
345 pci_dev->ops.raise_irq = &vpci_raise_irq;
347 for (i = 0; i < PCI_IO_REGIONS; i++) {
348 pci_dev->ioregion[i] = NULL;
351 //config space initiate
353 bus->device_list[dev_num] = pci_dev;
359 static void init_fake_device(struct pci_internal * pci_state) {
360 //maybe need table to map device, but just
361 //bus_num=0, dev_num=0
364 struct pci_device *fake_device;
367 fake_device = pci_register_device(pci_state->bus_list[0],
368 "fake ide", sizeof(struct pci_device),
381 fake_device->config.vendor_id = 0x8086;
382 fake_device->config.device_id = 0x1222;
383 fake_device->config.command = 0x0;
384 fake_device->config.status = 0x0;
385 fake_device->config.revision = 0x07;
386 fake_device->config.class_code[0] = 0x1;
387 fake_device->config.class_code[1] = 0x1;
388 fake_device->config.class_code[2] = 0x1;
389 fake_device->config.header_type = 0x0;
392 fake_device->config.BAR[0] = 0x1F0;
393 fake_device->config.BAR[1] = 0;
394 fake_device->config.BAR[2] = 0;
395 fake_device->config.BAR[3] = 0;
396 fake_device->config.BAR[4] = 0;
397 fake_device->config.BAR[5] = 0;
401 //need to register io regions
403 pci_state->bus_list[0]->device_list[0] = fake_device;
404 fake_device->bus = pci_state->bus_list[0];
405 fake_device->next = NULL;
413 /* if region_num == -1, assign automatically
415 //TODO: Should be v3_pci_register...
417 pci_register_io_region(struct pci_device * pci_dev, int region_num,
418 uint32_t size, int type,
419 pci_mapioregion_fn * map_func) {
421 struct pci_ioregion * region = NULL;
423 if (region_num < 0) {
424 for (region_num = 0; region_num < 256; region_num++) {
425 if (pci_dev->ioregion[region_num] == NULL) {
436 if (pci_dev->ioregion[region_num] != NULL) {
440 region = (struct pci_ioregion *)V3_Malloc(sizeof(struct pci_ioregion));
441 if (region == NULL) {
446 region->reg_num = region_num;
448 region->mapped_size = -1;
450 region->map_func = map_func;
451 region->port_reads = NULL;
452 region->port_writes = NULL;
454 pci_dev->ioregion[region_num] = region;
464 vpci_addrport_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
466 struct pci_internal *pci_state = (struct pci_internal *)dev->private_data;
468 uchar_t * addr = NULL;
471 start = port - PCI_CONFIG_ADDRESS;
473 if ((length + start) > 4) {
474 //cross port boundary, is memory mapped IO style
478 addr = (uchar_t *)&(pci_state->config_address);
481 memcpy(dst, addr, length); //be careful, PCI is little endian
483 PrintDebug("PCI Address: reading %d bytes from port %x: 0x", length, port);
484 for (i = (length - 1); i >= 0; i--) {
485 PrintDebug("%.2x", ((uchar_t*)dst)[i]);
494 vpci_addrport_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
495 struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;
497 uchar_t * addr = NULL;
500 start = port - PCI_CONFIG_ADDRESS;
502 if ((length + start) > 4){
503 //cross port boundary, is memory mapped IO style
507 addr = (uchar_t *)&(pci_state->config_address);
509 memcpy(addr, src, length); //be careful, PCI is little endian
511 PrintDebug("PCI Address: writing %d bytes to port %x: 0x", length, port);
513 for (i = (length - 1); i >= 0; i--) {
514 PrintDebug("%.2x", ((uchar_t*)src)[i]);
523 vpci_dataport_read(ushort_t port, void * dst, uint_t length, struct vm_device * vmdev) {
525 decode address of config_address
526 bus num = config_address[23:16]
527 device num = config_address[15:11]
528 func num = config_address[10:08]
529 reg num = config_address[07:02]
532 struct pci_internal * pci_state = NULL;
533 struct pci_device * pci_dev = NULL;
537 uint32_t address = 0;
542 PrintDebug("Read more than 4 bytes from port 0x%x\n", (int)port);
546 pci_state = (struct pci_internal *)vmdev->private_data;
548 address = pci_state->config_address;
549 offset = address & 0xff;
550 devfn = (address >> 8) & 0xff;
551 bus_num = (address >> 16) & 0xff;
553 pci_dev = get_device(vmdev, bus_num, devfn);
555 if (pci_dev == NULL) {
559 val = pci_dev->ops.config_read(pci_dev, offset, length);
562 memcpy(dst, &val, length);
564 PrintDebug("PCI Data: reading %d bytes from port %x: 0x", length, port);
566 for (i = (length - 1); i >= 0; i--) {
567 PrintDebug("%.2x", ((uchar_t*)dst)[i]);
575 vpci_dataport_write(ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
576 struct pci_internal * pci_state = NULL;
578 uint32_t address = 0;
579 struct pci_device * pdev = NULL;
580 // TODO: Why are these 'char', but the read variables 'int'
587 PrintDebug("Write more than 4 bytes to port 0x%x\n", (int)port);
591 pci_state = (struct pci_internal *)vmdev->private_data;
593 address = pci_state->config_address;
594 offset = address & 0xff;
595 devfn = (address >> 8) & 0xff;
596 bus = (address >> 16) & 0xff;
598 pdev = get_device(vmdev, bus, devfn);
601 // not sure what to do here, just ignore it
606 memcpy(&val, src, length);
608 pdev->ops.config_write(pdev, offset, val, length);
610 PrintDebug("PCI Data: writing %d bytes to port %x: 0x", length, port);
612 for (i = (length - 1); i >= 0; i--) {
613 PrintDebug("%.2x", ((uchar_t*)src)[i]);
622 static void init_pci_bus(struct pci_internal * pci_state) {
624 struct pci_bus * first_bus = NULL;
626 first_bus = (struct pci_bus *)V3_Malloc(sizeof(struct pci_bus));
628 first_bus->bus_num = 0; //?? not sure
630 for (i = 0; i < NUM_DEVICES; i++) {
631 first_bus->device_list[i] = NULL;
634 first_bus->next = NULL;
636 pci_state->num_buses = 1;
637 pci_state->bus_list[0] = first_bus;
639 for (i = 1; i < NUM_BUS; i++) {
640 pci_state->bus_list[i] = NULL;
645 static void init_pci_internal(struct pci_internal * pci_state) {
646 pci_state->config_address = 0x00; //Not sure????
647 init_pci_bus(pci_state);
651 static int vpci_set_defaults(struct vm_device * dev) {
652 PrintDebug("vpci: set defaults\n");
657 static int vpci_reset_device(struct vm_device * dev) {
658 PrintDebug("vpci: reset device\n");
660 vpci_set_defaults(dev);
666 static int vpci_start_device(struct vm_device * dev) {
667 PrintDebug("vpci: start device\n");
672 // TODO: This should be static
673 int vpci_stop_device(struct vm_device * dev) {
674 PrintDebug("vpci: stop device\n");
678 // TODO: this should be static?
679 int vpci_init_device(struct vm_device * dev) {
680 struct pci_internal *pci_state = NULL;
683 PrintDebug("vpci: init_device\n");
685 pci_state = (struct pci_internal *)dev->private_data;
687 init_pci_internal(pci_state);
689 init_fake_device(pci_state); //Chang
691 for (i = 0; i < 4; i++){
692 v3_dev_hook_io(dev, PCI_CONFIG_ADDRESS + i, &vpci_addrport_read, &vpci_addrport_write);
693 v3_dev_hook_io(dev, PCI_CONFIG_DATA + i, &vpci_dataport_read, &vpci_dataport_write);
699 // TODO: This should be static
700 int vpci_deinit_device(struct vm_device * dev) {
703 for (i = 0; i < 4; i++){
704 v3_dev_unhook_io(dev, PCI_CONFIG_ADDRESS + i);
705 v3_dev_unhook_io(dev, PCI_CONFIG_DATA + i);
708 vpci_reset_device(dev);
712 static struct vm_device_ops dev_ops = {
713 .init = vpci_init_device,
714 .deinit = vpci_deinit_device,
715 .reset = vpci_reset_device,
716 .start = vpci_start_device,
717 .stop = vpci_stop_device,
720 struct vm_device * v3_create_vpci() {
721 struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
723 PrintDebug("PCI internal at %p\n",(void *)pci_state);
725 struct vm_device * device = v3_create_device("PCI", &dev_ops, pci_state);