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.


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