ia64/xen-unstable

view xen/arch/ia64/xen/dom_fw.c @ 6467:b2312c14f144

Temporary fix to ensure store page is accessible to domain.
author djm@kirby.fc.hp.com
date Wed Sep 07 10:51:28 2005 -0600 (2005-09-07)
parents 3ca4ca7a9cc2
children 2c823d27cf33
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 */
8 #include <xen/config.h>
9 #include <asm/system.h>
10 #include <asm/pgalloc.h>
12 #include <linux/efi.h>
13 #include <asm/io.h>
14 #include <asm/pal.h>
15 #include <asm/sal.h>
16 #include <xen/acpi.h>
18 #include <asm/dom_fw.h>
20 struct ia64_boot_param *dom_fw_init(struct domain *, char *,int,char *,int);
21 extern unsigned long domain_mpa_to_imva(struct domain *,unsigned long mpaddr);
22 extern struct domain *dom0;
23 extern unsigned long dom0_start;
25 extern unsigned long running_on_sim;
28 unsigned long dom_fw_base_mpa = -1;
29 unsigned long imva_fw_base = -1;
31 // return domain (meta)physical address for a given imva
32 // this function is a call-back from dom_fw_init
33 unsigned long dom_pa(unsigned long imva)
34 {
35 if (dom_fw_base_mpa == -1 || imva_fw_base == -1) {
36 printf("dom_pa: uninitialized! (spinning...)\n");
37 while(1);
38 }
39 if (imva - imva_fw_base > PAGE_SIZE) {
40 printf("dom_pa: bad offset! imva=%p, imva_fw_base=%p (spinning...)\n",imva,imva_fw_base);
41 while(1);
42 }
43 return dom_fw_base_mpa + (imva - imva_fw_base);
44 }
46 // builds a hypercall bundle at domain physical address
47 void dom_efi_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long hypercall)
48 {
49 unsigned long imva;
51 if (d == dom0) paddr += dom0_start;
52 imva = domain_mpa_to_imva(d,paddr);
53 build_hypercall_bundle(imva,d->arch.breakimm,hypercall,1);
54 }
57 // builds a hypercall bundle at domain physical address
58 void dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long hypercall,unsigned long ret)
59 {
60 unsigned long imva;
62 if (d == dom0) paddr += dom0_start;
63 imva = domain_mpa_to_imva(d,paddr);
64 build_hypercall_bundle(imva,d->arch.breakimm,hypercall,ret);
65 }
68 // FIXME: This is really a hack: Forcing the boot parameter block
69 // at domain mpaddr 0 page, then grabbing only the low bits of the
70 // Xen imva, which is the offset into the page
71 unsigned long dom_fw_setup(struct domain *d, char *args, int arglen)
72 {
73 struct ia64_boot_param *bp;
75 dom_fw_base_mpa = 0;
76 if (d == dom0) dom_fw_base_mpa += dom0_start;
77 imva_fw_base = domain_mpa_to_imva(d,dom_fw_base_mpa);
78 bp = dom_fw_init(d,args,arglen,imva_fw_base,PAGE_SIZE);
79 return dom_pa((unsigned long)bp);
80 }
83 /* the following heavily leveraged from linux/arch/ia64/hp/sim/fw-emu.c */
85 #define MB (1024*1024UL)
87 #define NUM_EFI_SYS_TABLES 6
88 #define PASS_THRU_IOPORT_SPACE
89 #ifdef PASS_THRU_IOPORT_SPACE
90 # define NUM_MEM_DESCS 4
91 #else
92 # define NUM_MEM_DESCS 3
93 #endif
96 #define SECS_PER_HOUR (60 * 60)
97 #define SECS_PER_DAY (SECS_PER_HOUR * 24)
99 /* Compute the `struct tm' representation of *T,
100 offset OFFSET seconds east of UTC,
101 and store year, yday, mon, mday, wday, hour, min, sec into *TP.
102 Return nonzero if successful. */
103 int
104 offtime (unsigned long t, efi_time_t *tp)
105 {
106 const unsigned short int __mon_yday[2][13] =
107 {
108 /* Normal years. */
109 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
110 /* Leap years. */
111 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
112 };
113 long int days, rem, y;
114 const unsigned short int *ip;
116 days = t / SECS_PER_DAY;
117 rem = t % SECS_PER_DAY;
118 while (rem < 0) {
119 rem += SECS_PER_DAY;
120 --days;
121 }
122 while (rem >= SECS_PER_DAY) {
123 rem -= SECS_PER_DAY;
124 ++days;
125 }
126 tp->hour = rem / SECS_PER_HOUR;
127 rem %= SECS_PER_HOUR;
128 tp->minute = rem / 60;
129 tp->second = rem % 60;
130 /* January 1, 1970 was a Thursday. */
131 y = 1970;
133 # define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
134 # define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
135 # define __isleap(year) \
136 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
138 while (days < 0 || days >= (__isleap (y) ? 366 : 365)) {
139 /* Guess a corrected year, assuming 365 days per year. */
140 long int yg = y + days / 365 - (days % 365 < 0);
142 /* Adjust DAYS and Y to match the guessed year. */
143 days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1)
144 - LEAPS_THRU_END_OF (y - 1));
145 y = yg;
146 }
147 tp->year = y;
148 ip = __mon_yday[__isleap(y)];
149 for (y = 11; days < (long int) ip[y]; --y)
150 continue;
151 days -= ip[y];
152 tp->month = y + 1;
153 tp->day = days + 1;
154 return 1;
155 }
157 extern struct ia64_pal_retval pal_emulator_static (unsigned long);
159 /* Macro to emulate SAL call using legacy IN and OUT calls to CF8, CFC etc.. */
161 #define BUILD_CMD(addr) ((0x80000000 | (addr)) & ~3)
163 #define REG_OFFSET(addr) (0x00000000000000FF & (addr))
164 #define DEVICE_FUNCTION(addr) (0x000000000000FF00 & (addr))
165 #define BUS_NUMBER(addr) (0x0000000000FF0000 & (addr))
167 #ifndef XEN
168 static efi_status_t
169 fw_efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
170 {
171 #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
172 struct {
173 int tv_sec; /* must be 32bits to work */
174 int tv_usec;
175 } tv32bits;
177 ssc((unsigned long) &tv32bits, 0, 0, 0, SSC_GET_TOD);
179 memset(tm, 0, sizeof(*tm));
180 offtime(tv32bits.tv_sec, tm);
182 if (tc)
183 memset(tc, 0, sizeof(*tc));
184 #else
185 # error Not implemented yet...
186 #endif
187 return EFI_SUCCESS;
188 }
190 static void
191 efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
192 {
193 #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
194 ssc(status, 0, 0, 0, SSC_EXIT);
195 #else
196 # error Not implemented yet...
197 #endif
198 }
200 static efi_status_t
201 efi_unimplemented (void)
202 {
203 return EFI_UNSUPPORTED;
204 }
205 #endif /* !XEN */
207 struct sal_ret_values
208 sal_emulator (long index, unsigned long in1, unsigned long in2,
209 unsigned long in3, unsigned long in4, unsigned long in5,
210 unsigned long in6, unsigned long in7)
211 {
212 long r9 = 0;
213 long r10 = 0;
214 long r11 = 0;
215 long status;
217 /*
218 * Don't do a "switch" here since that gives us code that
219 * isn't self-relocatable.
220 */
221 status = 0;
222 if (index == SAL_FREQ_BASE) {
223 if (!running_on_sim)
224 status = ia64_sal_freq_base(in1,&r9,&r10);
225 else switch (in1) {
226 case SAL_FREQ_BASE_PLATFORM:
227 r9 = 200000000;
228 break;
230 case SAL_FREQ_BASE_INTERVAL_TIMER:
231 r9 = 700000000;
232 break;
234 case SAL_FREQ_BASE_REALTIME_CLOCK:
235 r9 = 1;
236 break;
238 default:
239 status = -1;
240 break;
241 }
242 } else if (index == SAL_PCI_CONFIG_READ) {
243 if (current->domain == dom0) {
244 u64 value;
245 // note that args 2&3 are swapped!!
246 status = ia64_sal_pci_config_read(in1,in3,in2,&value);
247 r9 = value;
248 }
249 else printf("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_READ\n");
250 } else if (index == SAL_PCI_CONFIG_WRITE) {
251 if (current->domain == dom0) {
252 if (((in1 & ~0xffffffffUL) && (in4 == 0)) ||
253 (in4 > 1) ||
254 (in2 > 8) || (in2 & (in2-1)))
255 printf("*** SAL_PCI_CONF_WRITE?!?(adr=%p,typ=%p,sz=%p,val=%p)\n",in1,in4,in2,in3);
256 // note that args are in a different order!!
257 status = ia64_sal_pci_config_write(in1,in4,in2,in3);
258 }
259 else printf("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_WRITE\n");
260 } else if (index == SAL_SET_VECTORS) {
261 printf("*** CALLED SAL_SET_VECTORS. IGNORED...\n");
262 } else if (index == SAL_GET_STATE_INFO) {
263 printf("*** CALLED SAL_GET_STATE_INFO. IGNORED...\n");
264 } else if (index == SAL_GET_STATE_INFO_SIZE) {
265 printf("*** CALLED SAL_GET_STATE_INFO_SIZE. IGNORED...\n");
266 } else if (index == SAL_CLEAR_STATE_INFO) {
267 printf("*** CALLED SAL_CLEAR_STATE_INFO. IGNORED...\n");
268 } else if (index == SAL_MC_RENDEZ) {
269 printf("*** CALLED SAL_MC_RENDEZ. IGNORED...\n");
270 } else if (index == SAL_MC_SET_PARAMS) {
271 printf("*** CALLED SAL_MC_SET_PARAMS. IGNORED...\n");
272 } else if (index == SAL_CACHE_FLUSH) {
273 printf("*** CALLED SAL_CACHE_FLUSH. IGNORED...\n");
274 } else if (index == SAL_CACHE_INIT) {
275 printf("*** CALLED SAL_CACHE_INIT. IGNORED...\n");
276 } else if (index == SAL_UPDATE_PAL) {
277 printf("*** CALLED SAL_UPDATE_PAL. IGNORED...\n");
278 } else {
279 printf("*** CALLED SAL_ WITH UNKNOWN INDEX. IGNORED...\n");
280 status = -1;
281 }
282 return ((struct sal_ret_values) {status, r9, r10, r11});
283 }
285 struct ia64_pal_retval
286 xen_pal_emulator(unsigned long index, unsigned long in1,
287 unsigned long in2, unsigned long in3)
288 {
289 long r9 = 0;
290 long r10 = 0;
291 long r11 = 0;
292 long status = -1;
294 #define USE_PAL_EMULATOR
295 #ifdef USE_PAL_EMULATOR
296 return pal_emulator_static(index);
297 #endif
298 if (running_on_sim) return pal_emulator_static(index);
299 if (index >= PAL_COPY_PAL) {
300 printk("xen_pal_emulator: UNIMPLEMENTED PAL CALL %d!!!!\n",
301 index);
302 }
303 else switch (index) {
304 case PAL_MEM_ATTRIB:
305 status = ia64_pal_mem_attrib(&r9);
306 break;
307 case PAL_FREQ_BASE:
308 status = ia64_pal_freq_base(&r9);
309 break;
310 case PAL_PROC_GET_FEATURES:
311 status = ia64_pal_proc_get_features(&r9,&r10,&r11);
312 break;
313 case PAL_BUS_GET_FEATURES:
314 status = ia64_pal_bus_get_features(&r9,&r10,&r11);
315 break;
316 case PAL_FREQ_RATIOS:
317 status = ia64_pal_freq_ratios(&r9,&r10,&r11);
318 break;
319 case PAL_PTCE_INFO:
320 {
321 // return hard-coded xen-specific values because ptc.e
322 // is emulated on xen to always flush everything
323 // these values result in only one ptc.e instruction
324 status = 0; r9 = 0; r10 = (1L << 32) | 1L; r11 = 0;
325 }
326 break;
327 case PAL_VERSION:
328 status = ia64_pal_version(&r9,&r10);
329 break;
330 case PAL_VM_PAGE_SIZE:
331 status = ia64_pal_vm_page_size(&r9,&r10);
332 break;
333 case PAL_DEBUG_INFO:
334 status = ia64_pal_debug_info(&r9,&r10);
335 break;
336 case PAL_CACHE_SUMMARY:
337 status = ia64_pal_cache_summary(&r9,&r10);
338 break;
339 case PAL_VM_SUMMARY:
340 // FIXME: what should xen return for these, figure out later
341 // For now, linux does the right thing if pal call fails
342 // In particular, rid_size must be set properly!
343 //status = ia64_pal_vm_summary(&r9,&r10);
344 break;
345 case PAL_RSE_INFO:
346 status = ia64_pal_rse_info(&r9,&r10);
347 break;
348 case PAL_VM_INFO:
349 status = ia64_pal_vm_info(in1,in2,&r9,&r10);
350 break;
351 case PAL_REGISTER_INFO:
352 status = ia64_pal_register_info(in1,&r9,&r10);
353 break;
354 case PAL_CACHE_FLUSH:
355 /* FIXME */
356 printk("PAL_CACHE_FLUSH NOT IMPLEMENTED!\n");
357 BUG();
358 break;
359 case PAL_PERF_MON_INFO:
360 {
361 unsigned long pm_buffer[16];
362 int i;
363 status = ia64_pal_perf_mon_info(pm_buffer,&r9);
364 if (status != 0) {
365 while(1)
366 printk("PAL_PERF_MON_INFO fails ret=%d\n",status);
367 break;
368 }
369 if (copy_to_user((void __user *)in1,pm_buffer,128)) {
370 while(1)
371 printk("xen_pal_emulator: PAL_PERF_MON_INFO "
372 "can't copy to user!!!!\n");
373 status = -1;
374 break;
375 }
376 }
377 break;
378 case PAL_CACHE_INFO:
379 {
380 pal_cache_config_info_t ci;
381 status = ia64_pal_cache_config_info(in1,in2,&ci);
382 if (status != 0) break;
383 r9 = ci.pcci_info_1.pcci1_data;
384 r10 = ci.pcci_info_2.pcci2_data;
385 }
386 break;
387 case PAL_VM_TR_READ: /* FIXME: vcpu_get_tr?? */
388 printk("PAL_VM_TR_READ NOT IMPLEMENTED, IGNORED!\n");
389 break;
390 case PAL_HALT_INFO: /* inappropriate info for guest? */
391 printk("PAL_HALT_INFO NOT IMPLEMENTED, IGNORED!\n");
392 break;
393 default:
394 printk("xen_pal_emulator: UNIMPLEMENTED PAL CALL %d!!!!\n",
395 index);
396 break;
397 }
398 return ((struct ia64_pal_retval) {status, r9, r10, r11});
399 }
401 #define NFUNCPTRS 20
403 void print_md(efi_memory_desc_t *md)
404 {
405 #if 1
406 printk("domain mem: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
407 md->type, md->attribute, md->phys_addr,
408 md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
409 md->num_pages >> (20 - EFI_PAGE_SHIFT));
410 #endif
411 }
413 #define LSAPIC_NUM 16 // TEMP
414 static u32 lsapic_flag=1;
416 /* Provide only one LP to guest */
417 static int
418 acpi_update_lsapic (acpi_table_entry_header *header)
419 {
420 struct acpi_table_lsapic *lsapic;
422 lsapic = (struct acpi_table_lsapic *) header;
423 if (!lsapic)
424 return -EINVAL;
426 if (lsapic->flags.enabled && lsapic_flag) {
427 printk("enable lsapic entry: 0x%lx\n", (u64)lsapic);
428 lsapic_flag = 0; /* disable all the following processros */
429 } else if (lsapic->flags.enabled) {
430 printk("DISABLE lsapic entry: 0x%lx\n", (u64)lsapic);
431 lsapic->flags.enabled = 0;
432 } else
433 printk("lsapic entry is already disabled: 0x%lx\n", (u64)lsapic);
435 return 0;
436 }
438 static int
439 acpi_update_madt_checksum (unsigned long phys_addr, unsigned long size)
440 {
441 u8 checksum=0;
442 u8* ptr;
443 int len;
444 struct acpi_table_madt* acpi_madt;
446 if (!phys_addr || !size)
447 return -EINVAL;
449 acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
450 acpi_madt->header.checksum=0;
452 /* re-calculate MADT checksum */
453 ptr = (u8*)acpi_madt;
454 len = acpi_madt->header.length;
455 while (len>0){
456 checksum = (u8)( checksum + (*ptr++) );
457 len--;
458 }
459 acpi_madt->header.checksum = 0x0 - checksum;
461 return 0;
462 }
464 /* base is physical address of acpi table */
465 void touch_acpi_table(void)
466 {
467 u64 count = 0;
468 count = acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_update_lsapic, NR_CPUS);
469 if ( count < 1)
470 printk("Error parsing MADT - no LAPIC entires\n");
471 printk("Total %d lsapic entry\n", count);
472 acpi_table_parse(ACPI_APIC, acpi_update_madt_checksum);
474 return;
475 }
478 struct ia64_boot_param *
479 dom_fw_init (struct domain *d, char *args, int arglen, char *fw_mem, int fw_mem_size)
480 {
481 efi_system_table_t *efi_systab;
482 efi_runtime_services_t *efi_runtime;
483 efi_config_table_t *efi_tables;
484 struct ia64_sal_systab *sal_systab;
485 efi_memory_desc_t *efi_memmap, *md;
486 unsigned long *pal_desc, *sal_desc;
487 struct ia64_sal_desc_entry_point *sal_ed;
488 struct ia64_boot_param *bp;
489 unsigned long *pfn;
490 unsigned char checksum = 0;
491 char *cp, *cmd_line, *fw_vendor;
492 int i = 0;
493 unsigned long maxmem = d->max_pages * PAGE_SIZE;
494 unsigned long start_mpaddr = ((d==dom0)?dom0_start:0);
496 # define MAKE_MD(typ, attr, start, end, abs) \
497 do { \
498 md = efi_memmap + i++; \
499 md->type = typ; \
500 md->pad = 0; \
501 md->phys_addr = abs ? start : start_mpaddr + start; \
502 md->virt_addr = 0; \
503 md->num_pages = (end - start) >> 12; \
504 md->attribute = attr; \
505 print_md(md); \
506 } while (0)
508 /* FIXME: should check size but for now we have a whole MB to play with.
509 And if stealing code from fw-emu.c, watch out for new fw_vendor on the end!
510 if (fw_mem_size < sizeof(fw_mem_proto)) {
511 printf("sys_fw_init: insufficient space for fw_mem\n");
512 return 0;
513 }
514 */
515 /* Last page is for xenstore, and not exported to domain */
516 if (d != dom0)
517 maxmem = (d->max_pages - 1) * PAGE_SIZE;
519 memset(fw_mem, 0, fw_mem_size);
521 #ifdef XEN
522 #else
523 pal_desc = (unsigned long *) &pal_emulator_static;
524 sal_desc = (unsigned long *) &sal_emulator;
525 #endif
527 cp = fw_mem;
528 efi_systab = (void *) cp; cp += sizeof(*efi_systab);
529 efi_runtime = (void *) cp; cp += sizeof(*efi_runtime);
530 efi_tables = (void *) cp; cp += NUM_EFI_SYS_TABLES * sizeof(*efi_tables);
531 sal_systab = (void *) cp; cp += sizeof(*sal_systab);
532 sal_ed = (void *) cp; cp += sizeof(*sal_ed);
533 efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap);
534 bp = (void *) cp; cp += sizeof(*bp);
535 pfn = (void *) cp; cp += NFUNCPTRS * 2 * sizeof(pfn);
536 cmd_line = (void *) cp;
538 if (args) {
539 if (arglen >= 1024)
540 arglen = 1023;
541 memcpy(cmd_line, args, arglen);
542 } else {
543 arglen = 0;
544 }
545 cmd_line[arglen] = '\0';
547 memset(efi_systab, 0, sizeof(efi_systab));
548 efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
549 efi_systab->hdr.revision = EFI_SYSTEM_TABLE_REVISION;
550 efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
551 cp = fw_vendor = &cmd_line[arglen] + (2-(arglen&1)); // round to 16-bit boundary
552 #define FW_VENDOR "X\0e\0n\0/\0i\0a\0\066\0\064\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
553 cp += sizeof(FW_VENDOR) + (8-((unsigned long)cp & 7)); // round to 64-bit boundary
555 memcpy(fw_vendor,FW_VENDOR,sizeof(FW_VENDOR));
556 efi_systab->fw_vendor = dom_pa(fw_vendor);
558 efi_systab->fw_revision = 1;
559 efi_systab->runtime = (void *) dom_pa(efi_runtime);
560 efi_systab->nr_tables = NUM_EFI_SYS_TABLES;
561 efi_systab->tables = dom_pa(efi_tables);
563 efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
564 efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
565 efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr);
566 #define EFI_HYPERCALL_PATCH(tgt,call) do { \
567 dom_efi_hypercall_patch(d,FW_HYPERCALL_##call##_PADDR,FW_HYPERCALL_##call); \
568 tgt = dom_pa(pfn); \
569 *pfn++ = FW_HYPERCALL_##call##_PADDR + ((d==dom0)?dom0_start:0); \
570 *pfn++ = 0; \
571 } while (0)
573 EFI_HYPERCALL_PATCH(efi_runtime->get_time,EFI_GET_TIME);
574 EFI_HYPERCALL_PATCH(efi_runtime->set_time,EFI_SET_TIME);
575 EFI_HYPERCALL_PATCH(efi_runtime->get_wakeup_time,EFI_GET_WAKEUP_TIME);
576 EFI_HYPERCALL_PATCH(efi_runtime->set_wakeup_time,EFI_SET_WAKEUP_TIME);
577 EFI_HYPERCALL_PATCH(efi_runtime->set_virtual_address_map,EFI_SET_VIRTUAL_ADDRESS_MAP);
578 EFI_HYPERCALL_PATCH(efi_runtime->get_variable,EFI_GET_VARIABLE);
579 EFI_HYPERCALL_PATCH(efi_runtime->get_next_variable,EFI_GET_NEXT_VARIABLE);
580 EFI_HYPERCALL_PATCH(efi_runtime->set_variable,EFI_SET_VARIABLE);
581 EFI_HYPERCALL_PATCH(efi_runtime->get_next_high_mono_count,EFI_GET_NEXT_HIGH_MONO_COUNT);
582 EFI_HYPERCALL_PATCH(efi_runtime->reset_system,EFI_RESET_SYSTEM);
584 efi_tables[0].guid = SAL_SYSTEM_TABLE_GUID;
585 efi_tables[0].table = dom_pa(sal_systab);
586 for (i = 1; i < NUM_EFI_SYS_TABLES; i++) {
587 efi_tables[i].guid = NULL_GUID;
588 efi_tables[i].table = 0;
589 }
590 if (d == dom0) {
591 printf("Domain0 EFI passthrough:");
592 i = 1;
593 if (efi.mps) {
594 efi_tables[i].guid = MPS_TABLE_GUID;
595 efi_tables[i].table = __pa(efi.mps);
596 printf(" MPS=%0xlx",efi_tables[i].table);
597 i++;
598 }
600 touch_acpi_table();
602 if (efi.acpi20) {
603 efi_tables[i].guid = ACPI_20_TABLE_GUID;
604 efi_tables[i].table = __pa(efi.acpi20);
605 printf(" ACPI 2.0=%0xlx",efi_tables[i].table);
606 i++;
607 }
608 if (efi.acpi) {
609 efi_tables[i].guid = ACPI_TABLE_GUID;
610 efi_tables[i].table = __pa(efi.acpi);
611 printf(" ACPI=%0xlx",efi_tables[i].table);
612 i++;
613 }
614 if (efi.smbios) {
615 efi_tables[i].guid = SMBIOS_TABLE_GUID;
616 efi_tables[i].table = __pa(efi.smbios);
617 printf(" SMBIOS=%0xlx",efi_tables[i].table);
618 i++;
619 }
620 if (efi.hcdp) {
621 efi_tables[i].guid = HCDP_TABLE_GUID;
622 efi_tables[i].table = __pa(efi.hcdp);
623 printf(" HCDP=%0xlx",efi_tables[i].table);
624 i++;
625 }
626 printf("\n");
627 }
629 /* fill in the SAL system table: */
630 memcpy(sal_systab->signature, "SST_", 4);
631 sal_systab->size = sizeof(*sal_systab);
632 sal_systab->sal_rev_minor = 1;
633 sal_systab->sal_rev_major = 0;
634 sal_systab->entry_count = 1;
636 strcpy(sal_systab->oem_id, "Xen/ia64");
637 strcpy(sal_systab->product_id, "Xen/ia64");
639 /* fill in an entry point: */
640 sal_ed->type = SAL_DESC_ENTRY_POINT;
641 #define FW_HYPERCALL_PATCH(tgt,call,ret) do { \
642 dom_fw_hypercall_patch(d,FW_HYPERCALL_##call##_PADDR,FW_HYPERCALL_##call,ret); \
643 tgt = FW_HYPERCALL_##call##_PADDR + ((d==dom0)?dom0_start:0); \
644 } while (0)
645 FW_HYPERCALL_PATCH(sal_ed->pal_proc,PAL_CALL,0);
646 FW_HYPERCALL_PATCH(sal_ed->sal_proc,SAL_CALL,1);
647 sal_ed->gp = 0; // will be ignored
649 for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp)
650 checksum += *cp;
652 sal_systab->checksum = -checksum;
654 /* simulate 1MB free memory at physical address zero */
655 i = 0;
656 MAKE_MD(EFI_BOOT_SERVICES_DATA,EFI_MEMORY_WB,0*MB,1*MB, 0);
657 /* hypercall patches live here, masquerade as reserved PAL memory */
658 MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB,HYPERCALL_START,HYPERCALL_END, 0);
659 MAKE_MD(EFI_CONVENTIONAL_MEMORY,EFI_MEMORY_WB,HYPERCALL_END,maxmem, 0);
660 #ifdef PASS_THRU_IOPORT_SPACE
661 if (d == dom0 && !running_on_sim) {
662 /* pass through the I/O port space */
663 efi_memory_desc_t *efi_get_io_md(void);
664 efi_memory_desc_t *ia64_efi_io_md = efi_get_io_md();
665 u32 type;
666 u64 iostart, ioend, ioattr;
668 type = ia64_efi_io_md->type;
669 iostart = ia64_efi_io_md->phys_addr;
670 ioend = ia64_efi_io_md->phys_addr +
671 (ia64_efi_io_md->num_pages << 12);
672 ioattr = ia64_efi_io_md->attribute;
673 MAKE_MD(type,ioattr,iostart,ioend, 1);
674 }
675 else
676 MAKE_MD(EFI_RESERVED_TYPE,0,0,0,0);
677 #endif
679 bp->efi_systab = dom_pa(fw_mem);
680 bp->efi_memmap = dom_pa(efi_memmap);
681 bp->efi_memmap_size = NUM_MEM_DESCS*sizeof(efi_memory_desc_t);
682 bp->efi_memdesc_size = sizeof(efi_memory_desc_t);
683 bp->efi_memdesc_version = 1;
684 bp->command_line = dom_pa(cmd_line);
685 bp->console_info.num_cols = 80;
686 bp->console_info.num_rows = 25;
687 bp->console_info.orig_x = 0;
688 bp->console_info.orig_y = 24;
689 bp->fpswa = 0;
691 return bp;
692 }