ia64/xen-unstable

view tools/firmware/hvmloader/acpi/build.c @ 18394:dade7f0bdc8d

hvm: Use main memory for video memory.

When creating an HVM domain, if e.g. another domain is created before
qemu allocates video memory, the extra 8MB memory ballooning is not
available any more, because it got consumed by the other domain.

This fixes it by taking video memory from the main memory:

- make hvmloader use e820_malloc to reserve some of the main memory
and notify ioemu of its address through the Xen platform PCI card.
- add XENMAPSPACE_mfn to the xen_add_to_physmap memory op, to allow
ioemu to move the MFNs between the original position and the PCI
mapping, when LFB acceleration is disabled/enabled
- add a remove_from_physmap memory op, to allow ioemu to unmap it
completely for the case of old guests with acceleration disabled.
- add xc_domain_memory_translate_gpfn_list to libxc to allow ioemu to
get the MFNs of the video memory.
- have xend save the PCI memory space instead of ioemu: if a memory
page is there, the guest can access it like usual memory, so xend
can safely be responsible to save it. The extra benefit is that
live migration will apply the logdirty optimization there too.
- handle old saved images, populating the video memory from ioemu if
really needed.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Aug 27 14:53:39 2008 +0100 (2008-08-27)
parents a538185695ed
children 551c3480beee
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 "../config.h"
22 #include "../util.h"
24 #define align16(sz) (((sz) + 15) & ~15)
25 #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
27 extern struct acpi_20_rsdp Rsdp;
28 extern struct acpi_20_rsdt Rsdt;
29 extern struct acpi_20_xsdt Xsdt;
30 extern struct acpi_20_fadt Fadt;
31 extern struct acpi_20_facs Facs;
32 extern unsigned char AmlCode[];
33 extern int DsdtLen;
35 static void set_checksum(
36 void *table, uint32_t checksum_offset, uint32_t length)
37 {
38 uint8_t *p, sum = 0;
40 p = table;
41 p[checksum_offset] = 0;
43 while ( length-- )
44 sum = sum + *p++;
46 p = table;
47 p[checksum_offset] = -sum;
48 }
50 static int uart_exists(uint16_t uart_base)
51 {
52 uint16_t ier = uart_base + 1;
53 uint8_t a, b, c;
55 a = inb(ier);
56 outb(ier, 0);
57 b = inb(ier);
58 outb(ier, 0xf);
59 c = inb(ier);
60 outb(ier, a);
62 return ((b == 0) && (c == 0xf));
63 }
65 static int hpet_exists(unsigned long hpet_base)
66 {
67 uint32_t hpet_id = *(uint32_t *)hpet_base;
68 return ((hpet_id >> 16) == 0x8086);
69 }
71 static int construct_bios_info_table(uint8_t *buf)
72 {
73 struct bios_info *bios_info = (struct bios_info *)buf;
75 memset(bios_info, 0, sizeof(*bios_info));
77 bios_info->com1_present = uart_exists(0x3f8);
78 bios_info->com2_present = uart_exists(0x2f8);
80 bios_info->hpet_present = hpet_exists(ACPI_HPET_ADDRESS);
82 bios_info->pci_min = PCI_MEMBASE;
83 bios_info->pci_len = PCI_MEMSIZE;
84 bios_info->xen_pfiob = 0xdead;
86 return align16(sizeof(*bios_info));
87 }
89 static int construct_madt(struct acpi_20_madt *madt)
90 {
91 struct acpi_20_madt_intsrcovr *intsrcovr;
92 struct acpi_20_madt_ioapic *io_apic;
93 struct acpi_20_madt_lapic *lapic;
94 int i, offset = 0;
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 = LAPIC_BASE_ADDRESS;
105 madt->flags = ACPI_PCAT_COMPAT;
106 offset += sizeof(*madt);
108 intsrcovr = (struct acpi_20_madt_intsrcovr *)(madt + 1);
109 for ( i = 0; i < 16; i++ )
110 {
111 memset(intsrcovr, 0, sizeof(*intsrcovr));
112 intsrcovr->type = ACPI_INTERRUPT_SOURCE_OVERRIDE;
113 intsrcovr->length = sizeof(*intsrcovr);
114 intsrcovr->source = i;
116 if ( i == 0 )
117 {
118 /* ISA IRQ0 routed to IOAPIC GSI 2. */
119 intsrcovr->gsi = 2;
120 intsrcovr->flags = 0x0;
121 }
122 else if ( PCI_ISA_IRQ_MASK & (1U << i) )
123 {
124 /* PCI: active-low level-triggered. */
125 intsrcovr->gsi = i;
126 intsrcovr->flags = 0xf;
127 }
128 else
129 {
130 /* No need for a INT source override structure. */
131 continue;
132 }
134 offset += sizeof(*intsrcovr);
135 intsrcovr++;
136 }
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 = IOAPIC_ID;
143 io_apic->ioapic_addr = IOAPIC_BASE_ADDRESS;
144 offset += sizeof(*io_apic);
146 lapic = (struct acpi_20_madt_lapic *)(io_apic + 1);
147 for ( i = 0; i < get_vcpu_nr(); i++ )
148 {
149 memset(lapic, 0, sizeof(*lapic));
150 lapic->type = ACPI_PROCESSOR_LOCAL_APIC;
151 lapic->length = sizeof(*lapic);
152 /* Processor ID must match processor-object IDs in the DSDT. */
153 lapic->acpi_processor_id = i;
154 lapic->apic_id = LAPIC_ID(i);
155 lapic->flags = ACPI_LOCAL_APIC_ENABLED;
156 offset += sizeof(*lapic);
157 lapic++;
158 }
160 madt->header.length = offset;
161 set_checksum(madt, offsetof(struct acpi_header, checksum), offset);
163 return align16(offset);
164 }
166 static int construct_hpet(struct acpi_20_hpet *hpet)
167 {
168 int offset;
170 memset(hpet, 0, sizeof(*hpet));
171 hpet->header.signature = ACPI_2_0_HPET_SIGNATURE;
172 hpet->header.revision = ACPI_2_0_HPET_REVISION;
173 fixed_strcpy(hpet->header.oem_id, ACPI_OEM_ID);
174 fixed_strcpy(hpet->header.oem_table_id, ACPI_OEM_TABLE_ID);
175 hpet->header.oem_revision = ACPI_OEM_REVISION;
176 hpet->header.creator_id = ACPI_CREATOR_ID;
177 hpet->header.creator_revision = ACPI_CREATOR_REVISION;
178 hpet->timer_block_id = 0x8086a201;
179 hpet->addr.address = ACPI_HPET_ADDRESS;
180 offset = sizeof(*hpet);
182 hpet->header.length = offset;
183 set_checksum(hpet, offsetof(struct acpi_header, checksum), offset);
185 return offset;
186 }
188 static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
189 {
190 int offset = 0, nr_tables = 0;
191 struct acpi_20_madt *madt;
192 struct acpi_20_hpet *hpet;
193 struct acpi_20_tcpa *tcpa;
194 static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
195 uint16_t *tis_hdr;
197 /* MADT. */
198 if ( (get_vcpu_nr() > 1) || get_apic_mode() )
199 {
200 madt = (struct acpi_20_madt *)&buf[offset];
201 offset += construct_madt(madt);
202 table_ptrs[nr_tables++] = (unsigned long)madt;
203 }
205 /* HPET. */
206 if ( hpet_exists(ACPI_HPET_ADDRESS) )
207 {
208 hpet = (struct acpi_20_hpet *)&buf[offset];
209 offset += construct_hpet(hpet);
210 table_ptrs[nr_tables++] = (unsigned long)hpet;
211 }
213 /* TPM TCPA and SSDT. */
214 tis_hdr = (uint16_t *)0xFED40F00;
215 if ( (tis_hdr[0] == tis_signature[0]) &&
216 (tis_hdr[1] == tis_signature[1]) &&
217 (tis_hdr[2] == tis_signature[2]) )
218 {
219 memcpy(&buf[offset], AmlCode_TPM, sizeof(AmlCode_TPM));
220 table_ptrs[nr_tables++] = (unsigned long)&buf[offset];
221 offset += align16(sizeof(AmlCode_TPM));
223 tcpa = (struct acpi_20_tcpa *)&buf[offset];
224 memset(tcpa, 0, sizeof(*tcpa));
225 offset += align16(sizeof(*tcpa));
226 table_ptrs[nr_tables++] = (unsigned long)tcpa;
228 tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE;
229 tcpa->header.length = sizeof(*tcpa);
230 tcpa->header.revision = ACPI_2_0_TCPA_REVISION;
231 fixed_strcpy(tcpa->header.oem_id, ACPI_OEM_ID);
232 fixed_strcpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID);
233 tcpa->header.oem_revision = ACPI_OEM_REVISION;
234 tcpa->header.creator_id = ACPI_CREATOR_ID;
235 tcpa->header.creator_revision = ACPI_CREATOR_REVISION;
236 tcpa->lasa = e820_malloc(ACPI_2_0_TCPA_LAML_SIZE, 0);
237 if ( tcpa->lasa )
238 {
239 tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
240 memset((char *)(unsigned long)tcpa->lasa, 0, tcpa->laml);
241 set_checksum(tcpa,
242 offsetof(struct acpi_header, checksum),
243 tcpa->header.length);
244 }
245 }
247 table_ptrs[nr_tables] = 0;
248 return align16(offset);
249 }
251 static void __acpi_build_tables(uint8_t *buf, int *low_sz, int *high_sz)
252 {
253 struct acpi_20_rsdp *rsdp;
254 struct acpi_20_rsdt *rsdt;
255 struct acpi_20_xsdt *xsdt;
256 struct acpi_20_fadt *fadt;
257 struct acpi_10_fadt *fadt_10;
258 struct acpi_20_facs *facs;
259 unsigned char *dsdt;
260 unsigned long secondary_tables[16];
261 int offset = 0, i;
263 /*
264 * Fill in high-memory data structures, starting at @buf.
265 */
267 facs = (struct acpi_20_facs *)&buf[offset];
268 memcpy(facs, &Facs, sizeof(struct acpi_20_facs));
269 offset += align16(sizeof(struct acpi_20_facs));
271 dsdt = (unsigned char *)&buf[offset];
272 memcpy(dsdt, &AmlCode, DsdtLen);
273 offset += align16(DsdtLen);
275 /*
276 * N.B. ACPI 1.0 operating systems may not handle FADT with revision 2
277 * or above properly, notably Windows 2000, which tries to copy FADT
278 * into a 116 bytes buffer thus causing an overflow. The solution is to
279 * link the higher revision FADT with the XSDT only and introduce a
280 * compatible revision 1 FADT that is linked with the RSDT. Refer to:
281 * http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt
282 */
283 fadt_10 = (struct acpi_10_fadt *)&buf[offset];
284 memcpy(fadt_10, &Fadt, sizeof(struct acpi_10_fadt));
285 offset += align16(sizeof(struct acpi_10_fadt));
286 fadt_10->header.length = sizeof(struct acpi_10_fadt);
287 fadt_10->header.revision = ACPI_1_0_FADT_REVISION;
288 fadt_10->dsdt = (unsigned long)dsdt;
289 fadt_10->firmware_ctrl = (unsigned long)facs;
290 set_checksum(fadt_10,
291 offsetof(struct acpi_header, checksum),
292 sizeof(struct acpi_10_fadt));
294 fadt = (struct acpi_20_fadt *)&buf[offset];
295 memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt));
296 offset += align16(sizeof(struct acpi_20_fadt));
297 fadt->dsdt = (unsigned long)dsdt;
298 fadt->x_dsdt = (unsigned long)dsdt;
299 fadt->firmware_ctrl = (unsigned long)facs;
300 fadt->x_firmware_ctrl = (unsigned long)facs;
301 set_checksum(fadt,
302 offsetof(struct acpi_header, checksum),
303 sizeof(struct acpi_20_fadt));
305 offset += construct_secondary_tables(&buf[offset], secondary_tables);
307 xsdt = (struct acpi_20_xsdt *)&buf[offset];
308 memcpy(xsdt, &Xsdt, sizeof(struct acpi_header));
309 xsdt->entry[0] = (unsigned long)fadt;
310 for ( i = 0; secondary_tables[i]; i++ )
311 xsdt->entry[i+1] = secondary_tables[i];
312 xsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint64_t);
313 offset += align16(xsdt->header.length);
314 set_checksum(xsdt,
315 offsetof(struct acpi_header, checksum),
316 xsdt->header.length);
318 rsdt = (struct acpi_20_rsdt *)&buf[offset];
319 memcpy(rsdt, &Rsdt, sizeof(struct acpi_header));
320 rsdt->entry[0] = (unsigned long)fadt_10;
321 for ( i = 0; secondary_tables[i]; i++ )
322 rsdt->entry[i+1] = secondary_tables[i];
323 rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t);
324 offset += align16(rsdt->header.length);
325 set_checksum(rsdt,
326 offsetof(struct acpi_header, checksum),
327 rsdt->header.length);
329 *high_sz = offset;
331 /*
332 * Fill in low-memory data structures: bios_info_table and RSDP.
333 */
335 buf = (uint8_t *)ACPI_PHYSICAL_ADDRESS;
336 offset = 0;
338 offset += construct_bios_info_table(&buf[offset]);
339 rsdp = (struct acpi_20_rsdp *)&buf[offset];
341 memcpy(rsdp, &Rsdp, sizeof(struct acpi_20_rsdp));
342 offset += align16(sizeof(struct acpi_20_rsdp));
343 rsdp->rsdt_address = (unsigned long)rsdt;
344 rsdp->xsdt_address = (unsigned long)xsdt;
345 set_checksum(rsdp,
346 offsetof(struct acpi_10_rsdp, checksum),
347 sizeof(struct acpi_10_rsdp));
348 set_checksum(rsdp,
349 offsetof(struct acpi_20_rsdp, extended_checksum),
350 sizeof(struct acpi_20_rsdp));
352 *low_sz = offset;
353 }
355 void acpi_build_tables(void)
356 {
357 int high_sz, low_sz;
358 uint8_t *buf;
360 /* Find out size of high-memory ACPI data area. */
361 buf = (uint8_t *)&_end;
362 __acpi_build_tables(buf, &low_sz, &high_sz);
363 memset(buf, 0, high_sz);
365 /* Allocate data area and set up ACPI tables there. */
366 buf = (uint8_t *)e820_malloc(high_sz, 0);
367 __acpi_build_tables(buf, &low_sz, &high_sz);
369 printf(" - Lo data: %08lx-%08lx\n"
370 " - Hi data: %08lx-%08lx\n",
371 (unsigned long)ACPI_PHYSICAL_ADDRESS,
372 (unsigned long)ACPI_PHYSICAL_ADDRESS + low_sz - 1,
373 (unsigned long)buf, (unsigned long)buf + high_sz - 1);
374 }
376 /*
377 * Local variables:
378 * mode: C
379 * c-set-style: "BSD"
380 * c-basic-offset: 4
381 * tab-width: 4
382 * indent-tabs-mode: nil
383 * End:
384 */