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
6  * it under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation; version 2.1 only. with the special
8  * exception on linking described in file LICENSE.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  */
15 
16 #include LIBACPI_STDUTILS
17 #include "acpi2_0.h"
18 #include "libacpi.h"
19 #include "ssdt_s3.h"
20 #include "ssdt_s4.h"
21 #include "ssdt_tpm.h"
22 #include "ssdt_pm.h"
23 #include "ssdt_laptop_slate.h"
24 #include <xen/hvm/hvm_info_table.h>
25 #include <xen/hvm/hvm_xs_strings.h>
26 #include <xen/hvm/params.h>
27 #include <xen/memory.h>
28 
29 #define ACPI_MAX_SECONDARY_TABLES 16
30 
31 #define align16(sz)        (((sz) + 15) & ~15)
32 #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
33 
34 extern struct acpi_20_rsdp Rsdp;
35 extern struct acpi_20_rsdt Rsdt;
36 extern struct acpi_20_xsdt Xsdt;
37 extern struct acpi_fadt Fadt;
38 extern struct acpi_20_facs Facs;
39 extern struct acpi_20_waet Waet;
40 
41 /*
42  * Located at ACPI_INFO_PHYSICAL_ADDRESS.
43  *
44  * This must match the Field("BIOS"....) definition in the DSDT.
45  */
46 struct acpi_info {
47     uint8_t  com1_present:1;    /* 0[0] - System has COM1? */
48     uint8_t  com2_present:1;    /* 0[1] - System has COM2? */
49     uint8_t  lpt1_present:1;    /* 0[2] - System has LPT1? */
50     uint8_t  hpet_present:1;    /* 0[3] - System has HPET? */
51     uint16_t nr_cpus;           /* 2    - Number of CPUs */
52     uint32_t pci_min, pci_len;  /* 4, 8 - PCI I/O hole boundaries */
53     uint32_t madt_csum_addr;    /* 12   - Address of MADT checksum */
54     uint32_t madt_lapic0_addr;  /* 16   - Address of first MADT LAPIC struct */
55     uint32_t vm_gid_addr;       /* 20   - Address of VM generation id buffer */
56     uint64_t pci_hi_min, pci_hi_len; /* 24, 32 - PCI I/O hole boundaries */
57 };
58 
set_checksum(void * table,uint32_t checksum_offset,uint32_t length)59 static void set_checksum(
60     void *table, uint32_t checksum_offset, uint32_t length)
61 {
62     uint8_t *p, sum = 0;
63 
64     p = table;
65     p[checksum_offset] = 0;
66 
67     while ( length-- )
68         sum = sum + *p++;
69 
70     p = table;
71     p[checksum_offset] = -sum;
72 }
73 
construct_madt(struct acpi_ctxt * ctxt,const struct acpi_config * config,struct acpi_info * info)74 static struct acpi_20_madt *construct_madt(struct acpi_ctxt *ctxt,
75                                            const struct acpi_config *config,
76                                            struct acpi_info *info)
77 {
78     struct acpi_20_madt           *madt;
79     struct acpi_20_madt_intsrcovr *intsrcovr;
80     struct acpi_20_madt_ioapic    *io_apic;
81     struct acpi_20_madt_lapic     *lapic;
82     const struct hvm_info_table   *hvminfo = config->hvminfo;
83     int i, sz;
84 
85     if ( config->lapic_id == NULL )
86         return NULL;
87 
88     sz  = sizeof(struct acpi_20_madt);
89     sz += sizeof(struct acpi_20_madt_intsrcovr) * 16;
90     sz += sizeof(struct acpi_20_madt_ioapic);
91     sz += sizeof(struct acpi_20_madt_lapic) * hvminfo->nr_vcpus;
92 
93     madt = ctxt->mem_ops.alloc(ctxt, sz, 16);
94     if (!madt) return NULL;
95 
96     memset(madt, 0, sizeof(*madt));
97     madt->header.signature    = ACPI_2_0_MADT_SIGNATURE;
98     madt->header.revision     = ACPI_2_0_MADT_REVISION;
99     fixed_strcpy(madt->header.oem_id, ACPI_OEM_ID);
100     fixed_strcpy(madt->header.oem_table_id, ACPI_OEM_TABLE_ID);
101     madt->header.oem_revision = ACPI_OEM_REVISION;
102     madt->header.creator_id   = ACPI_CREATOR_ID;
103     madt->header.creator_revision = ACPI_CREATOR_REVISION;
104     madt->lapic_addr = config->lapic_base_address;
105     madt->flags      = ACPI_PCAT_COMPAT;
106 
107     if ( config->table_flags & ACPI_HAS_IOAPIC )
108     {
109         intsrcovr = (struct acpi_20_madt_intsrcovr *)(madt + 1);
110         for ( i = 0; i < 16; i++ )
111         {
112             memset(intsrcovr, 0, sizeof(*intsrcovr));
113             intsrcovr->type   = ACPI_INTERRUPT_SOURCE_OVERRIDE;
114             intsrcovr->length = sizeof(*intsrcovr);
115             intsrcovr->source = i;
116 
117             if ( i == 0 )
118             {
119                 /* ISA IRQ0 routed to IOAPIC GSI 2. */
120                 intsrcovr->gsi    = 2;
121                 intsrcovr->flags  = 0x0;
122             }
123             else if ( config->pci_isa_irq_mask & (1U << i) )
124             {
125                 /* PCI: active-low level-triggered. */
126                 intsrcovr->gsi    = i;
127                 intsrcovr->flags  = 0xf;
128             }
129             else
130             {
131                 /* No need for a INT source override structure. */
132                 continue;
133             }
134 
135             intsrcovr++;
136         }
137 
138         io_apic = (struct acpi_20_madt_ioapic *)intsrcovr;
139         memset(io_apic, 0, sizeof(*io_apic));
140         io_apic->type        = ACPI_IO_APIC;
141         io_apic->length      = sizeof(*io_apic);
142         io_apic->ioapic_id   = config->ioapic_id;
143         io_apic->ioapic_addr = config->ioapic_base_address;
144 
145         lapic = (struct acpi_20_madt_lapic *)(io_apic + 1);
146     }
147     else
148         lapic = (struct acpi_20_madt_lapic *)(madt + 1);
149 
150     info->nr_cpus = hvminfo->nr_vcpus;
151     info->madt_lapic0_addr = ctxt->mem_ops.v2p(ctxt, lapic);
152     for ( i = 0; i < hvminfo->nr_vcpus; i++ )
153     {
154         memset(lapic, 0, sizeof(*lapic));
155         lapic->type    = ACPI_PROCESSOR_LOCAL_APIC;
156         lapic->length  = sizeof(*lapic);
157         /* Processor ID must match processor-object IDs in the DSDT. */
158         lapic->acpi_processor_id = i;
159         lapic->apic_id = config->lapic_id(i);
160         lapic->flags = (test_bit(i, hvminfo->vcpu_online)
161                         ? ACPI_LOCAL_APIC_ENABLED : 0);
162         lapic++;
163     }
164 
165     madt->header.length = (unsigned char *)lapic - (unsigned char *)madt;
166     set_checksum(madt, offsetof(struct acpi_header, checksum),
167                  madt->header.length);
168     info->madt_csum_addr =
169         ctxt->mem_ops.v2p(ctxt, &madt->header.checksum);
170 
171     return madt;
172 }
173 
construct_hpet(struct acpi_ctxt * ctxt,const struct acpi_config * config)174 static struct acpi_20_hpet *construct_hpet(struct acpi_ctxt *ctxt,
175                                            const struct acpi_config *config)
176 {
177     struct acpi_20_hpet *hpet;
178 
179     hpet = ctxt->mem_ops.alloc(ctxt, sizeof(*hpet), 16);
180     if (!hpet) return NULL;
181 
182     memset(hpet, 0, sizeof(*hpet));
183     hpet->header.signature    = ACPI_2_0_HPET_SIGNATURE;
184     hpet->header.revision     = ACPI_2_0_HPET_REVISION;
185     fixed_strcpy(hpet->header.oem_id, ACPI_OEM_ID);
186     fixed_strcpy(hpet->header.oem_table_id, ACPI_OEM_TABLE_ID);
187     hpet->header.oem_revision = ACPI_OEM_REVISION;
188     hpet->header.creator_id   = ACPI_CREATOR_ID;
189     hpet->header.creator_revision = ACPI_CREATOR_REVISION;
190     hpet->timer_block_id      = 0x8086a201;
191     hpet->addr.address        = ACPI_HPET_ADDRESS;
192 
193     hpet->header.length = sizeof(*hpet);
194     set_checksum(hpet, offsetof(struct acpi_header, checksum), sizeof(*hpet));
195     return hpet;
196 }
197 
construct_waet(struct acpi_ctxt * ctxt,const struct acpi_config * config)198 static struct acpi_20_waet *construct_waet(struct acpi_ctxt *ctxt,
199                                            const struct acpi_config *config)
200 {
201     struct acpi_20_waet *waet;
202 
203     waet = ctxt->mem_ops.alloc(ctxt, sizeof(*waet), 16);
204     if (!waet) return NULL;
205 
206     memcpy(waet, &Waet, sizeof(*waet));
207 
208     waet->header.length = sizeof(*waet);
209     set_checksum(waet, offsetof(struct acpi_header, checksum), sizeof(*waet));
210 
211     return waet;
212 }
213 
construct_srat(struct acpi_ctxt * ctxt,const struct acpi_config * config)214 static struct acpi_20_srat *construct_srat(struct acpi_ctxt *ctxt,
215                                            const struct acpi_config *config)
216 {
217     struct acpi_20_srat *srat;
218     struct acpi_20_srat_processor *processor;
219     struct acpi_20_srat_memory *memory;
220     unsigned int size;
221     void *p;
222     unsigned int i;
223 
224     size = sizeof(*srat) + sizeof(*processor) * config->hvminfo->nr_vcpus +
225            sizeof(*memory) * config->numa.nr_vmemranges;
226 
227     p = ctxt->mem_ops.alloc(ctxt, size, 16);
228     if ( !p )
229         return NULL;
230 
231     srat = memset(p, 0, size);
232     srat->header.signature    = ACPI_2_0_SRAT_SIGNATURE;
233     srat->header.revision     = ACPI_2_0_SRAT_REVISION;
234     fixed_strcpy(srat->header.oem_id, ACPI_OEM_ID);
235     fixed_strcpy(srat->header.oem_table_id, ACPI_OEM_TABLE_ID);
236     srat->header.oem_revision = ACPI_OEM_REVISION;
237     srat->header.creator_id   = ACPI_CREATOR_ID;
238     srat->header.creator_revision = ACPI_CREATOR_REVISION;
239     srat->table_revision      = ACPI_SRAT_TABLE_REVISION;
240 
241     processor = (struct acpi_20_srat_processor *)(srat + 1);
242     for ( i = 0; i < config->hvminfo->nr_vcpus; i++ )
243     {
244         processor->type     = ACPI_PROCESSOR_AFFINITY;
245         processor->length   = sizeof(*processor);
246         processor->domain   = config->numa.vcpu_to_vnode[i];
247         processor->apic_id  = config->lapic_id(i);
248         processor->flags    = ACPI_LOCAL_APIC_AFFIN_ENABLED;
249         processor++;
250     }
251 
252     memory = (struct acpi_20_srat_memory *)processor;
253     for ( i = 0; i < config->numa.nr_vmemranges; i++ )
254     {
255         memory->type          = ACPI_MEMORY_AFFINITY;
256         memory->length        = sizeof(*memory);
257         memory->domain        = config->numa.vmemrange[i].nid;
258         memory->flags         = ACPI_MEM_AFFIN_ENABLED;
259         memory->base_address  = config->numa.vmemrange[i].start;
260         memory->mem_length    = config->numa.vmemrange[i].end -
261                                 config->numa.vmemrange[i].start;
262         memory++;
263     }
264 
265     ASSERT(((unsigned long)memory) - ((unsigned long)p) == size);
266 
267     srat->header.length = size;
268     set_checksum(srat, offsetof(struct acpi_header, checksum), size);
269 
270     return srat;
271 }
272 
construct_slit(struct acpi_ctxt * ctxt,const struct acpi_config * config)273 static struct acpi_20_slit *construct_slit(struct acpi_ctxt *ctxt,
274                                            const struct acpi_config *config)
275 {
276     struct acpi_20_slit *slit;
277     unsigned int i, num, size;
278 
279     num = config->numa.nr_vnodes * config->numa.nr_vnodes;
280     size = sizeof(*slit) + num * sizeof(uint8_t);
281 
282     slit = ctxt->mem_ops.alloc(ctxt, size, 16);
283     if ( !slit )
284         return NULL;
285 
286     memset(slit, 0, size);
287     slit->header.signature    = ACPI_2_0_SLIT_SIGNATURE;
288     slit->header.revision     = ACPI_2_0_SLIT_REVISION;
289     fixed_strcpy(slit->header.oem_id, ACPI_OEM_ID);
290     fixed_strcpy(slit->header.oem_table_id, ACPI_OEM_TABLE_ID);
291     slit->header.oem_revision = ACPI_OEM_REVISION;
292     slit->header.creator_id   = ACPI_CREATOR_ID;
293     slit->header.creator_revision = ACPI_CREATOR_REVISION;
294 
295     for ( i = 0; i < num; i++ )
296         slit->entry[i] = config->numa.vdistance[i];
297 
298     slit->localities = config->numa.nr_vnodes;
299 
300     slit->header.length = size;
301     set_checksum(slit, offsetof(struct acpi_header, checksum), size);
302 
303     return slit;
304 }
305 
construct_passthrough_tables(struct acpi_ctxt * ctxt,unsigned long * table_ptrs,int nr_tables,struct acpi_config * config)306 static int construct_passthrough_tables(struct acpi_ctxt *ctxt,
307                                         unsigned long *table_ptrs,
308                                         int nr_tables,
309                                         struct acpi_config *config)
310 {
311     unsigned long pt_addr;
312     struct acpi_header *header;
313     int nr_added;
314     int nr_max = (ACPI_MAX_SECONDARY_TABLES - nr_tables - 1);
315     uint32_t total = 0;
316     uint8_t *buffer;
317 
318     if ( config->pt.addr == 0 )
319         return 0;
320 
321     pt_addr = config->pt.addr;
322 
323     for ( nr_added = 0; nr_added < nr_max; nr_added++ )
324     {
325         if ( (config->pt.length - total) < sizeof(struct acpi_header) )
326             break;
327 
328         header = (struct acpi_header*)pt_addr;
329 
330         buffer = ctxt->mem_ops.alloc(ctxt, header->length, 16);
331         if ( buffer == NULL )
332             break;
333         memcpy(buffer, header, header->length);
334 
335         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, buffer);
336         total += header->length;
337         pt_addr += header->length;
338     }
339 
340     return nr_added;
341 }
342 
construct_secondary_tables(struct acpi_ctxt * ctxt,unsigned long * table_ptrs,struct acpi_config * config,struct acpi_info * info)343 static int construct_secondary_tables(struct acpi_ctxt *ctxt,
344                                       unsigned long *table_ptrs,
345                                       struct acpi_config *config,
346                                       struct acpi_info *info)
347 {
348     int nr_tables = 0;
349     struct acpi_20_madt *madt;
350     struct acpi_20_hpet *hpet;
351     struct acpi_20_waet *waet;
352     struct acpi_20_tcpa *tcpa;
353     unsigned char *ssdt;
354     static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
355     void *lasa;
356 
357     /* MADT. */
358     if ( (config->hvminfo->nr_vcpus > 1) || config->hvminfo->apic_mode )
359     {
360         madt = construct_madt(ctxt, config, info);
361         if (!madt) return -1;
362         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, madt);
363     }
364 
365     /* HPET. */
366     if ( info->hpet_present )
367     {
368         hpet = construct_hpet(ctxt, config);
369         if (!hpet) return -1;
370         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, hpet);
371     }
372 
373     /* WAET. */
374     if ( config->table_flags & ACPI_HAS_WAET )
375     {
376         waet = construct_waet(ctxt, config);
377         if ( !waet )
378             return -1;
379         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, waet);
380     }
381 
382     if ( config->table_flags & ACPI_HAS_SSDT_PM )
383     {
384         ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_pm), 16);
385         if (!ssdt) return -1;
386         memcpy(ssdt, ssdt_pm, sizeof(ssdt_pm));
387         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
388     }
389 
390     if ( config->table_flags & ACPI_HAS_SSDT_S3 )
391     {
392         ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_s3), 16);
393         if (!ssdt) return -1;
394         memcpy(ssdt, ssdt_s3, sizeof(ssdt_s3));
395         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
396     } else {
397         printf("S3 disabled\n");
398     }
399 
400     if ( config->table_flags & ACPI_HAS_SSDT_S4 )
401     {
402         ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_s4), 16);
403         if (!ssdt) return -1;
404         memcpy(ssdt, ssdt_s4, sizeof(ssdt_s4));
405         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
406     } else {
407         printf("S4 disabled\n");
408     }
409 
410     if ( config->table_flags & ACPI_HAS_SSDT_LAPTOP_SLATE )
411     {
412         ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_laptop_slate), 16);
413         if (!ssdt) return -1;
414         memcpy(ssdt, ssdt_laptop_slate, sizeof(ssdt_laptop_slate));
415         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
416     } else {
417         printf("CONV disabled\n");
418     }
419 
420     /* TPM TCPA and SSDT. */
421     if ( (config->table_flags & ACPI_HAS_TCPA) &&
422          (config->tis_hdr[0] == tis_signature[0]) &&
423          (config->tis_hdr[1] == tis_signature[1]) &&
424          (config->tis_hdr[2] == tis_signature[2]) )
425     {
426         ssdt = ctxt->mem_ops.alloc(ctxt, sizeof(ssdt_tpm), 16);
427         if (!ssdt) return -1;
428         memcpy(ssdt, ssdt_tpm, sizeof(ssdt_tpm));
429         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, ssdt);
430 
431         tcpa = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_20_tcpa), 16);
432         if (!tcpa) return -1;
433         memset(tcpa, 0, sizeof(*tcpa));
434         table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, tcpa);
435 
436         tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE;
437         tcpa->header.length    = sizeof(*tcpa);
438         tcpa->header.revision  = ACPI_2_0_TCPA_REVISION;
439         fixed_strcpy(tcpa->header.oem_id, ACPI_OEM_ID);
440         fixed_strcpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID);
441         tcpa->header.oem_revision = ACPI_OEM_REVISION;
442         tcpa->header.creator_id   = ACPI_CREATOR_ID;
443         tcpa->header.creator_revision = ACPI_CREATOR_REVISION;
444         if ( (lasa = ctxt->mem_ops.alloc(ctxt, ACPI_2_0_TCPA_LAML_SIZE, 16)) != NULL )
445         {
446             tcpa->lasa = ctxt->mem_ops.v2p(ctxt, lasa);
447             tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
448             memset(lasa, 0, tcpa->laml);
449             set_checksum(tcpa,
450                          offsetof(struct acpi_header, checksum),
451                          tcpa->header.length);
452         }
453     }
454 
455     /* SRAT and SLIT */
456     if ( config->numa.nr_vnodes > 0 )
457     {
458         struct acpi_20_srat *srat = construct_srat(ctxt, config);
459         struct acpi_20_slit *slit = construct_slit(ctxt, config);
460 
461         if ( srat )
462             table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, srat);
463         else
464             printf("Failed to build SRAT, skipping...\n");
465         if ( slit )
466             table_ptrs[nr_tables++] = ctxt->mem_ops.v2p(ctxt, slit);
467         else
468             printf("Failed to build SLIT, skipping...\n");
469     }
470 
471     /* Load any additional tables passed through. */
472     nr_tables += construct_passthrough_tables(ctxt, table_ptrs,
473                                               nr_tables, config);
474 
475     table_ptrs[nr_tables] = 0;
476     return nr_tables;
477 }
478 
479 /**
480  * Allocate and initialize Windows Generation ID
481  * If value is not present in the XenStore or if all zeroes
482  * the device will be not active
483  *
484  * Return 0 if memory failure, != 0 if success
485  */
new_vm_gid(struct acpi_ctxt * ctxt,struct acpi_config * config,struct acpi_info * info)486 static int new_vm_gid(struct acpi_ctxt *ctxt,
487                       struct acpi_config *config,
488                       struct acpi_info *info)
489 {
490     uint64_t *buf;
491 
492     info->vm_gid_addr = 0;
493 
494     /* check for 0 ID*/
495     if ( !config->vm_gid[0] && !config->vm_gid[1] )
496         return 1;
497 
498     /* copy to allocate BIOS memory */
499     buf = ctxt->mem_ops.alloc(ctxt, sizeof(config->vm_gid), 8);
500     if ( !buf )
501         return 0;
502     memcpy(buf, config->vm_gid, sizeof(config->vm_gid));
503 
504     /* set the address into ACPI table and also pass it back to the caller */
505     info->vm_gid_addr = ctxt->mem_ops.v2p(ctxt, buf);
506     config->vm_gid_addr = info->vm_gid_addr;
507 
508     return 1;
509 }
510 
acpi_build_tables(struct acpi_ctxt * ctxt,struct acpi_config * config)511 int acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config)
512 {
513     struct acpi_info *acpi_info;
514     struct acpi_20_rsdp *rsdp;
515     struct acpi_20_rsdt *rsdt;
516     struct acpi_20_xsdt *xsdt;
517     struct acpi_fadt    *fadt;
518     struct acpi_10_fadt *fadt_10;
519     struct acpi_20_facs *facs;
520     unsigned char       *dsdt;
521     unsigned long        secondary_tables[ACPI_MAX_SECONDARY_TABLES];
522     int                  nr_secondaries, i;
523     unsigned int         fadt_size;
524 
525     acpi_info = (struct acpi_info *)config->infop;
526     memset(acpi_info, 0, sizeof(*acpi_info));
527     acpi_info->com1_present = !!(config->table_flags & ACPI_HAS_COM1);
528     acpi_info->com2_present = !!(config->table_flags & ACPI_HAS_COM2);
529     acpi_info->lpt1_present = !!(config->table_flags & ACPI_HAS_LPT1);
530     acpi_info->hpet_present = !!(config->table_flags & ACPI_HAS_HPET);
531     acpi_info->pci_min = config->pci_start;
532     acpi_info->pci_len = config->pci_len;
533     if ( config->pci_hi_len )
534     {
535         acpi_info->pci_hi_min = config->pci_hi_start;
536         acpi_info->pci_hi_len = config->pci_hi_len;
537     }
538 
539     /*
540      * Fill in high-memory data structures, starting at @buf.
541      */
542 
543     facs = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_20_facs), 16);
544     if (!facs) goto oom;
545     memcpy(facs, &Facs, sizeof(struct acpi_20_facs));
546 
547     /*
548      * Alternative DSDTs we get linked against. A cover-all DSDT for up to the
549      * implementation-defined maximum number of VCPUs, and an alternative for use
550      * when a guest can only have up to 15 VCPUs.
551      *
552      * The latter is required for Windows 2000, which experiences a BSOD of
553      * KMODE_EXCEPTION_NOT_HANDLED if it sees more than 15 processor objects.
554      */
555     if ( config->hvminfo->nr_vcpus <= 15 && config->dsdt_15cpu)
556     {
557         dsdt = ctxt->mem_ops.alloc(ctxt, config->dsdt_15cpu_len, 16);
558         if (!dsdt) goto oom;
559         memcpy(dsdt, config->dsdt_15cpu, config->dsdt_15cpu_len);
560     }
561     else
562     {
563         dsdt = ctxt->mem_ops.alloc(ctxt, config->dsdt_anycpu_len, 16);
564         if (!dsdt) goto oom;
565         memcpy(dsdt, config->dsdt_anycpu, config->dsdt_anycpu_len);
566     }
567 
568     /*
569      * N.B. ACPI 1.0 operating systems may not handle FADT with revision 2
570      * or above properly, notably Windows 2000, which tries to copy FADT
571      * into a 116 bytes buffer thus causing an overflow. The solution is to
572      * link the higher revision FADT with the XSDT only and introduce a
573      * compatible revision 1 FADT that is linked with the RSDT. Refer to:
574      *     http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt
575      */
576     fadt_10 = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_10_fadt), 16);
577     if (!fadt_10) goto oom;
578     memcpy(fadt_10, &Fadt, sizeof(struct acpi_10_fadt));
579     fadt_10->header.length = sizeof(struct acpi_10_fadt);
580     fadt_10->header.revision = ACPI_1_0_FADT_REVISION;
581     fadt_10->dsdt          = ctxt->mem_ops.v2p(ctxt, dsdt);
582     fadt_10->firmware_ctrl = ctxt->mem_ops.v2p(ctxt, facs);
583     set_checksum(fadt_10,
584                  offsetof(struct acpi_header, checksum),
585                  sizeof(struct acpi_10_fadt));
586 
587     switch ( config->acpi_revision )
588     {
589     case 4:
590         /*
591          * NB: we can use offsetof because there's no padding between
592          * x_gpe1_blk and sleep_control.
593          */
594         fadt_size = offsetof(struct acpi_fadt, sleep_control);
595         break;
596     case 5:
597         fadt_size = sizeof(*fadt);
598         break;
599     default:
600         printf("ACPI revision %u not supported\n", config->acpi_revision);
601         return -1;
602     }
603     fadt = ctxt->mem_ops.alloc(ctxt, fadt_size, 16);
604     if (!fadt) goto oom;
605     if ( !(config->table_flags & ACPI_HAS_PMTIMER) )
606     {
607         Fadt.pm_tmr_blk = Fadt.pm_tmr_len = 0;
608         memset(&Fadt.x_pm_tmr_blk, 0, sizeof(Fadt.x_pm_tmr_blk));
609     }
610     if ( !(config->table_flags & ACPI_HAS_BUTTONS) )
611         Fadt.flags |= (ACPI_PWR_BUTTON | ACPI_SLP_BUTTON);
612     memcpy(fadt, &Fadt, fadt_size);
613     /*
614      * For both ACPI 4 and 5 the revision of the FADT matches the ACPI
615      * revision.
616      */
617     fadt->header.revision = config->acpi_revision;
618     fadt->header.length = fadt_size;
619     fadt->dsdt   = ctxt->mem_ops.v2p(ctxt, dsdt);
620     fadt->x_dsdt = ctxt->mem_ops.v2p(ctxt, dsdt);
621     fadt->firmware_ctrl   = ctxt->mem_ops.v2p(ctxt, facs);
622     fadt->x_firmware_ctrl = ctxt->mem_ops.v2p(ctxt, facs);
623     if ( !(config->table_flags & ACPI_HAS_VGA) )
624         fadt->iapc_boot_arch |= ACPI_FADT_NO_VGA;
625     if ( config->table_flags & ACPI_HAS_8042 )
626         fadt->iapc_boot_arch |= ACPI_FADT_8042;
627     if ( !(config->table_flags & ACPI_HAS_CMOS_RTC) )
628     {
629         if ( fadt->header.revision < 5 )
630         {
631             printf("ACPI_FADT_NO_CMOS_RTC requires FADT revision 5\n");
632             return -1;
633         }
634         fadt->iapc_boot_arch |= ACPI_FADT_NO_CMOS_RTC;
635     }
636     set_checksum(fadt, offsetof(struct acpi_header, checksum), fadt_size);
637 
638     nr_secondaries = construct_secondary_tables(ctxt, secondary_tables,
639                  config, acpi_info);
640     if ( nr_secondaries < 0 )
641         goto oom;
642 
643     xsdt = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_20_xsdt) +
644                                sizeof(uint64_t) * nr_secondaries,
645                                16);
646     if (!xsdt) goto oom;
647     memcpy(xsdt, &Xsdt, sizeof(struct acpi_header));
648     xsdt->entry[0] = ctxt->mem_ops.v2p(ctxt, fadt);
649     for ( i = 0; secondary_tables[i]; i++ )
650         xsdt->entry[i+1] = secondary_tables[i];
651     xsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint64_t);
652     set_checksum(xsdt,
653                  offsetof(struct acpi_header, checksum),
654                  xsdt->header.length);
655 
656     rsdt = ctxt->mem_ops.alloc(ctxt, sizeof(struct acpi_20_rsdt) +
657                                sizeof(uint32_t) * nr_secondaries,
658                                16);
659     if (!rsdt) goto oom;
660     memcpy(rsdt, &Rsdt, sizeof(struct acpi_header));
661     rsdt->entry[0] = ctxt->mem_ops.v2p(ctxt, fadt_10);
662     for ( i = 0; secondary_tables[i]; i++ )
663         rsdt->entry[i+1] = secondary_tables[i];
664     rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t);
665     set_checksum(rsdt,
666                  offsetof(struct acpi_header, checksum),
667                  rsdt->header.length);
668 
669     /*
670      * Fill in low-memory data structures: acpi_info and RSDP.
671      */
672     rsdp = (struct acpi_20_rsdp *)config->rsdp;
673 
674     memcpy(rsdp, &Rsdp, sizeof(struct acpi_20_rsdp));
675     rsdp->rsdt_address = ctxt->mem_ops.v2p(ctxt, rsdt);
676     rsdp->xsdt_address = ctxt->mem_ops.v2p(ctxt, xsdt);
677     set_checksum(rsdp,
678                  offsetof(struct acpi_10_rsdp, checksum),
679                  sizeof(struct acpi_10_rsdp));
680     set_checksum(rsdp,
681                  offsetof(struct acpi_20_rsdp, extended_checksum),
682                  sizeof(struct acpi_20_rsdp));
683 
684     if ( !new_vm_gid(ctxt, config, acpi_info) )
685         goto oom;
686 
687     return 0;
688 
689 oom:
690     printf("unable to build ACPI tables: out of memory\n");
691     return -1;
692 }
693 
694 /*
695  * Local variables:
696  * mode: C
697  * c-file-style: "BSD"
698  * c-basic-offset: 4
699  * tab-width: 4
700  * indent-tabs-mode: nil
701  * End:
702  */
703