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.


44a00ed2452c272486d68e80506f7b45f6c83efe
[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
361 //irq is pirq_rc[intr_pin + pci_dev_num - 1] & 0x3
362
363 static int raise_pci_irq(struct vm_device * dev, struct pci_device * pci_dev) {
364     struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
365     struct pci_device * piix3_pci = piix3->southbridge_pci;
366     struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(piix3_pci->config_data);
367     int intr_pin = pci_dev->config_header.intr_pin - 1;
368     int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
369     
370     //        PrintError("Raising PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
371     
372     v3_raise_irq(dev->vm, piix3_cfg->pirq_rc[irq_index]);
373
374     return 0;
375 }
376
377
378
379 static int lower_pci_irq(struct vm_device * dev, struct pci_device * pci_dev) {
380     struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
381     struct pci_device * piix3_pci = piix3->southbridge_pci;
382     struct piix3_config_space * piix3_cfg = (struct piix3_config_space *)(piix3_pci->config_data);
383     int intr_pin = pci_dev->config_header.intr_pin - 1;
384     int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
385     
386     //    PrintError("Lowering PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
387     
388     v3_lower_irq(dev->vm, piix3_cfg->pirq_rc[irq_index]);
389
390     return 0;
391 }
392
393
394
395 static int piix_free(struct vm_device * dev) {
396     return 0;
397 }
398
399
400 static struct v3_device_ops dev_ops = {
401     .free = piix_free,
402     .reset = reset_piix3,
403     .start = NULL,
404     .stop = NULL,
405 };
406
407
408
409
410 static int setup_pci(struct vm_device * dev) {
411     struct v3_southbridge * piix3 = (struct v3_southbridge *)(dev->private_data);
412     struct pci_device * pci_dev = NULL;
413     struct v3_pci_bar bars[6];
414     int i;
415     int bus_num = 0;
416
417     for (i = 0; i < 6; i++) {
418         bars[i].type = PCI_BAR_NONE;
419     }
420
421     pci_dev = v3_pci_register_device(piix3->pci_bus, PCI_MULTIFUNCTION, 
422                                      bus_num, -1, 0, 
423                                      "PIIX3", bars, 
424                                      NULL, NULL, NULL, dev, NULL);
425     if (pci_dev == NULL) {
426         PrintError("Could not register PCI Device for PIIX3\n");
427         return -1;
428     }
429
430     pci_dev->config_header.vendor_id = 0x8086;
431     pci_dev->config_header.device_id = 0x7000; // PIIX4 is 0x7001
432     pci_dev->config_header.class = PCI_CLASS_BRIDGE;
433     pci_dev->config_header.subclass = PCI_BRIDGE_SUBCLASS_PCI_ISA; 
434
435     piix3->southbridge_pci = pci_dev;
436
437     v3_pci_set_irq_bridge(piix3->pci_bus, bus_num, raise_pci_irq, lower_pci_irq, dev);
438
439     reset_piix3(dev);
440
441     return 0;
442 }
443
444 static int piix3_init(struct guest_info * vm, void * cfg_data) {
445     struct v3_southbridge * piix3 = (struct v3_southbridge *)V3_Malloc(sizeof(struct v3_southbridge));
446     struct vm_device * dev = NULL;
447     struct vm_device * pci = v3_find_dev(vm, (char *)cfg_data);
448
449     if (!pci) {
450         PrintError("Could not find PCI device\n");
451         return -1;
452     }
453
454     piix3->pci_bus = pci;
455     piix3->type = V3_SB_PIIX3;
456     
457     dev = v3_allocate_device("PIIX3", &dev_ops, piix3);
458
459     if (v3_attach_device(vm, dev) == -1) {
460         PrintError("Could not attach device %s\n", "PIIX3");
461         return -1;
462     }
463
464     PrintDebug("Created PIIX3\n");
465
466     return setup_pci(dev);
467 }
468
469
470 device_register("PIIX3", piix3_init)