ia64/xen-unstable

view xen/arch/ia64/xen/dom_fw_common.c @ 18878:559809738237

[IA64]: fix compilation error.

BUILD_BUG_ON() was changed so that now BUILD_BUG_ON() can't be
used with symbol values.
Fortunately dom_fpswa_hypercall_patch() isn't performance critical
so replace BUILD_BUG_ON() with BUG_ON().
Fixed the wrong condition which has off-by-one bug.

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