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.


checkpoint changes to get "reset to BIOS" working.
[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, Jack Lange <jarusl@cs.northwestern.edu>
11  * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu>
12  * Copyright (c) 2009, Chang Seok Bae <jhuell@gmail.com>
13  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
14  * All rights reserved.
15  *
16  * Author:  Jack Lange <jarusl@cs.northwestern.edu>
17  *          Lei Xia <lxia@northwestern.edu>
18  *          Chang Seok Bae <jhuell@gmail.com>
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 #include <palacios/vmm_dev_mgr.h>
32
33 #include <devices/pci.h>
34 #include <devices/pci_types.h>
35
36 #include <palacios/vm_guest.h>
37
38
39
40 #ifndef V3_CONFIG_DEBUG_PCI
41 #undef PrintDebug
42 #define PrintDebug(fmt, args...)
43 #endif
44
45
46 #define CONFIG_ADDR_PORT    0x0cf8
47 #define CONFIG_DATA_PORT    0x0cfc
48
49 #define PCI_DEV_IO_PORT_BASE 0xc000
50
51 #define PCI_BUS_COUNT 1
52
53 // This must always be a multiple of 8
54 #define MAX_BUS_DEVICES 32
55
56 struct pci_addr_reg {
57     union {
58         uint32_t val;
59         struct {
60             uint_t rsvd       : 2;
61             uint_t reg_num    : 6;
62             uint_t fn_num     : 3;
63             uint_t dev_num    : 5;
64             uint_t bus_num    : 8;
65             uint_t rsvd2      : 7;
66             uint_t enable     : 1;
67         } __attribute__((packed));
68     } __attribute__((packed));
69 } __attribute__((packed));
70
71
72
73
74
75 struct pci_bus {
76     int bus_num;
77
78     // Red Black tree containing all attached devices
79     struct rb_root devices;
80
81     // Bitmap of the allocated device numbers
82     uint8_t dev_map[MAX_BUS_DEVICES / 8];
83
84
85     int (*raise_pci_irq)(struct pci_device * pci_dev, void * dev_data);
86     int (*lower_pci_irq)(struct pci_device * pci_dev, void * dev_data);
87     void * irq_dev_data;
88 };
89
90
91
92 struct pci_internal {
93     // Configuration address register
94     struct pci_addr_reg addr_reg;
95
96     // Base IO Port which PCI devices will register with...
97     uint16_t dev_io_base; 
98
99     // Attached Busses
100     struct pci_bus bus_list[PCI_BUS_COUNT];
101 };
102
103
104
105
106
107 #ifdef V3_CONFIG_DEBUG_PCI
108
109 static void pci_dump_state(struct pci_internal * pci_state) {
110     struct rb_node * node = v3_rb_first(&(pci_state->bus_list[0].devices));
111     struct pci_device * tmp_dev = NULL;
112     
113     PrintDebug("===PCI: Dumping state Begin ==========\n");
114     
115     do {
116         tmp_dev = rb_entry(node, struct pci_device, dev_tree_node);
117
118         PrintDebug("PCI Device Number: %d (%s):\n", tmp_dev->dev_num,  tmp_dev->name);
119         PrintDebug("irq = %d\n", tmp_dev->config_header.intr_line);
120         PrintDebug("Vend ID: 0x%x\n", tmp_dev->config_header.vendor_id);
121         PrintDebug("Device ID: 0x%x\n", tmp_dev->config_header.device_id);
122
123     } while ((node = v3_rb_next(node)));
124     
125     PrintDebug("====PCI: Dumping state End==========\n");
126 }
127
128 #endif
129
130
131
132
133 // Scan the dev_map bitmap for the first '0' bit
134 static int get_free_dev_num(struct pci_bus * bus) {
135     int i, j;
136
137     for (i = 0; i < sizeof(bus->dev_map); i++) {
138         PrintDebug("i=%d\n", i);
139         if (bus->dev_map[i] != 0xff) {
140             // availability
141             for (j = 0; j < 8; j++) {
142                 PrintDebug("\tj=%d\n", j);
143                 if (!(bus->dev_map[i] & (0x1 << j))) {
144                     return ((i * 8) + j);
145                 }
146             }
147         }
148     }
149
150     return -1;
151 }
152
153 static void allocate_dev_num(struct pci_bus * bus, int dev_num) {
154     int major = (dev_num / 8);
155     int minor = dev_num % 8;
156
157     bus->dev_map[major] |= (0x1 << minor);
158 }
159
160
161
162 static inline 
163 struct pci_device * __add_device_to_bus(struct pci_bus * bus, struct pci_device * dev) {
164
165   struct rb_node ** p = &(bus->devices.rb_node);
166   struct rb_node * parent = NULL;
167   struct pci_device * tmp_dev = NULL;
168
169   while (*p) {
170     parent = *p;
171     tmp_dev = rb_entry(parent, struct pci_device, dev_tree_node);
172
173     if (dev->devfn < tmp_dev->devfn) {
174       p = &(*p)->rb_left;
175     } else if (dev->devfn > tmp_dev->devfn) {
176       p = &(*p)->rb_right;
177     } else {
178       return tmp_dev;
179     }
180   }
181
182   rb_link_node(&(dev->dev_tree_node), parent, p);
183
184   return NULL;
185 }
186
187
188 static inline 
189 struct pci_device * add_device_to_bus(struct pci_bus * bus, struct pci_device * dev) {
190
191   struct pci_device * ret = NULL;
192
193   if ((ret = __add_device_to_bus(bus, dev))) {
194     return ret;
195   }
196
197   v3_rb_insert_color(&(dev->dev_tree_node), &(bus->devices));
198
199   allocate_dev_num(bus, dev->dev_num);
200
201   return NULL;
202 }
203
204
205 static struct pci_device * get_device(struct pci_bus * bus, uint8_t dev_num, uint8_t fn_num) {
206     struct rb_node * n = bus->devices.rb_node;
207     struct pci_device * dev = NULL;
208     uint8_t devfn = ((dev_num & 0x1f) << 3) | (fn_num & 0x7);
209
210     while (n) {
211         dev = rb_entry(n, struct pci_device, dev_tree_node);
212         
213         if (devfn < dev->devfn) {
214             n = n->rb_left;
215         } else if (devfn > dev->devfn) {
216             n = n->rb_right;
217         } else {
218             return dev;
219         }
220     }
221     
222     return NULL;
223 }
224
225
226
227
228
229
230
231 static int addr_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
232     struct pci_internal * pci_state = priv_data;
233     int reg_offset = port & 0x3;
234     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
235
236     PrintDebug("Reading PCI Address Port (%x): %x len=%d\n", port, pci_state->addr_reg.val, length);
237
238     if (length == 4) {
239         if (reg_offset != 0) {
240             PrintError("Invalid Address Port Read\n");
241             return -1;
242         }
243         *(uint32_t *)dst = *(uint32_t *)reg_addr;
244     } else if (length == 2) {
245         if (reg_offset > 2) {
246             PrintError("Invalid Address Port Read\n");
247             return -1;
248         }
249         *(uint16_t *)dst = *(uint16_t *)reg_addr;
250     } else if (length == 1) {
251         *(uint8_t *)dst = *(uint8_t *)reg_addr;
252     } else {
253         PrintError("Invalid read length (%d) for PCI address register\n", length);
254         return -1;
255     }
256     
257
258     return length;
259 }
260
261
262 static int addr_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
263     struct pci_internal * pci_state = priv_data;
264     int reg_offset = port & 0x3; 
265     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
266
267
268     if (length == 4) {
269         if (reg_offset != 0) {
270             PrintError("Invalid Address Port Write\n");
271             return -1;
272         }
273
274         PrintDebug("Writing PCI 4 bytes Val=%x\n",  *(uint32_t *)src);
275
276         *(uint32_t *)reg_addr = *(uint32_t *)src;
277     } else if (length == 2) {
278         if (reg_offset > 2) {
279             PrintError("Invalid Address Port Write\n");
280             return -1;
281         }
282
283         PrintDebug("Writing PCI 2 byte Val=%x\n",  *(uint16_t *)src);
284
285         *(uint16_t *)reg_addr = *(uint16_t *)src;
286     } else if (length == 1) {
287         PrintDebug("Writing PCI 1 byte Val=%x\n",  *(uint8_t *)src);
288         *(uint8_t *)reg_addr = *(uint8_t *)src;
289     } else {
290         PrintError("Invalid write length (%d) for PCI address register\n", length);
291         return -1;
292     }
293
294     PrintDebug("Writing PCI Address Port(%x): %x\n", port, pci_state->addr_reg.val);
295
296     return length;
297 }
298
299
300 static int data_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
301     struct pci_internal * pci_state =  priv_data;
302     struct pci_device * pci_dev = NULL;
303     uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3);
304     int i;
305
306     if (pci_state->addr_reg.bus_num != 0) {
307         int i = 0;
308         for (i = 0; i < length; i++) {
309             *((uint8_t *)dst + i) = 0xff;
310         }
311
312         return length;
313     }
314
315     PrintDebug("Reading PCI Data register. bus = %d, dev = %d, reg = %d (%x), cfg_reg = %x\n", 
316                pci_state->addr_reg.bus_num, 
317                pci_state->addr_reg.dev_num, 
318                reg_num, reg_num, 
319                pci_state->addr_reg.val);
320
321     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
322     
323     if (pci_dev == NULL) {
324         for (i = 0; i < length; i++) {
325             *(uint8_t *)((uint8_t *)dst + i) = 0xff;
326         }
327
328         return length;
329     }
330
331     if (pci_dev->type == PCI_PASSTHROUGH) {
332         if (pci_dev->config_read(reg_num, dst, length, pci_dev->priv_data) == -1) {
333             PrintError("Failed to handle configuration update for passthrough pci_device\n");
334             return -1;
335         }
336         
337         return 0;
338     }
339
340     for (i = 0; i < length; i++) {
341         *(uint8_t *)((uint8_t *)dst + i) = pci_dev->config_space[reg_num + i];
342     }
343
344     PrintDebug("\tVal=%x, len=%d\n", *(uint32_t *)dst, length);
345
346     return length;
347 }
348
349
350 static inline int is_cfg_reg_writable(uchar_t header_type, int reg_num) {
351     if (header_type == 0x00) {
352         switch (reg_num) {
353             case 0x00:
354             case 0x01:
355             case 0x02:
356             case 0x03:
357             case 0x08:
358             case 0x09:
359             case 0x0a:
360             case 0x0b:
361             case 0x0e:
362             case 0x3d:
363                 return 0;
364                            
365            default:
366                return 1;
367  
368         }
369     } else if (header_type == 0x80) {
370         switch (reg_num) {
371             case 0x00:
372             case 0x01:
373             case 0x02:
374             case 0x03:
375             case 0x08:
376             case 0x09:
377             case 0x0a:
378             case 0x0b:
379             case 0x0e:
380             case 0x3d:
381                 return 0;
382                            
383            default:
384                return 1;
385  
386         }
387     } else {
388         // PCI to PCI Bridge = 0x01
389         // CardBus Bridge = 0x02
390
391         // huh?
392         PrintError("Invalid PCI Header type (0x%.2x)\n", header_type);
393
394         return -1;
395     }
396 }
397
398 static int bar_update(struct guest_info * info, struct pci_device * pci, int bar_num, uint32_t new_val) {
399     struct v3_pci_bar * bar = &(pci->bar[bar_num]);
400
401     PrintDebug("Updating BAR Register  (Dev=%s) (bar=%d) (old_val=0x%x) (new_val=0x%x)\n", 
402                pci->name, bar_num, bar->val, new_val);
403
404     switch (bar->type) {
405         case PCI_BAR_IO: {
406             int i = 0;
407
408             PrintDebug("\tRehooking %d IO ports from base 0x%x to 0x%x for %d ports\n",
409                        bar->num_ports, PCI_IO_BASE(bar->val), PCI_IO_BASE(new_val),
410                        bar->num_ports);
411                 
412             // only do this if pci device is enabled....
413             if (!(pci->config_header.status & 0x1)) {
414                 PrintError("PCI Device IO space not enabled\n");
415             }
416
417             for (i = 0; i < bar->num_ports; i++) {
418
419                 PrintDebug("Rehooking PCI IO port (old port=%u) (new port=%u)\n",  
420                            PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
421
422                 v3_unhook_io_port(info->vm_info, PCI_IO_BASE(bar->val) + i);
423
424                 if (v3_hook_io_port(info->vm_info, PCI_IO_BASE(new_val) + i, 
425                                     bar->io_read, bar->io_write, 
426                                     bar->private_data) == -1) {
427
428                     PrintError("Could not hook PCI IO port (old port=%u) (new port=%u)\n",  
429                                PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
430                     v3_print_io_map(info->vm_info);
431                     return -1;
432                 }
433             }
434
435             bar->val = new_val;
436
437             break;
438         }
439         case PCI_BAR_MEM32: {
440             v3_unhook_mem(info->vm_info, V3_MEM_CORE_ANY, (addr_t)(bar->val));
441             
442             if (bar->mem_read) {
443                 v3_hook_full_mem(info->vm_info, V3_MEM_CORE_ANY, PCI_MEM32_BASE(new_val), 
444                                  PCI_MEM32_BASE(new_val) + (bar->num_pages * PAGE_SIZE_4KB),
445                                  bar->mem_read, bar->mem_write, pci->priv_data);
446             } else {
447                 PrintError("Write hooks not supported for PCI\n");
448                 return -1;
449             }
450
451             bar->val = new_val;
452
453             break;
454         }
455         case PCI_BAR_NONE: {
456             PrintDebug("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", 
457                        pci->name, bar_num, new_val);
458             break;
459         }
460         default:
461             PrintError("Invalid Bar Reg updated (bar=%d)\n", bar_num);
462             return -1;
463     }
464
465     return 0;
466 }
467
468
469 static int data_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
470     struct pci_internal * pci_state = priv_data;
471     struct pci_device * pci_dev = NULL;
472     uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3);
473     int i;
474
475
476     if (pci_state->addr_reg.bus_num != 0) {
477         return length;
478     }
479
480     PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (0x%x) addr_reg = 0x%x (val=0x%x, len=%d)\n", 
481                pci_state->addr_reg.bus_num, 
482                pci_state->addr_reg.dev_num, 
483                pci_state->addr_reg.fn_num,
484                reg_num, reg_num, 
485                pci_state->addr_reg.val,
486                *(uint32_t *)src, length);
487
488
489     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
490     
491     if (pci_dev == NULL) {
492         PrintError("Writing configuration space for non-present device (dev_num=%d)\n", 
493                    pci_state->addr_reg.dev_num); 
494         return -1;
495     }
496     
497     if (pci_dev->type == PCI_PASSTHROUGH) {
498         if (pci_dev->config_write(reg_num, src, length, pci_dev->priv_data) == -1) {
499             PrintError("Failed to handle configuration update for passthrough pci_device\n");
500             return -1;
501         }
502         
503         return 0;
504     }
505
506
507     for (i = 0; i < length; i++) {
508         uint_t cur_reg = reg_num + i;
509         int writable = is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg);
510         
511         if (writable == -1) {
512             PrintError("Invalid PCI configuration space\n");
513             return -1;
514         }
515
516         if (writable) {
517             pci_dev->config_space[cur_reg] = *(uint8_t *)((uint8_t *)src + i);
518
519             if ((cur_reg >= 0x10) && (cur_reg < 0x28)) {
520                 // BAR Register Update
521                 int bar_reg = ((cur_reg & ~0x3) - 0x10) / 4;
522                 
523                 pci_dev->bar_update_flag = 1;
524                 pci_dev->bar[bar_reg].updated = 1;
525                 
526                 // PrintDebug("Updating BAR register %d\n", bar_reg);
527
528             } else if ((cur_reg >= 0x30) && (cur_reg < 0x34)) {
529                 // Extension ROM update
530
531                 pci_dev->exp_rom_update_flag = 1;
532             } else if (cur_reg == 0x04) {
533                 // COMMAND update            
534                 uint8_t command = *((uint8_t *)src + i);
535                 
536                 PrintError("command update for %s old=%x new=%x\n",
537                            pci_dev->name, 
538                            pci_dev->config_space[cur_reg],command);
539
540                 pci_dev->config_space[cur_reg] = command;             
541
542                 if (pci_dev->cmd_update) {
543                     pci_dev->cmd_update(pci_dev, (command & 0x01), (command & 0x02));
544                 }
545                 
546             } else if (cur_reg == 0x0f) {
547                 // BIST update
548                 pci_dev->config_header.BIST = 0x00;
549             }
550         } else {
551             PrintError("PCI Write to read only register %d\n", cur_reg);
552         }
553     }
554
555     if (pci_dev->config_update) {
556         pci_dev->config_update(reg_num, src, length, pci_dev->priv_data);
557     }
558
559     // Scan for BAR updated
560     if (pci_dev->bar_update_flag) {
561         for (i = 0; i < 6; i++) {
562             if (pci_dev->bar[i].updated) {
563                 int bar_offset = 0x10 + 4 * i;
564
565
566                 if (pci_dev->bar[i].type == PCI_BAR_PASSTHROUGH) {
567                     if (pci_dev->bar[i].bar_write(i, (uint32_t *)(pci_dev->config_space + bar_offset), pci_dev->bar[i].private_data) == -1) {
568                         PrintError("Error in passthrough bar write operation\n");
569                         return -1;
570                     }
571                 } else {
572
573                     *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask;
574                     // check special flags....
575
576                     // bar_update
577                     if (bar_update(core, pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) {
578                         PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i);
579                         return -1;
580                     }
581                 }
582
583                 pci_dev->bar[i].updated = 0;
584             }
585         }
586         pci_dev->bar_update_flag = 0;
587     }
588
589     if ((pci_dev->exp_rom_update_flag) && (pci_dev->exp_rom_update)) {
590         pci_dev->exp_rom_update(pci_dev, &(pci_dev->config_header.expansion_rom_address), pci_dev->priv_data);
591         pci_dev->exp_rom_update_flag = 0;
592     }
593
594
595     return length;
596 }
597
598
599
600
601
602 static void init_pci_busses(struct pci_internal * pci_state) {
603     int i;
604
605     for (i = 0; i < PCI_BUS_COUNT; i++) {
606         pci_state->bus_list[i].bus_num = i;
607         pci_state->bus_list[i].devices.rb_node = NULL;
608         memset(pci_state->bus_list[i].dev_map, 0, sizeof(pci_state->bus_list[i].dev_map));
609     }
610 }
611
612
613 static int pci_free(struct pci_internal * pci_state) {
614     int i;
615
616
617     // cleanup devices
618     for (i = 0; i < PCI_BUS_COUNT; i++) {
619         struct pci_bus * bus = &(pci_state->bus_list[i]);
620         struct rb_node * node = v3_rb_first(&(bus->devices));
621         struct pci_device * dev = NULL;
622
623         while (node) {
624             dev = rb_entry(node, struct pci_device, dev_tree_node);
625             node = v3_rb_next(node);
626             
627             v3_rb_erase(&(dev->dev_tree_node), &(bus->devices));
628             V3_Free(dev);
629         }
630
631     }
632     
633     V3_Free(pci_state);
634     return 0;
635 }
636
637 #ifdef V3_CONFIG_CHECKPOINT
638
639 #include <palacios/vmm_sprintf.h>
640
641 static int pci_save(struct v3_chkpt_ctx * ctx, void * private_data) {
642     struct pci_internal * pci = (struct pci_internal *)private_data;
643     char buf[128];
644     int i = 0;    
645     
646     v3_chkpt_save_32(ctx, "ADDR_REG", &(pci->addr_reg.val));
647     v3_chkpt_save_16(ctx, "IO_BASE", &(pci->dev_io_base));
648
649     for (i = 0; i < PCI_BUS_COUNT; i++) {
650         struct pci_bus * bus = &(pci->bus_list[i]);
651         struct rb_node * node = v3_rb_first(&(bus->devices));
652         struct pci_device * dev = NULL;
653         struct v3_chkpt_ctx * bus_ctx = NULL;
654
655         snprintf(buf, 128, "pci-%d\n", i);
656         
657         bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
658
659         while (node) {
660             struct v3_chkpt_ctx * dev_ctx = NULL;
661             int bar_idx = 0;
662             dev = rb_entry(node, struct pci_device, dev_tree_node);
663
664             snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num);
665             dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf);
666             
667             v3_chkpt_save(dev_ctx, "CONFIG_SPACE", 256, dev->config_space);
668
669             for (bar_idx = 0; bar_idx < 6; bar_idx++) {
670                 snprintf(buf, 128, "BAR-%d", bar_idx);
671                 v3_chkpt_save_32(dev_ctx, buf, &(dev->bar[bar_idx].val));
672             }
673
674             node = v3_rb_next(node);
675         }
676     }
677
678
679     return 0;
680 }
681
682
683 static int pci_load(struct v3_chkpt_ctx * ctx, void * private_data) {
684     struct pci_internal * pci = (struct pci_internal *)private_data;
685     char buf[128];
686     int i = 0;    
687     
688     v3_chkpt_load_32(ctx, "ADDR_REG", &(pci->addr_reg.val));
689     v3_chkpt_load_16(ctx, "IO_BASE", &(pci->dev_io_base));
690
691     for (i = 0; i < PCI_BUS_COUNT; i++) {
692         struct pci_bus * bus = &(pci->bus_list[i]);
693         struct rb_node * node = v3_rb_first(&(bus->devices));
694         struct pci_device * dev = NULL;
695         struct v3_chkpt_ctx * bus_ctx = NULL;
696
697         snprintf(buf, 128, "pci-%d\n", i);
698         
699         bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
700
701         while (node) {
702             struct v3_chkpt_ctx * dev_ctx = NULL;
703             int bar_idx = 0;
704             dev = rb_entry(node, struct pci_device, dev_tree_node);
705
706             snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num);
707             dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf);
708             
709             v3_chkpt_load(dev_ctx, "CONFIG_SPACE", 256, dev->config_space);
710
711             for (bar_idx = 0; bar_idx < 6; bar_idx++) {
712                 snprintf(buf, 128, "BAR-%d", bar_idx);
713                 v3_chkpt_load_32(dev_ctx, buf, &(dev->bar[bar_idx].val));
714             }
715
716             node = v3_rb_next(node);
717         }
718     }
719
720
721     return 0;
722 }
723
724
725 #endif
726
727
728
729
730 static struct v3_device_ops dev_ops = {
731     .free = (int (*)(void *))pci_free,
732 #ifdef V3_CONFIG_CHECKPOINT
733     .save = pci_save,
734     .load = pci_load
735 #endif
736 };
737
738
739
740
741 static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
742     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
743     int i = 0;
744     char * dev_id = v3_cfg_val(cfg, "ID");
745     int ret = 0;
746     
747     PrintDebug("PCI internal at %p\n",(void *)pci_state);
748     
749     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, pci_state);
750     
751     if (dev == NULL) {
752         PrintError("Could not attach device %s\n", dev_id);
753         V3_Free(pci_state);
754         return -1;
755     }
756
757     
758     pci_state->addr_reg.val = 0; 
759     pci_state->dev_io_base = PCI_DEV_IO_PORT_BASE;
760
761     init_pci_busses(pci_state);
762     
763     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
764     
765     for (i = 0; i < 4; i++) {
766         ret |= v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write);
767         ret |= v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write);
768     }
769     
770     if (ret != 0) {
771         PrintError("Error hooking PCI IO ports\n");
772         v3_remove_device(dev);
773         return -1;
774     }
775
776     return 0;
777 }
778
779
780 device_register("PCI", pci_init)
781
782
783 static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev) {
784     int i = 0;
785
786     for (i = 0; i < 6; i++) {
787         int bar_offset = 0x10 + (4 * i);
788
789         if (pci_dev->bar[i].type == PCI_BAR_IO) {
790             int j = 0;
791             pci_dev->bar[i].mask = (~((pci_dev->bar[i].num_ports) - 1)) | 0x01;
792
793             if (pci_dev->bar[i].default_base_port != 0xffff) {
794                 pci_dev->bar[i].val = pci_dev->bar[i].default_base_port & pci_dev->bar[i].mask;
795             } else {
796                 pci_dev->bar[i].val = 0;
797             }
798
799             pci_dev->bar[i].val |= 0x00000001;
800
801             for (j = 0; j < pci_dev->bar[i].num_ports; j++) {
802                 // hook IO
803                 if (pci_dev->bar[i].default_base_port != 0xffff) {
804                     if (v3_hook_io_port(vm, pci_dev->bar[i].default_base_port + j,
805                                         pci_dev->bar[i].io_read, pci_dev->bar[i].io_write, 
806                                         pci_dev->bar[i].private_data) == -1) {
807                         PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j);
808                         return -1;
809                     }
810                 }
811             }
812
813             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
814
815         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
816             pci_dev->bar[i].mask = ~((pci_dev->bar[i].num_pages << 12) - 1);
817             pci_dev->bar[i].mask |= 0xf; // preserve the configuration flags
818
819             if (pci_dev->bar[i].default_base_addr != 0xffffffff) {
820                 pci_dev->bar[i].val = pci_dev->bar[i].default_base_addr & pci_dev->bar[i].mask;
821             } else {
822                 pci_dev->bar[i].val = 0;
823             }
824
825             // hook memory
826             if (pci_dev->bar[i].mem_read) {
827                 // full hook
828                 v3_hook_full_mem(vm, V3_MEM_CORE_ANY, pci_dev->bar[i].default_base_addr,
829                                  pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
830                                  pci_dev->bar[i].mem_read, pci_dev->bar[i].mem_write, pci_dev->priv_data);
831             } else if (pci_dev->bar[i].mem_write) {
832                 // write hook
833                 PrintError("Write hooks not supported for PCI devices\n");
834                 return -1;
835                 /*
836                   v3_hook_write_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr, 
837                   pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
838                   pci_dev->bar[i].mem_write, pci_dev->vm_dev);
839                 */
840             } else {
841                 // set the prefetchable flag...
842                 pci_dev->bar[i].val |= 0x00000008;
843             }
844
845
846             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
847
848         } else if (pci_dev->bar[i].type == PCI_BAR_MEM24) {
849             PrintError("16 Bit memory ranges not supported (reg: %d)\n", i);
850             return -1;
851         } else if (pci_dev->bar[i].type == PCI_BAR_NONE) {
852             pci_dev->bar[i].val = 0x00000000;
853             pci_dev->bar[i].mask = 0x00000000; // This ensures that all updates will be dropped
854             *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val;
855         } else if (pci_dev->bar[i].type == PCI_BAR_PASSTHROUGH) {
856
857             // Call the bar init function to get the local cached value
858             pci_dev->bar[i].bar_init(i, &(pci_dev->bar[i].val), pci_dev->bar[i].private_data);
859
860         } else {
861             PrintError("Invalid BAR type for bar #%d\n", i);
862             return -1;
863         }
864     }
865
866     return 0;
867 }
868
869
870 int v3_pci_set_irq_bridge(struct  vm_device * pci_bus, int bus_num, 
871                           int (*raise_pci_irq)(struct pci_device * pci_dev, void * dev_data),
872                           int (*lower_pci_irq)(struct pci_device * pci_dev, void * dev_data),
873                           void * priv_data) {
874     struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
875
876
877     pci_state->bus_list[bus_num].raise_pci_irq = raise_pci_irq;
878     pci_state->bus_list[bus_num].lower_pci_irq = lower_pci_irq;
879     pci_state->bus_list[bus_num].irq_dev_data = priv_data;
880
881     return 0;
882 }
883
884 int v3_pci_raise_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) {
885    struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
886    struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
887
888    return bus->raise_pci_irq(dev, bus->irq_dev_data);
889 }
890
891 int v3_pci_lower_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) {
892    struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
893    struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
894
895    return bus->lower_pci_irq(dev, bus->irq_dev_data);
896 }
897
898 // if dev_num == -1, auto assign 
899 struct pci_device * v3_pci_register_device(struct vm_device * pci,
900                                            pci_device_type_t dev_type, 
901                                            int bus_num,
902                                            int dev_num,
903                                            int fn_num,
904                                            const char * name,
905                                            struct v3_pci_bar * bars,
906                                            int (*config_update)(uint_t reg_num, void * src, uint_t length, void * priv_data),
907                                            int (*cmd_update)(struct pci_device * pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
908                                            int (*exp_rom_update)(struct pci_device * pci_dev, uint32_t * src, void * priv_data),
909                                            void * priv_data) {
910
911     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
912     struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
913     struct pci_device * pci_dev = NULL;
914     int i;
915
916     if (dev_num > MAX_BUS_DEVICES) {
917         PrintError("Requested Invalid device number (%d)\n", dev_num);
918         return NULL;
919     }
920
921     if (dev_num == PCI_AUTO_DEV_NUM) {
922         PrintDebug("Searching for free device number\n");
923         if ((dev_num = get_free_dev_num(bus)) == -1) {
924             PrintError("No more available PCI slots on bus %d\n", bus->bus_num);
925             return NULL;
926         }
927     }
928     
929     PrintDebug("Checking for PCI Device\n");
930
931     if (get_device(bus, dev_num, fn_num) != NULL) {
932         PrintError("PCI Device already registered at slot %d on bus %d\n", 
933                    dev_num, bus->bus_num);
934         return NULL;
935     }
936
937     
938     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
939
940     if (pci_dev == NULL) {
941         PrintError("Could not allocate pci device\n");
942         return NULL;
943     }
944
945     memset(pci_dev, 0, sizeof(struct pci_device));
946
947
948     pci_dev->type = dev_type;
949     
950     switch (pci_dev->type) {
951         case PCI_STD_DEVICE:
952             pci_dev->config_header.header_type = 0x00;
953             break;
954         case PCI_MULTIFUNCTION:
955             pci_dev->config_header.header_type = 0x80;
956             break;
957         default:
958             PrintError("Unhandled PCI Device Type: %d\n", dev_type);
959             return NULL;
960     }
961
962
963
964     pci_dev->bus_num = bus_num;
965     pci_dev->dev_num = dev_num;
966     pci_dev->fn_num = fn_num;
967
968     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
969     pci_dev->priv_data = priv_data;
970
971     // register update callbacks
972     pci_dev->config_update = config_update;
973     pci_dev->cmd_update = cmd_update;
974     pci_dev->exp_rom_update = exp_rom_update;
975
976
977     //copy bars
978     for (i = 0; i < 6; i ++) {
979         pci_dev->bar[i].type = bars[i].type;
980         pci_dev->bar[i].private_data = bars[i].private_data;
981
982         if (pci_dev->bar[i].type == PCI_BAR_IO) {
983             pci_dev->bar[i].num_ports = bars[i].num_ports;
984
985             // This is a horrible HACK becaues the BIOS is supposed to set the PCI base ports 
986             // And if the BIOS doesn't, Linux just happily overlaps device port assignments
987             if (bars[i].default_base_port != (uint16_t)-1) {
988                 pci_dev->bar[i].default_base_port = bars[i].default_base_port;
989             } else {
990                 pci_dev->bar[i].default_base_port = pci_state->dev_io_base;
991                 pci_state->dev_io_base += ( 0x100 * ((bars[i].num_ports / 0x100) + 1) );
992             }
993
994             pci_dev->bar[i].io_read = bars[i].io_read;
995             pci_dev->bar[i].io_write = bars[i].io_write;
996         } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
997             pci_dev->bar[i].num_pages = bars[i].num_pages;
998             pci_dev->bar[i].default_base_addr = bars[i].default_base_addr;
999             pci_dev->bar[i].mem_read = bars[i].mem_read;
1000             pci_dev->bar[i].mem_write = bars[i].mem_write;
1001         } else if (pci_dev->bar[i].type == PCI_BAR_PASSTHROUGH) {
1002             pci_dev->bar[i].bar_init = bars[i].bar_init;
1003             pci_dev->bar[i].bar_write = bars[i].bar_write;
1004         } else {
1005             pci_dev->bar[i].num_pages = 0;
1006             pci_dev->bar[i].default_base_addr = 0;
1007             pci_dev->bar[i].mem_read = NULL;
1008             pci_dev->bar[i].mem_write = NULL;
1009         }
1010     }
1011
1012     if (init_bars(pci->vm, pci_dev) == -1) {
1013         PrintError("could not initialize bar registers\n");
1014         return NULL;
1015     }
1016
1017     // add the device
1018     add_device_to_bus(bus, pci_dev);
1019
1020 #ifdef V3_CONFIG_DEBUG_PCI
1021     pci_dump_state(pci_state);
1022 #endif
1023
1024     return pci_dev;
1025 }
1026
1027
1028
1029 // if dev_num == -1, auto assign 
1030 struct pci_device * v3_pci_register_passthrough_device(struct vm_device * pci,
1031                                                        int bus_num,
1032                                                        int dev_num,
1033                                                        int fn_num,
1034                                                        const char * name,
1035                                                        int (*config_write)(uint_t reg_num, void * src, uint_t length, void * private_data),
1036                                                        int (*config_read)(uint_t reg_num, void * dst, uint_t length, void * private_data),
1037                                                        void * private_data) {
1038
1039     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
1040     struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
1041     struct pci_device * pci_dev = NULL;
1042
1043     if (dev_num > MAX_BUS_DEVICES) {
1044         PrintError("Requested Invalid device number (%d)\n", dev_num);
1045         return NULL;
1046     }
1047
1048     if (dev_num == PCI_AUTO_DEV_NUM) {
1049         PrintDebug("Searching for free device number\n");
1050         if ((dev_num = get_free_dev_num(bus)) == -1) {
1051             PrintError("No more available PCI slots on bus %d\n", bus->bus_num);
1052             return NULL;
1053         }
1054     }
1055     
1056     PrintDebug("Checking for PCI Device\n");
1057
1058     if (get_device(bus, dev_num, fn_num) != NULL) {
1059         PrintError("PCI Device already registered at slot %d on bus %d\n", 
1060                    dev_num, bus->bus_num);
1061         return NULL;
1062     }
1063
1064     
1065     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
1066
1067     if (pci_dev == NULL) {
1068         PrintError("Could not allocate pci device\n");
1069         return NULL;
1070     }
1071
1072     memset(pci_dev, 0, sizeof(struct pci_device));
1073     
1074     pci_dev->bus_num = bus_num;
1075     pci_dev->dev_num = dev_num;
1076     pci_dev->fn_num = fn_num;
1077
1078     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
1079     pci_dev->priv_data = private_data;
1080
1081     // register update callbacks
1082     pci_dev->config_write = config_write;
1083     pci_dev->config_read = config_read;
1084
1085     // add the device
1086     add_device_to_bus(bus, pci_dev);
1087
1088 #ifdef V3_CONFIG_DEBUG_PCI
1089     pci_dump_state(pci_state);
1090 #endif
1091
1092     return pci_dev;
1093 }