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.


More detailed error handling on msr writes
[palacios.git] / palacios / src / devices / piix3.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, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */ 
19  
20
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_dev_mgr.h>
23 #include <palacios/vmm_intr.h>
24
25 #include <devices/pci.h>
26 #include <devices/southbridge.h>
27
28
29 struct iort_reg {
30     union {
31         uint8_t value;
32         struct {
33             uint8_t times_16bit   : 2;
34             uint8_t enable_16bit  : 1;
35             uint8_t times_8bit    : 3;
36             uint8_t enable_8bit   : 1;
37             uint8_t dmaac         : 1;
38         } __attribute__((packed));
39     } __attribute__((packed));
40 } __attribute__((packed));
41
42 struct xbcs_reg {
43     union {
44         uint16_t value;
45         struct {
46             uint8_t rtc_addr_en        : 1;
47             uint8_t kb_ctrl_en         : 1;
48             uint8_t bioscs_wprot_en    : 1;
49             uint8_t rsvd1              : 1;
50             uint8_t irq12_mouse_fn_en  : 1;
51             uint8_t coproc_err_fn_en   : 1;
52             uint8_t lower_bios_en      : 1;
53             uint8_t ext_bios_en        : 1;
54             uint8_t apic_chip_sel      : 1;
55             uint8_t piix_rsvd          : 7;
56         } __attribute__((packed));
57     } __attribute__((packed));
58 } __attribute__((packed));
59
60
61 struct pirq_route_ctrl_req {
62     union {
63         uint8_t value;
64         struct {
65             uint8_t irq_routing        : 4;
66             uint8_t rsvd               : 3;
67             uint8_t irq_route_en       : 1;
68         } __attribute__((packed));
69     } __attribute__((packed));
70 } __attribute__((packed));
71
72 struct top_of_mem_reg {
73     union {
74         uint8_t value;
75         struct {
76             uint8_t rsvd1                    : 1;
77     uint8_t isadma_reg_fwd_en        : 1;
78             uint8_t piix_rsvd                : 1;
79             uint8_t isadma_lo_bios_fwd_en    : 1;
80             uint8_t top_of_mem               : 4;
81         } __attribute__((packed));
82     } __attribute__((packed));
83 } __attribute__((packed));
84
85 // Miscellaneous Status register
86 struct misc_stat_reg {
87     union {
88         uint16_t value;
89         struct {
90             uint8_t isa_clk_div              : 1;
91             uint8_t piix_rsvd1               : 1;
92             uint8_t pci_hdr_type_en          : 1;
93             uint8_t rsvd1                    : 1;
94             uint8_t usb_en                   : 1;
95             uint8_t rsvd2                    : 1;
96             uint8_t ext_sm_mode_en           : 1;
97             uint8_t nb_retry_en              : 1;
98             uint8_t rsvd3                    : 7;
99             uint8_t serr_gen_delayed_tranx   : 1;
100         } __attribute__((packed));
101     } __attribute__((packed));
102 } __attribute__((packed));
103
104
105
106 // Motherboard Device IRQ route control register
107 struct mb_irq_ctrl_reg {
108     union {
109         uint8_t value;
110         struct {
111             uint8_t irq_routing              : 4;
112             uint8_t rsvd                     : 1;
113             uint8_t irq0_en                  : 1;
114             uint8_t irq_sharing_en           : 1;
115             uint8_t irq_routing_en           : 1;
116         } __attribute__((packed));
117     } __attribute__((packed));
118 } __attribute__((packed));
119
120 // Motherboard Device DMA control register
121 struct mb_dma_ctrl_reg {
122     union {
123         uint8_t value;
124         struct {
125             uint8_t type_f_dma_routing       : 3;
126             uint8_t piix_rsvd                : 1;
127             uint8_t rsvd                     : 3;
128             uint8_t type_f_dma_buf_en        : 1;
129         } __attribute__((packed));
130     } __attribute__((packed));
131 } __attribute__((packed));
132
133
134 // Programmable Chip Select Control Register
135 struct prg_chip_sel_ctrl_reg {
136     union {
137         uint16_t value;
138         struct {
139             uint8_t pcs_addr_mask            : 2;
140             uint16_t pcs_addr                : 14;
141         } __attribute__((packed));
142     } __attribute__((packed));
143 } __attribute__((packed));
144
145
146 // APIC base address relocation register
147 struct apic_base_addr_reg {
148     union {
149         uint8_t value;
150         struct {
151             uint8_t y_base_addr             : 2;
152             uint8_t x_base_addr             : 4;
153             uint8_t a12_mask                : 1;
154             uint8_t rsvd                    : 1;
155         } __attribute__((packed));
156     } __attribute__((packed));
157 } __attribute__((packed));
158
159
160 // Deterministic Latency control register
161 struct deter_lat_ctrl_reg {
162     union {
163         uint8_t value;
164         struct {
165             uint8_t delayed_trans_en        : 1;
166             uint8_t pass_release_en         : 1;
167             uint8_t usb_pass_release_en     : 1;
168             uint8_t serr_gen_trans_tmout_en : 1;
169             uint8_t rsvd                    : 4;
170         } __attribute__((packed));
171     } __attribute__((packed));
172 } __attribute__((packed));
173
174 // SMI Control Register
175 struct smi_ctrl_reg {
176     union {
177         uint8_t value;
178         struct {
179             uint8_t smi_gate               : 1;
180             uint8_t stpclk_sig_en          : 1;
181             uint8_t stpclk_scaling_en      : 1;
182             uint8_t fast_off_tmr_freeze    : 2;
183             uint8_t rsvd                   : 3;
184         } __attribute__((packed));
185     } __attribute__((packed));
186 } __attribute__((packed));
187
188 // SMI Enable register
189 struct smi_enable_reg {
190     union {
191         uint16_t value;
192         struct {
193             uint8_t irq1_smi_en            : 1; // (keyboard irq)
194             uint8_t irq3_smi_en            : 1; // (COM1/COM3/Mouse irq)
195             uint8_t irq4_smi_en            : 1; // (COM2/COM4/Mouse irq)
196             uint8_t irq8_smi_en            : 1; // (RTC irq)
197             uint8_t irq12_smi_en           : 1; // (PS/2 mouse irq)
198             uint8_t fast_off_tmr_en        : 1;
199             uint8_t ext_smi_en             : 1;
200             uint8_t apic_wr_smi_en         : 1;
201             uint8_t legacy_usb_smi_en      : 1;
202             uint8_t rsvd                   : 7;
203         } __attribute__((packed));
204     } __attribute__((packed));
205 } __attribute__((packed));
206
207
208 // System Event Enable register
209 struct sys_evt_en_reg {
210     union {
211         uint32_t value;
212         struct {
213             uint8_t firq0_en               : 1;
214             uint8_t firq1_en               : 1;
215             uint8_t rsvd1                  : 1;
216             uint8_t firq3_en               : 1;
217             uint8_t firq4_en               : 1;
218             uint8_t firq5_en               : 1;
219             uint8_t firq6_en               : 1;
220             uint8_t firq7_en               : 1;
221             uint8_t firq8_en               : 1;
222             uint8_t firq9_en               : 1;
223             uint8_t firq10_en              : 1;
224             uint8_t firq11_en              : 1;
225             uint8_t firq12_en              : 1;
226             uint8_t firq13_en              : 1;
227             uint8_t firq14_en              : 1;
228             uint8_t firq15_en              : 1;
229             uint16_t rsvd2                 : 12;
230             uint8_t fast_off_apic_en       : 1;
231             uint8_t fast_off_nmi_en        : 1;
232             uint8_t intr_en                : 1;
233             uint8_t fast_off_smi_en        : 1;
234         } __attribute__((packed));
235     } __attribute__((packed));
236 } __attribute__((packed));
237
238
239 // SMI Request Register
240 struct smi_req_reg {
241     union {
242         uint16_t value;
243         struct {
244             uint8_t irq1_req_smi_stat      : 1;
245             uint8_t irq3_req_smi_stat      : 1;
246             uint8_t irq4_req_smi_stat      : 1;
247             uint8_t irq8_req_smi_stat      : 1;
248             uint8_t irq12_req_smi_stat     : 1;
249             uint8_t fast_off_tmr_exp_stat  : 1;
250             uint8_t extsmi_stat            : 1;
251             uint8_t apm_smi_stat           : 1;
252             uint8_t legacy_usb_smi_stat    : 1;
253             uint8_t rsvd                   : 7;
254         } __attribute__((packed));
255     } __attribute__((packed));
256 } __attribute__((packed));
257
258
259 struct piix3_config_space {
260     uint8_t rsvd1[12];            // 0x40 - 0x4b
261
262     // ISA I/O Recovery timer register
263     uint8_t iort;                 // 0x4c        (default 0x4d)
264     uint8_t rsvd2;                // 0x4d
265
266     // X-Bus Chip select register
267     uint16_t xbcs;                // 0x4e - 0x4f (default: 0x03)
268     uint8_t rsvd3[16];            // 0x50 - 0x5f
269
270     // pirq route control register (IRQs A-D)
271     uint8_t pirq_rc[4];           // 0x60 - 0x63 (default: 0x80) 
272     uint8_t rsvd4[5];             // 0x64 - 0x68
273
274     // top of memory register
275     uint8_t top_of_mem;           // 0x69        (default: 0x02)
276
277     // Miscellaneous status register
278     uint16_t mstat;               // 0x6A - 0x6B (default: undefined)
279     uint8_t rsvd5[4];             // 0x6c - 0x6f
280
281     // Motherboard device IRQ route control register
282     uint8_t mbirq0;                // 0x70        (default: 0x80)
283     uint8_t rsvd6;                 // 0x71 (piix only)
284     uint8_t rsvd7[4];              // 0x72 - 0x75
285
286     // Motherboard Device DMA Control registers
287     uint8_t mbdma0;                // 0x76        (default: 0x0c)
288     uint8_t mbdma1;                // 0x77        (default: 0x0c)
289
290     // Programmable Chip Select Control Register  
291     uint16_t pcsc;                 // 0x78 - 0x79 (default: 0x0002)
292     uint8_t rsvd8[6];              // 0x7A - 0x7F
293
294     // APIC base address relocation register
295     uint8_t apicbase;              // 0x80        (default: 0x00)
296     uint8_t rsvd9;                 // 0x81
297
298
299     // Deterministic Latency control register
300     uint8_t dlc;                   // 0x82        (default: 0x00)
301     uint8_t rsvd10[29];            // 0x83 - 0x9f
302
303
304     // SMI Control Register
305     uint8_t smicntl;               // 0xa0        (default: 0x08)
306     uint8_t rsvd11;                // 0xa1
307
308     // SMI Enable register
309     uint16_t smien;                // 0xa2 - 0xa3 (default: 0x0000)
310
311     // System Event Enable register
312     uint32_t see;                  // 0xa4 - 0xa7 (default: 0x00000000)
313
314     // Fast off timer register
315     uint8_t ftmr;                  // 0xa8        (default: 0x0f)
316     uint8_t rsvd12;                // 0xa9
317
318     // SMI Request Register
319     uint16_t smireq;               // 0xaa - 0xab (default: 0x0000)
320
321     // Clock Scale stpclk low timer
322     uint8_t ctltmr;                // 0xac        (default: 0x00)
323     uint8_t rsvd13;                // 0xad
324
325     // Slock Scale STPCLK high timer
326     uint8_t cthtmr;                // 0xae        (default: 0x00)
327
328 } __attribute__((packed));
329
330
331
332 static int reset_piix3(struct v3_southbridge * piix3) {
333     struct pci_device * pci_dev = piix3->southbridge_pci;
334     struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(pci_dev->config_data);
335
336     pci_dev->config_header.command = 0x0007; // master, memory and I/O
337     pci_dev->config_header.status = 0x0200;
338
339     piix3_cfg->iort = 0x4d;
340     piix3_cfg->xbcs = 0x0003;
341     piix3_cfg->pirq_rc[0] = 0x80;
342     piix3_cfg->pirq_rc[1] = 0x80;
343     piix3_cfg->pirq_rc[2] = 0x80;
344     piix3_cfg->pirq_rc[3] = 0x80;
345     piix3_cfg->top_of_mem = 0x02;
346     piix3_cfg->mbirq0 = 0x80;
347     piix3_cfg->mbdma0 = 0x0c;
348     piix3_cfg->mbdma1 = 0x0c;
349     piix3_cfg->pcsc = 0x0002;
350     piix3_cfg->apicbase = 0x00;
351     piix3_cfg->dlc = 0x00;
352     piix3_cfg->smicntl = 0x08;
353     piix3_cfg->smien = 0x0000;
354     piix3_cfg->see = 0x00000000;
355     piix3_cfg->ftmr = 0x0f;
356     piix3_cfg->smireq = 0x0000;
357     piix3_cfg->ctltmr = 0x00;
358     piix3_cfg->cthtmr = 0x00;
359
360     return 0;
361 }
362
363
364 //irq is pirq_rc[intr_pin + pci_dev_num - 1] & 0xf
365 /*
366 struct pirq_rc_reg {
367        uint8_t irq         : 4;
368        uint8_t rsvd        : 3;
369        uint8_t disabled    : 1; // (1=disabled, 0=enabled)
370 }
371 */
372
373
374 static int raise_pci_irq(struct pci_device * pci_dev, void * dev_data) {
375     struct v3_southbridge * piix3 = dev_data;
376     struct pci_device * piix3_pci = piix3->southbridge_pci;
377     struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(piix3_pci->config_data);
378     int intr_pin = pci_dev->config_header.intr_pin - 1;
379     int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
380
381     /*
382     PrintError("Raising PCI dev %d intr %d via IOAPIC as IRQ %d and via PIRQ as IRQ %d on VM %p\n", 
383                pci_dev->dev_num, pci_dev->config_header.intr_pin, 
384                16+irq_index,
385                piix3_cfg->pirq_rc[irq_index], piix3->vm);
386     */
387
388     // deliver first by PIRQ, if it exists
389     //
390     if (piix3_cfg->pirq_rc[irq_index] < 16) {
391         v3_raise_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index] & 0xf);
392     } else {
393       // not an error
394     }
395
396     // deliver next via the PCI0 to ioapic mapping defined in the 
397     // mptable (ioapic, pins 16->19 are used for PCI0)
398     // ideally this would check to verify that an ioapic is actually available
399     v3_raise_irq(piix3->vm, 16+irq_index);
400     
401
402     return 0;
403 }
404
405
406
407 static int lower_pci_irq(struct pci_device * pci_dev, void * dev_data) {
408     struct v3_southbridge * piix3 = dev_data;
409     struct pci_device * piix3_pci = piix3->southbridge_pci;
410     struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(piix3_pci->config_data);
411     int intr_pin = pci_dev->config_header.intr_pin - 1;
412     int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
413     
414     //    PrintError("Lowering PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
415
416     // First, lower the pin on the ioapic
417     v3_lower_irq(piix3->vm, irq_index+16);
418     
419     // Next, lower whatever we asserted by the PIRQs
420     if (piix3_cfg->pirq_rc[irq_index] < 16) {
421         v3_lower_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index] & 0xf);
422     } else {
423       // not an error
424     }
425
426     return 0;
427 }
428
429
430
431 static int piix_free(struct v3_southbridge * piix3) {
432
433     // unregister pci
434
435     V3_Free(piix3);
436     return 0;
437 }
438
439
440 static struct v3_device_ops dev_ops = {
441     .free = (int (*)(void *))piix_free,
442 };
443
444
445
446
447 static int setup_pci(struct v3_southbridge * piix3) {
448     struct pci_device * pci_dev = NULL;
449     struct v3_pci_bar bars[6];
450     int i;
451     int bus_num = 0;
452
453     for (i = 0; i < 6; i++) {
454         bars[i].type = PCI_BAR_NONE;
455     }
456
457     pci_dev = v3_pci_register_device(piix3->pci_bus, PCI_MULTIFUNCTION, 
458                                      bus_num, -1, 0, 
459                                      "PIIX3", bars, 
460                                      NULL, NULL, NULL, piix3);
461     if (pci_dev == NULL) {
462         PrintError("Could not register PCI Device for PIIX3\n");
463         return -1;
464     }
465
466     pci_dev->config_header.vendor_id = 0x8086;
467     pci_dev->config_header.device_id = 0x7000; // PIIX4 is 0x7001
468     pci_dev->config_header.class = PCI_CLASS_BRIDGE;
469     pci_dev->config_header.subclass = PCI_BRIDGE_SUBCLASS_PCI_ISA; 
470
471     piix3->southbridge_pci = pci_dev;
472
473     v3_pci_set_irq_bridge(piix3->pci_bus, bus_num, raise_pci_irq, lower_pci_irq, piix3);
474
475     reset_piix3(piix3);
476
477     return 0;
478 }
479
480 static int piix3_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
481     struct v3_southbridge * piix3 = (struct v3_southbridge *)V3_Malloc(sizeof(struct v3_southbridge));
482     struct vm_device * dev = NULL;
483     struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
484     char * dev_id = v3_cfg_val(cfg, "ID");
485
486     if (!pci) {
487         PrintError("Could not find PCI device\n");
488         return -1;
489     }
490
491     piix3->pci_bus = pci;
492     piix3->type = V3_SB_PIIX3;
493     piix3->vm = vm;
494     
495     dev = v3_add_device(vm, dev_id, &dev_ops, piix3);
496
497     if (dev == NULL) {
498         PrintError("Could not attach device %s\n", dev_id);
499         V3_Free(piix3);
500         return -1;
501     }
502
503     PrintDebug("Created PIIX3\n");
504
505     if (setup_pci(piix3) == -1) {
506         v3_remove_device(dev);
507         return -1;
508     }
509
510     return 0;
511 }
512
513
514 device_register("PIIX3", piix3_init)