direct-io.hg

view xen/arch/ia64/xen/fw_emul.c @ 11343:5586fd904efa

[IA64] Remove warning message in fw_emul.c

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author awilliam@xenbuild.aw
date Mon Aug 28 13:14:52 2006 -0600 (2006-08-28)
parents d42e9a6f5378
children 9fed76231248
line source
1 /*
2 * fw_emul.c:
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307 USA.
16 *
17 */
18 #include <xen/config.h>
19 #include <xen/console.h>
20 #include <asm/system.h>
21 #include <asm/pgalloc.h>
23 #include <linux/efi.h>
24 #include <asm/pal.h>
25 #include <asm/sal.h>
27 #include <public/sched.h>
28 #include "hpsim_ssc.h"
29 #include <asm/vcpu.h>
30 #include <asm/dom_fw.h>
31 #include <asm/uaccess.h>
33 extern unsigned long running_on_sim;
35 struct sal_ret_values
36 sal_emulator (long index, unsigned long in1, unsigned long in2,
37 unsigned long in3, unsigned long in4, unsigned long in5,
38 unsigned long in6, unsigned long in7)
39 {
40 unsigned long r9 = 0;
41 unsigned long r10 = 0;
42 long r11 = 0;
43 long status;
45 status = 0;
46 switch (index) {
47 case SAL_FREQ_BASE:
48 if (!running_on_sim)
49 status = ia64_sal_freq_base(in1,&r9,&r10);
50 else switch (in1) {
51 case SAL_FREQ_BASE_PLATFORM:
52 r9 = 200000000;
53 break;
55 case SAL_FREQ_BASE_INTERVAL_TIMER:
56 r9 = 700000000;
57 break;
59 case SAL_FREQ_BASE_REALTIME_CLOCK:
60 r9 = 1;
61 break;
63 default:
64 status = -1;
65 break;
66 }
67 break;
68 case SAL_PCI_CONFIG_READ:
69 if (current->domain == dom0) {
70 u64 value;
71 // note that args 2&3 are swapped!!
72 status = ia64_sal_pci_config_read(in1,in3,in2,&value);
73 r9 = value;
74 }
75 else
76 printf("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_READ\n");
77 break;
78 case SAL_PCI_CONFIG_WRITE:
79 if (current->domain == dom0) {
80 if (((in1 & ~0xffffffffUL) && (in4 == 0)) ||
81 (in4 > 1) ||
82 (in2 > 8) || (in2 & (in2-1)))
83 printf("*** SAL_PCI_CONF_WRITE?!?(adr=0x%lx,typ=0x%lx,sz=0x%lx,val=0x%lx)\n",
84 in1,in4,in2,in3);
85 // note that args are in a different order!!
86 status = ia64_sal_pci_config_write(in1,in4,in2,in3);
87 }
88 else
89 printf("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_WRITE\n");
90 break;
91 case SAL_SET_VECTORS:
92 if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
93 if (in4 != 0 || in5 != 0 || in6 != 0 || in7 != 0) {
94 /* Sanity check: cs_length1 must be 0,
95 second vector is reserved. */
96 status = -2;
97 }
98 else {
99 struct domain *d = current->domain;
100 d->arch.sal_data->boot_rdv_ip = in2;
101 d->arch.sal_data->boot_rdv_r1 = in3;
102 }
103 }
104 else
105 printf("*** CALLED SAL_SET_VECTORS %lu. IGNORED...\n",
106 in1);
107 break;
108 case SAL_GET_STATE_INFO:
109 /* No more info. */
110 status = -5;
111 r9 = 0;
112 break;
113 case SAL_GET_STATE_INFO_SIZE:
114 /* Return a dummy size. */
115 status = 0;
116 r9 = 128;
117 break;
118 case SAL_CLEAR_STATE_INFO:
119 /* Noop. */
120 break;
121 case SAL_MC_RENDEZ:
122 printf("*** CALLED SAL_MC_RENDEZ. IGNORED...\n");
123 break;
124 case SAL_MC_SET_PARAMS:
125 printf("*** CALLED SAL_MC_SET_PARAMS. IGNORED...\n");
126 break;
127 case SAL_CACHE_FLUSH:
128 if (1) {
129 /* Flush using SAL.
130 This method is faster but has a side effect on
131 other vcpu running on this cpu. */
132 status = ia64_sal_cache_flush (in1);
133 }
134 else {
135 /* Flush with fc all the domain.
136 This method is slower but has no side effects. */
137 domain_cache_flush (current->domain, in1 == 4 ? 1 : 0);
138 status = 0;
139 }
140 break;
141 case SAL_CACHE_INIT:
142 printf("*** CALLED SAL_CACHE_INIT. IGNORED...\n");
143 break;
144 case SAL_UPDATE_PAL:
145 printf("*** CALLED SAL_UPDATE_PAL. IGNORED...\n");
146 break;
147 default:
148 printf("*** CALLED SAL_ WITH UNKNOWN INDEX. IGNORED...\n");
149 status = -1;
150 break;
151 }
152 return ((struct sal_ret_values) {status, r9, r10, r11});
153 }
155 struct ia64_pal_retval
156 xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3)
157 {
158 unsigned long r9 = 0;
159 unsigned long r10 = 0;
160 unsigned long r11 = 0;
161 long status = PAL_STATUS_UNIMPLEMENTED;
163 if (running_on_sim)
164 return pal_emulator_static(index);
166 // pal code must be mapped by a TR when pal is called, however
167 // calls are rare enough that we will map it lazily rather than
168 // at every context switch
169 //efi_map_pal_code();
170 switch (index) {
171 case PAL_MEM_ATTRIB:
172 status = ia64_pal_mem_attrib(&r9);
173 break;
174 case PAL_FREQ_BASE:
175 status = ia64_pal_freq_base(&r9);
176 break;
177 case PAL_PROC_GET_FEATURES:
178 status = ia64_pal_proc_get_features(&r9,&r10,&r11);
179 break;
180 case PAL_BUS_GET_FEATURES:
181 status = ia64_pal_bus_get_features(
182 (pal_bus_features_u_t *) &r9,
183 (pal_bus_features_u_t *) &r10,
184 (pal_bus_features_u_t *) &r11);
185 break;
186 case PAL_FREQ_RATIOS:
187 status = ia64_pal_freq_ratios(
188 (struct pal_freq_ratio *) &r9,
189 (struct pal_freq_ratio *) &r10,
190 (struct pal_freq_ratio *) &r11);
191 break;
192 case PAL_PTCE_INFO:
193 {
194 // return hard-coded xen-specific values because ptc.e
195 // is emulated on xen to always flush everything
196 // these values result in only one ptc.e instruction
197 status = 0; r9 = 0; r10 = (1L << 32) | 1L; r11 = 0;
198 }
199 break;
200 case PAL_VERSION:
201 status = ia64_pal_version(
202 (pal_version_u_t *) &r9,
203 (pal_version_u_t *) &r10);
204 break;
205 case PAL_VM_PAGE_SIZE:
206 status = ia64_pal_vm_page_size(&r9,&r10);
207 break;
208 case PAL_DEBUG_INFO:
209 status = ia64_pal_debug_info(&r9,&r10);
210 break;
211 case PAL_CACHE_SUMMARY:
212 status = ia64_pal_cache_summary(&r9,&r10);
213 break;
214 case PAL_VM_SUMMARY:
215 {
216 /* Use xen-specific values.
217 hash_tag_id is somewhat random! */
218 const pal_vm_info_1_u_t v1 =
219 {.pal_vm_info_1_s =
220 { .vw = 1,
221 .phys_add_size = 44,
222 .key_size = 16,
223 .max_pkr = 15,
224 .hash_tag_id = 0x30,
225 .max_dtr_entry = NDTRS - 1,
226 .max_itr_entry = NITRS - 1,
227 #ifdef VHPT_GLOBAL
228 .max_unique_tcs = 3,
229 .num_tc_levels = 2
230 #else
231 .max_unique_tcs = 2,
232 .num_tc_levels = 1
233 #endif
234 }};
235 const pal_vm_info_2_u_t v2 =
236 { .pal_vm_info_2_s =
237 { .impl_va_msb = 50,
238 .rid_size = current->domain->arch.rid_bits,
239 .reserved = 0 }};
240 r9 = v1.pvi1_val;
241 r10 = v2.pvi2_val;
242 status = PAL_STATUS_SUCCESS;
243 }
244 break;
245 case PAL_VM_INFO:
246 #ifdef VHPT_GLOBAL
247 if (in1 == 0 && in2 == 2) {
248 /* Level 1: VHPT */
249 const pal_tc_info_u_t v =
250 { .pal_tc_info_s = {.num_sets = 128,
251 .associativity = 1,
252 .num_entries = 128,
253 .pf = 1,
254 .unified = 1,
255 .reduce_tr = 0,
256 .reserved = 0}};
257 r9 = v.pti_val;
258 /* Only support PAGE_SIZE tc. */
259 r10 = PAGE_SIZE;
260 status = PAL_STATUS_SUCCESS;
261 }
262 #endif
263 else if (
264 #ifdef VHPT_GLOBAL
265 in1 == 1 /* Level 2. */
266 #else
267 in1 == 0 /* Level 1. */
268 #endif
269 && (in2 == 1 || in2 == 2))
270 {
271 /* itlb/dtlb, 1 entry. */
272 const pal_tc_info_u_t v =
273 { .pal_tc_info_s = {.num_sets = 1,
274 .associativity = 1,
275 .num_entries = 1,
276 .pf = 1,
277 .unified = 0,
278 .reduce_tr = 0,
279 .reserved = 0}};
280 r9 = v.pti_val;
281 /* Only support PAGE_SIZE tc. */
282 r10 = PAGE_SIZE;
283 status = PAL_STATUS_SUCCESS;
284 }
285 else
286 status = PAL_STATUS_EINVAL;
287 break;
288 case PAL_RSE_INFO:
289 status = ia64_pal_rse_info(
290 &r9,
291 (pal_hints_u_t *) &r10);
292 break;
293 case PAL_REGISTER_INFO:
294 status = ia64_pal_register_info(in1, &r9, &r10);
295 break;
296 case PAL_CACHE_FLUSH:
297 /* FIXME */
298 printk("PAL_CACHE_FLUSH NOT IMPLEMENTED!\n");
299 BUG();
300 break;
301 case PAL_PERF_MON_INFO:
302 {
303 unsigned long pm_buffer[16];
304 status = ia64_pal_perf_mon_info(
305 pm_buffer,
306 (pal_perf_mon_info_u_t *) &r9);
307 if (status != 0) {
308 while(1)
309 printk("PAL_PERF_MON_INFO fails ret=%ld\n", status);
310 break;
311 }
312 if (copy_to_user((void __user *)in1,pm_buffer,128)) {
313 while(1)
314 printk("xen_pal_emulator: PAL_PERF_MON_INFO "
315 "can't copy to user!!!!\n");
316 status = PAL_STATUS_UNIMPLEMENTED;
317 break;
318 }
319 }
320 break;
321 case PAL_CACHE_INFO:
322 {
323 pal_cache_config_info_t ci;
324 status = ia64_pal_cache_config_info(in1,in2,&ci);
325 if (status != 0) break;
326 r9 = ci.pcci_info_1.pcci1_data;
327 r10 = ci.pcci_info_2.pcci2_data;
328 }
329 break;
330 case PAL_VM_TR_READ: /* FIXME: vcpu_get_tr?? */
331 printk("PAL_VM_TR_READ NOT IMPLEMENTED, IGNORED!\n");
332 break;
333 case PAL_HALT_INFO:
334 {
335 /* 1000 cycles to enter/leave low power state,
336 consumes 10 mW, implemented and cache/TLB coherent. */
337 unsigned long res = 1000UL | (1000UL << 16) | (10UL << 32)
338 | (1UL << 61) | (1UL << 60);
339 if (copy_to_user ((void *)in1, &res, sizeof (res)))
340 status = PAL_STATUS_EINVAL;
341 else
342 status = PAL_STATUS_SUCCESS;
343 }
344 break;
345 case PAL_HALT:
346 if (current->domain == dom0) {
347 printf ("Domain0 halts the machine\n");
348 console_start_sync();
349 (*efi.reset_system)(EFI_RESET_SHUTDOWN,0,0,NULL);
350 }
351 else
352 domain_shutdown (current->domain,
353 SHUTDOWN_poweroff);
354 break;
355 default:
356 printk("xen_pal_emulator: UNIMPLEMENTED PAL CALL %lu!!!!\n",
357 index);
358 break;
359 }
360 return ((struct ia64_pal_retval) {status, r9, r10, r11});
361 }
363 // given a current domain (virtual or metaphysical) address, return the virtual address
364 static unsigned long
365 efi_translate_domain_addr(unsigned long domain_addr, IA64FAULT *fault,
366 struct page_info** page)
367 {
368 struct vcpu *v = current;
369 unsigned long mpaddr = domain_addr;
370 unsigned long virt;
371 *fault = IA64_NO_FAULT;
373 again:
374 if (v->domain->arch.sal_data->efi_virt_mode) {
375 *fault = vcpu_tpa(v, domain_addr, &mpaddr);
376 if (*fault != IA64_NO_FAULT) return 0;
377 }
379 virt = (unsigned long)domain_mpa_to_imva(v->domain, mpaddr);
380 *page = virt_to_page(virt);
381 if (get_page(*page, current->domain) == 0) {
382 if (page_get_owner(*page) != current->domain) {
383 // which code is appropriate?
384 *fault = IA64_FAULT;
385 return 0;
386 }
387 goto again;
388 }
390 return virt;
391 }
393 static efi_status_t
394 efi_emulate_get_time(
395 unsigned long tv_addr, unsigned long tc_addr,
396 IA64FAULT *fault)
397 {
398 unsigned long tv = 0, tc = 0;
399 struct page_info *tv_page = NULL;
400 struct page_info *tc_page = NULL;
401 efi_status_t status;
403 //printf("efi_get_time(%016lx,%016lx) called\n", tv_addr, tc_addr);
404 tv = efi_translate_domain_addr(tv_addr, fault, &tv_page);
405 if (*fault != IA64_NO_FAULT)
406 return 0;
407 if (tc_addr) {
408 tc = efi_translate_domain_addr(tc_addr, fault, &tc_page);
409 if (*fault != IA64_NO_FAULT) {
410 put_page(tv_page);
411 return 0;
412 }
413 }
414 //printf("efi_get_time(%016lx,%016lx) translated to xen virtual address\n", tv, tc);
415 status = (*efi.get_time)((efi_time_t *) tv, (efi_time_cap_t *) tc);
416 //printf("efi_get_time returns %lx\n", status);
417 if (tc_page != NULL)
418 put_page(tc_page);
419 put_page(tv_page);
420 return status;
421 }
423 static efi_status_t
424 efi_emulate_get_variable(
425 unsigned long name_addr, unsigned long vendor_addr,
426 unsigned long attr_addr, unsigned long data_size_addr,
427 unsigned long data_addr, IA64FAULT *fault)
428 {
429 unsigned long name, vendor, attr = 0, data_size, data;
430 struct page_info *name_page = NULL, *vendor_page = NULL,
431 *attr_page = NULL, *data_size_page = NULL,
432 *data_page = NULL;
433 efi_status_t status = 0;
435 if (current->domain != dom0)
436 return EFI_UNSUPPORTED;
438 name = efi_translate_domain_addr(name_addr, fault, &name_page);
439 if (*fault != IA64_NO_FAULT)
440 goto errout;
441 vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page);
442 if (*fault != IA64_NO_FAULT)
443 goto errout;
444 data_size = efi_translate_domain_addr(data_size_addr, fault,
445 &data_size_page);
446 if (*fault != IA64_NO_FAULT)
447 goto errout;
448 data = efi_translate_domain_addr(data_addr, fault, &data_page);
449 if (*fault != IA64_NO_FAULT)
450 goto errout;
451 if (attr_addr) {
452 attr = efi_translate_domain_addr(attr_addr, fault, &attr_page);
453 if (*fault != IA64_NO_FAULT)
454 goto errout;
455 }
457 status = (*efi.get_variable)((efi_char16_t *)name,
458 (efi_guid_t *)vendor,
459 (u32 *)attr,
460 (unsigned long *)data_size,
461 (void *)data);
463 errout:
464 if (name_page != NULL)
465 put_page(name_page);
466 if (vendor_page != NULL)
467 put_page(vendor_page);
468 if (attr_page != NULL)
469 put_page(attr_page);
470 if (data_size_page != NULL)
471 put_page(data_size_page);
472 if (data_page != NULL)
473 put_page(data_page);
475 return status;
476 }
478 static efi_status_t
479 efi_emulate_get_next_variable(
480 unsigned long name_size_addr, unsigned long name_addr,
481 unsigned long vendor_addr, IA64FAULT *fault)
482 {
483 unsigned long name_size, name, vendor;
484 struct page_info *name_size_page = NULL, *name_page = NULL,
485 *vendor_page = NULL;
486 efi_status_t status = 0;
488 if (current->domain != dom0)
489 return EFI_UNSUPPORTED;
491 name_size = efi_translate_domain_addr(name_size_addr, fault,
492 &name_size_page);
493 if (*fault != IA64_NO_FAULT)
494 goto errout;
495 name = efi_translate_domain_addr(name_addr, fault, &name_page);
496 if (*fault != IA64_NO_FAULT)
497 goto errout;
498 vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page);
499 if (*fault != IA64_NO_FAULT)
500 goto errout;
502 status = (*efi.get_next_variable)((unsigned long *)name_size,
503 (efi_char16_t *)name,
504 (efi_guid_t *)vendor);
506 errout:
507 if (name_size_page != NULL)
508 put_page(name_size_page);
509 if (name_page != NULL)
510 put_page(name_page);
511 if (vendor_page != NULL)
512 put_page(vendor_page);
514 return status;
515 }
517 static efi_status_t
518 efi_emulate_set_variable(
519 unsigned long name_addr, unsigned long vendor_addr,
520 unsigned long attr, unsigned long data_size,
521 unsigned long data_addr, IA64FAULT *fault)
522 {
523 unsigned long name, vendor, data;
524 struct page_info *name_page = NULL, *vendor_page = NULL,
525 *data_page = NULL;
526 efi_status_t status = 0;
528 if (current->domain != dom0)
529 return EFI_UNSUPPORTED;
531 name = efi_translate_domain_addr(name_addr, fault, &name_page);
532 if (*fault != IA64_NO_FAULT)
533 goto errout;
534 vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page);
535 if (*fault != IA64_NO_FAULT)
536 goto errout;
537 data = efi_translate_domain_addr(data_addr, fault, &data_page);
538 if (*fault != IA64_NO_FAULT)
539 goto errout;
541 status = (*efi.set_variable)((efi_char16_t *)name,
542 (efi_guid_t *)vendor,
543 attr,
544 data_size,
545 (void *)data);
547 errout:
548 if (name_page != NULL)
549 put_page(name_page);
550 if (vendor_page != NULL)
551 put_page(vendor_page);
552 if (data_page != NULL)
553 put_page(data_page);
555 return status;
556 }
558 static efi_status_t
559 efi_emulate_set_virtual_address_map(
560 unsigned long memory_map_size, unsigned long descriptor_size,
561 u32 descriptor_version, efi_memory_desc_t *virtual_map)
562 {
563 void *efi_map_start, *efi_map_end, *p;
564 efi_memory_desc_t entry, *md = &entry;
565 u64 efi_desc_size;
567 unsigned long *vfn;
568 struct domain *d = current->domain;
569 efi_runtime_services_t *efi_runtime = d->arch.efi_runtime;
570 fpswa_interface_t *fpswa_inf = d->arch.fpswa_inf;
572 if (descriptor_version != EFI_MEMDESC_VERSION) {
573 printf ("efi_emulate_set_virtual_address_map: memory "
574 "descriptor version unmatched (%d vs %d)\n",
575 (int)descriptor_version, EFI_MEMDESC_VERSION);
576 return EFI_INVALID_PARAMETER;
577 }
579 if (descriptor_size != sizeof(efi_memory_desc_t)) {
580 printf ("efi_emulate_set_virtual_address_map: memory descriptor size unmatched\n");
581 return EFI_INVALID_PARAMETER;
582 }
584 if (d->arch.sal_data->efi_virt_mode)
585 return EFI_UNSUPPORTED;
587 efi_map_start = virtual_map;
588 efi_map_end = efi_map_start + memory_map_size;
589 efi_desc_size = sizeof(efi_memory_desc_t);
591 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
592 if (copy_from_user(&entry, p, sizeof(efi_memory_desc_t))) {
593 printf ("efi_emulate_set_virtual_address_map: copy_from_user() fault. addr=0x%p\n", p);
594 return EFI_UNSUPPORTED;
595 }
597 /* skip over non-PAL_CODE memory descriptors; EFI_RUNTIME is included in PAL_CODE. */
598 if (md->type != EFI_PAL_CODE)
599 continue;
601 #define EFI_HYPERCALL_PATCH_TO_VIRT(tgt,call) \
602 do { \
603 vfn = (unsigned long *) domain_mpa_to_imva(d, tgt); \
604 *vfn++ = FW_HYPERCALL_##call##_INDEX * 16UL + md->virt_addr; \
605 *vfn++ = 0; \
606 } while (0)
608 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_time,EFI_GET_TIME);
609 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_time,EFI_SET_TIME);
610 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_wakeup_time,EFI_GET_WAKEUP_TIME);
611 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_wakeup_time,EFI_SET_WAKEUP_TIME);
612 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_virtual_address_map,EFI_SET_VIRTUAL_ADDRESS_MAP);
613 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_variable,EFI_GET_VARIABLE);
614 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_variable,EFI_GET_NEXT_VARIABLE);
615 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_variable,EFI_SET_VARIABLE);
616 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_high_mono_count,EFI_GET_NEXT_HIGH_MONO_COUNT);
617 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->reset_system,EFI_RESET_SYSTEM);
619 vfn = (unsigned long *) domain_mpa_to_imva(d, (unsigned long) fpswa_inf->fpswa);
620 *vfn++ = FW_HYPERCALL_FPSWA_PATCH_INDEX * 16UL + md->virt_addr;
621 *vfn = 0;
622 fpswa_inf->fpswa = (void *) (FW_HYPERCALL_FPSWA_ENTRY_INDEX * 16UL + md->virt_addr);
623 break;
624 }
626 /* The virtual address map has been applied. */
627 d->arch.sal_data->efi_virt_mode = 1;
629 return EFI_SUCCESS;
630 }
632 efi_status_t
633 efi_emulator (struct pt_regs *regs, IA64FAULT *fault)
634 {
635 struct vcpu *v = current;
636 efi_status_t status;
638 *fault = IA64_NO_FAULT;
640 switch (regs->r2) {
641 case FW_HYPERCALL_EFI_RESET_SYSTEM:
642 {
643 u8 reason;
644 unsigned long val = vcpu_get_gr(v,32);
645 switch (val)
646 {
647 case EFI_RESET_SHUTDOWN:
648 reason = SHUTDOWN_poweroff;
649 break;
650 case EFI_RESET_COLD:
651 case EFI_RESET_WARM:
652 default:
653 reason = SHUTDOWN_reboot;
654 break;
655 }
656 domain_shutdown (current->domain, reason);
657 }
658 status = EFI_UNSUPPORTED;
659 break;
660 case FW_HYPERCALL_EFI_GET_TIME:
661 status = efi_emulate_get_time (
662 vcpu_get_gr(v,32),
663 vcpu_get_gr(v,33),
664 fault);
665 break;
666 case FW_HYPERCALL_EFI_GET_VARIABLE:
667 status = efi_emulate_get_variable (
668 vcpu_get_gr(v,32),
669 vcpu_get_gr(v,33),
670 vcpu_get_gr(v,34),
671 vcpu_get_gr(v,35),
672 vcpu_get_gr(v,36),
673 fault);
674 break;
675 case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE:
676 status = efi_emulate_get_next_variable (
677 vcpu_get_gr(v,32),
678 vcpu_get_gr(v,33),
679 vcpu_get_gr(v,34),
680 fault);
681 break;
682 case FW_HYPERCALL_EFI_SET_VARIABLE:
683 status = efi_emulate_set_variable (
684 vcpu_get_gr(v,32),
685 vcpu_get_gr(v,33),
686 vcpu_get_gr(v,34),
687 vcpu_get_gr(v,35),
688 vcpu_get_gr(v,36),
689 fault);
690 break;
691 case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP:
692 status = efi_emulate_set_virtual_address_map (
693 vcpu_get_gr(v,32),
694 vcpu_get_gr(v,33),
695 (u32) vcpu_get_gr(v,34),
696 (efi_memory_desc_t *) vcpu_get_gr(v,35));
697 break;
698 case FW_HYPERCALL_EFI_SET_TIME:
699 case FW_HYPERCALL_EFI_GET_WAKEUP_TIME:
700 case FW_HYPERCALL_EFI_SET_WAKEUP_TIME:
701 // FIXME: need fixes in efi.h from 2.6.9
702 case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT:
703 // FIXME: need fixes in efi.h from 2.6.9
704 status = EFI_UNSUPPORTED;
705 break;
706 default:
707 printf("unknown ia64 fw hypercall %lx\n", regs->r2);
708 status = EFI_UNSUPPORTED;
709 }
711 return status;
712 }
714 void
715 do_ssc(unsigned long ssc, struct pt_regs *regs)
716 {
717 unsigned long arg0, arg1, arg2, arg3, retval;
718 char buf[2];
719 /**/ static int last_fd, last_count; // FIXME FIXME FIXME
720 /**/ // BROKEN FOR MULTIPLE DOMAINS & SMP
721 /**/ struct ssc_disk_stat { int fd; unsigned count;} *stat, last_stat;
723 arg0 = vcpu_get_gr(current,32);
724 switch(ssc) {
725 case SSC_PUTCHAR:
726 buf[0] = arg0;
727 buf[1] = '\0';
728 printf(buf);
729 break;
730 case SSC_GETCHAR:
731 retval = ia64_ssc(0,0,0,0,ssc);
732 vcpu_set_gr(current,8,retval,0);
733 break;
734 case SSC_WAIT_COMPLETION:
735 if (arg0) { // metaphysical address
737 arg0 = translate_domain_mpaddr(arg0, NULL);
738 /**/ stat = (struct ssc_disk_stat *)__va(arg0);
739 ///**/ if (stat->fd == last_fd) stat->count = last_count;
740 /**/ stat->count = last_count;
741 //if (last_count >= PAGE_SIZE) printf("ssc_wait: stat->fd=%d,last_fd=%d,last_count=%d\n",stat->fd,last_fd,last_count);
742 ///**/ retval = ia64_ssc(arg0,0,0,0,ssc);
743 /**/ retval = 0;
744 }
745 else retval = -1L;
746 vcpu_set_gr(current,8,retval,0);
747 break;
748 case SSC_OPEN:
749 arg1 = vcpu_get_gr(current,33); // access rights
750 if (!running_on_sim) { printf("SSC_OPEN, not implemented on hardware. (ignoring...)\n"); arg0 = 0; }
751 if (arg0) { // metaphysical address
752 arg0 = translate_domain_mpaddr(arg0, NULL);
753 retval = ia64_ssc(arg0,arg1,0,0,ssc);
754 }
755 else retval = -1L;
756 vcpu_set_gr(current,8,retval,0);
757 break;
758 case SSC_WRITE:
759 case SSC_READ:
760 //if (ssc == SSC_WRITE) printf("DOING AN SSC_WRITE\n");
761 arg1 = vcpu_get_gr(current,33);
762 arg2 = vcpu_get_gr(current,34);
763 arg3 = vcpu_get_gr(current,35);
764 if (arg2) { // metaphysical address of descriptor
765 struct ssc_disk_req *req;
766 unsigned long mpaddr;
767 long len;
769 arg2 = translate_domain_mpaddr(arg2, NULL);
770 req = (struct ssc_disk_req *) __va(arg2);
771 req->len &= 0xffffffffL; // avoid strange bug
772 len = req->len;
773 /**/ last_fd = arg1;
774 /**/ last_count = len;
775 mpaddr = req->addr;
776 //if (last_count >= PAGE_SIZE) printf("do_ssc: read fd=%d, addr=%p, len=%lx ",last_fd,mpaddr,len);
777 retval = 0;
778 if ((mpaddr & PAGE_MASK) != ((mpaddr+len-1) & PAGE_MASK)) {
779 // do partial page first
780 req->addr = translate_domain_mpaddr(mpaddr, NULL);
781 req->len = PAGE_SIZE - (req->addr & ~PAGE_MASK);
782 len -= req->len; mpaddr += req->len;
783 retval = ia64_ssc(arg0,arg1,arg2,arg3,ssc);
784 arg3 += req->len; // file offset
785 /**/ last_stat.fd = last_fd;
786 /**/ (void)ia64_ssc(__pa(&last_stat),0,0,0,SSC_WAIT_COMPLETION);
787 //if (last_count >= PAGE_SIZE) printf("ssc(%p,%lx)[part]=%x ",req->addr,req->len,retval);
788 }
789 if (retval >= 0) while (len > 0) {
790 req->addr = translate_domain_mpaddr(mpaddr, NULL);
791 req->len = (len > PAGE_SIZE) ? PAGE_SIZE : len;
792 len -= PAGE_SIZE; mpaddr += PAGE_SIZE;
793 retval = ia64_ssc(arg0,arg1,arg2,arg3,ssc);
794 arg3 += req->len; // file offset
795 // TEMP REMOVED AGAIN arg3 += req->len; // file offset
796 /**/ last_stat.fd = last_fd;
797 /**/ (void)ia64_ssc(__pa(&last_stat),0,0,0,SSC_WAIT_COMPLETION);
798 //if (last_count >= PAGE_SIZE) printf("ssc(%p,%lx)=%x ",req->addr,req->len,retval);
799 }
800 // set it back to the original value
801 req->len = last_count;
802 }
803 else retval = -1L;
804 vcpu_set_gr(current,8,retval,0);
805 //if (last_count >= PAGE_SIZE) printf("retval=%x\n",retval);
806 break;
807 case SSC_CONNECT_INTERRUPT:
808 arg1 = vcpu_get_gr(current,33);
809 arg2 = vcpu_get_gr(current,34);
810 arg3 = vcpu_get_gr(current,35);
811 if (!running_on_sim) { printf("SSC_CONNECT_INTERRUPT, not implemented on hardware. (ignoring...)\n"); break; }
812 (void)ia64_ssc(arg0,arg1,arg2,arg3,ssc);
813 break;
814 case SSC_NETDEV_PROBE:
815 vcpu_set_gr(current,8,-1L,0);
816 break;
817 default:
818 printf("ia64_handle_break: bad ssc code %lx, iip=0x%lx, b0=0x%lx... spinning\n",
819 ssc, regs->cr_iip, regs->b0);
820 while(1);
821 break;
822 }
823 vcpu_increment_iip(current);
824 }