debuggers.hg

view xen/arch/ia64/xen/dom_fw_common.c @ 19826:2f9e1348aa98

x86_64: allow more vCPU-s per guest

Since the shared info layout is fixed, guests are required to use
VCPUOP_register_vcpu_info prior to booting any vCPU beyond the
traditional limit of 32.

MAX_VIRT_CPUS, being an implemetation detail of the hypervisor, is no
longer being exposed in the public headers.

The tools changes are clearly incomplete (and done only so things
would
build again), and the current state of the tools (using scalar
variables all over the place to represent vCPU bitmaps) very likely
doesn't permit booting DomU-s with more than the traditional number of
vCPU-s. Testing of the extended functionality was done with Dom0 (96
vCPU-s, as well as 128 vCPU-s out of which the kernel elected - by way
of a simple kernel side patch - to use only some, resulting in a
sparse
bitmap).

ia64 changes only to make things build, and build-tested only (and the
tools part only as far as the build would go without encountering
unrelated problems in the blktap code).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 10:14:16 2009 +0100 (2009-06-18)
parents 559809738237
children 3ffdb094c2c0
line source
1 /*
2 * Xen domain firmware emulation support
3 * Copyright (C) 2004 Hewlett-Packard Co.
4 * Dan Magenheimer (dan.magenheimer@hp.com)
5 *
6 * Copyright (c) 2006, 2007
7 * Isaku Yamahata <yamahata at valinux co jp>
8 * VA Linux Systems Japan K.K.
9 * dom0 vp model support
10 */
12 #ifdef __XEN__
13 #include <asm/system.h>
14 #include <asm/dom_fw_dom0.h>
15 #include <asm/dom_fw_utils.h>
16 #else
17 #include <string.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <assert.h>
21 #include <inttypes.h>
23 #include <xen/xen.h>
24 #include <asm/bundle.h>
26 #include "xg_private.h"
27 #include "xc_dom.h"
28 #include "ia64/xc_dom_ia64_util.h"
30 #define ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory")
31 #define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS /* XXX */
32 #endif /* __XEN__ */
34 #include <xen/acpi.h>
35 #include <acpi/actables.h>
36 #include <asm/dom_fw.h>
37 #include <asm/dom_fw_domu.h>
39 void
40 xen_ia64_efi_make_md(efi_memory_desc_t *md,
41 uint32_t type, uint64_t attr,
42 uint64_t start, uint64_t end)
43 {
44 md->type = type;
45 md->pad = 0;
46 md->phys_addr = start;
47 md->virt_addr = 0;
48 md->num_pages = (end - start) >> EFI_PAGE_SHIFT;
49 md->attribute = attr;
50 }
52 #define EFI_HYPERCALL_PATCH(tgt, call) \
53 do { \
54 dom_efi_hypercall_patch(brkimm, \
55 FW_HYPERCALL_##call##_PADDR, \
56 FW_HYPERCALL_##call, hypercalls_imva); \
57 /* Descriptor address. */ \
58 tables->efi_runtime.tgt = \
59 FW_FIELD_MPA(func_ptrs) + 8 * pfn; \
60 /* Descriptor. */ \
61 tables->func_ptrs[pfn++] = FW_HYPERCALL_##call##_PADDR; \
62 tables->func_ptrs[pfn++] = 0; \
63 } while (0)
65 /**************************************************************************
66 Hypercall bundle creation
67 **************************************************************************/
69 static void
70 build_hypercall_bundle(uint64_t *imva, uint64_t brkimm, uint64_t hypnum, uint64_t ret)
71 {
72 INST64_A5 slot0;
73 INST64_I19 slot1;
74 INST64_B4 slot2;
75 IA64_BUNDLE bundle;
77 // slot1: mov r2 = hypnum (low 20 bits)
78 slot0.inst = 0;
79 slot0.qp = 0; slot0.r1 = 2; slot0.r3 = 0; slot0.major = 0x9;
80 slot0.imm7b = hypnum; slot0.imm9d = hypnum >> 7;
81 slot0.imm5c = hypnum >> 16; slot0.s = 0;
82 // slot1: break brkimm
83 slot1.inst = 0;
84 slot1.qp = 0; slot1.x6 = 0; slot1.x3 = 0; slot1.major = 0x0;
85 slot1.imm20 = brkimm; slot1.i = brkimm >> 20;
86 // if ret slot2: br.ret.sptk.many rp
87 // else slot2: br.cond.sptk.many rp
88 slot2.inst = 0; slot2.qp = 0; slot2.p = 1; slot2.b2 = 0;
89 slot2.wh = 0; slot2.d = 0; slot2.major = 0x0;
90 if (ret) {
91 slot2.btype = 4; slot2.x6 = 0x21;
92 }
93 else {
94 slot2.btype = 0; slot2.x6 = 0x20;
95 }
97 bundle.i64[0] = 0; bundle.i64[1] = 0;
98 bundle.template = 0x11;
99 bundle.slot0 = slot0.inst; bundle.slot2 = slot2.inst;
100 bundle.slot1a = slot1.inst; bundle.slot1b = slot1.inst >> 18;
102 imva[0] = bundle.i64[0]; imva[1] = bundle.i64[1];
103 ia64_fc(imva);
104 ia64_fc(imva + 1);
105 }
107 static void
108 build_pal_hypercall_bundles(uint64_t *imva, uint64_t brkimm, uint64_t hypnum)
109 {
110 extern unsigned long xen_ia64_pal_call_stub[];
111 IA64_BUNDLE bundle;
112 INST64_A5 slot_a5;
113 INST64_M37 slot_m37;
115 /*
116 * The source of the hypercall stub is
117 * the xen_ia64_pal_call_stub function defined in dom_fw_asm.S.
118 */
120 /* Copy the first bundle and patch the hypercall number. */
121 bundle.i64[0] = xen_ia64_pal_call_stub[0];
122 bundle.i64[1] = xen_ia64_pal_call_stub[1];
123 slot_a5.inst = bundle.slot0;
124 slot_a5.imm7b = hypnum;
125 slot_a5.imm9d = hypnum >> 7;
126 slot_a5.imm5c = hypnum >> 16;
127 bundle.slot0 = slot_a5.inst;
128 imva[0] = bundle.i64[0];
129 imva[1] = bundle.i64[1];
130 ia64_fc(imva);
131 ia64_fc(imva + 1);
133 /* Copy the second bundle and patch the hypercall vector. */
134 bundle.i64[0] = xen_ia64_pal_call_stub[2];
135 bundle.i64[1] = xen_ia64_pal_call_stub[3];
136 slot_m37.inst = bundle.slot0;
137 slot_m37.imm20a = brkimm;
138 slot_m37.i = brkimm >> 20;
139 bundle.slot0 = slot_m37.inst;
140 imva[2] = bundle.i64[0];
141 imva[3] = bundle.i64[1];
142 ia64_fc(imva + 2);
143 ia64_fc(imva + 3);
144 }
146 /* xen fpswa call stub. 14 bundles */
147 extern const unsigned long xen_ia64_fpswa_call_stub[];
148 extern const unsigned long xen_ia64_fpswa_call_stub_end[];
149 extern const unsigned long xen_ia64_fpswa_call_stub_patch[];
150 asm(
151 ".align 32\n"
152 ".proc xen_ia64_fpswa_call_stub;\n"
153 "xen_ia64_fpswa_call_stub:\n"
154 ".prologue\n"
155 "alloc r3 = ar.pfs, 8, 0, 0, 0\n"
156 ".body\n"
157 "mov r14 = in0\n"
158 "ld8 r15 = [in1], 8\n"
159 ";;\n"
160 "ld8 r16 = [in1]\n"
161 "ld8 r17 = [in2]\n"
162 "ld8 r18 = [in3]\n"
163 "ld8 r19 = [in4]\n"
164 "ld8 r20 = [in5]\n"
165 "ld8 r21 = [in6]\n"
166 "ld8 r22 = [in7], 8\n"
167 ";;\n"
168 "ld8 r23 = [in7], 8\n"
169 ";;\n"
170 "ld8 r24 = [in7], 8\n"
171 ";;\n"
172 "cmp.ne p6, p0 = r24, r0\n"
173 "ld8 r25 = [in7], 8\n"
174 ";;\n"
175 "(p6) tpa r24 = r24\n"
176 "cmp.ne p7, p0 = r25, r0\n"
177 "ld8 r26 = [in7], 8\n"
178 ";;\n"
179 "(p7)tpa r25 = r25\n"
180 "cmp.ne p8, p0 = r26, r0\n"
181 "ld8 r27 = [in7], 8\n"
182 ";;\n"
183 "(p8)tpa r26 = r26\n"
184 "cmp.ne p9, p0 = r27, r0\n"
185 ";;\n"
186 "tpa r27 = r27\n"
187 "xen_ia64_fpswa_call_stub_patch:"
188 "{\n"
189 "mov r2 = " FW_HYPERCALL_FPSWA_STR "\n"
190 "break " __IA64_XEN_HYPERCALL_DEFAULT_STR "\n"
191 "nop.i 0\n"
192 "}\n"
193 "st8 [in2] = r17\n"
194 "st8 [in3] = r18\n"
195 "st8 [in4] = r19\n"
196 "st8 [in5] = r20\n"
197 "st8 [in6] = r21\n"
198 "br.ret.sptk.many rp\n"
199 "xen_ia64_fpswa_call_stub_end:"
200 ".endp xen_ia64_fpswa_call_stub\n"
201 );
203 static void
204 build_fpswa_hypercall_bundle(uint64_t *imva, uint64_t brkimm, uint64_t hypnum)
205 {
206 INST64_A5 slot0;
207 INST64_I19 slot1;
208 INST64_I18 slot2;
209 IA64_BUNDLE bundle;
211 /* slot0: mov r2 = hypnum (low 20 bits) */
212 slot0.inst = 0;
213 slot0.qp = 0;
214 slot0.r1 = 2;
215 slot0.r3 = 0;
216 slot0.major = 0x9;
218 slot0.s = 0;
219 slot0.imm9d = hypnum >> 7;
220 slot0.imm5c = hypnum >> 16;
221 slot0.imm7b = hypnum;
223 /* slot1: break brkimm */
224 slot1.inst = 0;
225 slot1.qp = 0;
226 slot1.x6 = 0;
227 slot1.x3 = 0;
228 slot1.major = 0x0;
229 slot1.i = brkimm >> 20;
230 slot1.imm20 = brkimm;
232 /* slot2: nop.i */
233 slot2.inst = 0;
234 slot2.qp = 0;
235 slot2.imm20 = 0;
236 slot2.y = 0;
237 slot2.x6 = 1;
238 slot2.x3 = 0;
239 slot2.i = 0;
240 slot2.major = 0;
242 /* MII bundle */
243 bundle.i64[0] = 0;
244 bundle.i64[1] = 0;
245 bundle.template = 0x0; /* MII */
246 bundle.slot0 = slot0.inst;
247 bundle.slot1a = slot1.inst;
248 bundle.slot1b = slot1.inst >> 18;
249 bundle.slot2 = slot2.inst;
251 imva[0] = bundle.i64[0];
252 imva[1] = bundle.i64[1];
253 ia64_fc(imva);
254 ia64_fc(imva + 1);
255 }
257 // builds a hypercall bundle at domain physical address
258 static void
259 dom_fpswa_hypercall_patch(uint64_t brkimm, unsigned long imva)
260 {
261 unsigned long *entry_imva, *patch_imva;
262 const unsigned long entry_paddr = FW_HYPERCALL_FPSWA_ENTRY_PADDR;
263 const unsigned long patch_paddr = FW_HYPERCALL_FPSWA_PATCH_PADDR;
264 const size_t stub_size =
265 (char*)xen_ia64_fpswa_call_stub_end -
266 (char*)xen_ia64_fpswa_call_stub;
267 size_t i;
269 entry_imva = (unsigned long *)(imva + entry_paddr -
270 FW_HYPERCALL_BASE_PADDR);
271 patch_imva = (unsigned long *)(imva + patch_paddr -
272 FW_HYPERCALL_BASE_PADDR);
274 /* Descriptor. */
275 *entry_imva++ = patch_paddr;
276 *entry_imva = 0;
278 /* see dom_fw.h */
279 BUG_ON((char*)xen_ia64_fpswa_call_stub_end -
280 (char*)xen_ia64_fpswa_call_stub > 0xff - 16 + 1);
282 /* call stub */
283 memcpy(patch_imva, xen_ia64_fpswa_call_stub, stub_size);
284 for (i = 0; i < stub_size; i++)
285 ia64_fc(imva + i);
286 patch_imva +=
287 xen_ia64_fpswa_call_stub_patch - xen_ia64_fpswa_call_stub;
288 build_fpswa_hypercall_bundle(patch_imva, brkimm, FW_HYPERCALL_FPSWA);
289 }
291 // builds a hypercall bundle at domain physical address
292 static void
293 dom_efi_hypercall_patch(uint64_t brkimm, unsigned long paddr,
294 unsigned long hypercall, unsigned long imva)
295 {
296 build_hypercall_bundle((uint64_t *)(imva + paddr -
297 FW_HYPERCALL_BASE_PADDR),
298 brkimm, hypercall, 1);
299 }
301 // builds a hypercall bundle at domain physical address
302 static void
303 dom_fw_hypercall_patch(uint64_t brkimm, unsigned long paddr,
304 unsigned long hypercall,unsigned long ret,
305 unsigned long imva)
306 {
307 build_hypercall_bundle((uint64_t *)(imva + paddr -
308 FW_HYPERCALL_BASE_PADDR),
309 brkimm, hypercall, ret);
310 }
312 static void
313 dom_fw_pal_hypercall_patch(uint64_t brkimm, unsigned long paddr, unsigned long imva)
314 {
315 build_pal_hypercall_bundles((uint64_t*)(imva + paddr -
316 FW_HYPERCALL_BASE_PADDR),
317 brkimm, FW_HYPERCALL_PAL_CALL);
318 }
320 static inline void
321 print_md(efi_memory_desc_t *md)
322 {
323 uint64_t size;
325 printk(XENLOG_INFO "dom mem: type=%2u, attr=0x%016lx, "
326 "range=[0x%016lx-0x%016lx) ",
327 md->type, md->attribute, md->phys_addr,
328 md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT));
330 size = md->num_pages << EFI_PAGE_SHIFT;
331 if (size > ONE_MB)
332 printk("(%luMB)\n", size >> 20);
333 else
334 printk("(%luKB)\n", size >> 10);
335 }
337 struct fake_acpi_tables {
338 struct acpi_table_rsdp rsdp;
339 struct acpi_table_xsdt xsdt;
340 uint64_t madt_ptr;
341 struct acpi_table_fadt fadt;
342 struct acpi_table_facs facs;
343 struct acpi_table_header dsdt;
344 uint8_t aml[8 + 11 * MAX_VIRT_CPUS];
345 struct acpi_table_madt madt;
346 struct acpi_table_lsapic lsapic[MAX_VIRT_CPUS];
347 uint8_t pm1a_event_block[4];
348 uint8_t pm1a_control_block[1];
349 uint8_t pm_timer_block[4];
350 };
351 #define ACPI_TABLE_MPA(field) \
352 FW_ACPI_BASE_PADDR + offsetof(struct fake_acpi_tables, field);
354 /* Create enough of an ACPI structure to make the guest OS ACPI happy. */
355 void
356 dom_fw_fake_acpi(domain_t *d, struct fake_acpi_tables *tables)
357 {
358 struct acpi_table_rsdp *rsdp = &tables->rsdp;
359 struct acpi_table_xsdt *xsdt = &tables->xsdt;
360 struct acpi_table_fadt *fadt = &tables->fadt;
361 struct acpi_table_facs *facs = &tables->facs;
362 struct acpi_table_header *dsdt = &tables->dsdt;
363 struct acpi_table_madt *madt = &tables->madt;
364 struct acpi_table_lsapic *lsapic = tables->lsapic;
365 int i;
366 int aml_len;
367 int nbr_cpus;
369 BUILD_BUG_ON(sizeof(struct fake_acpi_tables) >
370 (FW_ACPI_END_PADDR - FW_ACPI_BASE_PADDR));
372 memset(tables, 0, sizeof(struct fake_acpi_tables));
374 /* setup XSDT (64bit version of RSDT) */
375 memcpy(xsdt->header.signature, ACPI_SIG_XSDT,
376 sizeof(xsdt->header.signature));
377 /* XSDT points to both the FADT and the MADT, so add one entry */
378 xsdt->header.length = sizeof(struct acpi_table_xsdt) + sizeof(uint64_t);
379 xsdt->header.revision = 1;
380 memcpy(xsdt->header.oem_id, "XEN", 3);
381 memcpy(xsdt->header.oem_table_id, "Xen/ia64", 8);
382 memcpy(xsdt->header.asl_compiler_id, "XEN", 3);
383 xsdt->header.asl_compiler_revision = xen_ia64_version(d);
385 xsdt->table_offset_entry[0] = ACPI_TABLE_MPA(fadt);
386 tables->madt_ptr = ACPI_TABLE_MPA(madt);
388 xsdt->header.checksum = -acpi_tb_checksum((u8*)xsdt,
389 xsdt->header.length);
391 /* setup FADT */
392 memcpy(fadt->header.signature, ACPI_SIG_FADT,
393 sizeof(fadt->header.signature));
394 fadt->header.length = sizeof(struct acpi_table_fadt);
395 fadt->header.revision = FADT2_REVISION_ID;
396 memcpy(fadt->header.oem_id, "XEN", 3);
397 memcpy(fadt->header.oem_table_id, "Xen/ia64", 8);
398 memcpy(fadt->header.asl_compiler_id, "XEN", 3);
399 fadt->header.asl_compiler_revision = xen_ia64_version(d);
401 memcpy(facs->signature, ACPI_SIG_FACS, sizeof(facs->signature));
402 facs->version = 1;
403 facs->length = sizeof(struct acpi_table_facs);
405 fadt->Xfacs = ACPI_TABLE_MPA(facs);
406 fadt->Xdsdt = ACPI_TABLE_MPA(dsdt);
408 /*
409 * All of the below FADT entries are filled it to prevent warnings
410 * from sanity checks in the ACPI CA. Emulate required ACPI hardware
411 * registers in system memory.
412 */
413 fadt->pm1_event_length = 4;
414 fadt->xpm1a_event_block.space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY;
415 fadt->xpm1a_event_block.bit_width = 8;
416 fadt->xpm1a_event_block.address = ACPI_TABLE_MPA(pm1a_event_block);
417 fadt->pm1_control_length = 1;
418 fadt->xpm1a_control_block.space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY;
419 fadt->xpm1a_control_block.bit_width = 8;
420 fadt->xpm1a_control_block.address = ACPI_TABLE_MPA(pm1a_control_block);
421 fadt->pm_timer_length = 4;
422 fadt->xpm_timer_block.space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY;
423 fadt->xpm_timer_block.bit_width = 8;
424 fadt->xpm_timer_block.address = ACPI_TABLE_MPA(pm_timer_block);
426 fadt->header.checksum = -acpi_tb_checksum((u8*)fadt,
427 fadt->header.length);
429 /* setup RSDP */
430 memcpy(rsdp->signature, ACPI_SIG_RSDP, strlen(ACPI_SIG_RSDP));
431 memcpy(rsdp->oem_id, "XEN", 3);
432 rsdp->revision = 2; /* ACPI 2.0 includes XSDT */
433 rsdp->length = sizeof(struct acpi_table_rsdp);
434 rsdp->xsdt_physical_address = ACPI_TABLE_MPA(xsdt);
436 rsdp->checksum = -acpi_tb_checksum((u8*)rsdp,
437 ACPI_RSDP_CHECKSUM_LENGTH);
438 rsdp->extended_checksum = -acpi_tb_checksum((u8*)rsdp, rsdp->length);
440 /* setup DSDT with trivial namespace. */
441 memcpy(dsdt->signature, ACPI_SIG_DSDT, strlen(ACPI_SIG_DSDT));
442 dsdt->revision = 1;
443 memcpy(dsdt->oem_id, "XEN", 3);
444 memcpy(dsdt->oem_table_id, "Xen/ia64", 8);
445 memcpy(dsdt->asl_compiler_id, "XEN", 3);
446 dsdt->asl_compiler_revision = xen_ia64_version(d);
448 /* Trivial namespace, avoids ACPI CA complaints */
449 tables->aml[0] = 0x10; /* Scope */
450 tables->aml[1] = 0x40; /* length/offset to next object (patched) */
451 tables->aml[2] = 0x00;
452 memcpy(&tables->aml[3], "_SB_", 4);
454 /* The processor object isn't absolutely necessary, revist for SMP */
455 aml_len = 7;
456 for (i = 0; i < 3; i++) {
457 unsigned char *p = tables->aml + aml_len;
458 p[0] = 0x5b; /* processor object */
459 p[1] = 0x83;
460 p[2] = 0x0b; /* next */
461 p[3] = 'C';
462 p[4] = 'P';
463 snprintf ((char *)p + 5, 3, "%02x", i);
464 if (i < 16)
465 p[5] = 'U';
466 p[7] = i; /* acpi_id */
467 p[8] = 0; /* pblk_addr */
468 p[9] = 0;
469 p[10] = 0;
470 p[11] = 0;
471 p[12] = 0; /* pblk_len */
472 aml_len += 13;
473 }
474 tables->aml[1] = 0x40 + ((aml_len - 1) & 0x0f);
475 tables->aml[2] = (aml_len - 1) >> 4;
476 dsdt->length = sizeof(struct acpi_table_header) + aml_len;
477 dsdt->checksum = -acpi_tb_checksum((u8*)dsdt, dsdt->length);
479 /* setup MADT */
480 memcpy(madt->header.signature, ACPI_SIG_MADT,
481 sizeof(madt->header.signature));
482 madt->header.revision = 2;
483 memcpy(madt->header.oem_id, "XEN", 3);
484 memcpy(madt->header.oem_table_id, "Xen/ia64", 8);
485 memcpy(madt->header.asl_compiler_id, "XEN", 3);
486 madt->header.asl_compiler_revision = xen_ia64_version(d);
488 /* An LSAPIC entry describes a CPU. */
489 nbr_cpus = 0;
490 for (i = 0; i < MAX_VIRT_CPUS; i++) {
491 lsapic[i].header.type = ACPI_MADT_LSAPIC;
492 lsapic[i].header.length = sizeof(struct acpi_table_lsapic);
493 lsapic[i].acpi_id = i;
494 lsapic[i].id = i;
495 lsapic[i].eid = 0;
496 if (xen_ia64_is_vcpu_allocated(d, i)) {
497 lsapic[i].flags.enabled = 1;
498 nbr_cpus++;
499 }
500 }
501 madt->header.length = sizeof(struct acpi_table_madt) +
502 nbr_cpus * sizeof(struct acpi_table_lsapic);
503 madt->header.checksum = -acpi_tb_checksum((u8*)madt,
504 madt->header.length);
505 return;
506 }
508 int
509 efi_mdt_cmp(const void *a, const void *b)
510 {
511 const efi_memory_desc_t *x = a, *y = b;
513 if (x->phys_addr > y->phys_addr)
514 return 1;
515 if (x->phys_addr < y->phys_addr)
516 return -1;
518 /* num_pages == 0 is allowed. */
519 if (x->num_pages > y->num_pages)
520 return 1;
521 if (x->num_pages < y->num_pages)
522 return -1;
524 return 0;
525 }
527 int
528 dom_fw_init(domain_t *d,
529 uint64_t brkimm,
530 struct xen_ia64_boot_param *bp,
531 struct fw_tables *tables,
532 unsigned long hypercalls_imva,
533 unsigned long maxmem)
534 {
535 unsigned long pfn;
536 unsigned char checksum;
537 char *cp;
538 int num_mds, i;
539 int fpswa_supported = 0;
541 /* Caller must zero-clear fw_tables */
543 /* EFI systab. */
544 tables->efi_systab.hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
545 tables->efi_systab.hdr.revision = ((1 << 16) | 00); /* EFI 1.00 */
546 tables->efi_systab.hdr.headersize = sizeof(tables->efi_systab.hdr);
548 memcpy(tables->fw_vendor,FW_VENDOR,sizeof(FW_VENDOR));
549 tables->efi_systab.fw_vendor = FW_FIELD_MPA(fw_vendor);
550 tables->efi_systab.fw_revision = 1;
551 tables->efi_systab.runtime = (void *)FW_FIELD_MPA(efi_runtime);
552 tables->efi_systab.nr_tables = NUM_EFI_SYS_TABLES;
553 tables->efi_systab.tables = FW_FIELD_MPA(efi_tables);
555 /* EFI runtime. */
556 tables->efi_runtime.hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
557 tables->efi_runtime.hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
558 tables->efi_runtime.hdr.headersize = sizeof(tables->efi_runtime.hdr);
560 pfn = 0;
561 EFI_HYPERCALL_PATCH(get_time,EFI_GET_TIME);
562 EFI_HYPERCALL_PATCH(set_time,EFI_SET_TIME);
563 EFI_HYPERCALL_PATCH(get_wakeup_time,EFI_GET_WAKEUP_TIME);
564 EFI_HYPERCALL_PATCH(set_wakeup_time,EFI_SET_WAKEUP_TIME);
565 EFI_HYPERCALL_PATCH(set_virtual_address_map,
566 EFI_SET_VIRTUAL_ADDRESS_MAP);
567 EFI_HYPERCALL_PATCH(get_variable,EFI_GET_VARIABLE);
568 EFI_HYPERCALL_PATCH(get_next_variable,EFI_GET_NEXT_VARIABLE);
569 EFI_HYPERCALL_PATCH(set_variable,EFI_SET_VARIABLE);
570 EFI_HYPERCALL_PATCH(get_next_high_mono_count,
571 EFI_GET_NEXT_HIGH_MONO_COUNT);
572 EFI_HYPERCALL_PATCH(reset_system,EFI_RESET_SYSTEM);
574 /* System tables. */
575 tables->efi_tables[0].guid = SAL_SYSTEM_TABLE_GUID;
576 tables->efi_tables[0].table = FW_FIELD_MPA(sal_systab);
577 for (i = 1; i < NUM_EFI_SYS_TABLES; i++) {
578 tables->efi_tables[i].guid = NULL_GUID;
579 tables->efi_tables[i].table = 0;
580 }
581 if (xen_ia64_is_dom0(d)) {
582 efi_systable_init_dom0(tables);
583 } else {
584 efi_systable_init_domu(tables);
585 }
587 /* fill in the SAL system table: */
588 memcpy(tables->sal_systab.signature, "SST_", 4);
589 tables->sal_systab.size = sizeof(tables->sal_systab);
590 tables->sal_systab.sal_rev_minor = 1;
591 tables->sal_systab.sal_rev_major = 0;
592 tables->sal_systab.entry_count = 2;
594 memcpy((char *)tables->sal_systab.oem_id, "Xen/ia64", 8);
595 memcpy((char *)tables->sal_systab.product_id, "Xen/ia64", 8);
597 /* PAL entry point: */
598 tables->sal_ed.type = SAL_DESC_ENTRY_POINT;
599 tables->sal_ed.pal_proc = FW_HYPERCALL_PAL_CALL_PADDR;
600 dom_fw_pal_hypercall_patch(brkimm, tables->sal_ed.pal_proc,
601 hypercalls_imva);
602 /* SAL entry point. */
603 tables->sal_ed.sal_proc = FW_HYPERCALL_SAL_CALL_PADDR;
604 dom_fw_hypercall_patch(brkimm, tables->sal_ed.sal_proc,
605 FW_HYPERCALL_SAL_CALL, 1, hypercalls_imva);
606 tables->sal_ed.gp = 0; /* will be ignored */
608 /* Fill an AP wakeup descriptor. */
609 tables->sal_wakeup.type = SAL_DESC_AP_WAKEUP;
610 tables->sal_wakeup.mechanism = IA64_SAL_AP_EXTERNAL_INT;
611 tables->sal_wakeup.vector = XEN_SAL_BOOT_RENDEZ_VEC;
613 /* Compute checksum. */
614 checksum = 0;
615 for (cp = (char *)&tables->sal_systab;
616 cp < (char *)&tables->fpswa_inf;
617 ++cp)
618 checksum += *cp;
619 tables->sal_systab.checksum = -checksum;
621 /* SAL return point. */
622 dom_fw_hypercall_patch(brkimm, FW_HYPERCALL_SAL_RETURN_PADDR,
623 FW_HYPERCALL_SAL_RETURN, 0, hypercalls_imva);
625 /* Fill in the FPSWA interface: */
626 if (!xen_ia64_fpswa_revision(d, &tables->fpswa_inf.revision)) {
627 fpswa_supported = 1;
628 dom_fpswa_hypercall_patch(brkimm, hypercalls_imva);
629 tables->fpswa_inf.fpswa =
630 (void *)FW_HYPERCALL_FPSWA_ENTRY_PADDR;
631 }
633 tables->num_mds = 0;
634 /* hypercall patches live here, masquerade as reserved PAL memory */
635 xen_ia64_efi_make_md(&tables->efi_memmap[tables->num_mds],
636 EFI_PAL_CODE, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME,
637 FW_HYPERCALL_BASE_PADDR, FW_HYPERCALL_END_PADDR);
638 tables->num_mds++;
640 /* Create dom0/domu md entry for fw and cpi tables area. */
641 xen_ia64_efi_make_md(&tables->efi_memmap[tables->num_mds],
642 EFI_ACPI_MEMORY_NVS,
643 EFI_MEMORY_WB | EFI_MEMORY_RUNTIME,
644 FW_ACPI_BASE_PADDR, FW_ACPI_END_PADDR);
645 tables->num_mds++;
646 xen_ia64_efi_make_md(&tables->efi_memmap[tables->num_mds],
647 EFI_RUNTIME_SERVICES_DATA,
648 EFI_MEMORY_WB | EFI_MEMORY_RUNTIME,
649 FW_TABLES_BASE_PADDR,
650 tables->fw_tables_end_paddr);
651 tables->num_mds++;
653 if (!xen_ia64_is_dom0(d) || xen_ia64_is_running_on_sim(d)) {
654 /* DomU (or hp-ski).
655 Create a continuous memory area. */
656 /* kludge: bp->efi_memmap is used to pass memmap_info
657 * page's pfn and number of pages to reserve.
658 * Currently the following pages must be reserved.
659 * memmap info page, start info page, xenstore page
660 * and console page.
661 * see ia64_setup_memmap() @ xc_dom_boot.c
662 */
663 num_mds = complete_domu_memmap(d, tables, maxmem,
664 XEN_IA64_MEMMAP_INFO_PFN(bp),
665 XEN_IA64_MEMMAP_INFO_NUM_PAGES(bp));
666 } else {
667 /* Dom0.
668 We must preserve ACPI data from real machine,
669 as well as IO areas. */
670 num_mds = complete_dom0_memmap(d, tables);
671 }
672 if (num_mds < 0)
673 return num_mds;
674 BUG_ON(num_mds != tables->num_mds);
676 /* Display memmap. */
677 for (i = 0 ; i < tables->num_mds; i++)
678 print_md(&tables->efi_memmap[i]);
680 /* Fill boot_param */
681 bp->efi_systab = FW_FIELD_MPA(efi_systab);
682 bp->efi_memmap = FW_FIELD_MPA(efi_memmap);
683 bp->efi_memmap_size = tables->num_mds * sizeof(efi_memory_desc_t);
684 bp->efi_memdesc_size = sizeof(efi_memory_desc_t);
685 bp->efi_memdesc_version = EFI_MEMDESC_VERSION;
686 bp->command_line = 0;
687 bp->console_info.num_cols = 80;
688 bp->console_info.num_rows = 25;
689 bp->console_info.orig_x = 0;
690 bp->console_info.orig_y = 24;
691 if (fpswa_supported)
692 bp->fpswa = FW_FIELD_MPA(fpswa_inf);
693 return 0;
694 }