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.


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