debuggers.hg

view tools/firmware/hvmloader/acpi/build.c @ 20981:27f5ff8c0aa0

hvmloader: Fix parallel build of ACPI tables.

Make build.c dependency on ssdt_{pm,tpm}.h explicit, else they can be
built in the wrong order.

Also, improve naming of target DSDT structures, and specify -p option
to iasl so that all generated files for a given target have
target-unique names, hence build can proceed safely in parallel.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Feb 12 09:16:10 2010 +0000 (2010-02-12)
parents a259e779467c
children
line source
1 /*
2 * Copyright (c) 2004, Intel Corporation.
3 * Copyright (c) 2006, Keir Fraser, XenSource Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License, version
7 * 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT ANY
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 */
19 #include "acpi2_0.h"
20 #include "ssdt_tpm.h"
21 #include "ssdt_pm.h"
22 #include "../config.h"
23 #include "../util.h"
25 #define align16(sz) (((sz) + 15) & ~15)
26 #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
28 /* MADT parameters for filling in bios_info structure for DSDT. */
29 uint32_t madt_csum_addr, madt_lapic0_addr;
31 extern struct acpi_20_rsdp Rsdp;
32 extern struct acpi_20_rsdt Rsdt;
33 extern struct acpi_20_xsdt Xsdt;
34 extern struct acpi_20_fadt Fadt;
35 extern struct acpi_20_facs Facs;
37 /*
38 * Alternative DSDTs we get linked against. A cover-all DSDT for up to the
39 * implementation-defined maximum number of VCPUs, and an alternative for use
40 * when a guest can only have up to 15 VCPUs.
41 *
42 * The latter is required for Windows 2000, which experiences a BSOD of
43 * KMODE_EXCEPTION_NOT_HANDLED if it sees more than 15 processor objects.
44 */
45 extern unsigned char dsdt_anycpu[], dsdt_15cpu;
46 extern int dsdt_anycpu_len, dsdt_15cpu_len;
48 /* Number of processor objects in the chosen DSDT. */
49 static unsigned int nr_processor_objects;
51 static void set_checksum(
52 void *table, uint32_t checksum_offset, uint32_t length)
53 {
54 uint8_t *p, sum = 0;
56 p = table;
57 p[checksum_offset] = 0;
59 while ( length-- )
60 sum = sum + *p++;
62 p = table;
63 p[checksum_offset] = -sum;
64 }
66 static uint8_t battery_port_exists(void)
67 {
68 return (inb(0x88) == 0x1F);
69 }
71 static int construct_madt(struct acpi_20_madt *madt)
72 {
73 struct acpi_20_madt_intsrcovr *intsrcovr;
74 struct acpi_20_madt_ioapic *io_apic;
75 struct acpi_20_madt_lapic *lapic;
76 int i, offset = 0;
78 memset(madt, 0, sizeof(*madt));
79 madt->header.signature = ACPI_2_0_MADT_SIGNATURE;
80 madt->header.revision = ACPI_2_0_MADT_REVISION;
81 fixed_strcpy(madt->header.oem_id, ACPI_OEM_ID);
82 fixed_strcpy(madt->header.oem_table_id, ACPI_OEM_TABLE_ID);
83 madt->header.oem_revision = ACPI_OEM_REVISION;
84 madt->header.creator_id = ACPI_CREATOR_ID;
85 madt->header.creator_revision = ACPI_CREATOR_REVISION;
86 madt->lapic_addr = LAPIC_BASE_ADDRESS;
87 madt->flags = ACPI_PCAT_COMPAT;
88 offset += sizeof(*madt);
90 intsrcovr = (struct acpi_20_madt_intsrcovr *)(madt + 1);
91 for ( i = 0; i < 16; i++ )
92 {
93 memset(intsrcovr, 0, sizeof(*intsrcovr));
94 intsrcovr->type = ACPI_INTERRUPT_SOURCE_OVERRIDE;
95 intsrcovr->length = sizeof(*intsrcovr);
96 intsrcovr->source = i;
98 if ( i == 0 )
99 {
100 /* ISA IRQ0 routed to IOAPIC GSI 2. */
101 intsrcovr->gsi = 2;
102 intsrcovr->flags = 0x0;
103 }
104 else if ( PCI_ISA_IRQ_MASK & (1U << i) )
105 {
106 /* PCI: active-low level-triggered. */
107 intsrcovr->gsi = i;
108 intsrcovr->flags = 0xf;
109 }
110 else
111 {
112 /* No need for a INT source override structure. */
113 continue;
114 }
116 offset += sizeof(*intsrcovr);
117 intsrcovr++;
118 }
120 io_apic = (struct acpi_20_madt_ioapic *)intsrcovr;
121 memset(io_apic, 0, sizeof(*io_apic));
122 io_apic->type = ACPI_IO_APIC;
123 io_apic->length = sizeof(*io_apic);
124 io_apic->ioapic_id = IOAPIC_ID;
125 io_apic->ioapic_addr = IOAPIC_BASE_ADDRESS;
126 offset += sizeof(*io_apic);
128 lapic = (struct acpi_20_madt_lapic *)(io_apic + 1);
129 madt_lapic0_addr = (uint32_t)lapic;
130 for ( i = 0; i < nr_processor_objects; i++ )
131 {
132 memset(lapic, 0, sizeof(*lapic));
133 lapic->type = ACPI_PROCESSOR_LOCAL_APIC;
134 lapic->length = sizeof(*lapic);
135 /* Processor ID must match processor-object IDs in the DSDT. */
136 lapic->acpi_processor_id = i;
137 lapic->apic_id = LAPIC_ID(i);
138 lapic->flags = ((i < hvm_info->nr_vcpus) &&
139 test_bit(i, hvm_info->vcpu_online)
140 ? ACPI_LOCAL_APIC_ENABLED : 0);
141 offset += sizeof(*lapic);
142 lapic++;
143 }
145 madt->header.length = offset;
146 set_checksum(madt, offsetof(struct acpi_header, checksum), offset);
147 madt_csum_addr = (uint32_t)&madt->header.checksum;
149 return align16(offset);
150 }
152 static int construct_hpet(struct acpi_20_hpet *hpet)
153 {
154 int offset;
156 memset(hpet, 0, sizeof(*hpet));
157 hpet->header.signature = ACPI_2_0_HPET_SIGNATURE;
158 hpet->header.revision = ACPI_2_0_HPET_REVISION;
159 fixed_strcpy(hpet->header.oem_id, ACPI_OEM_ID);
160 fixed_strcpy(hpet->header.oem_table_id, ACPI_OEM_TABLE_ID);
161 hpet->header.oem_revision = ACPI_OEM_REVISION;
162 hpet->header.creator_id = ACPI_CREATOR_ID;
163 hpet->header.creator_revision = ACPI_CREATOR_REVISION;
164 hpet->timer_block_id = 0x8086a201;
165 hpet->addr.address = ACPI_HPET_ADDRESS;
166 offset = sizeof(*hpet);
168 hpet->header.length = offset;
169 set_checksum(hpet, offsetof(struct acpi_header, checksum), offset);
171 return offset;
172 }
174 static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
175 {
176 int offset = 0, nr_tables = 0;
177 struct acpi_20_madt *madt;
178 struct acpi_20_hpet *hpet;
179 struct acpi_20_tcpa *tcpa;
180 static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
181 uint16_t *tis_hdr;
182 void *lasa;
184 /* MADT. */
185 if ( (hvm_info->nr_vcpus > 1) || hvm_info->apic_mode )
186 {
187 madt = (struct acpi_20_madt *)&buf[offset];
188 offset += construct_madt(madt);
189 table_ptrs[nr_tables++] = (unsigned long)madt;
190 }
192 /* HPET. */
193 if ( hpet_exists(ACPI_HPET_ADDRESS) )
194 {
195 hpet = (struct acpi_20_hpet *)&buf[offset];
196 offset += construct_hpet(hpet);
197 table_ptrs[nr_tables++] = (unsigned long)hpet;
198 }
200 if ( battery_port_exists() )
201 {
202 table_ptrs[nr_tables++] = (unsigned long)&buf[offset];
203 memcpy(&buf[offset], ssdt_pm, sizeof(ssdt_pm));
204 offset += align16(sizeof(ssdt_pm));
205 }
207 /* TPM TCPA and SSDT. */
208 tis_hdr = (uint16_t *)0xFED40F00;
209 if ( (tis_hdr[0] == tis_signature[0]) &&
210 (tis_hdr[1] == tis_signature[1]) &&
211 (tis_hdr[2] == tis_signature[2]) )
212 {
213 memcpy(&buf[offset], ssdt_tpm, sizeof(ssdt_tpm));
214 table_ptrs[nr_tables++] = (unsigned long)&buf[offset];
215 offset += align16(sizeof(ssdt_tpm));
217 tcpa = (struct acpi_20_tcpa *)&buf[offset];
218 memset(tcpa, 0, sizeof(*tcpa));
219 offset += align16(sizeof(*tcpa));
220 table_ptrs[nr_tables++] = (unsigned long)tcpa;
222 tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE;
223 tcpa->header.length = sizeof(*tcpa);
224 tcpa->header.revision = ACPI_2_0_TCPA_REVISION;
225 fixed_strcpy(tcpa->header.oem_id, ACPI_OEM_ID);
226 fixed_strcpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID);
227 tcpa->header.oem_revision = ACPI_OEM_REVISION;
228 tcpa->header.creator_id = ACPI_CREATOR_ID;
229 tcpa->header.creator_revision = ACPI_CREATOR_REVISION;
230 if ( (lasa = mem_alloc(ACPI_2_0_TCPA_LAML_SIZE, 0)) != NULL )
231 {
232 tcpa->lasa = virt_to_phys(lasa);
233 tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
234 memset(lasa, 0, tcpa->laml);
235 set_checksum(tcpa,
236 offsetof(struct acpi_header, checksum),
237 tcpa->header.length);
238 }
239 }
241 table_ptrs[nr_tables] = 0;
242 return align16(offset);
243 }
245 static void __acpi_build_tables(uint8_t *buf, int *low_sz, int *high_sz)
246 {
247 struct acpi_20_rsdp *rsdp;
248 struct acpi_20_rsdt *rsdt;
249 struct acpi_20_xsdt *xsdt;
250 struct acpi_20_fadt *fadt;
251 struct acpi_10_fadt *fadt_10;
252 struct acpi_20_facs *facs;
253 unsigned char *dsdt;
254 unsigned long secondary_tables[16];
255 int offset = 0, i;
257 /*
258 * Fill in high-memory data structures, starting at @buf.
259 */
261 facs = (struct acpi_20_facs *)&buf[offset];
262 memcpy(facs, &Facs, sizeof(struct acpi_20_facs));
263 offset += align16(sizeof(struct acpi_20_facs));
265 dsdt = (unsigned char *)&buf[offset];
266 if ( hvm_info->nr_vcpus <= 15 )
267 {
268 memcpy(dsdt, &dsdt_15cpu, dsdt_15cpu_len);
269 offset += align16(dsdt_15cpu_len);
270 nr_processor_objects = 15;
271 }
272 else
273 {
274 memcpy(dsdt, &dsdt_anycpu, dsdt_anycpu_len);
275 offset += align16(dsdt_anycpu_len);
276 nr_processor_objects = HVM_MAX_VCPUS;
277 }
279 /*
280 * N.B. ACPI 1.0 operating systems may not handle FADT with revision 2
281 * or above properly, notably Windows 2000, which tries to copy FADT
282 * into a 116 bytes buffer thus causing an overflow. The solution is to
283 * link the higher revision FADT with the XSDT only and introduce a
284 * compatible revision 1 FADT that is linked with the RSDT. Refer to:
285 * http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt
286 */
287 fadt_10 = (struct acpi_10_fadt *)&buf[offset];
288 memcpy(fadt_10, &Fadt, sizeof(struct acpi_10_fadt));
289 offset += align16(sizeof(struct acpi_10_fadt));
290 fadt_10->header.length = sizeof(struct acpi_10_fadt);
291 fadt_10->header.revision = ACPI_1_0_FADT_REVISION;
292 fadt_10->dsdt = (unsigned long)dsdt;
293 fadt_10->firmware_ctrl = (unsigned long)facs;
294 set_checksum(fadt_10,
295 offsetof(struct acpi_header, checksum),
296 sizeof(struct acpi_10_fadt));
298 fadt = (struct acpi_20_fadt *)&buf[offset];
299 memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt));
300 offset += align16(sizeof(struct acpi_20_fadt));
301 fadt->dsdt = (unsigned long)dsdt;
302 fadt->x_dsdt = (unsigned long)dsdt;
303 fadt->firmware_ctrl = (unsigned long)facs;
304 fadt->x_firmware_ctrl = (unsigned long)facs;
305 set_checksum(fadt,
306 offsetof(struct acpi_header, checksum),
307 sizeof(struct acpi_20_fadt));
309 offset += construct_secondary_tables(&buf[offset], secondary_tables);
311 xsdt = (struct acpi_20_xsdt *)&buf[offset];
312 memcpy(xsdt, &Xsdt, sizeof(struct acpi_header));
313 xsdt->entry[0] = (unsigned long)fadt;
314 for ( i = 0; secondary_tables[i]; i++ )
315 xsdt->entry[i+1] = secondary_tables[i];
316 xsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint64_t);
317 offset += align16(xsdt->header.length);
318 set_checksum(xsdt,
319 offsetof(struct acpi_header, checksum),
320 xsdt->header.length);
322 rsdt = (struct acpi_20_rsdt *)&buf[offset];
323 memcpy(rsdt, &Rsdt, sizeof(struct acpi_header));
324 rsdt->entry[0] = (unsigned long)fadt_10;
325 for ( i = 0; secondary_tables[i]; i++ )
326 rsdt->entry[i+1] = secondary_tables[i];
327 rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t);
328 offset += align16(rsdt->header.length);
329 set_checksum(rsdt,
330 offsetof(struct acpi_header, checksum),
331 rsdt->header.length);
333 *high_sz = offset;
335 /*
336 * Fill in low-memory data structures: bios_info_table and RSDP.
337 */
339 buf = (uint8_t *)ACPI_PHYSICAL_ADDRESS;
340 offset = 0;
342 rsdp = (struct acpi_20_rsdp *)&buf[offset];
343 memcpy(rsdp, &Rsdp, sizeof(struct acpi_20_rsdp));
344 offset += align16(sizeof(struct acpi_20_rsdp));
345 rsdp->rsdt_address = (unsigned long)rsdt;
346 rsdp->xsdt_address = (unsigned long)xsdt;
347 set_checksum(rsdp,
348 offsetof(struct acpi_10_rsdp, checksum),
349 sizeof(struct acpi_10_rsdp));
350 set_checksum(rsdp,
351 offsetof(struct acpi_20_rsdp, extended_checksum),
352 sizeof(struct acpi_20_rsdp));
354 *low_sz = offset;
355 }
357 void acpi_build_tables(void)
358 {
359 int high_sz, low_sz;
360 uint8_t *buf;
362 /* Find out size of high-memory ACPI data area. */
363 buf = (uint8_t *)&_end;
364 __acpi_build_tables(buf, &low_sz, &high_sz);
365 memset(buf, 0, high_sz);
367 /* Allocate data area and set up ACPI tables there. */
368 buf = mem_alloc(high_sz, 0);
369 __acpi_build_tables(buf, &low_sz, &high_sz);
371 printf(" - Lo data: %08lx-%08lx\n"
372 " - Hi data: %08lx-%08lx\n",
373 (unsigned long)ACPI_PHYSICAL_ADDRESS,
374 (unsigned long)ACPI_PHYSICAL_ADDRESS + low_sz - 1,
375 (unsigned long)buf, (unsigned long)buf + high_sz - 1);
376 }
378 /*
379 * Local variables:
380 * mode: C
381 * c-set-style: "BSD"
382 * c-basic-offset: 4
383 * tab-width: 4
384 * indent-tabs-mode: nil
385 * End:
386 */