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.


integrated new configuration system
[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 vm_device * dev) {
333     struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
334     struct pci_device * pci_dev = piix3->southbridge_pci;
335     struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(pci_dev->config_data);
336
337     pci_dev->config_header.command = 0x0007; // master, memory and I/O
338     pci_dev->config_header.status = 0x0200;
339
340     piix3_cfg->iort = 0x4d;
341     piix3_cfg->xbcs = 0x0003;
342     piix3_cfg->pirq_rc[0] = 0x80;
343     piix3_cfg->pirq_rc[1] = 0x80;
344     piix3_cfg->pirq_rc[2] = 0x80;
345     piix3_cfg->pirq_rc[3] = 0x80;
346     piix3_cfg->top_of_mem = 0x02;
347     piix3_cfg->mbirq0 = 0x80;
348     piix3_cfg->mbdma0 = 0x0c;
349     piix3_cfg->mbdma1 = 0x0c;
350     piix3_cfg->pcsc = 0x0002;
351     piix3_cfg->apicbase = 0x00;
352     piix3_cfg->dlc = 0x00;
353     piix3_cfg->smicntl = 0x08;
354     piix3_cfg->smien = 0x0000;
355     piix3_cfg->see = 0x00000000;
356     piix3_cfg->ftmr = 0x0f;
357     piix3_cfg->smireq = 0x0000;
358     piix3_cfg->ctltmr = 0x00;
359     piix3_cfg->cthtmr = 0x00;
360
361     return 0;
362 }
363
364
365 //irq is pirq_rc[intr_pin + pci_dev_num - 1] & 0x3
366
367 static int raise_pci_irq(struct vm_device * dev, struct pci_device * pci_dev) {
368     struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
369     struct pci_device * piix3_pci = piix3->southbridge_pci;
370     struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(piix3_pci->config_data);
371     int intr_pin = pci_dev->config_header.intr_pin - 1;
372     int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
373     
374     //        PrintError("Raising PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
375     
376     v3_raise_irq(dev->vm, piix3_cfg->pirq_rc[irq_index]);
377
378     return 0;
379 }
380
381
382
383 static int lower_pci_irq(struct vm_device * dev, struct pci_device * pci_dev) {
384     struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
385     struct pci_device * piix3_pci = piix3->southbridge_pci;
386     struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(piix3_pci->config_data);
387     int intr_pin = pci_dev->config_header.intr_pin - 1;
388     int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
389     
390     //    PrintError("Lowering PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
391     
392     v3_lower_irq(dev->vm, piix3_cfg->pirq_rc[irq_index]);
393
394     return 0;
395 }
396
397
398
399 static int piix_free(struct vm_device * dev) {
400     return 0;
401 }
402
403
404 static struct v3_device_ops dev_ops = {
405     .free = piix_free,
406     .reset = reset_piix3,
407     .start = NULL,
408     .stop = NULL,
409 };
410
411
412
413
414 static int setup_pci(struct vm_device * dev) {
415     struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
416     struct pci_device * pci_dev = NULL;
417     struct v3_pci_bar bars[6];
418     int i;
419     int bus_num = 0;
420
421     for (i = 0; i < 6; i++) {
422         bars[i].type = PCI_BAR_NONE;
423     }
424
425     pci_dev = v3_pci_register_device(piix3->pci_bus, PCI_MULTIFUNCTION, 
426                                      bus_num, -1, 0, 
427                                      "PIIX3", bars, 
428                                      NULL, NULL, NULL, dev);
429     if (pci_dev == NULL) {
430         PrintError("Could not register PCI Device for PIIX3\n");
431         return -1;
432     }
433
434     pci_dev->config_header.vendor_id = 0x8086;
435     pci_dev->config_header.device_id = 0x7000; // PIIX4 is 0x7001
436     pci_dev->config_header.class = PCI_CLASS_BRIDGE;
437     pci_dev->config_header.subclass = PCI_BRIDGE_SUBCLASS_PCI_ISA; 
438
439     piix3->southbridge_pci = pci_dev;
440
441     v3_pci_set_irq_bridge(piix3->pci_bus, bus_num, raise_pci_irq, lower_pci_irq, dev);
442
443     reset_piix3(dev);
444
445     return 0;
446 }
447
448 static int piix3_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
449     struct v3_southbridge * piix3 = (struct v3_southbridge *)V3_Malloc(sizeof(struct v3_southbridge));
450     struct vm_device * dev = NULL;
451     struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
452     char * name = v3_cfg_val(cfg, "name");
453
454     if (!pci) {
455         PrintError("Could not find PCI device\n");
456         return -1;
457     }
458
459     piix3->pci_bus = pci;
460     piix3->type = V3_SB_PIIX3;
461     
462     dev = v3_allocate_device(name, &dev_ops, piix3);
463
464     if (v3_attach_device(vm, dev) == -1) {
465         PrintError("Could not attach device %s\n", name);
466         return -1;
467     }
468
469     PrintDebug("Created PIIX3\n");
470
471     return setup_pci(dev);
472 }
473
474
475 device_register("PIIX3", piix3_init)