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.


caca890cccf74f2f4a1a9b1f1cdfc8e0d2f25c9b
[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     switch(len) {
178         case 1:
179             *dev_config = (val & 0xff);
180             break;
181         case 2:
182             *(uint16_t *)dev_config = (val & 0xffff);
183             break;
184         case 4:
185             *(uint32_t *)dev_config = val;
186             break;
187         default:
188             PrintDebug("pci_write_config: wrong length %d\n", len);
189             break;
190     }
191 }
192
193 //Lei
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;
197     int irq_line = 0;
198     
199     vm = pdev->bus->vm_dev->vm;
200     irq_line = pdev->config.intr_line;
201     
202     v3_raise_irq(vm, irq_line);
203 }
204
205 #if 0
206 //Chang
207 static void pci_write_config(struct pci_device *dev, uint32_t address, uint32_t val, int len) 
208 {
209     int can_write, i, reg_num;
210     uint32_t addr;
211     
212     if(len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || //base address registers
213                     (address >= 0x30 && address < 0x34))) { //expansion rom base address
214         
215         struct pci_ioregion * ioregion;
216         if(address >= 0x30) {
217             reg_num = PCI_ROM_SLOT;
218         }else {
219             reg_num = ((address - 0x10) >>2); 
220         }
221         
222         ioregion = &dev->io_regions[reg_num];
223         
224         if(ioregion->size == 0) {//default config
225             
226             addr = address;
227             for (i=0;i<len;i++) {
228                 switch(*(uint8_t *)(&(dev->config)+0x0e)) {
229                     case 0x00:
230                     case 0x80:
231                         switch(addr) {
232                             case 0x00:
233                             case 0x01:
234                             case 0x02:
235                             case 0x03:
236                             case 0x08:
237                             case 0x09:
238                             case 0x0a:
239                             case 0x0b:
240                             case 0x0e:
241                             case 0x10 ... 0x27:
242                             case 0x3d:
243                                 can_write = 0;
244                                 break;
245                             default:
246                                 can_write = 1;
247                                 break;
248                         }
249                         break;  
250                     default:
251                     case 0x01:
252                         switch(addr) {
253                             case 0x00:
254                             case 0x01:
255                             case 0x02:
256                             case 0x03:
257                             case 0x08:
258                             case 0x09:
259                             case 0x0a:
260                             case 0x0b:
261                             case 0x0e:
262                             case 0x38 ... 0x3b: 
263                             case 0x3d:
264                                 can_write = 0;
265                                 break;
266                             default:
267                                 can_write = 1;
268                                 break;
269                         }
270                         break;
271                 }
272                 if (can_write) {
273                     *(uint32_t *)(&(dev->config)+addr) = val;
274                 }
275                 if(++addr > 0xff) break;
276                 val >>= 8;
277             }
278             
279             return;
280             
281         }else {
282             if(reg_num== PCI_ROM_SLOT) {
283                 val &= (~(ioregion->size -1 )) | 1;
284             } else {
285                 val &= ~(ioregion->size -1);
286                 val |= ioregion->type;
287             }
288         }
289         //pci_update_mappings();
290         return;
291     }
292 }
293 #endif
294
295 /* -1 for dev_num means auto assign */
296 // TODO: Should be v3_pci_register_device
297 struct pci_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))  {
302   
303     struct pci_device * pci_dev = NULL;
304     int found = 0;
305     int i = 0;
306     
307     if (dev_num < 0) {
308         for (dev_num = 0; dev_num < 256; dev_num++) {
309             if (!bus->device_list[dev_num]) { 
310                 found = 1;
311                 break;
312             }
313         }
314     }
315     
316     if (found == 0) {
317         return NULL;
318     }
319     
320     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
321     
322     if (pci_dev == NULL) {
323         return NULL;
324     }
325     
326     pci_dev->bus = bus;
327     pci_dev->dev_num = dev_num;
328     pci_dev->irqline = -1;
329     
330     strcpy(pci_dev->name, name);
331     
332     if (config_read != NULL) {
333         pci_dev->ops.config_read = config_read;
334     } else {
335         pci_dev->ops.config_read = &vpci_read_config;
336     }
337     
338     if (config_write != NULL) {
339         pci_dev->ops.config_write = config_write;
340     } else {
341         pci_dev->ops.config_write = &vpci_write_config;
342     }
343     
344     
345     pci_dev->ops.raise_irq = &vpci_raise_irq;
346     
347     for (i = 0; i < PCI_IO_REGIONS; i++) {
348         pci_dev->ioregion[i] = NULL;
349     }  
350     
351     //config space initiate
352     
353     bus->device_list[dev_num] = pci_dev;
354     
355     return pci_dev;
356 }
357
358 //Chang
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
362     
363     //int i=0;
364     struct pci_device *fake_device;
365     
366     //fake dev
367     fake_device = pci_register_device(pci_state->bus_list[0],
368                                       "fake ide", sizeof(struct pci_device),
369                                       -1,
370                                       NULL,NULL);
371     
372     if (!fake_device) {
373         return;
374     }
375     
376     /*
377       intel, ide ctroller
378       vendor id:0x8086
379       device id: 0x1222
380     */
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;
390     
391     //base address
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; 
398     
399     //fake dev end
400     
401     //need to register io regions
402     
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;
406     
407     return;
408 }
409
410
411
412 // Lei
413 /* if region_num == -1, assign automatically
414  */
415 //TODO: Should be v3_pci_register...
416 int 
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) {
420     int found = 0;
421     struct pci_ioregion * region = NULL;
422     
423     if (region_num < 0) {
424         for (region_num = 0; region_num < 256; region_num++) {
425             if (pci_dev->ioregion[region_num] == NULL) { 
426                 found = 1;
427                 break;
428             }
429         }
430     }
431     
432     if (found == 0) { 
433         return -1;
434     }
435     
436     if (pci_dev->ioregion[region_num] != NULL) {
437         return -1;
438     }
439     
440     region = (struct pci_ioregion *)V3_Malloc(sizeof(struct pci_ioregion));
441     if (region == NULL) {
442         return -1;
443     }
444     
445     region->addr = -1;
446     region->reg_num = region_num;
447     region->size = size;
448     region->mapped_size = -1;
449     region->type = type;
450     region->map_func = map_func;
451     region->port_reads = NULL;
452     region->port_writes = NULL;
453     
454     pci_dev->ioregion[region_num] = region;
455     
456     return region_num;
457 }
458
459
460
461
462 //Chang
463 static int 
464 vpci_addrport_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
465     
466     struct pci_internal *pci_state = (struct pci_internal *)dev->private_data;
467     int start = 0;
468     uchar_t * addr = NULL;
469     int i = 0;
470     
471     start = port - PCI_CONFIG_ADDRESS;
472     
473     if ((length + start) > 4) {
474         //cross port boundary, is memory mapped IO style
475         return length;   
476     }
477     
478     addr = (uchar_t *)&(pci_state->config_address);
479     addr += start;
480     
481     memcpy(dst, addr, length);    //be careful, PCI is little endian
482     
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]);
486     }
487     PrintDebug("\n");
488     
489     return length;
490 }
491
492 //Lei
493 static int 
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;
496     int start = 0;
497     uchar_t * addr = NULL;
498     int i = 0;
499     
500     start = port - PCI_CONFIG_ADDRESS;
501     
502     if ((length + start) > 4){
503         //cross port boundary, is memory mapped IO style
504         return length;
505     }
506     
507     addr = (uchar_t *)&(pci_state->config_address);
508     addr += start;
509     memcpy(addr, src, length);    //be careful, PCI is little endian
510     
511     PrintDebug("PCI Address: writing %d bytes to port %x: 0x", length, port);
512     
513     for (i = (length - 1); i >= 0; i--) { 
514         PrintDebug("%.2x", ((uchar_t*)src)[i]);
515     }
516     PrintDebug("\n");
517     
518     return length;
519 }
520
521 //Chang
522 static int 
523 vpci_dataport_read(ushort_t port, void * dst, uint_t length, struct vm_device * vmdev) {
524     /*
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]
530     */
531     
532     struct pci_internal * pci_state = NULL;
533     struct pci_device * pci_dev = NULL;
534     int bus_num = 0;
535     int devfn = 0;
536     int offset = 0;
537     uint32_t address = 0;
538     uint32_t val = 0;
539     int i = 0;
540     
541     if (length > 4){
542         PrintDebug("Read more than 4 bytes from port 0x%x\n", (int)port);
543         return length;
544     }
545     
546     pci_state = (struct pci_internal *)vmdev->private_data;
547     
548     address = pci_state->config_address;
549     offset = address & 0xff;
550     devfn = (address >> 8) & 0xff;
551     bus_num = (address >> 16) & 0xff; 
552     
553     pci_dev = get_device(vmdev, bus_num, devfn);
554     
555     if (pci_dev == NULL) {
556         val = 0xffffffff;
557     } else {
558         val = 0x0;
559         val = pci_dev->ops.config_read(pci_dev, offset, length);
560     }
561     
562     memcpy(dst, &val, length);
563     
564     PrintDebug("PCI Data: reading %d bytes from port %x: 0x", length, port);
565     
566     for (i = (length - 1); i >= 0; i--) { 
567         PrintDebug("%.2x", ((uchar_t*)dst)[i]);
568     }
569     PrintDebug("\n");
570     
571     return length;
572 }
573
574 static int 
575 vpci_dataport_write(ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
576     struct pci_internal * pci_state = NULL;
577     uint32_t val = 0;
578     uint32_t address = 0;
579     struct pci_device * pdev = NULL;
580     // TODO: Why are these 'char', but the read variables 'int'
581     char bus = 0; 
582     char devfn = 0; 
583     char offset = 0;
584     int i = 0;
585     
586     if (length > 4){
587         PrintDebug("Write more than 4 bytes to port 0x%x\n", (int)port);
588         return length;
589     }
590     
591     pci_state = (struct pci_internal *)vmdev->private_data;
592     
593     address = pci_state->config_address;
594     offset = address & 0xff;
595     devfn = (address >> 8) & 0xff;
596     bus = (address >> 16) & 0xff; 
597     
598     pdev = get_device(vmdev, bus, devfn);
599     
600     if (pdev == NULL){
601         // not sure what to do here, just ignore it
602         return length;
603     }
604     
605     val = 0x0;
606     memcpy(&val, src, length);
607     
608     pdev->ops.config_write(pdev, offset, val, length);
609     
610     PrintDebug("PCI Data: writing %d bytes to port %x: 0x", length, port);
611     
612     for (i = (length - 1); i >= 0; i--) { 
613         PrintDebug("%.2x", ((uchar_t*)src)[i]);
614     }
615     PrintDebug("\n");
616     
617     return length;
618 }
619
620
621 //Lei
622 static void init_pci_bus(struct pci_internal * pci_state) {
623     int i = 0;
624     struct pci_bus * first_bus = NULL;
625     
626     first_bus = (struct pci_bus *)V3_Malloc(sizeof(struct pci_bus));
627     
628     first_bus->bus_num = 0;  //?? not sure
629     
630     for (i = 0; i < NUM_DEVICES; i++) {
631         first_bus->device_list[i] = NULL;
632     }
633     
634     first_bus->next = NULL;
635     
636     pci_state->num_buses = 1;
637     pci_state->bus_list[0] = first_bus;
638     
639     for (i = 1; i < NUM_BUS; i++) {
640         pci_state->bus_list[i] = NULL;
641     }
642 }
643
644 //Lei
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);
648 }
649
650
651 static int vpci_set_defaults(struct vm_device * dev) {
652     PrintDebug("vpci: set defaults\n");
653     return 0;
654 }
655
656
657 static int vpci_reset_device(struct vm_device * dev) {
658     PrintDebug("vpci: reset device\n");
659     
660     vpci_set_defaults(dev);
661     
662     return 0;
663 }
664
665
666 static int vpci_start_device(struct vm_device * dev) {
667     PrintDebug("vpci: start device\n");
668     return 0;
669 }
670
671
672 // TODO: This should be static
673 int vpci_stop_device(struct vm_device * dev) {
674     PrintDebug("vpci: stop device\n");  
675     return 0;
676 }
677
678 // TODO: this should be static?
679 int vpci_init_device(struct vm_device * dev) {
680     struct pci_internal *pci_state = NULL;
681     int i = 0;
682     
683     PrintDebug("vpci: init_device\n");
684     
685     pci_state = (struct pci_internal *)dev->private_data;
686     
687     init_pci_internal(pci_state);
688     
689     init_fake_device(pci_state); //Chang
690     
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);
694     }
695     
696     return 0;
697 }
698
699 // TODO: This should be static
700 int vpci_deinit_device(struct vm_device * dev) {
701     int i = 0;
702     
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);
706     }
707     
708     vpci_reset_device(dev);
709     return 0;
710 }
711
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,
718 };
719
720 struct vm_device * v3_create_vpci() {
721     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
722     
723     PrintDebug("PCI internal at %p\n",(void *)pci_state);
724     
725     struct vm_device * device = v3_create_device("PCI", &dev_ops, pci_state);
726     
727     return device;
728 }