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>
38 #define PrintDebug(fmt, args...)
41 #define NUM_DEVICES 255
46 struct pci_device *device_list[NUM_DEVICES];
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;
72 if (bus_no >= NUM_BUS || devfn_no >= NUM_DEVICES)
75 pci_state = (struct pci_internal *)vmdev->private_data;
76 bus = pci_state->bus_list[bus_no];
78 dev = bus->device_list[devfn_no];
85 int pci_hook_ports(struct pci_device *dev,
88 port_read_fn *port_reads[],
89 port_write_fn *port_writes[])
91 struct pci_ioregion *ioreg;
93 ioreg = dev->ioregion[reg_num];
95 if (!ioreg) return -1;
97 if (ioreg->size != num_ports) return -1;
99 ioreg->port_reads = port_reads;
100 ioreg->port_writes = port_writes;
106 static inline void hook_ioregion(struct pci_device *dev, struct pci_ioregion *ioreg)
110 if (ioreg->addr == -1) return;
111 if (ioreg->type == PCI_ADDRESS_SPACE_IO){
112 for (i = 0; i < ioreg->size; i++)
113 if (ioreg->port_reads[i] || ioreg->port_writes[i])
114 v3_dev_hook_io(dev->bus->vm_dev,
116 ioreg->port_reads[i],
117 ioreg->port_writes[i]);
124 static uint32_t vpci_read_config(struct pci_device *pdev, uchar_t offset, int len)
131 val = *(uint32_t *)(&(pdev->config)+offset);
136 val = *(uint16_t *)(&(pdev->config)+offset);
140 val = *(uint8_t *)(&(pdev->config)+offset);
150 static void vpci_write_config(struct pci_device *dev, uchar_t offset, uint32_t val, int len)
154 dev_config = (uchar_t *)&(dev->config);
155 dev_config += offset;
159 *dev_config = val & 0xff;
162 *((uint16_t *)dev_config) = val & 0xffff;
165 *((uint32_t *)dev_config) = val;
168 PrintDebug("pci_write_config: wrong length %d\n", len);
174 void vpci_raise_irq(struct pci_device *pdev, void *data)
176 struct guest_info *vm;
179 vm = pdev->bus->vm_dev->vm;
180 irq_line = pdev->config.intr_line;
181 v3_raise_irq(vm, irq_line);
186 static void pci_write_config(struct pci_device *dev, uint32_t address, uint32_t val, int len)
188 int can_write, i, reg_num;
191 if(len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || //base address registers
192 (address >= 0x30 && address < 0x34))) { //expansion rom base address
194 struct pci_ioregion * ioregion;
195 if(address >= 0x30) {
196 reg_num = PCI_ROM_SLOT;
198 reg_num = ((address - 0x10) >>2);
201 ioregion = &dev->io_regions[reg_num];
203 if(ioregion->size == 0) {//default config
206 for (i=0;i<len;i++) {
207 switch(*(uint8_t *)(&(dev->config)+0x0e)) {
252 *(uint32_t *)(&(dev->config)+addr) = val;
254 if(++addr > 0xff) break;
261 if(reg_num== PCI_ROM_SLOT) {
262 val &= (~(ioregion->size -1 )) | 1;
264 val &= ~(ioregion->size -1);
265 val |= ioregion->type;
268 //pci_update_mappings();
274 /* -1 for dev_num means auto assign */
276 pci_register_device(struct pci_bus *bus, const char *name,
277 int instance_size, int dev_num,
278 uint32_t (*config_read)(struct pci_device *pci_dev, uchar_t addr, int len),
279 void (*config_write)(struct pci_device *pci_dev, uchar_t addr, uint32_t val, int len))
282 struct pci_device * pci_dev;
287 for(dev_num = 0; dev_num < 256; dev_num++) {
288 if(!bus->device_list[dev_num]) {
294 if (found == 0) return NULL;
296 pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
298 if(!pci_dev) return NULL;
301 pci_dev->dev_num = dev_num;
302 pci_dev->irqline = -1;
304 strcpy(pci_dev->name,name);
307 pci_dev->ops.config_read = config_read;
309 pci_dev->ops.config_read=&vpci_read_config;
311 pci_dev->ops.config_write = config_write;
313 pci_dev->ops.config_write=&vpci_write_config;
315 pci_dev->ops.raise_irq = &vpci_raise_irq;
317 for (i = 0; i < PCI_IO_REGIONS; i++)
318 pci_dev->ioregion[i] = NULL;
320 //config space initiate
322 bus->device_list[dev_num] = pci_dev;
328 static void init_fake_device(struct pci_internal *pci_state)
330 //maybe need table to map device, but just
331 //bus_num=0, dev_num=0
334 struct pci_device *fake_device;
337 fake_device = pci_register_device(pci_state->bus_list[0],
338 "fake ide", sizeof(struct pci_device),
342 if (!fake_device) return;
349 fake_device->config.vendor_id = 0x8086;
350 fake_device->config.device_id = 0x1222;
351 fake_device->config.command = 0x0;
352 fake_device->config.status = 0x0;
353 fake_device->config.revision = 0x07;
354 fake_device->config.class_code[0] = 0x1;
355 fake_device->config.class_code[1] = 0x1;
356 fake_device->config.class_code[2] = 0x1;
357 fake_device->config.header_type = 0x0;
359 fake_device->config.BAR[0] = 0x1F0;
360 fake_device->config.BAR[1] = 0;
361 fake_device->config.BAR[2] = 0;
362 fake_device->config.BAR[3] = 0;
363 fake_device->config.BAR[4] = 0;
364 fake_device->config.BAR[5] = 0;
368 //need to register io regions
370 pci_state->bus_list[0]->device_list[0] = fake_device;
371 fake_device->bus = pci_state->bus_list[0];
372 fake_device->next = NULL;
380 /* if region_num == -1, assign automatically
383 pci_register_io_region(struct pci_device *pci_dev, int region_num,
384 uint32_t size, int type,
385 pci_mapioregion_fn *map_func)
388 struct pci_ioregion *region;
391 for(region_num = 0; region_num < 256; region_num++) {
392 if(!pci_dev->ioregion[region_num]) {
398 if (found == 0) return -1;
399 if (pci_dev->ioregion[region_num] != NULL)
402 region = (struct pci_ioregion *)V3_Malloc(sizeof(struct pci_ioregion));
403 if (!region) return -1;
406 region->reg_num = region_num;
408 region->mapped_size = -1;
410 region->map_func = map_func;
411 region->port_reads = NULL;
412 region->port_writes = NULL;
414 pci_dev->ioregion[region_num] = region;
424 vpci_addrport_read(ushort_t port,
427 struct vm_device *dev)
430 struct pci_internal *pci_state = (struct pci_internal *)dev->private_data;
435 start = port - PCI_CONFIG_ADDRESS;
436 if (length + start > 4){
437 return length; //cross port boundary, is memory mapped IO style
439 addr = (uchar_t *)&(pci_state->config_address);
441 memcpy(dst, addr, length); //be careful, PCI is little endian
443 PrintDebug("PCI Address: reading %d bytes from port %x: 0x", length, port);
445 for (i = length - 1; i >= 0; i--) {
446 PrintDebug("%.2x", ((uchar_t*)dst)[i]);
454 vpci_addrport_write(ushort_t port,
457 struct vm_device *dev)
459 struct pci_internal *pci_state = (struct pci_internal *)dev->private_data;
464 start = port - PCI_CONFIG_ADDRESS;
465 if (length + start > 4){
466 return length; //cross port boundary, is memory mapped IO style
468 addr = (uchar_t *)&(pci_state->config_address);
470 memcpy(addr, src, length); //be careful, PCI is little endian
472 PrintDebug("PCI Address: writing %d bytes to port %x: 0x", length, port);
474 for (i = length - 1; i >= 0; i--) {
475 PrintDebug("%.2x", ((uchar_t*)src)[i]);
483 vpci_dataport_read(ushort_t port,
486 struct vm_device *vmdev)
489 decode address of config_address
490 bus num = config_address[23:16]
491 device num = config_address[15:11]
492 func num = config_address[10:08]
493 reg num = config_address[07:02]
496 struct pci_internal * pci_state;
497 struct pci_device * pci_dev = NULL;
498 int bus_num, devfn, offset;
504 PrintDebug("Read more than 4 bytes from port 0x%x\n", (int)port);
508 pci_state = (struct pci_internal *)vmdev->private_data;
509 address = pci_state->config_address;
510 offset = address & 0xff;
511 devfn = (address >> 8) & 0xff;
512 bus_num = (address >> 16) & 0xff;
514 pci_dev = get_device(vmdev, bus_num, devfn);
520 val = pci_dev->ops.config_read(pci_dev, offset, length);
522 memcpy(dst,&val,length);
524 PrintDebug("PCI Data: reading %d bytes from port %x: 0x", length, port);
526 for (i = length - 1; i >= 0; i--) {
527 PrintDebug("%.2x", ((uchar_t*)dst)[i]);
536 vpci_dataport_write(ushort_t port,
539 struct vm_device *vmdev)
541 struct pci_internal *pci_state;
544 struct pci_device *pdev;
545 char bus, devfn, offset;
549 PrintDebug("Write more than 4 bytes to port 0x%x\n", (int)port);
553 pci_state = (struct pci_internal *)vmdev->private_data;
554 address = pci_state->config_address;
555 offset = address & 0xff;
556 devfn = (address >> 8) & 0xff;
557 bus = (address >> 16) & 0xff;
559 pdev = get_device(vmdev, bus, devfn);
561 // not sure what to do here, just ignore it
566 memcpy(&val, src, length);
568 pdev->ops.config_write(pdev, offset, val, length);
570 PrintDebug("PCI Data: writing %d bytes to port %x: 0x", length, port);
572 for (i = length - 1; i >= 0; i--) {
573 PrintDebug("%.2x", ((uchar_t*)src)[i]);
582 static void init_pci_bus(struct pci_internal *pci_state)
585 struct pci_bus *first_bus;
587 first_bus = (struct pci_bus *)V3_Malloc(sizeof(struct pci_bus));
589 first_bus->bus_num = 0; //?? not sure
590 for (i = 0; i < NUM_DEVICES; i++)
591 first_bus->device_list[i] = NULL;
592 first_bus->next = NULL;
594 pci_state->num_buses = 1;
595 pci_state->bus_list[0] = first_bus;
596 for (i=1; i<NUM_BUS; i++)
597 pci_state->bus_list[i] = NULL;
601 static void init_pci_internal(struct pci_internal *pci_state)
604 pci_state->config_address = 0x00; //Not sure????
605 init_pci_bus(pci_state);
610 static int vpci_set_defaults(struct vm_device *dev)
612 PrintDebug("vpci: set defaults\n");
617 static int vpci_reset_device(struct vm_device * dev)
620 PrintDebug("vpci: reset device\n");
622 vpci_set_defaults(dev);
628 static int vpci_start_device(struct vm_device *dev)
630 PrintDebug("vpci: start device\n");
636 int vpci_stop_device(struct vm_device *dev)
638 PrintDebug("vpci: stop device\n");
644 int vpci_init_device(struct vm_device * dev)
646 struct pci_internal *pci_state;
649 PrintDebug("vpci: init_device\n");
651 pci_state = (struct pci_internal *)dev->private_data;
653 init_pci_internal(pci_state);
655 init_fake_device(pci_state); //Chang
657 for (i = 0; i<4; i++){
658 v3_dev_hook_io(dev, PCI_CONFIG_ADDRESS + i, &vpci_addrport_read, &vpci_addrport_write);
659 v3_dev_hook_io(dev, PCI_CONFIG_DATA + i, &vpci_dataport_read, &vpci_dataport_write);
666 int vpci_deinit_device(struct vm_device *dev)
670 for (i = 0; i<4; i++){
671 v3_dev_unhook_io(dev, PCI_CONFIG_ADDRESS + i);
672 v3_dev_unhook_io(dev, PCI_CONFIG_DATA + i);
675 vpci_reset_device(dev);
679 static struct vm_device_ops dev_ops = {
680 .init = vpci_init_device,
681 .deinit = vpci_deinit_device,
682 .reset = vpci_reset_device,
683 .start = vpci_start_device,
684 .stop = vpci_stop_device,
687 struct vm_device *v3_create_vpci() {
688 struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
690 PrintDebug("PCI internal at %x\n",(int)(long)pci_state);
691 struct vm_device *device = v3_create_device("PCI", &dev_ops, pci_state);