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.


Add Virtual PCI and Virtual NIC
[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 #define DEBUG_PCI
34
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;
71
72         if (bus_no >= NUM_BUS || devfn_no >= NUM_DEVICES)
73                 return dev;
74         
75         pci_state = (struct pci_internal *)vmdev->private_data;
76         bus = pci_state->bus_list[bus_no];
77         if (bus)
78                 dev = bus->device_list[devfn_no];
79
80         return dev;
81 }
82
83
84 //Lei
85 int pci_hook_ports(struct pci_device *dev, 
86                                         int reg_num, 
87                                         int num_ports, 
88                                         port_read_fn *port_reads[], 
89                                         port_write_fn *port_writes[])
90 {
91        struct pci_ioregion *ioreg;
92
93         ioreg = dev->ioregion[reg_num];
94
95         if (!ioreg) return -1;
96
97         if (ioreg->size != num_ports) return -1;
98
99         ioreg->port_reads = port_reads;
100         ioreg->port_writes = port_writes;
101
102         return 0;
103 }
104
105 //Lei
106 static inline void hook_ioregion(struct pci_device *dev, struct pci_ioregion *ioreg)
107 {
108         int i;
109
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, 
115                                                                 ioreg->addr + i, 
116                                                                 ioreg->port_reads[i], 
117                                                                 ioreg->port_writes[i]);
118         }
119
120 }
121
122
123 //Chang
124 static uint32_t vpci_read_config(struct pci_device *pdev, uchar_t offset, int len) 
125 {
126         uint32_t val = 0x0;
127
128         switch(len) {
129                 case 4:
130                         if(offset <= 0xfc) {
131                                 val = *(uint32_t *)(&(pdev->config)+offset);
132                                 break;
133                         }
134                 case 2:
135                         if(offset <= 0xfe) {
136                                 val = *(uint16_t *)(&(pdev->config)+offset);
137                                 break;
138                         }
139                 case 1:
140                         val = *(uint8_t *)(&(pdev->config)+offset);
141                         break;
142                 default:
143                         break;                  
144         }
145         
146         return val;
147 }
148
149 //Lei
150 static void vpci_write_config(struct pci_device *dev, uchar_t offset, uint32_t val, int len)
151 {
152     uchar_t *dev_config;
153
154     dev_config = (uchar_t *)&(dev->config);
155     dev_config += offset;
156
157     switch(len){
158         case 1:
159                 *dev_config = val & 0xff;
160                 break;
161         case 2:
162                 *((uint16_t *)dev_config) = val & 0xffff;
163                 break;
164         case 4:
165                 *((uint32_t *)dev_config) = val;
166                 break;
167         default:
168                 PrintDebug("pci_write_config: wrong length %d\n", len);
169                 break;
170         }
171 }
172
173 //Lei
174 void vpci_raise_irq(struct pci_device *pdev, void *data)
175 {
176         struct guest_info *vm;
177         int irq_line;
178
179         vm = pdev->bus->vm_dev->vm;
180         irq_line = pdev->config.intr_line;
181         v3_raise_irq(vm, irq_line);
182 }
183
184 #if 0
185 //Chang
186 static void pci_write_config(struct pci_device *dev, uint32_t address, uint32_t val, int len) 
187 {
188         int can_write, i, reg_num;
189         uint32_t addr;
190
191         if(len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || //base address registers
192                 (address >= 0x30 && address < 0x34))) { //expansion rom base address
193
194                 struct pci_ioregion * ioregion;
195                 if(address >= 0x30) {
196                                 reg_num = PCI_ROM_SLOT;
197                 }else {
198                         reg_num = ((address - 0x10) >>2); 
199                 }
200
201                 ioregion = &dev->io_regions[reg_num];
202
203                 if(ioregion->size == 0) {//default config
204
205                 addr = address;
206                         for (i=0;i<len;i++) {
207                                 switch(*(uint8_t *)(&(dev->config)+0x0e)) {
208                                 case 0x00:
209                                 case 0x80:
210                                         switch(addr) {
211                                         case 0x00:
212                                         case 0x01:
213                                         case 0x02:
214                                         case 0x03:
215                                         case 0x08:
216                                         case 0x09:
217                                         case 0x0a:
218                                         case 0x0b:
219                                         case 0x0e:
220                                         case 0x10 ... 0x27:
221                                         case 0x3d:
222                                                 can_write = 0;
223                                                 break;
224                                         default:
225                                                 can_write = 1;
226                                                 break;
227                                         }
228                                         break;  
229                                 default:
230                                 case 0x01:
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 0x38 ... 0x3b: 
242                                         case 0x3d:
243                                                 can_write = 0;
244                                                 break;
245                                         default:
246                                                 can_write = 1;
247                                                 break;
248                                         }
249                                         break;
250                                 }
251                                 if (can_write) {
252                                         *(uint32_t *)(&(dev->config)+addr) = val;
253                                 }
254                                 if(++addr > 0xff) break;
255                                 val >>= 8;
256                         }
257
258                         return;
259         
260                 }else {
261                         if(reg_num== PCI_ROM_SLOT) {
262                                 val &= (~(ioregion->size -1 )) | 1;
263                         } else {
264                                 val &= ~(ioregion->size -1);
265                                 val |= ioregion->type;
266                         }
267                 }
268                 //pci_update_mappings();
269                 return;
270         }
271 }
272 #endif
273
274 /* -1 for dev_num means auto assign */
275 struct pci_device *
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)) 
280 {
281
282         struct pci_device * pci_dev;
283         int found = 0;
284         int i;
285         
286         if(dev_num < 0) {
287                 for(dev_num = 0; dev_num < 256; dev_num++) {
288                         if(!bus->device_list[dev_num]) { 
289                                 found = 1;
290                                 break;
291                         }
292                 }
293         }
294         if (found == 0) return NULL;
295
296         pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
297
298         if(!pci_dev) return NULL;
299
300         pci_dev->bus = bus;
301         pci_dev->dev_num = dev_num;
302         pci_dev->irqline = -1;
303
304         strcpy(pci_dev->name,name);
305         
306         if(config_read) 
307                pci_dev->ops.config_read = config_read;
308         else
309                 pci_dev->ops.config_read=&vpci_read_config;
310         if(config_write) 
311                 pci_dev->ops.config_write = config_write;
312         else
313                 pci_dev->ops.config_write=&vpci_write_config;
314
315         pci_dev->ops.raise_irq = &vpci_raise_irq;
316
317       for (i = 0; i < PCI_IO_REGIONS; i++)
318                 pci_dev->ioregion[i] = NULL;
319
320       //config space initiate
321
322         bus->device_list[dev_num] = pci_dev;
323
324         return pci_dev;
325 }
326
327 //Chang
328 static void init_fake_device(struct pci_internal *pci_state) 
329 {
330         //maybe need table to map device, but just 
331         //bus_num=0, dev_num=0
332         
333         //int i=0;
334        struct pci_device *fake_device;
335
336         //fake dev
337         fake_device = pci_register_device(pci_state->bus_list[0],
338                                 "fake ide", sizeof(struct pci_device),
339                                 -1,
340                                 NULL,NULL);
341         
342         if (!fake_device) return;
343
344         /*
345         intel, ide ctroller
346         vendor id:0x8086
347         device id: 0x1222
348         */
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;
358        //base address
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; 
365         
366         //fake dev end
367
368        //need to register io regions
369
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;
373         
374         return;
375 }
376
377
378
379 // Lei
380 /* if region_num == -1, assign automatically
381  */
382 int 
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)
386 {
387         int found = 0;
388       struct pci_ioregion *region;
389
390         if(region_num < 0) {
391                 for(region_num = 0; region_num < 256; region_num++) {
392                         if(!pci_dev->ioregion[region_num]) { 
393                                 found = 1;
394                                 break;
395                         }
396                 }
397         }
398         if (found == 0) return -1;
399         if (pci_dev->ioregion[region_num] != NULL)
400                 return -1;
401
402         region = (struct pci_ioregion *)V3_Malloc(sizeof(struct pci_ioregion));
403         if (!region) return -1;
404
405         region->addr = -1;
406         region->reg_num = region_num;
407         region->size = size;
408         region->mapped_size = -1;
409         region->type = type;
410         region->map_func = map_func;
411         region->port_reads = NULL;
412         region->port_writes = NULL;
413
414         pci_dev->ioregion[region_num] = region;
415
416         return region_num;
417 }
418
419
420
421
422 //Chang
423 static int 
424 vpci_addrport_read(ushort_t port,
425                                         void * dst,
426                                         uint_t length,
427                                         struct vm_device *dev) 
428 {
429
430   struct pci_internal *pci_state = (struct pci_internal *)dev->private_data;
431   int start;
432   uchar_t *addr;
433   int i;
434
435   start = port - PCI_CONFIG_ADDRESS;
436   if (length + start > 4){
437         return length;   //cross port boundary, is memory mapped IO style
438   }
439   addr = (uchar_t *)&(pci_state->config_address);
440   addr += start;
441   memcpy(dst, addr, length);    //be careful, PCI is little endian
442
443   PrintDebug("PCI Address: reading %d bytes from port %x: 0x", length, port);
444
445   for (i = length - 1; i >= 0; i--) { 
446     PrintDebug("%.2x", ((uchar_t*)dst)[i]);
447   }
448    PrintDebug("\n");
449   return length;
450 }
451
452 //Lei
453 static int 
454 vpci_addrport_write(ushort_t port,
455                                                 void *src,
456                                                 uint_t length,
457                                                 struct vm_device *dev)
458 {
459   struct pci_internal *pci_state = (struct pci_internal *)dev->private_data;
460   int start;
461   uchar_t *addr;
462   int i;
463
464   start = port - PCI_CONFIG_ADDRESS;
465   if (length + start > 4){
466         return length;   //cross port boundary, is memory mapped IO style
467   }
468   addr = (uchar_t *)&(pci_state->config_address);
469   addr += start;
470   memcpy(addr, src, length);    //be careful, PCI is little endian
471
472   PrintDebug("PCI Address: writing %d bytes to port %x: 0x", length, port);
473
474   for (i = length - 1; i >= 0; i--) { 
475     PrintDebug("%.2x", ((uchar_t*)src)[i]);
476   }
477    PrintDebug("\n");
478   return length;
479 }
480
481 //Chang
482 static int 
483 vpci_dataport_read(ushort_t port,
484                                         void * dst,
485                                         uint_t length,
486                                         struct vm_device *vmdev) 
487 {
488         /*
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]
494         */
495         
496         struct pci_internal * pci_state;
497         struct pci_device * pci_dev = NULL;
498         int bus_num, devfn, offset;
499         uint32_t address;
500         uint32_t val;
501         int i;
502
503        if (length > 4){
504                 PrintDebug("Read more than 4 bytes from port 0x%x\n", (int)port);
505                 return length;
506        }
507
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; 
513
514        pci_dev = get_device(vmdev, bus_num, devfn);
515
516         if(!pci_dev) {
517                 val = 0xffffffff;
518         }else {
519         val = 0x0;
520                 val = pci_dev->ops.config_read(pci_dev, offset, length);
521         }
522         memcpy(dst,&val,length);
523
524         PrintDebug("PCI Data: reading %d bytes from port %x: 0x", length, port);
525
526         for (i = length - 1; i >= 0; i--) { 
527                 PrintDebug("%.2x", ((uchar_t*)dst)[i]);
528         }
529       PrintDebug("\n");
530                 
531         return length;
532
533 }
534
535 static int 
536 vpci_dataport_write(ushort_t port,
537                                                 void * src,
538                                                 uint_t length,
539                                                 struct vm_device *vmdev)
540 {
541   struct pci_internal *pci_state;
542   uint32_t val;
543   uint32_t address;
544   struct pci_device *pdev;
545   char bus, devfn, offset;
546   int i;
547
548   if (length > 4){
549                 PrintDebug("Write more than 4 bytes to port 0x%x\n", (int)port);
550                 return length;
551   }
552
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; 
558
559   pdev = get_device(vmdev, bus, devfn);
560   if (pdev == NULL){
561         // not sure what to do here, just ignore it
562         return length;
563   }
564   
565   val = 0x0;
566   memcpy(&val, src, length);
567   
568   pdev->ops.config_write(pdev, offset, val, length);
569
570   PrintDebug("PCI Data: writing %d bytes to port %x: 0x", length, port);
571
572   for (i = length - 1; i >= 0; i--) { 
573                 PrintDebug("%.2x", ((uchar_t*)src)[i]);
574  }
575   PrintDebug("\n");
576   
577   return length;
578 }
579         
580
581 //Lei
582 static void init_pci_bus(struct pci_internal *pci_state) 
583 {
584   int i;
585   struct pci_bus *first_bus;
586
587   first_bus = (struct pci_bus *)V3_Malloc(sizeof(struct pci_bus));
588
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;
593
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;
598 }
599
600 //Lei
601 static void init_pci_internal(struct pci_internal *pci_state) 
602 {
603
604   pci_state->config_address = 0x00;  //Not sure????
605   init_pci_bus(pci_state);
606
607 }
608
609
610 static int vpci_set_defaults(struct vm_device *dev)
611 {
612   PrintDebug("vpci: set defaults\n");
613   return 0;
614 }
615
616
617 static int vpci_reset_device(struct vm_device * dev)
618 {
619   
620   PrintDebug("vpci: reset device\n");
621
622   vpci_set_defaults(dev);
623   
624   return 0;
625 }
626
627
628 static int vpci_start_device(struct vm_device *dev)
629 {
630   PrintDebug("vpci: start device\n");
631   
632   return 0;
633 }
634
635
636 int vpci_stop_device(struct vm_device *dev)
637 {
638   PrintDebug("vpci: stop device\n");
639   
640   return 0;
641 }
642
643
644 int vpci_init_device(struct vm_device * dev) 
645 {
646   struct pci_internal *pci_state;
647   int i;
648
649   PrintDebug("vpci: init_device\n");
650   
651   pci_state = (struct pci_internal *)dev->private_data;
652
653   init_pci_internal(pci_state);
654
655   init_fake_device(pci_state); //Chang
656
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);
660  }
661
662
663   return 0;
664 }
665
666 int vpci_deinit_device(struct vm_device *dev)
667 {
668    int i;
669    
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);
673   }
674
675   vpci_reset_device(dev);
676   return 0;
677 }
678
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,
685 };
686
687 struct vm_device *v3_create_vpci() {
688   struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
689
690   PrintDebug("PCI internal at %x\n",(int)(long)pci_state);
691   struct vm_device *device = v3_create_device("PCI", &dev_ops, pci_state);
692
693   return device;
694 }