Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added DMA write functionality to ide harddisk
[palacios.git] / palacios / src / devices / vpci.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
14  *
15  * Author:  Lei Xia <lxia@northwestern.edu>
16  *          Chang Seok Bae <jhuell@gmail.com>
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */ 
21  
22 /*
23  * Virtual PCI
24  */
25  
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>
32
33
34 // TODO: Add Debugging directives to Makefiles
35
36 #ifndef DEBUG_PCI
37 #undef PrintDebug
38 #define PrintDebug(fmt, args...)
39 #endif
40
41 #define NUM_DEVICES 255
42 #define NUM_BUS 1
43
44 struct pci_bus {
45     int bus_num;
46     struct pci_device * device_list[NUM_DEVICES];
47     struct pci_bus * next;
48     struct vm_device * vm_dev;
49 };
50
51 struct pci_internal {
52     uint_t     num_buses;
53     uint32_t   config_address;   //current value of corresponding to configure port
54     struct pci_bus * bus_list[NUM_BUS];
55 };
56
57
58 struct port_ops_map {
59     uint32_t port;
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);
62 };
63
64
65 //Lei
66 struct pci_device * get_device (struct vm_device * vmdev, uchar_t bus_no, uchar_t devfn_no)
67 {
68     struct pci_device * dev = NULL;
69     struct pci_bus * bus = NULL;
70     struct pci_internal * pci_state = NULL;
71     
72     if ((bus_no >= NUM_BUS) || (devfn_no >= NUM_DEVICES)) {
73         return dev;
74     }
75     
76     pci_state = (struct pci_internal *)vmdev->private_data;
77     bus = pci_state->bus_list[bus_no];
78     
79     if (bus != NULL) {
80         dev = bus->device_list[devfn_no];
81     }
82     
83     return dev;
84 }
85
86
87 //Lei
88 // TODO: Should this be static? If not it should be v3_pci_...
89 int pci_hook_ports(struct pci_device * dev, 
90                    int reg_num, 
91                    int num_ports, 
92                    port_read_fn * port_reads[], 
93                    port_write_fn * port_writes[]) {
94     struct pci_ioregion * ioreg = NULL;
95     
96     ioreg = dev->ioregion[reg_num];
97     
98     if (ioreg == NULL) {
99         PrintError("No Device registered at ioregion %d\n", reg_num);
100         return -1;
101     }
102     
103     if (ioreg->size != num_ports) {
104         // TODO: What does this error mean?
105         PrintError("IO registration size mismatch\n");
106         return -1;
107     }
108     
109     ioreg->port_reads = port_reads;
110     ioreg->port_writes = port_writes;
111     
112     return 0;
113 }
114
115 //Lei
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) {
119     int i = 0;
120     
121     if (ioreg->addr == -1) {
122         // TODO: Is this an error?
123         return;
124     }
125     
126     if (ioreg->type != PCI_ADDRESS_SPACE_IO) {
127         // TODO: is this an error?
128         return;
129     }
130     
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]);
135         }
136     }
137     
138     // TODO: return 0;
139 }
140
141
142 //Chang
143 static uint32_t vpci_read_config(struct pci_device * pdev, uchar_t offset, int len) {
144     uint32_t val = 0;
145     
146     switch(len) {
147         case 4:
148             if (offset <= 0xfc) {
149                 val = *(uint32_t *)(&(pdev->config) + offset);
150                 break;
151             }
152             // TODO: Shouldn't this break unconditionally?
153         case 2:
154             if (offset <= 0xfe) {
155                 val = *(uint16_t *)(&(pdev->config) + offset);
156                 break;
157             }
158             // TODO: Shouldn't this break unconditionally?
159         case 1:
160             val = *(uint8_t *)(&(pdev->config) + offset);
161             break;
162         default:
163             break;                      
164     }
165     
166     return val;
167 }
168
169 //Lei
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;
173     
174     dev_config = (uchar_t *)&(dev->config);
175     dev_config += offset;
176     
177
178     // TODO: cast 'val' instead of masking it
179     switch(len) {
180         case 1:
181             *dev_config = (val & 0xff);
182             break;
183         case 2:
184             *(uint16_t *)dev_config = (val & 0xffff);
185             break;
186         case 4:
187             *(uint32_t *)dev_config = val;
188             break;
189         default:
190             PrintDebug("pci_write_config: wrong length %d\n", len);
191             break;
192     }
193 }
194
195 //Lei
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;
199     int irq_line = 0;
200     
201     vm = pdev->bus->vm_dev->vm;
202     irq_line = pdev->config.intr_line;
203     
204     v3_raise_irq(vm, irq_line);
205 }
206
207 #if 0
208 //Chang
209 static void pci_write_config(struct pci_device *dev, uint32_t address, uint32_t val, int len) 
210 {
211     int can_write, i, reg_num;
212     uint32_t addr;
213     
214     if(len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || //base address registers
215                     (address >= 0x30 && address < 0x34))) { //expansion rom base address
216         
217         struct pci_ioregion * ioregion;
218         if(address >= 0x30) {
219             reg_num = PCI_ROM_SLOT;
220         }else {
221             reg_num = ((address - 0x10) >>2); 
222         }
223         
224         ioregion = &dev->io_regions[reg_num];
225         
226         if(ioregion->size == 0) {//default config
227             
228             addr = address;
229             for (i=0;i<len;i++) {
230                 switch(*(uint8_t *)(&(dev->config)+0x0e)) {
231                     case 0x00:
232                     case 0x80:
233                         switch(addr) {
234                             case 0x00:
235                             case 0x01:
236                             case 0x02:
237                             case 0x03:
238                             case 0x08:
239                             case 0x09:
240                             case 0x0a:
241                             case 0x0b:
242                             case 0x0e:
243                             case 0x10 ... 0x27:
244                             case 0x3d:
245                                 can_write = 0;
246                                 break;
247                             default:
248                                 can_write = 1;
249                                 break;
250                         }
251                         break;  
252                     default:
253                     case 0x01:
254                         switch(addr) {
255                             case 0x00:
256                             case 0x01:
257                             case 0x02:
258                             case 0x03:
259                             case 0x08:
260                             case 0x09:
261                             case 0x0a:
262                             case 0x0b:
263                             case 0x0e:
264                             case 0x38 ... 0x3b: 
265                             case 0x3d:
266                                 can_write = 0;
267                                 break;
268                             default:
269                                 can_write = 1;
270                                 break;
271                         }
272                         break;
273                 }
274                 if (can_write) {
275                     *(uint32_t *)(&(dev->config)+addr) = val;
276                 }
277                 if(++addr > 0xff) break;
278                 val >>= 8;
279             }
280             
281             return;
282             
283         }else {
284             if(reg_num== PCI_ROM_SLOT) {
285                 val &= (~(ioregion->size -1 )) | 1;
286             } else {
287                 val &= ~(ioregion->size -1);
288                 val |= ioregion->type;
289             }
290         }
291         //pci_update_mappings();
292         return;
293     }
294 }
295 #endif
296
297 /* -1 for dev_num means auto assign */
298 // TODO: Should be v3_pci_register_device
299 struct pci_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))  {
304   
305     struct pci_device * pci_dev = NULL;
306     int found = 0;
307     int i = 0;
308     
309     if (dev_num < 0) {
310         for (dev_num = 0; dev_num < 256; dev_num++) {
311             if (!bus->device_list[dev_num]) { 
312                 found = 1;
313                 break;
314             }
315         }
316     }
317     
318     if (found == 0) {
319         return NULL;
320     }
321     
322     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
323     
324     if (pci_dev == NULL) {
325         return NULL;
326     }
327     
328     pci_dev->bus = bus;
329     pci_dev->dev_num = dev_num;
330     pci_dev->irqline = -1;
331     
332     strcpy(pci_dev->name, name);
333     
334     if (config_read != NULL) {
335         pci_dev->ops.config_read = config_read;
336     } else {
337         pci_dev->ops.config_read = &vpci_read_config;
338     }
339     
340     if (config_write != NULL) {
341         pci_dev->ops.config_write = config_write;
342     } else {
343         pci_dev->ops.config_write = &vpci_write_config;
344     }
345     
346     
347     pci_dev->ops.raise_irq = &vpci_raise_irq;
348     
349     for (i = 0; i < PCI_IO_REGIONS; i++) {
350         pci_dev->ioregion[i] = NULL;
351     }  
352     
353     //config space initiate
354     
355     bus->device_list[dev_num] = pci_dev;
356     
357     return pci_dev;
358 }
359
360 //Chang
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
364     
365     //int i=0;
366     struct pci_device *fake_device;
367     
368     //fake dev
369     fake_device = pci_register_device(pci_state->bus_list[0],
370                                       "fake ide", sizeof(struct pci_device),
371                                       -1,
372                                       NULL,NULL);
373     
374     if (!fake_device) {
375         return;
376     }
377     
378     /*
379       intel, ide ctroller
380       vendor id:0x8086
381       device id: 0x1222
382     */
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;
392     
393     //base address
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; 
400     
401     //fake dev end
402     
403     //need to register io regions
404     
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;
408     
409     return;
410 }
411
412
413
414 // Lei
415 /* if region_num == -1, assign automatically
416  */
417 //TODO: Should be v3_pci_register...
418 int 
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) {
422     int found = 0;
423     struct pci_ioregion * region = NULL;
424     
425     if (region_num < 0) {
426         for (region_num = 0; region_num < 256; region_num++) {
427             if (pci_dev->ioregion[region_num] == NULL) { 
428                 found = 1;
429                 break;
430             }
431         }
432     }
433     
434     if (found == 0) { 
435         return -1;
436     }
437     
438     if (pci_dev->ioregion[region_num] != NULL) {
439         return -1;
440     }
441     
442     region = (struct pci_ioregion *)V3_Malloc(sizeof(struct pci_ioregion));
443     if (region == NULL) {
444         return -1;
445     }
446     
447     region->addr = -1;
448     region->reg_num = region_num;
449     region->size = size;
450     region->mapped_size = -1;
451     region->type = type;
452     region->map_func = map_func;
453     region->port_reads = NULL;
454     region->port_writes = NULL;
455     
456     pci_dev->ioregion[region_num] = region;
457     
458     return region_num;
459 }
460
461
462
463
464 //Chang
465 static int 
466 vpci_addrport_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
467     
468     struct pci_internal *pci_state = (struct pci_internal *)dev->private_data;
469     int start = 0;
470     uchar_t * addr = NULL;
471     int i = 0;
472     
473     start = port - PCI_CONFIG_ADDRESS;
474     
475     if ((length + start) > 4) {
476         //cross port boundary, is memory mapped IO style
477         return length;   
478     }
479     
480     addr = (uchar_t *)&(pci_state->config_address);
481     addr += start;
482     
483     memcpy(dst, addr, length);    //be careful, PCI is little endian
484     
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]);
488     }
489     PrintDebug("\n");
490     
491     return length;
492 }
493
494 //Lei
495 static int 
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;
498     int start = 0;
499     uchar_t * addr = NULL;
500     int i = 0;
501     
502     start = port - PCI_CONFIG_ADDRESS;
503     
504     if ((length + start) > 4){
505         //cross port boundary, is memory mapped IO style
506         return length;
507     }
508     
509     addr = (uchar_t *)&(pci_state->config_address);
510     addr += start;
511     memcpy(addr, src, length);    //be careful, PCI is little endian
512     
513     PrintDebug("PCI Address: writing %d bytes to port %x: 0x", length, port);
514     
515     for (i = (length - 1); i >= 0; i--) { 
516         PrintDebug("%.2x", ((uchar_t*)src)[i]);
517     }
518     PrintDebug("\n");
519     
520     return length;
521 }
522
523 //Chang
524 static int 
525 vpci_dataport_read(ushort_t port, void * dst, uint_t length, struct vm_device * vmdev) {
526     /*
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]
532     */
533     
534     struct pci_internal * pci_state = NULL;
535     struct pci_device * pci_dev = NULL;
536     int bus_num = 0;
537     int devfn = 0;
538     int offset = 0;
539     uint32_t address = 0;
540     uint32_t val = 0;
541     int i = 0;
542     
543     if (length > 4){
544         PrintDebug("Read more than 4 bytes from port 0x%x\n", (int)port);
545         return length;
546     }
547     
548     pci_state = (struct pci_internal *)vmdev->private_data;
549     
550     address = pci_state->config_address;
551     offset = address & 0xff;
552     devfn = (address >> 8) & 0xff;
553     bus_num = (address >> 16) & 0xff; 
554     
555     pci_dev = get_device(vmdev, bus_num, devfn);
556     
557     if (pci_dev == NULL) {
558         val = 0xffffffff;
559     } else {
560         val = 0x0;
561         val = pci_dev->ops.config_read(pci_dev, offset, length);
562     }
563     
564     memcpy(dst, &val, length);
565     
566     PrintDebug("PCI Data: reading %d bytes from port %x: 0x", length, port);
567     
568     for (i = (length - 1); i >= 0; i--) { 
569         PrintDebug("%.2x", ((uchar_t*)dst)[i]);
570     }
571     PrintDebug("\n");
572     
573     return length;
574 }
575
576 static int 
577 vpci_dataport_write(ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
578     struct pci_internal * pci_state = NULL;
579     uint32_t val = 0;
580     uint32_t address = 0;
581     struct pci_device * pdev = NULL;
582     // TODO: Why are these 'char', but the read variables 'int'
583     char bus = 0; 
584     char devfn = 0; 
585     char offset = 0;
586     int i = 0;
587     
588     if (length > 4){
589         PrintDebug("Write more than 4 bytes to port 0x%x\n", (int)port);
590         return length;
591     }
592     
593     pci_state = (struct pci_internal *)vmdev->private_data;
594     
595     address = pci_state->config_address;
596     offset = address & 0xff;
597     devfn = (address >> 8) & 0xff;
598     bus = (address >> 16) & 0xff; 
599     
600     pdev = get_device(vmdev, bus, devfn);
601     
602     if (pdev == NULL){
603         // not sure what to do here, just ignore it
604         return length;
605     }
606     
607     val = 0x0;
608     memcpy(&val, src, length);
609     
610     pdev->ops.config_write(pdev, offset, val, length);
611     
612     PrintDebug("PCI Data: writing %d bytes to port %x: 0x", length, port);
613     
614     for (i = (length - 1); i >= 0; i--) { 
615         PrintDebug("%.2x", ((uchar_t*)src)[i]);
616     }
617     PrintDebug("\n");
618     
619     return length;
620 }
621
622
623 //Lei
624 static void init_pci_bus(struct pci_internal * pci_state) {
625     int i = 0;
626     struct pci_bus * first_bus = NULL;
627     
628     first_bus = (struct pci_bus *)V3_Malloc(sizeof(struct pci_bus));
629     
630     first_bus->bus_num = 0;  //?? not sure
631     
632     for (i = 0; i < NUM_DEVICES; i++) {
633         first_bus->device_list[i] = NULL;
634     }
635     
636     first_bus->next = NULL;
637     
638     pci_state->num_buses = 1;
639     pci_state->bus_list[0] = first_bus;
640     
641     for (i = 1; i < NUM_BUS; i++) {
642         pci_state->bus_list[i] = NULL;
643     }
644 }
645
646 //Lei
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);
650 }
651
652
653 static int vpci_set_defaults(struct vm_device * dev) {
654     PrintDebug("vpci: set defaults\n");
655     return 0;
656 }
657
658
659 static int vpci_reset_device(struct vm_device * dev) {
660     PrintDebug("vpci: reset device\n");
661     
662     vpci_set_defaults(dev);
663     
664     return 0;
665 }
666
667
668 static int vpci_start_device(struct vm_device * dev) {
669     PrintDebug("vpci: start device\n");
670     return 0;
671 }
672
673
674 // TODO: This should be static
675 int vpci_stop_device(struct vm_device * dev) {
676     PrintDebug("vpci: stop device\n");  
677     return 0;
678 }
679
680 // TODO: this should be static?
681 int vpci_init_device(struct vm_device * dev) {
682     struct pci_internal *pci_state = NULL;
683     int i = 0;
684     
685     PrintDebug("vpci: init_device\n");
686     
687     pci_state = (struct pci_internal *)dev->private_data;
688     
689     init_pci_internal(pci_state);
690     
691     init_fake_device(pci_state); //Chang
692     
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);
696     }
697     
698     return 0;
699 }
700
701 // TODO: This should be static
702 int vpci_deinit_device(struct vm_device * dev) {
703     int i = 0;
704     
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);
708     }
709     
710     vpci_reset_device(dev);
711     return 0;
712 }
713
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,
720 };
721
722 struct vm_device * v3_create_vpci() {
723     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
724     
725     PrintDebug("PCI internal at %p\n",(void *)pci_state);
726     
727     struct vm_device * device = v3_create_device("PCI", &dev_ops, pci_state);
728     
729     return device;
730 }