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.


imported SEABIOS source tree
[palacios.git] / bios / seabios / src / mptable.c
1 // MPTable generation (on emulators)
2 //
3 // Copyright (C) 2008-2010  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2006 Fabrice Bellard
5 //
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
7
8 #include "util.h" // dprintf
9 #include "config.h" // CONFIG_*
10 #include "mptable.h" // MPTABLE_SIGNATURE
11 #include "paravirt.h" // qemu_cfg_irq0_override
12 #include "pci.h"
13 #include "pci_regs.h"
14
15 void
16 mptable_init(void)
17 {
18     if (! CONFIG_MPTABLE)
19         return;
20
21     dprintf(3, "init MPTable\n");
22
23     // Config structure in temp area.
24     struct mptable_config_s *config = malloc_tmp(32*1024);
25     if (!config) {
26         warn_noalloc();
27         return;
28     }
29     memset(config, 0, sizeof(*config));
30     config->signature = MPCONFIG_SIGNATURE;
31     config->spec = 4;
32     memcpy(config->oemid, CONFIG_CPUNAME8, sizeof(config->oemid));
33     memcpy(config->productid, "0.1         ", sizeof(config->productid));
34     config->lapic = BUILD_APIC_ADDR;
35
36     // Detect cpu info
37     u32 cpuid_signature, ebx, ecx, cpuid_features;
38     cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
39     if (! cpuid_signature) {
40         // Use default values.
41         cpuid_signature = 0x600;
42         cpuid_features = 0x201;
43     }
44     int pkgcpus = 1;
45     if (cpuid_features & (1 << 28)) {
46         /* Only populate the MPS tables with the first logical CPU in
47            each package */
48         pkgcpus = (ebx >> 16) & 0xff;
49         pkgcpus = 1 << (__fls(pkgcpus - 1) + 1); /* round up to power of 2 */
50     }
51     u8 apic_version = readl((u8*)BUILD_APIC_ADDR + 0x30) & 0xff;
52
53     // CPU definitions.
54     struct mpt_cpu *cpus = (void*)&config[1], *cpu = cpus;
55     int i;
56     for (i = 0; i < MaxCountCPUs; i+=pkgcpus) {
57         memset(cpu, 0, sizeof(*cpu));
58         cpu->type = MPT_TYPE_CPU;
59         cpu->apicid = i;
60         cpu->apicver = apic_version;
61         /* cpu flags: enabled, bootstrap cpu */
62         cpu->cpuflag = ((i<CountCPUs) ? 0x01 : 0x00) | ((i==0) ? 0x02 : 0x00);
63         cpu->cpusignature = cpuid_signature;
64         cpu->featureflag = cpuid_features;
65         cpu++;
66     }
67     int entrycount = cpu - cpus;
68
69     // PCI buses
70     struct mpt_bus *buses = (void*)cpu, *bus = buses;
71     int lastbus = -1;
72     struct pci_device *pci;
73     foreachpci(pci) {
74         int curbus = pci_bdf_to_bus(pci->bdf);
75         if (curbus == lastbus)
76             continue;
77         lastbus = curbus;
78         memset(bus, 0, sizeof(*bus));
79         bus->type = MPT_TYPE_BUS;
80         bus->busid = curbus;
81         memcpy(bus->bustype, "PCI   ", sizeof(bus->bustype));
82         bus++;
83     }
84
85     /* isa bus */
86     int isabusid;
87     memset(bus, 0, sizeof(*bus));
88     bus->type = MPT_TYPE_BUS;
89     isabusid = bus->busid = lastbus + 1;
90     memcpy(bus->bustype, "ISA   ", sizeof(bus->bustype));
91     bus++;
92     entrycount += bus - buses;
93
94     /* ioapic */
95     u8 ioapic_id = CountCPUs;
96     struct mpt_ioapic *ioapic = (void*)bus;
97     memset(ioapic, 0, sizeof(*ioapic));
98     ioapic->type = MPT_TYPE_IOAPIC;
99     ioapic->apicid = ioapic_id;
100     ioapic->apicver = 0x11;
101     ioapic->flags = 1; // enable
102     ioapic->apicaddr = BUILD_IOAPIC_ADDR;
103     entrycount++;
104
105     /* irqs */
106     struct mpt_intsrc *intsrcs = (void*)&ioapic[1], *intsrc = intsrcs;
107     int dev = -1;
108     unsigned short mask = 0, pinmask = 0;
109
110     foreachpci(pci) {
111         u16 bdf = pci->bdf;
112         int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
113         int irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
114         if (pin == 0)
115             continue;
116         if (dev != pci_bdf_to_busdev(bdf)) {
117             dev = pci_bdf_to_busdev(bdf);
118             pinmask = 0;
119         }
120         if (pinmask & (1 << pin)) /* pin was seen already */
121             continue;
122         pinmask |= (1 << pin);
123         mask |= (1 << irq);
124         memset(intsrc, 0, sizeof(*intsrc));
125         intsrc->type = MPT_TYPE_INTSRC;
126         intsrc->irqtype = 0; /* INT */
127         intsrc->irqflag = 1; /* active high */
128         intsrc->srcbus = pci_bdf_to_bus(bdf); /* PCI bus */
129         intsrc->srcbusirq = (pci_bdf_to_dev(bdf) << 2) | (pin - 1);
130         intsrc->dstapic = ioapic_id;
131         intsrc->dstirq = irq;
132         intsrc++;
133     }
134
135     for (i = 0; i < 16; i++) {
136         memset(intsrc, 0, sizeof(*intsrc));
137         if (mask & (1 << i))
138             continue;
139         intsrc->type = MPT_TYPE_INTSRC;
140         intsrc->irqtype = 0; /* INT */
141         intsrc->irqflag = 0; /* conform to bus spec */
142         intsrc->srcbus = isabusid; /* ISA bus */
143         intsrc->srcbusirq = i;
144         intsrc->dstapic = ioapic_id;
145         intsrc->dstirq = i;
146         if (qemu_cfg_irq0_override()) {
147             /* Destination 2 is covered by irq0->inti2 override (i ==
148                0). Source IRQ 2 is unused */
149             if (i == 0)
150                 intsrc->dstirq = 2;
151             else if (i == 2)
152                 intsrc--;
153         }
154         intsrc++;
155     }
156
157     /* Local interrupt assignment */
158     intsrc->type = MPT_TYPE_LOCAL_INT;
159     intsrc->irqtype = 3; /* ExtINT */
160     intsrc->irqflag = 0; /* PO, EL default */
161     intsrc->srcbus = isabusid; /* ISA */
162     intsrc->srcbusirq = 0;
163     intsrc->dstapic = 0; /* BSP == APIC #0 */
164     intsrc->dstirq = 0; /* LINTIN0 */
165     intsrc++;
166
167     intsrc->type = MPT_TYPE_LOCAL_INT;
168     intsrc->irqtype = 1; /* NMI */
169     intsrc->irqflag = 0; /* PO, EL default */
170     intsrc->srcbus = isabusid; /* ISA */
171     intsrc->srcbusirq = 0;
172     intsrc->dstapic = 0; /* BSP == APIC #0 */
173     intsrc->dstirq = 1; /* LINTIN1 */
174     intsrc++;
175     entrycount += intsrc - intsrcs;
176
177     // Finalize config structure.
178     int length = (void*)intsrc - (void*)config;
179     config->entrycount = entrycount;
180     config->length = length;
181     config->checksum -= checksum(config, length);
182
183     // Allocate final memory locations.  (In theory the config
184     // structure can go in high memory, but Linux kernels before
185     // v2.6.30 crash with that.)
186     struct mptable_config_s *finalconfig = malloc_fseg(length);
187     struct mptable_floating_s *floating = malloc_fseg(sizeof(*floating));
188     if (!finalconfig || !floating) {
189         warn_noalloc();
190         free(config);
191         free(finalconfig);
192         free(floating);
193         return;
194     }
195     memcpy(finalconfig, config, length);
196     free(config);
197
198     /* floating pointer structure */
199     memset(floating, 0, sizeof(*floating));
200     floating->signature = MPTABLE_SIGNATURE;
201     floating->physaddr = (u32)finalconfig;
202     floating->length = 1;
203     floating->spec_rev = 4;
204     floating->checksum -= checksum(floating, sizeof(*floating));
205
206     dprintf(1, "MP table addr=%p MPC table addr=%p size=%d\n",
207             floating, finalconfig, length);
208 }