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.


updated pci
[palacios.git] / palacios / src / devices / pci.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, Jack Lange <jarusl@cs.northwestern.edu>
13  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
14  * All rights reserved.
15  *
16  * Author:  Lei Xia <lxia@northwestern.edu>
17  *          Chang Seok Bae <jhuell@gmail.com>
18  *          Jack Lange <jarusl@cs.northwestern.edu>
19  *
20  * This is free software.  You are permitted to use,
21  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22  */ 
23  
24  
25
26 #include <palacios/vmm.h>
27 #include <palacios/vmm_types.h>
28 #include <palacios/vmm_io.h>
29 #include <palacios/vmm_intr.h>
30 #include <palacios/vmm_rbtree.h>
31
32 #include <devices/pci.h>
33 #include <devices/pci_types.h>
34
35 #ifndef DEBUG_PCI
36 #undef PrintDebug
37 #define PrintDebug(fmt, args...)
38 #endif
39
40
41 #define CONFIG_ADDR_PORT    0x0cf8
42 #define CONFIG_DATA_PORT    0x0cfc
43
44
45 #define PCI_BUS_COUNT 1
46
47 // This must always be a multiple of 8
48 #define MAX_BUS_DEVICES 32
49
50 struct pci_addr_reg {
51     union {
52         uint32_t val;
53         struct {
54             uint_t rsvd       : 2;
55             uint_t reg_num    : 6;
56             uint_t fn_num     : 3;
57             uint_t dev_num    : 5;
58             uint_t bus_num    : 8;
59             uint_t rsvd2      : 7;
60             uint_t enable     : 1;
61         } __attribute__((packed));
62     } __attribute__((packed));
63 } __attribute__((packed));
64
65
66
67
68
69 struct pci_bus {
70     int bus_num;
71
72     // Red Black tree containing all attached devices
73     struct rb_root devices;
74
75     // Bitmap of the allocated device numbers
76     uint8_t dev_map[MAX_BUS_DEVICES / 8];
77 };
78
79
80
81 struct pci_internal {
82     // Configuration address register
83     struct pci_addr_reg addr_reg;
84
85     // Attached Busses
86     struct pci_bus bus_list[PCI_BUS_COUNT];
87 };
88
89
90
91
92
93 #ifdef DEBUG_PCI
94
95 static void pci_dump_state(struct pci_internal * pci_state) {
96     struct rb_node * node = v3_rb_first(&(pci_state->bus_list[0].devices));
97     struct pci_device * tmp_dev = NULL;
98     
99     PrintDebug("===PCI: Dumping state Begin ==========\n");
100     
101     do {
102         tmp_dev = rb_entry(node, struct pci_device, dev_tree_node);
103
104         PrintDebug("PCI Device Number: %d (%s):\n", tmp_dev->dev_num,  tmp_dev->name);
105         PrintDebug("irq = %d\n", tmp_dev->config_header.intr_line);
106         PrintDebug("Vend ID: 0x%x\n", tmp_dev->config_header.vendor_id);
107         PrintDebug("Device ID: 0x%x\n", tmp_dev->config_header.device_id);
108
109     } while ((node = v3_rb_next(node)));
110     
111     PrintDebug("====PCI: Dumping state End==========\n");
112 }
113
114 #endif
115
116
117
118
119 // Scan the dev_map bitmap for the first '0' bit
120 static int get_free_dev_num(struct pci_bus * bus) {
121     int i, j;
122
123     for (i = 0; i < sizeof(bus->dev_map); i++) {
124         if (bus->dev_map[i] != 0xff) {
125             // availability
126             for (j = 0; j < 8; j++) {
127                 if (!(bus->dev_map[i] & (0x1 << j))) {
128                     return ((i * 8) + j);
129                 }
130             }
131         }
132     }
133
134     return -1;
135 }
136
137 static void allocate_dev_num(struct pci_bus * bus, int dev_num) {
138     int major = (dev_num / 8);
139     int minor = dev_num % 8;
140
141     bus->dev_map[major] |= (0x1 << minor);
142 }
143
144
145
146 static inline 
147 struct pci_device * __add_device_to_bus(struct pci_bus * bus, struct pci_device * dev) {
148
149   struct rb_node ** p = &(bus->devices.rb_node);
150   struct rb_node * parent = NULL;
151   struct pci_device * tmp_dev = NULL;
152
153   while (*p) {
154     parent = *p;
155     tmp_dev = rb_entry(parent, struct pci_device, dev_tree_node);
156
157     if (dev->dev_num < tmp_dev->dev_num) {
158       p = &(*p)->rb_left;
159     } else if (dev->dev_num > tmp_dev->dev_num) {
160       p = &(*p)->rb_right;
161     } else {
162       return tmp_dev;
163     }
164   }
165
166   rb_link_node(&(dev->dev_tree_node), parent, p);
167
168   return NULL;
169 }
170
171
172 static inline 
173 struct pci_device * add_device_to_bus(struct pci_bus * bus, struct pci_device * dev) {
174
175   struct pci_device * ret = NULL;
176
177   if ((ret = __add_device_to_bus(bus, dev))) {
178     return ret;
179   }
180
181   v3_rb_insert_color(&(dev->dev_tree_node), &(bus->devices));
182
183   allocate_dev_num(bus, dev->dev_num);
184
185   return NULL;
186 }
187
188
189 static struct pci_device * get_device(struct pci_bus * bus, int dev_num) {
190     struct rb_node * n = bus->devices.rb_node;
191     struct pci_device * dev = NULL;
192
193     while (n) {
194         dev = rb_entry(n, struct pci_device, dev_tree_node);
195         
196         if (dev_num < dev->dev_num) {
197             n = n->rb_left;
198         } else if (dev_num > dev->dev_num) {
199             n = n->rb_right;
200         } else {
201             return dev;
202         }
203     }
204     
205     return NULL;
206 }
207
208
209
210
211
212
213
214 static int addr_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
215     struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;
216     int reg_offset = port & 0x3;
217     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
218
219     PrintDebug("Reading PCI Address Port (%x): %x\n", port, pci_state->addr_reg.val);
220
221     if (length == 4) {
222         if (reg_offset != 0) {
223             PrintError("Invalid Address Port Read\n");
224             return -1;
225         }
226         *(uint32_t *)dst = *(uint32_t *)reg_addr;
227     } else if (length == 2) {
228         if (reg_offset > 2) {
229             PrintError("Invalid Address Port Read\n");
230             return -1;
231         }
232         *(uint16_t *)dst = *(uint16_t *)reg_addr;
233     } else if (length == 1) {
234         *(uint8_t *)dst = *(uint8_t *)reg_addr;
235     } else {
236         PrintError("Invalid read length (%d) for PCI address register\n", length);
237         return -1;
238     }
239     
240
241     return length;
242 }
243
244
245 static int addr_port_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
246     struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;
247     int reg_offset = port & 0x3; 
248     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
249
250
251     if (length == 4) {
252         if (reg_offset != 0) {
253             PrintError("Invalid Address Port Write\n");
254             return -1;
255         }
256
257         PrintDebug("Writing PCI 4 bytes Val=%x\n",  *(uint32_t *)src);
258
259         *(uint32_t *)reg_addr = *(uint32_t *)src;
260     } else if (length == 2) {
261         if (reg_offset > 2) {
262             PrintError("Invalid Address Port Write\n");
263             return -1;
264         }
265
266         PrintDebug("Writing PCI 2 byte Val=%x\n",  *(uint16_t *)src);
267
268         *(uint16_t *)reg_addr = *(uint16_t *)src;
269     } else if (length == 1) {
270         PrintDebug("Writing PCI 1 byte Val=%x\n",  *(uint8_t *)src);
271         *(uint8_t *)reg_addr = *(uint8_t *)src;
272     } else {
273         PrintError("Invalid write length (%d) for PCI address register\n", length);
274         return -1;
275     }
276
277     PrintDebug("Writing PCI Address Port(%x): %x\n", port, pci_state->addr_reg.val);
278
279
280     return length;
281 }
282
283
284 static int data_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * vmdev) {
285     struct pci_internal * pci_state =  (struct pci_internal *)vmdev->private_data;;
286     struct pci_device * pci_dev = NULL;
287     uint_t reg_num = pci_state->addr_reg.reg_num + (port & 0x3);
288     int i;
289
290     PrintDebug("Reading PCI Data register. bus = %d, dev = %d, reg = %d (%x), cfg_reg = %x\n", 
291                pci_state->addr_reg.bus_num, 
292                pci_state->addr_reg.dev_num, 
293                reg_num, reg_num, 
294                pci_state->addr_reg.val);
295
296
297     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num);
298     
299     if (pci_dev == NULL) {
300         for (i = 0; i < length; i++) {
301             *((uint8_t *)dst + i) = 0xff;
302         }
303
304         return length;
305     }
306
307     for (i = 0; i < length; i++) {
308         *((uint8_t *)dst + i) = pci_dev->config_space[reg_num + i];
309     }
310     
311     return length;
312 }
313
314
315 static inline int is_cfg_reg_writable(uchar_t header_type, int reg_num) {
316     if (header_type == 0x00) {
317         switch (reg_num) {
318             case 0x00:
319             case 0x01:
320             case 0x02:
321             case 0x03:
322             case 0x08:
323             case 0x09:
324             case 0x0a:
325             case 0x0b:
326             case 0x0e:
327             case 0x3d:
328                 return 0;
329                            
330            default:
331                return 1;
332  
333         }
334     } else {
335         // PCI to PCI Bridge = 0x01
336         // CardBus Bridge = 0x02
337
338         // huh?
339         PrintError("Invalid PCI Header type (0x%.2x)\n", header_type);
340
341         return -1;
342     }
343 }
344
345
346 static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
347     struct pci_internal * pci_state = (struct pci_internal *)vmdev->private_data;
348     struct pci_device * pci_dev = NULL;
349     uint_t reg_num = pci_state->addr_reg.reg_num + (port & 0x3);
350     int i;
351
352     PrintDebug("Writing PCI Data register. bus = %d, dev = %d, reg = %d (%x) addr_reg = %x\n", 
353                pci_state->addr_reg.bus_num, 
354                pci_state->addr_reg.dev_num, 
355                reg_num, reg_num, 
356                pci_state->addr_reg.val);
357
358
359     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num);
360     
361     if (pci_dev == NULL) {
362         PrintError("Writing configuration space for non-present device (dev_num=%d)\n", 
363                    pci_state->addr_reg.dev_num); 
364         return -1;
365     }
366     
367
368     for (i = 0; i < length; i++) {
369         uint_t cur_reg = reg_num + i;
370         
371         if (is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg)) {
372             pci_dev->config_space[cur_reg] = *((uint8_t *)src + i);
373
374             if ((cur_reg >= 0x10) && (cur_reg < 0x28)) {
375                 // BAR Reg
376                 int bar_reg = (cur_reg & ~0x3) - 0x10;
377
378                 if (pci_dev->bar[bar_reg].bar_update) {
379                     pci_dev->bar_update_flag = 1;               
380                     pci_dev->bar[bar_reg].updated = 1;
381                 }
382             } else if ((cur_reg >= 0x30) && (cur_reg < 0x34)) {
383                 pci_dev->ext_rom_update_flag = 1;
384             } else if (cur_reg == 0x04) {
385               // COMMAND update      
386               uint8_t command = *((uint8_t *)src + i);
387
388               pci_dev->config_space[cur_reg] = command;       
389
390               if (pci_dev->cmd_update) {
391                 pci_dev->cmd_update(pci_dev, (command & 0x01), (command & 0x02));
392               }
393              
394
395             } else if (cur_reg == 0x0f) {
396                 // BIST update
397                 pci_dev->config_header.BIST = 0x00;
398             }
399         }
400     }
401
402     if (pci_dev->config_update) {
403         pci_dev->config_update(pci_dev, reg_num, length);
404     }
405
406     // Scan for BAR updated
407     if (pci_dev->bar_update_flag) {
408         for (i = 0; i < 6; i++) {
409             if (pci_dev->bar[i].updated) {
410                 int bar_offset = 0x10 + 4 * i;
411
412                 *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask;
413
414                 if (pci_dev->bar[i].bar_update) {
415                     pci_dev->bar[i].bar_update(pci_dev, i);
416                 }
417                 pci_dev->bar[i].updated = 0;
418             }
419         }
420         pci_dev->bar_update_flag = 0;
421     }
422
423     if ((pci_dev->ext_rom_update_flag) && (pci_dev->ext_rom_update)) {
424         pci_dev->ext_rom_update(pci_dev);
425         pci_dev->ext_rom_update_flag = 0;
426     }
427
428
429     return length;
430 }
431
432
433
434 static int pci_reset_device(struct vm_device * dev) {
435     PrintDebug("pci: reset device\n");    
436     return 0;
437 }
438
439
440 static int pci_start_device(struct vm_device * dev) {
441     PrintDebug("pci: start device\n");
442     return 0;
443 }
444
445
446 static int pci_stop_device(struct vm_device * dev) {
447     PrintDebug("pci: stop device\n");  
448     return 0;
449 }
450
451
452
453 static int pci_deinit_device(struct vm_device * dev) {
454     int i = 0;
455     
456     for (i = 0; i < 4; i++){
457         v3_dev_unhook_io(dev, CONFIG_ADDR_PORT + i);
458         v3_dev_unhook_io(dev, CONFIG_DATA_PORT + i);
459     }
460     
461     return 0;
462 }
463
464
465
466
467 static int init_i440fx(struct vm_device * dev) {
468     struct pci_device * pci_dev = NULL;
469     struct v3_pci_bar bars[6];
470     int i;
471     
472     for (i = 0; i < 6; i++) {
473         bars[i].type = PCI_BAR_NONE;
474         bars[i].mem_hook = 0;
475         bars[i].num_pages = 0;
476         bars[i].bar_update = NULL;
477     }    
478
479     pci_dev = v3_pci_register_device(dev, PCI_STD_DEVICE, 0, "i440FX", 0, bars,
480                                      NULL, NULL, NULL, NULL);
481     
482     if (!pci_dev) {
483         return -1;
484     }
485     
486     pci_dev->config_header.vendor_id = 0x8086;
487     pci_dev->config_header.device_id = 0x1237;
488     pci_dev->config_header.revision = 0x0002;
489     pci_dev->config_header.subclass = 0x00; //  SubClass: host2pci
490     pci_dev->config_header.class = 0x06;    // Class: PCI bridge
491
492     pci_dev->bus_num = 0;
493     return 0;
494 }
495
496
497
498 static void test_devices(struct vm_device * dev) {
499     struct pci_device * pci_dev = NULL;
500     struct v3_pci_bar bars[6];
501     int i;
502     
503     for (i = 0; i < 6; i++) {
504         bars[i].type = PCI_BAR_NONE;
505         bars[i].mem_hook = 0;
506         bars[i].num_pages = 0;
507         bars[i].bar_update = NULL;
508     }    
509
510
511     pci_dev = v3_pci_register_device(dev, PCI_STD_DEVICE, 0, "", 0, bars,
512                                      NULL, NULL, NULL, NULL);
513     
514     pci_dev->config_header.vendor_id = 0x8086;
515     pci_dev->config_header.device_id = 0x0101;
516     pci_dev->config_header.revision = 0x0002;
517     pci_dev->config_header.subclass = 0x01; //  SubClass: host2pci
518     pci_dev->config_header.class = 0x01;    // Class: PCI bridge
519
520     pci_dev = v3_pci_register_device(dev, PCI_STD_DEVICE, 0, "", 0, bars,
521                                      NULL, NULL, NULL, NULL);
522     
523     pci_dev->config_header.vendor_id = 0x8086;
524     pci_dev->config_header.device_id = 0x0101;
525     pci_dev->config_header.revision = 0x0002;
526     pci_dev->config_header.subclass = 0x00; //  SubClass: host2pci
527     pci_dev->config_header.class = 0x02;    // Class: PCI bridge
528     
529
530
531
532 }
533
534
535
536 static void init_pci_busses(struct pci_internal * pci_state) {
537     int i;
538
539     for (i = 0; i < PCI_BUS_COUNT; i++) {
540         pci_state->bus_list[i].bus_num = i;
541         pci_state->bus_list[i].devices.rb_node = NULL;
542         memset(pci_state->bus_list[i].dev_map, 0, sizeof(pci_state->bus_list[i].dev_map));
543     }
544 }
545
546
547
548 static int pci_init_device(struct vm_device * dev) {
549     struct pci_internal * pci_state = (struct pci_internal *)dev->private_data;;
550     int i = 0;
551     
552     PrintDebug("pci: init_device\n");
553
554     // JRL: Fix this....
555     //    dev->vm->pci = dev;   //should be in vmm_config.c
556     
557     pci_state->addr_reg.val = 0; 
558
559     init_pci_busses(pci_state);
560
561     if (init_i440fx(dev) == -1) {
562         PrintError("Could not intialize i440fx\n");
563         return -1;
564     }
565
566     test_devices(dev);
567     
568     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
569     
570     for (i = 0; i < 4; i++) {
571         v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write);
572         v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write);
573     }
574
575     return 0;
576 }
577
578
579 static struct vm_device_ops dev_ops = {
580     .init = pci_init_device, 
581     .deinit = pci_deinit_device,
582     .reset = pci_reset_device,
583     .start = pci_start_device,
584     .stop = pci_stop_device,
585 };
586
587
588 struct vm_device * v3_create_pci() {
589     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
590     
591     PrintDebug("PCI internal at %p\n",(void *)pci_state);
592     
593     struct vm_device * device = v3_create_device("PCI", &dev_ops, pci_state);
594     
595     return device;
596 }
597
598
599
600 static inline int init_bars(struct pci_device * pci_dev) {
601     int i = 0;
602
603     for (i = 0; i < 6; i++) {
604         int bar_offset = 0x10 + 4 * i;
605
606         if (pci_dev->bar[i].type == PCI_BAR_IO) {
607             pci_dev->bar[i].mask = 0x0000fffd;
608             *(uint32_t *)(pci_dev->config_space + bar_offset) = 0x00000001;
609         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
610             pci_dev->bar[i].mask = ~((pci_dev->bar[i].num_pages << 12) - 1);
611             pci_dev->bar[i].mask |= 0xf; // preserve the configuration flags
612              
613             *(uint32_t *)(pci_dev->config_space + bar_offset) = 0x00000008;
614             
615             if (pci_dev->bar[i].mem_hook) {
616                 // clear the prefetchable flag...
617                 *(uint8_t *)(pci_dev->config_space + bar_offset) &= ~0x00000008;
618             }
619         } else if (pci_dev->bar[i].type == PCI_BAR_MEM16) {
620             PrintError("16 Bit memory ranges not supported (reg: %d)\n", i);
621         } else if (pci_dev->bar[i].type == PCI_BAR_NONE) {
622             *(uint32_t *)(pci_dev->config_space + bar_offset) = 0x00000000;
623         } else {
624             PrintError("Invalid BAR type for bar #%d\n", i);
625             return -1;
626         }
627             
628
629     }
630
631     return 0;
632 }
633
634
635
636 // if dev_num == -1, auto assign 
637 struct pci_device * v3_pci_register_device(struct vm_device * pci,
638                                            pci_device_type_t dev_type, 
639                                            uint_t bus_num,
640                                            const char * name,
641                                            int dev_num,
642                                            struct v3_pci_bar * bars,
643                                            int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length),
644                                            int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
645                                            int (*ext_rom_update)(struct pci_device * pci_dev),
646                                            void * private_data) {
647
648     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
649     struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
650     struct pci_device * pci_dev = NULL;
651     int i;
652
653     if (dev_num > MAX_BUS_DEVICES) {
654         PrintError("Requested Invalid device number (%d)\n", dev_num);
655         return NULL;
656     }
657
658     if (dev_num == -1) {
659         if ((dev_num = get_free_dev_num(bus)) == -1) {
660             PrintError("No more available PCI slots on bus %d\n", bus->bus_num);
661             return NULL;
662         }
663     }
664     
665     if (get_device(bus, dev_num) != NULL) {
666         PrintError("PCI Device already registered at slot %d on bus %d\n", 
667                    dev_num, bus->bus_num);
668         return NULL;
669     }
670
671     
672     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
673
674     if (pci_dev == NULL) {
675         return NULL;
676     }
677
678     memset(pci_dev, 0, sizeof(struct pci_device));
679     
680     
681     switch (dev_type) {
682         case PCI_STD_DEVICE:
683             pci_dev->config_header.header_type = 0x00;
684             break;
685         default:
686             PrintError("Unhandled PCI Device Type: %d\n", dev_type);
687             return NULL;
688     }
689
690     pci_dev->bus_num = bus_num;
691     pci_dev->dev_num = dev_num;
692
693     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
694     pci_dev->vm_dev = pci;
695
696     // register update callbacks
697     pci_dev->config_update = config_update;
698     pci_dev->cmd_update = cmd_update;
699     pci_dev->ext_rom_update = ext_rom_update;
700
701     pci_dev->priv_data = private_data;
702
703     
704     //copy bars
705     for (i = 0; i < 6; i ++){
706       pci_dev->bar[i].type = bars[i].type;
707       pci_dev->bar[i].num_pages = bars[i].num_pages;
708       pci_dev->bar[i].mem_hook = bars[i].mem_hook;
709       pci_dev->bar[i].bar_update = bars[i].bar_update;
710     }
711
712     if (init_bars(pci_dev) == -1) {
713         PrintError("could not initialize bar registers\n");
714         return NULL;
715     }
716
717     pci_dev->cmd_update = cmd_update;
718     pci_dev->ext_rom_update = ext_rom_update;
719
720     // add the device
721     add_device_to_bus(bus, pci_dev);
722
723     
724 #ifdef DEBUG_PCI
725     pci_dump_state(pci_state);
726 #endif
727
728     return pci_dev;
729 }
730
731
732