ia64/xen-unstable

view xen/arch/ia64/xen/fw_emul.c @ 16622:e6069a715fd7

[IA64] Fix vulnerability of copy_to_user in PAL emulation

There is a security vulnerability in PAL emulation since alt-dtlb
miss handler of HVM absolutely inserts a identity-mapped TLB when
psr.vm=0. HVM guest can access an arbitrary machine physical
memory with this security hole. Actually windows 2008 destroys
the content of machine physical address 0x108000.

I think this patch is enough for normal usage. Please see SDM
Vol2 11.10.2.1.3 "Making PAL Procedure Calls in Physical or
Virtual Mode". If the caller has a responsibility of providing
DTR or DTC mapping, xencomm for PAL might be unnecessary.

I confirmed there is no problem in linux, windows 2003, windows
2008 with this patch.

As for PV domain, the same logic can't be used due to only one
vTLB. This patch only checks that the buffer never points VMM
address, that would avoid the vulnerability.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
author Alex Williamson <alex.williamson@hp.com>
date Fri Dec 14 10:25:03 2007 -0700 (2007-12-14)
parents a071725bda88
children b03e24f9c1d8
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 <asm/system.h>
20 #include <asm/pgalloc.h>
22 #include <linux/efi.h>
23 #include <asm/pal.h>
24 #include <asm/sal.h>
25 #include <asm/sn/sn_sal.h>
26 #include <asm/sn/hubdev.h>
27 #include <asm/xenmca.h>
29 #include <public/sched.h>
30 #include "hpsim_ssc.h"
31 #include <asm/vcpu.h>
32 #include <asm/vmx_vcpu.h>
33 #include <asm/dom_fw.h>
34 #include <asm/uaccess.h>
35 #include <xen/console.h>
36 #include <xen/hypercall.h>
37 #include <xen/softirq.h>
38 #include <xen/time.h>
39 #include <asm/debugger.h>
40 #include <asm/vmx_phy_mode.h>
42 static DEFINE_SPINLOCK(efi_time_services_lock);
44 struct sal_mc_params {
45 u64 param_type;
46 u64 i_or_m;
47 u64 i_or_m_val;
48 u64 timeout;
49 u64 rz_always;
50 } sal_mc_params[SAL_MC_PARAM_CPE_INT + 1];
52 struct sal_vectors {
53 u64 vector_type;
54 u64 handler_addr1;
55 u64 gp1;
56 u64 handler_len1;
57 u64 handler_addr2;
58 u64 gp2;
59 u64 handler_len2;
60 } sal_vectors[SAL_VECTOR_OS_BOOT_RENDEZ + 1];
62 struct smp_call_args_t {
63 u64 type;
64 u64 ret;
65 u64 target;
66 struct domain *domain;
67 int corrected;
68 int status;
69 void *data;
70 };
72 extern sal_log_record_header_t *sal_record;
73 DEFINE_SPINLOCK(sal_record_lock);
75 extern spinlock_t sal_queue_lock;
77 #define IA64_SAL_NO_INFORMATION_AVAILABLE -5
79 #if defined(IA64_SAL_DEBUG_INFO)
80 static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };
82 # define IA64_SAL_DEBUG(fmt...) printk("sal_emulator: " fmt)
83 #else
84 # define IA64_SAL_DEBUG(fmt...)
85 #endif
87 void get_state_info_on(void *data) {
88 struct smp_call_args_t *arg = data;
89 int flags;
91 spin_lock_irqsave(&sal_record_lock, flags);
92 memset(sal_record, 0, ia64_sal_get_state_info_size(arg->type));
93 arg->ret = ia64_sal_get_state_info(arg->type, (u64 *)sal_record);
94 IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s) on CPU#%d returns %ld.\n",
95 rec_name[arg->type], smp_processor_id(), arg->ret);
96 if (arg->corrected) {
97 sal_record->severity = sal_log_severity_corrected;
98 IA64_SAL_DEBUG("%s: IA64_SAL_CLEAR_STATE_INFO(SAL_INFO_TYPE_MCA)"
99 " force\n", __FUNCTION__);
100 }
101 if (arg->ret > 0) {
102 /*
103 * Save current->domain and set to local(caller) domain for
104 * xencomm_paddr_to_maddr() which calculates maddr from
105 * paddr using mpa value of current->domain.
106 */
107 struct domain *save;
108 save = current->domain;
109 current->domain = arg->domain;
110 if (xencomm_copy_to_guest((void*)arg->target,
111 sal_record, arg->ret, 0)) {
112 printk("SAL_GET_STATE_INFO can't copy to user!!!!\n");
113 arg->status = IA64_SAL_NO_INFORMATION_AVAILABLE;
114 arg->ret = 0;
115 }
116 /* Restore current->domain to saved value. */
117 current->domain = save;
118 }
119 spin_unlock_irqrestore(&sal_record_lock, flags);
120 }
122 void clear_state_info_on(void *data) {
123 struct smp_call_args_t *arg = data;
125 arg->ret = ia64_sal_clear_state_info(arg->type);
126 IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s) on CPU#%d returns %ld.\n",
127 rec_name[arg->type], smp_processor_id(), arg->ret);
129 }
131 struct sal_ret_values
132 sal_emulator (long index, unsigned long in1, unsigned long in2,
133 unsigned long in3, unsigned long in4, unsigned long in5,
134 unsigned long in6, unsigned long in7)
135 {
136 struct ia64_sal_retval ret_stuff;
137 unsigned long r9 = 0;
138 unsigned long r10 = 0;
139 long r11 = 0;
140 long status;
142 debugger_event(XEN_IA64_DEBUG_ON_SAL);
144 status = 0;
145 switch (index) {
146 case SAL_FREQ_BASE:
147 if (likely(!running_on_sim))
148 status = ia64_sal_freq_base(in1,&r9,&r10);
149 else switch (in1) {
150 case SAL_FREQ_BASE_PLATFORM:
151 r9 = 200000000;
152 break;
154 case SAL_FREQ_BASE_INTERVAL_TIMER:
155 r9 = 700000000;
156 break;
158 case SAL_FREQ_BASE_REALTIME_CLOCK:
159 r9 = 1;
160 break;
162 default:
163 status = -1;
164 break;
165 }
166 break;
167 case SAL_PCI_CONFIG_READ:
168 if (current->domain == dom0) {
169 u64 value;
170 // note that args 2&3 are swapped!!
171 status = ia64_sal_pci_config_read(in1,in3,in2,&value);
172 r9 = value;
173 }
174 else
175 printk("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_READ\n");
176 break;
177 case SAL_PCI_CONFIG_WRITE:
178 if (current->domain == dom0) {
179 if (((in1 & ~0xffffffffUL) && (in4 == 0)) ||
180 (in4 > 1) ||
181 (in2 > 8) || (in2 & (in2-1)))
182 printk("*** SAL_PCI_CONF_WRITE?!?(adr=0x%lx,typ=0x%lx,sz=0x%lx,val=0x%lx)\n",
183 in1,in4,in2,in3);
184 // note that args are in a different order!!
185 status = ia64_sal_pci_config_write(in1,in4,in2,in3);
186 }
187 else
188 printk("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_WRITE\n");
189 break;
190 case SAL_SET_VECTORS:
191 if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
192 if (in4 != 0 || in5 != 0 || in6 != 0 || in7 != 0) {
193 /* Sanity check: cs_length1 must be 0,
194 second vector is reserved. */
195 status = -2;
196 }
197 else {
198 struct domain *d = current->domain;
199 d->arch.sal_data->boot_rdv_ip = in2;
200 d->arch.sal_data->boot_rdv_r1 = in3;
201 }
202 }
203 else
204 {
205 if (in1 > sizeof(sal_vectors)/sizeof(sal_vectors[0])-1)
206 BUG();
207 sal_vectors[in1].vector_type = in1;
208 sal_vectors[in1].handler_addr1 = in2;
209 sal_vectors[in1].gp1 = in3;
210 sal_vectors[in1].handler_len1 = in4;
211 sal_vectors[in1].handler_addr2 = in5;
212 sal_vectors[in1].gp2 = in6;
213 sal_vectors[in1].handler_len2 = in7;
214 }
215 break;
216 case SAL_GET_STATE_INFO:
217 if (current->domain == dom0) {
218 sal_queue_entry_t *e;
219 unsigned long flags;
220 struct smp_call_args_t arg;
222 spin_lock_irqsave(&sal_queue_lock, flags);
223 if (!sal_queue || list_empty(&sal_queue[in1])) {
224 sal_log_record_header_t header;
225 XEN_GUEST_HANDLE(void) handle =
226 *(XEN_GUEST_HANDLE(void)*)&in3;
228 IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s) "
229 "no sal_queue entry found.\n",
230 rec_name[in1]);
231 memset(&header, 0, sizeof(header));
233 if (copy_to_guest(handle, &header, 1)) {
234 printk("sal_emulator: "
235 "SAL_GET_STATE_INFO can't copy "
236 "empty header to user: 0x%lx\n",
237 in3);
238 }
239 status = IA64_SAL_NO_INFORMATION_AVAILABLE;
240 r9 = 0;
241 spin_unlock_irqrestore(&sal_queue_lock, flags);
242 break;
243 }
244 e = list_entry(sal_queue[in1].next,
245 sal_queue_entry_t, list);
247 list_del(&e->list);
248 spin_unlock_irqrestore(&sal_queue_lock, flags);
250 IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s <= %s) "
251 "on CPU#%d.\n",
252 rec_name[e->sal_info_type],
253 rec_name[in1], e->cpuid);
255 arg.type = e->sal_info_type;
256 arg.target = in3;
257 arg.corrected = !!((in1 != e->sal_info_type) &&
258 (e->sal_info_type == SAL_INFO_TYPE_MCA));
259 arg.domain = current->domain;
260 arg.status = 0;
262 if (e->cpuid == smp_processor_id()) {
263 IA64_SAL_DEBUG("SAL_GET_STATE_INFO: local\n");
264 get_state_info_on(&arg);
265 } else {
266 int ret;
267 IA64_SAL_DEBUG("SAL_GET_STATE_INFO: remote\n");
268 ret = smp_call_function_single(e->cpuid,
269 get_state_info_on,
270 &arg, 0, 1);
271 if (ret < 0) {
272 printk("SAL_GET_STATE_INFO "
273 "smp_call_function_single error:"
274 " %d\n", ret);
275 arg.ret = 0;
276 arg.status =
277 IA64_SAL_NO_INFORMATION_AVAILABLE;
278 }
279 }
280 r9 = arg.ret;
281 status = arg.status;
282 if (r9 == 0) {
283 xfree(e);
284 } else {
285 /* Re-add the entry to sal_queue */
286 spin_lock_irqsave(&sal_queue_lock, flags);
287 list_add(&e->list, &sal_queue[in1]);
288 spin_unlock_irqrestore(&sal_queue_lock, flags);
289 }
290 } else {
291 status = IA64_SAL_NO_INFORMATION_AVAILABLE;
292 r9 = 0;
293 }
294 break;
295 case SAL_GET_STATE_INFO_SIZE:
296 r9 = ia64_sal_get_state_info_size(in1);
297 break;
298 case SAL_CLEAR_STATE_INFO:
299 if (current->domain == dom0) {
300 sal_queue_entry_t *e;
301 unsigned long flags;
302 struct smp_call_args_t arg;
304 spin_lock_irqsave(&sal_queue_lock, flags);
305 if (list_empty(&sal_queue[in1])) {
306 IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s) "
307 "no sal_queue entry found.\n",
308 rec_name[in1]);
309 status = IA64_SAL_NO_INFORMATION_AVAILABLE;
310 r9 = 0;
311 spin_unlock_irqrestore(&sal_queue_lock, flags);
312 break;
313 }
314 e = list_entry(sal_queue[in1].next,
315 sal_queue_entry_t, list);
317 list_del(&e->list);
318 spin_unlock_irqrestore(&sal_queue_lock, flags);
320 IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s <= %s) "
321 "on CPU#%d.\n",
322 rec_name[e->sal_info_type],
323 rec_name[in1], e->cpuid);
325 arg.type = e->sal_info_type;
326 arg.status = 0;
328 if (e->cpuid == smp_processor_id()) {
329 IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO: local\n");
330 clear_state_info_on(&arg);
331 } else {
332 int ret;
333 IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO: remote\n");
334 ret = smp_call_function_single(e->cpuid,
335 clear_state_info_on, &arg, 0, 1);
336 if (ret < 0) {
337 printk("sal_emulator: "
338 "SAL_CLEAR_STATE_INFO "
339 "smp_call_function_single error:"
340 " %d\n", ret);
341 arg.ret = 0;
342 arg.status =
343 IA64_SAL_NO_INFORMATION_AVAILABLE;
344 }
345 }
346 r9 = arg.ret;
347 status = arg.status;
348 xfree(e);
349 }
350 break;
351 case SAL_MC_RENDEZ:
352 printk("*** CALLED SAL_MC_RENDEZ. IGNORED...\n");
353 break;
354 case SAL_MC_SET_PARAMS:
355 if (in1 > sizeof(sal_mc_params)/sizeof(sal_mc_params[0]))
356 BUG();
357 sal_mc_params[in1].param_type = in1;
358 sal_mc_params[in1].i_or_m = in2;
359 sal_mc_params[in1].i_or_m_val = in3;
360 sal_mc_params[in1].timeout = in4;
361 sal_mc_params[in1].rz_always = in5;
362 break;
363 case SAL_CACHE_FLUSH:
364 if (1) {
365 /* Flush using SAL.
366 This method is faster but has a side effect on
367 other vcpu running on this cpu. */
368 status = ia64_sal_cache_flush (in1);
369 }
370 else {
371 /* Flush with fc all the domain.
372 This method is slower but has no side effects. */
373 domain_cache_flush (current->domain, in1 == 4 ? 1 : 0);
374 status = 0;
375 }
376 break;
377 case SAL_CACHE_INIT:
378 printk("*** CALLED SAL_CACHE_INIT. IGNORED...\n");
379 break;
380 case SAL_UPDATE_PAL:
381 printk("*** CALLED SAL_UPDATE_PAL. IGNORED...\n");
382 break;
383 case SAL_PHYSICAL_ID_INFO:
384 status = -1;
385 break;
386 case SAL_XEN_SAL_RETURN:
387 if (!test_and_set_bit(_VPF_down, &current->pause_flags))
388 vcpu_sleep_nosync(current);
389 break;
390 case SN_SAL_GET_MASTER_NASID:
391 status = -1;
392 if (current->domain == dom0) {
393 /* printk("*** Emulating SN_SAL_GET_MASTER_NASID ***\n"); */
394 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_MASTER_NASID,
395 0, 0, 0, 0, 0, 0, 0);
396 status = ret_stuff.status;
397 r9 = ret_stuff.v0;
398 r10 = ret_stuff.v1;
399 r11 = ret_stuff.v2;
400 }
401 break;
402 case SN_SAL_GET_KLCONFIG_ADDR:
403 status = -1;
404 if (current->domain == dom0) {
405 /* printk("*** Emulating SN_SAL_GET_KLCONFIG_ADDR ***\n"); */
406 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_KLCONFIG_ADDR,
407 in1, 0, 0, 0, 0, 0, 0);
408 status = ret_stuff.status;
409 r9 = ret_stuff.v0;
410 r10 = ret_stuff.v1;
411 r11 = ret_stuff.v2;
412 }
413 break;
414 case SN_SAL_GET_SAPIC_INFO:
415 status = -1;
416 if (current->domain == dom0) {
417 /* printk("*** Emulating SN_SAL_GET_SAPIC_INFO ***\n"); */
418 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SAPIC_INFO,
419 in1, 0, 0, 0, 0, 0, 0);
420 status = ret_stuff.status;
421 r9 = ret_stuff.v0;
422 r10 = ret_stuff.v1;
423 r11 = ret_stuff.v2;
424 }
425 break;
426 case SN_SAL_GET_SN_INFO:
427 status = -1;
428 if (current->domain == dom0) {
429 /* printk("*** Emulating SN_SAL_GET_SN_INFO ***\n"); */
430 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SN_INFO,
431 in1, 0, 0, 0, 0, 0, 0);
432 status = ret_stuff.status;
433 r9 = ret_stuff.v0;
434 r10 = ret_stuff.v1;
435 r11 = ret_stuff.v2;
436 }
437 break;
438 case SN_SAL_IOIF_GET_HUBDEV_INFO:
439 status = -1;
440 if (current->domain == dom0) {
441 /* printk("*** Emulating SN_SAL_IOIF_GET_HUBDEV_INFO ***\n"); */
442 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_IOIF_GET_HUBDEV_INFO,
443 in1, in2, 0, 0, 0, 0, 0);
444 status = ret_stuff.status;
445 r9 = ret_stuff.v0;
446 r10 = ret_stuff.v1;
447 r11 = ret_stuff.v2;
448 }
449 break;
450 case SN_SAL_IOIF_INIT:
451 status = -1;
452 if (current->domain == dom0) {
453 /* printk("*** Emulating SN_SAL_IOIF_INIT ***\n"); */
454 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_IOIF_INIT,
455 0, 0, 0, 0, 0, 0, 0);
456 status = ret_stuff.status;
457 r9 = ret_stuff.v0;
458 r10 = ret_stuff.v1;
459 r11 = ret_stuff.v2;
460 }
461 break;
462 case SN_SAL_GET_PROM_FEATURE_SET:
463 status = -1;
464 if (current->domain == dom0) {
465 /* printk("*** Emulating SN_SAL_GET_PROM_FEATURE_SET ***\n"); */
466 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_PROM_FEATURE_SET,
467 in1, 0, 0, 0, 0, 0, 0);
468 status = ret_stuff.status;
469 r9 = ret_stuff.v0;
470 r10 = ret_stuff.v1;
471 r11 = ret_stuff.v2;
472 }
473 break;
474 case SN_SAL_SET_OS_FEATURE_SET:
475 status = -1;
476 if (current->domain == dom0) {
477 /* printk("*** Emulating SN_SAL_SET_OS_FEATURE_SET ***\n"); */
478 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_SET_OS_FEATURE_SET,
479 in1, 0, 0, 0, 0, 0, 0);
480 status = ret_stuff.status;
481 r9 = ret_stuff.v0;
482 r10 = ret_stuff.v1;
483 r11 = ret_stuff.v2;
484 }
485 break;
486 case SN_SAL_SET_ERROR_HANDLING_FEATURES:
487 status = -1;
488 if (current->domain == dom0) {
489 /* printk("*** Emulating SN_SAL_SET_ERROR_HANDLING_FEATURES ***\n"); */
490 SAL_CALL_NOLOCK(ret_stuff,
491 SN_SAL_SET_ERROR_HANDLING_FEATURES,
492 in1, 0, 0, 0, 0, 0, 0);
493 status = ret_stuff.status;
494 r9 = ret_stuff.v0;
495 r10 = ret_stuff.v1;
496 r11 = ret_stuff.v2;
497 }
498 break;
499 #if 0
500 /*
501 * Somehow ACPI breaks if allowing this one
502 */
503 case SN_SAL_SET_CPU_NUMBER:
504 status = -1;
505 if (current->domain == dom0) {
506 printk("*** Emulating SN_SAL_SET_CPU_NUMBER ***\n");
507 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_SET_CPU_NUMBER,
508 in1, 0, 0, 0, 0, 0, 0);
509 status = ret_stuff.status;
510 r9 = ret_stuff.v0;
511 r10 = ret_stuff.v1;
512 r11 = ret_stuff.v2;
513 }
514 break;
515 #endif
516 case SN_SAL_LOG_CE:
517 status = -1;
518 if (current->domain == dom0) {
519 static int log_ce = 0;
520 if (!log_ce) {
521 printk("*** Emulating SN_SAL_LOG_CE *** "
522 " this will only be printed once\n");
523 log_ce = 1;
524 }
525 SAL_CALL_NOLOCK(ret_stuff, SN_SAL_LOG_CE,
526 0, 0, 0, 0, 0, 0, 0);
527 status = ret_stuff.status;
528 r9 = ret_stuff.v0;
529 r10 = ret_stuff.v1;
530 r11 = ret_stuff.v2;
531 }
532 break;
533 case SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST:
534 status = -1;
535 if (current->domain == dom0) {
536 struct sn_flush_device_common flush;
537 int flush_size;
539 flush_size = sizeof(struct sn_flush_device_common);
540 memset(&flush, 0, flush_size);
541 SAL_CALL_NOLOCK(ret_stuff,
542 SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
543 in1, in2, in3, &flush, 0, 0, 0);
544 #if 0
545 printk("*** Emulating "
546 "SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST ***\n");
547 #endif
548 if (ret_stuff.status == SALRET_OK) {
549 XEN_GUEST_HANDLE(void) handle =
550 *(XEN_GUEST_HANDLE(void)*)&in4;
551 if (copy_to_guest(handle, &flush, 1)) {
552 printk("SN_SAL_IOIF_GET_DEVICE_"
553 "DMAFLUSH_LIST can't copy "
554 "to user!\n");
555 ret_stuff.status = SALRET_ERROR;
556 }
557 }
559 status = ret_stuff.status;
560 r9 = ret_stuff.v0;
561 r10 = ret_stuff.v1;
562 r11 = ret_stuff.v2;
563 }
564 break;
565 default:
566 printk("*** CALLED SAL_ WITH UNKNOWN INDEX (%lx). "
567 "IGNORED...\n", index);
568 status = -1;
569 break;
570 }
571 return ((struct sal_ret_values) {status, r9, r10, r11});
572 }
574 static int
575 safe_copy_to_guest(unsigned long to, void *from, long size)
576 {
577 BUG_ON((unsigned)size > PAGE_SIZE);
579 if (VMX_DOMAIN(current)) {
580 if (is_virtual_mode(current)) {
581 thash_data_t *data;
582 unsigned long gpa, poff;
584 /* The caller must provide a DTR or DTC mapping */
585 data = vtlb_lookup(current, to, DSIDE_TLB);
586 if (data) {
587 gpa = data->page_flags & _PAGE_PPN_MASK;
588 } else {
589 data = vhpt_lookup(to);
590 if (!data)
591 return -1;
592 gpa = __mpa_to_gpa(
593 data->page_flags & _PAGE_PPN_MASK);
594 gpa &= _PAGE_PPN_MASK;
595 }
596 poff = POFFSET(to, data->ps);
597 if (poff + size > PSIZE(data->ps))
598 return -1;
599 to = PAGEALIGN(gpa, data->ps) | poff;
600 }
601 to |= XENCOMM_INLINE_FLAG;
602 if (xencomm_copy_to_guest((void *)to, from, size, 0) != 0)
603 return -1;
604 return 0;
605 } else {
606 /* check for vulnerability */
607 if (IS_VMM_ADDRESS(to) || IS_VMM_ADDRESS(to + size - 1))
608 panic_domain(NULL, "copy to bad address:0x%lx\n", to);
609 return copy_to_user((void __user *)to, from, size);
610 }
611 }
613 cpumask_t cpu_cache_coherent_map;
615 struct cache_flush_args {
616 u64 cache_type;
617 u64 operation;
618 u64 progress;
619 long status;
620 };
622 static void
623 remote_pal_cache_flush(void *v)
624 {
625 struct cache_flush_args *args = v;
626 long status;
627 u64 progress = args->progress;
629 status = ia64_pal_cache_flush(args->cache_type, args->operation,
630 &progress, NULL);
631 if (status != 0)
632 args->status = status;
633 }
635 static void
636 remote_pal_prefetch_visibility(void *v)
637 {
638 s64 trans_type = (s64)v;
639 ia64_pal_prefetch_visibility(trans_type);
640 }
642 static void
643 remote_pal_mc_drain(void *v)
644 {
645 ia64_pal_mc_drain();
646 }
648 struct ia64_pal_retval
649 xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3)
650 {
651 unsigned long r9 = 0;
652 unsigned long r10 = 0;
653 unsigned long r11 = 0;
654 long status = PAL_STATUS_UNIMPLEMENTED;
655 unsigned long flags;
656 int processor;
658 if (unlikely(running_on_sim))
659 return pal_emulator_static(index);
661 debugger_event(XEN_IA64_DEBUG_ON_PAL);
663 // pal code must be mapped by a TR when pal is called, however
664 // calls are rare enough that we will map it lazily rather than
665 // at every context switch
666 //efi_map_pal_code();
667 switch (index) {
668 case PAL_MEM_ATTRIB:
669 status = ia64_pal_mem_attrib(&r9);
670 break;
671 case PAL_FREQ_BASE:
672 status = ia64_pal_freq_base(&r9);
673 if (status == PAL_STATUS_UNIMPLEMENTED) {
674 status = ia64_sal_freq_base(0, &r9, &r10);
675 r10 = 0;
676 }
677 break;
678 case PAL_PROC_GET_FEATURES:
679 status = ia64_pal_proc_get_features(&r9,&r10,&r11);
680 break;
681 case PAL_BUS_GET_FEATURES:
682 status = ia64_pal_bus_get_features(
683 (pal_bus_features_u_t *) &r9,
684 (pal_bus_features_u_t *) &r10,
685 (pal_bus_features_u_t *) &r11);
686 break;
687 case PAL_FREQ_RATIOS:
688 status = ia64_pal_freq_ratios(
689 (struct pal_freq_ratio *) &r9,
690 (struct pal_freq_ratio *) &r10,
691 (struct pal_freq_ratio *) &r11);
692 break;
693 case PAL_PTCE_INFO:
694 /*
695 * return hard-coded xen-specific values because ptc.e
696 * is emulated on xen to always flush everything
697 * these values result in only one ptc.e instruction
698 */
699 status = PAL_STATUS_SUCCESS;
700 r10 = (1L << 32) | 1L;
701 break;
702 case PAL_VERSION:
703 status = ia64_pal_version(
704 (pal_version_u_t *) &r9,
705 (pal_version_u_t *) &r10);
706 break;
707 case PAL_VM_PAGE_SIZE:
708 status = ia64_pal_vm_page_size(&r9,&r10);
709 break;
710 case PAL_DEBUG_INFO:
711 status = ia64_pal_debug_info(&r9,&r10);
712 break;
713 case PAL_CACHE_SUMMARY:
714 status = ia64_pal_cache_summary(&r9,&r10);
715 break;
716 case PAL_VM_SUMMARY:
717 if (VMX_DOMAIN(current)) {
718 pal_vm_info_1_u_t v1;
719 pal_vm_info_2_u_t v2;
720 status = ia64_pal_vm_summary((pal_vm_info_1_u_t *)&v1,
721 (pal_vm_info_2_u_t *)&v2);
722 v1.pal_vm_info_1_s.max_itr_entry = NITRS - 1;
723 v1.pal_vm_info_1_s.max_dtr_entry = NDTRS - 1;
724 v2.pal_vm_info_2_s.impl_va_msb -= 1;
725 v2.pal_vm_info_2_s.rid_size =
726 current->domain->arch.rid_bits;
727 r9 = v1.pvi1_val;
728 r10 = v2.pvi2_val;
729 } else {
730 /* Use xen-specific values.
731 hash_tag_id is somewhat random! */
732 static const pal_vm_info_1_u_t v1 =
733 {.pal_vm_info_1_s =
734 { .vw = 1,
735 .phys_add_size = 44,
736 .key_size = 16,
737 .max_pkr = XEN_IA64_NPKRS,
738 .hash_tag_id = 0x30,
739 .max_dtr_entry = NDTRS - 1,
740 .max_itr_entry = NITRS - 1,
741 .max_unique_tcs = 3,
742 .num_tc_levels = 2
743 }};
744 pal_vm_info_2_u_t v2;
745 v2.pvi2_val = 0;
746 v2.pal_vm_info_2_s.rid_size =
747 current->domain->arch.rid_bits;
748 v2.pal_vm_info_2_s.impl_va_msb = 50;
749 r9 = v1.pvi1_val;
750 r10 = v2.pvi2_val;
751 status = PAL_STATUS_SUCCESS;
752 }
753 break;
754 case PAL_VM_INFO:
755 if (VMX_DOMAIN(current)) {
756 status = ia64_pal_vm_info(in1, in2,
757 (pal_tc_info_u_t *)&r9, &r10);
758 break;
759 }
760 if (in1 == 0 && in2 == 2) {
761 /* Level 1: VHPT */
762 const pal_tc_info_u_t v =
763 { .pal_tc_info_s = {.num_sets = 128,
764 .associativity = 1,
765 .num_entries = 128,
766 .pf = 1,
767 .unified = 1,
768 .reduce_tr = 0,
769 .reserved = 0}};
770 r9 = v.pti_val;
771 /* Only support PAGE_SIZE tc. */
772 r10 = PAGE_SIZE;
773 status = PAL_STATUS_SUCCESS;
774 }
775 else if (in1 == 1 && (in2 == 1 || in2 == 2)) {
776 /* Level 2: itlb/dtlb, 1 entry. */
777 const pal_tc_info_u_t v =
778 { .pal_tc_info_s = {.num_sets = 1,
779 .associativity = 1,
780 .num_entries = 1,
781 .pf = 1,
782 .unified = 0,
783 .reduce_tr = 0,
784 .reserved = 0}};
785 r9 = v.pti_val;
786 /* Only support PAGE_SIZE tc. */
787 r10 = PAGE_SIZE;
788 status = PAL_STATUS_SUCCESS;
789 } else
790 status = PAL_STATUS_EINVAL;
791 break;
792 case PAL_RSE_INFO:
793 status = ia64_pal_rse_info(&r9, (pal_hints_u_t *)&r10);
794 break;
795 case PAL_REGISTER_INFO:
796 status = ia64_pal_register_info(in1, &r9, &r10);
797 break;
798 case PAL_CACHE_FLUSH:
799 if (in3 != 0) /* Initially progress_indicator must be 0 */
800 panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
801 "progress_indicator=%lx", in3);
803 /* Always call Host Pal in int=0 */
804 in2 &= ~PAL_CACHE_FLUSH_CHK_INTRS;
806 if (in1 != PAL_CACHE_TYPE_COHERENT) {
807 struct cache_flush_args args = {
808 .cache_type = in1,
809 .operation = in2,
810 .progress = 0,
811 .status = 0
812 };
813 smp_call_function(remote_pal_cache_flush,
814 (void *)&args, 1, 1);
815 if (args.status != 0)
816 panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
817 "remote status %lx", args.status);
818 }
820 /*
821 * Call Host PAL cache flush
822 * Clear psr.ic when call PAL_CACHE_FLUSH
823 */
824 r10 = in3;
825 local_irq_save(flags);
826 processor = current->processor;
827 status = ia64_pal_cache_flush(in1, in2, &r10, &r9);
828 local_irq_restore(flags);
830 if (status != 0)
831 panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
832 "status %lx", status);
834 if (in1 == PAL_CACHE_TYPE_COHERENT) {
835 cpus_setall(current->arch.cache_coherent_map);
836 cpu_clear(processor, current->arch.cache_coherent_map);
837 cpus_setall(cpu_cache_coherent_map);
838 cpu_clear(processor, cpu_cache_coherent_map);
839 }
840 break;
841 case PAL_PERF_MON_INFO:
842 {
843 unsigned long pm_buffer[16];
844 status = ia64_pal_perf_mon_info(
845 pm_buffer,
846 (pal_perf_mon_info_u_t *) &r9);
847 if (status != 0) {
848 printk("PAL_PERF_MON_INFO fails ret=%ld\n", status);
849 break;
850 }
851 if (safe_copy_to_guest(
852 in1, pm_buffer, sizeof(pm_buffer))) {
853 status = PAL_STATUS_EINVAL;
854 goto fail_to_copy;
855 }
856 }
857 break;
858 case PAL_CACHE_INFO:
859 {
860 pal_cache_config_info_t ci;
861 status = ia64_pal_cache_config_info(in1,in2,&ci);
862 if (status != 0)
863 break;
864 r9 = ci.pcci_info_1.pcci1_data;
865 r10 = ci.pcci_info_2.pcci2_data;
866 }
867 break;
868 case PAL_VM_TR_READ: /* FIXME: vcpu_get_tr?? */
869 printk("%s: PAL_VM_TR_READ unimplmented, ignored\n", __func__);
870 break;
871 case PAL_HALT_INFO:
872 {
873 /* 1000 cycles to enter/leave low power state,
874 consumes 10 mW, implemented and cache/TLB coherent. */
875 unsigned long res = 1000UL | (1000UL << 16) | (10UL << 32)
876 | (1UL << 61) | (1UL << 60);
877 if (safe_copy_to_guest (in1, &res, sizeof (res))) {
878 status = PAL_STATUS_EINVAL;
879 goto fail_to_copy;
880 }
881 status = PAL_STATUS_SUCCESS;
882 }
883 break;
884 case PAL_HALT:
885 set_bit(_VPF_down, &current->pause_flags);
886 vcpu_sleep_nosync(current);
887 status = PAL_STATUS_SUCCESS;
888 break;
889 case PAL_HALT_LIGHT:
890 if (VMX_DOMAIN(current)) {
891 /* Called by VTI. */
892 if (!is_unmasked_irq(current)) {
893 do_sched_op_compat(SCHEDOP_block, 0);
894 do_softirq();
895 }
896 status = PAL_STATUS_SUCCESS;
897 }
898 break;
899 case PAL_PLATFORM_ADDR:
900 if (VMX_DOMAIN(current))
901 status = PAL_STATUS_SUCCESS;
902 break;
903 case PAL_FIXED_ADDR:
904 status = PAL_STATUS_SUCCESS;
905 r9 = current->vcpu_id;
906 break;
907 case PAL_PREFETCH_VISIBILITY:
908 status = ia64_pal_prefetch_visibility(in1);
909 if (status == 0) {
910 /* must be performed on all remote processors
911 in the coherence domain. */
912 smp_call_function(remote_pal_prefetch_visibility,
913 (void *)in1, 1, 1);
914 status = 1; /* no more necessary on remote processor */
915 }
916 break;
917 case PAL_MC_DRAIN:
918 status = ia64_pal_mc_drain();
919 /* FIXME: All vcpus likely call PAL_MC_DRAIN.
920 That causes the congestion. */
921 smp_call_function(remote_pal_mc_drain, NULL, 1, 1);
922 break;
923 case PAL_BRAND_INFO:
924 if (in1 == 0) {
925 char brand_info[128];
926 status = ia64_pal_get_brand_info(brand_info);
927 if (status != PAL_STATUS_SUCCESS)
928 break;
929 if (safe_copy_to_guest(in2, brand_info,
930 sizeof(brand_info))) {
931 status = PAL_STATUS_EINVAL;
932 goto fail_to_copy;
933 }
934 } else {
935 status = PAL_STATUS_EINVAL;
936 }
937 break;
938 case PAL_LOGICAL_TO_PHYSICAL:
939 case PAL_GET_PSTATE:
940 case PAL_CACHE_SHARED_INFO:
941 /* Optional, no need to complain about being unimplemented */
942 break;
943 default:
944 printk("%s: Unimplemented PAL Call %lu\n", __func__, index);
945 break;
946 }
947 return ((struct ia64_pal_retval) {status, r9, r10, r11});
949 fail_to_copy:
950 gdprintk(XENLOG_WARNING,
951 "PAL(%ld) fail to copy!!! args 0x%lx 0x%lx 0x%lx\n",
952 index, in1, in2, in3);
953 return ((struct ia64_pal_retval) {status, r9, r10, r11});
954 }
956 // given a current domain (virtual or metaphysical) address, return the virtual address
957 static unsigned long
958 efi_translate_domain_addr(unsigned long domain_addr, IA64FAULT *fault,
959 struct page_info** page)
960 {
961 struct vcpu *v = current;
962 unsigned long mpaddr = domain_addr;
963 unsigned long virt;
964 *fault = IA64_NO_FAULT;
966 again:
967 if (v->domain->arch.sal_data->efi_virt_mode) {
968 *fault = vcpu_tpa(v, domain_addr, &mpaddr);
969 if (*fault != IA64_NO_FAULT) return 0;
970 }
972 virt = (unsigned long)domain_mpa_to_imva(v->domain, mpaddr);
973 *page = virt_to_page(virt);
974 if (get_page(*page, current->domain) == 0) {
975 if (page_get_owner(*page) != current->domain) {
976 // which code is appropriate?
977 *fault = IA64_FAULT;
978 return 0;
979 }
980 goto again;
981 }
983 return virt;
984 }
986 static efi_status_t
987 efi_emulate_get_time(
988 unsigned long tv_addr, unsigned long tc_addr,
989 IA64FAULT *fault)
990 {
991 unsigned long tv, tc = 0;
992 struct page_info *tv_page = NULL;
993 struct page_info *tc_page = NULL;
994 efi_status_t status = 0;
995 efi_time_t *tvp;
996 struct tm timeptr;
997 unsigned long xtimesec;
999 tv = efi_translate_domain_addr(tv_addr, fault, &tv_page);
1000 if (*fault != IA64_NO_FAULT)
1001 goto errout;
1002 if (tc_addr) {
1003 tc = efi_translate_domain_addr(tc_addr, fault, &tc_page);
1004 if (*fault != IA64_NO_FAULT)
1005 goto errout;
1008 spin_lock(&efi_time_services_lock);
1009 status = (*efi.get_time)((efi_time_t *) tv, (efi_time_cap_t *) tc);
1010 tvp = (efi_time_t *)tv;
1011 xtimesec = mktime(tvp->year, tvp->month, tvp->day, tvp->hour,
1012 tvp->minute, tvp->second);
1013 xtimesec += current->domain->time_offset_seconds;
1014 timeptr = gmtime(xtimesec);
1015 tvp->second = timeptr.tm_sec;
1016 tvp->minute = timeptr.tm_min;
1017 tvp->hour = timeptr.tm_hour;
1018 tvp->day = timeptr.tm_mday;
1019 tvp->month = timeptr.tm_mon + 1;
1020 tvp->year = timeptr.tm_year + 1900;
1021 spin_unlock(&efi_time_services_lock);
1023 errout:
1024 if (tc_page != NULL)
1025 put_page(tc_page);
1026 if (tv_page != NULL)
1027 put_page(tv_page);
1029 return status;
1032 static efi_status_t
1033 efi_emulate_set_time(
1034 unsigned long tv_addr, IA64FAULT *fault)
1036 unsigned long tv;
1037 struct page_info *tv_page = NULL;
1038 efi_status_t status = 0;
1040 if (current->domain != dom0)
1041 return EFI_UNSUPPORTED;
1043 tv = efi_translate_domain_addr(tv_addr, fault, &tv_page);
1044 if (*fault != IA64_NO_FAULT)
1045 goto errout;
1047 spin_lock(&efi_time_services_lock);
1048 status = (*efi.set_time)((efi_time_t *)tv);
1049 spin_unlock(&efi_time_services_lock);
1051 errout:
1052 if (tv_page != NULL)
1053 put_page(tv_page);
1055 return status;
1058 static efi_status_t
1059 efi_emulate_get_wakeup_time(
1060 unsigned long e_addr, unsigned long p_addr,
1061 unsigned long tv_addr, IA64FAULT *fault)
1063 unsigned long enabled, pending, tv;
1064 struct page_info *e_page = NULL, *p_page = NULL,
1065 *tv_page = NULL;
1066 efi_status_t status = 0;
1068 if (current->domain != dom0)
1069 return EFI_UNSUPPORTED;
1071 if (!e_addr || !p_addr || !tv_addr)
1072 return EFI_INVALID_PARAMETER;
1074 enabled = efi_translate_domain_addr(e_addr, fault, &e_page);
1075 if (*fault != IA64_NO_FAULT)
1076 goto errout;
1077 pending = efi_translate_domain_addr(p_addr, fault, &p_page);
1078 if (*fault != IA64_NO_FAULT)
1079 goto errout;
1080 tv = efi_translate_domain_addr(tv_addr, fault, &tv_page);
1081 if (*fault != IA64_NO_FAULT)
1082 goto errout;
1084 spin_lock(&efi_time_services_lock);
1085 status = (*efi.get_wakeup_time)((efi_bool_t *)enabled,
1086 (efi_bool_t *)pending,
1087 (efi_time_t *)tv);
1088 spin_unlock(&efi_time_services_lock);
1090 errout:
1091 if (e_page != NULL)
1092 put_page(e_page);
1093 if (p_page != NULL)
1094 put_page(p_page);
1095 if (tv_page != NULL)
1096 put_page(tv_page);
1098 return status;
1101 static efi_status_t
1102 efi_emulate_set_wakeup_time(
1103 unsigned long enabled, unsigned long tv_addr,
1104 IA64FAULT *fault)
1106 unsigned long tv = 0;
1107 struct page_info *tv_page = NULL;
1108 efi_status_t status = 0;
1110 if (current->domain != dom0)
1111 return EFI_UNSUPPORTED;
1113 if (tv_addr) {
1114 tv = efi_translate_domain_addr(tv_addr, fault, &tv_page);
1115 if (*fault != IA64_NO_FAULT)
1116 goto errout;
1119 spin_lock(&efi_time_services_lock);
1120 status = (*efi.set_wakeup_time)((efi_bool_t)enabled,
1121 (efi_time_t *)tv);
1122 spin_unlock(&efi_time_services_lock);
1124 errout:
1125 if (tv_page != NULL)
1126 put_page(tv_page);
1128 return status;
1131 static efi_status_t
1132 efi_emulate_get_variable(
1133 unsigned long name_addr, unsigned long vendor_addr,
1134 unsigned long attr_addr, unsigned long data_size_addr,
1135 unsigned long data_addr, IA64FAULT *fault)
1137 unsigned long name, vendor, attr = 0, data_size, data;
1138 struct page_info *name_page = NULL, *vendor_page = NULL,
1139 *attr_page = NULL, *data_size_page = NULL,
1140 *data_page = NULL;
1141 efi_status_t status = 0;
1143 if (current->domain != dom0)
1144 return EFI_UNSUPPORTED;
1146 name = efi_translate_domain_addr(name_addr, fault, &name_page);
1147 if (*fault != IA64_NO_FAULT)
1148 goto errout;
1149 vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page);
1150 if (*fault != IA64_NO_FAULT)
1151 goto errout;
1152 data_size = efi_translate_domain_addr(data_size_addr, fault,
1153 &data_size_page);
1154 if (*fault != IA64_NO_FAULT)
1155 goto errout;
1156 data = efi_translate_domain_addr(data_addr, fault, &data_page);
1157 if (*fault != IA64_NO_FAULT)
1158 goto errout;
1159 if (attr_addr) {
1160 attr = efi_translate_domain_addr(attr_addr, fault, &attr_page);
1161 if (*fault != IA64_NO_FAULT)
1162 goto errout;
1165 status = (*efi.get_variable)((efi_char16_t *)name,
1166 (efi_guid_t *)vendor,
1167 (u32 *)attr,
1168 (unsigned long *)data_size,
1169 (void *)data);
1171 errout:
1172 if (name_page != NULL)
1173 put_page(name_page);
1174 if (vendor_page != NULL)
1175 put_page(vendor_page);
1176 if (attr_page != NULL)
1177 put_page(attr_page);
1178 if (data_size_page != NULL)
1179 put_page(data_size_page);
1180 if (data_page != NULL)
1181 put_page(data_page);
1183 return status;
1186 static efi_status_t
1187 efi_emulate_get_next_variable(
1188 unsigned long name_size_addr, unsigned long name_addr,
1189 unsigned long vendor_addr, IA64FAULT *fault)
1191 unsigned long name_size, name, vendor;
1192 struct page_info *name_size_page = NULL, *name_page = NULL,
1193 *vendor_page = NULL;
1194 efi_status_t status = 0;
1196 if (current->domain != dom0)
1197 return EFI_UNSUPPORTED;
1199 name_size = efi_translate_domain_addr(name_size_addr, fault,
1200 &name_size_page);
1201 if (*fault != IA64_NO_FAULT)
1202 goto errout;
1203 name = efi_translate_domain_addr(name_addr, fault, &name_page);
1204 if (*fault != IA64_NO_FAULT)
1205 goto errout;
1206 vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page);
1207 if (*fault != IA64_NO_FAULT)
1208 goto errout;
1210 status = (*efi.get_next_variable)((unsigned long *)name_size,
1211 (efi_char16_t *)name,
1212 (efi_guid_t *)vendor);
1214 errout:
1215 if (name_size_page != NULL)
1216 put_page(name_size_page);
1217 if (name_page != NULL)
1218 put_page(name_page);
1219 if (vendor_page != NULL)
1220 put_page(vendor_page);
1222 return status;
1225 static efi_status_t
1226 efi_emulate_set_variable(
1227 unsigned long name_addr, unsigned long vendor_addr,
1228 unsigned long attr, unsigned long data_size,
1229 unsigned long data_addr, IA64FAULT *fault)
1231 unsigned long name, vendor, data;
1232 struct page_info *name_page = NULL, *vendor_page = NULL,
1233 *data_page = NULL;
1234 efi_status_t status = 0;
1236 if (current->domain != dom0)
1237 return EFI_UNSUPPORTED;
1239 name = efi_translate_domain_addr(name_addr, fault, &name_page);
1240 if (*fault != IA64_NO_FAULT)
1241 goto errout;
1242 vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page);
1243 if (*fault != IA64_NO_FAULT)
1244 goto errout;
1245 data = efi_translate_domain_addr(data_addr, fault, &data_page);
1246 if (*fault != IA64_NO_FAULT)
1247 goto errout;
1249 status = (*efi.set_variable)((efi_char16_t *)name,
1250 (efi_guid_t *)vendor,
1251 attr,
1252 data_size,
1253 (void *)data);
1255 errout:
1256 if (name_page != NULL)
1257 put_page(name_page);
1258 if (vendor_page != NULL)
1259 put_page(vendor_page);
1260 if (data_page != NULL)
1261 put_page(data_page);
1263 return status;
1266 static efi_status_t
1267 efi_emulate_set_virtual_address_map(
1268 unsigned long memory_map_size, unsigned long descriptor_size,
1269 u32 descriptor_version, efi_memory_desc_t *virtual_map)
1271 void *efi_map_start, *efi_map_end, *p;
1272 efi_memory_desc_t entry, *md = &entry;
1273 u64 efi_desc_size;
1275 unsigned long *vfn;
1276 struct domain *d = current->domain;
1277 efi_runtime_services_t *efi_runtime = d->arch.efi_runtime;
1278 fpswa_interface_t *fpswa_inf = d->arch.fpswa_inf;
1280 if (descriptor_version != EFI_MEMDESC_VERSION) {
1281 printk ("efi_emulate_set_virtual_address_map: memory "
1282 "descriptor version unmatched (%d vs %d)\n",
1283 (int)descriptor_version, EFI_MEMDESC_VERSION);
1284 return EFI_INVALID_PARAMETER;
1287 if (descriptor_size != sizeof(efi_memory_desc_t)) {
1288 printk ("efi_emulate_set_virtual_address_map: memory descriptor size unmatched\n");
1289 return EFI_INVALID_PARAMETER;
1292 if (d->arch.sal_data->efi_virt_mode)
1293 return EFI_UNSUPPORTED;
1295 efi_map_start = virtual_map;
1296 efi_map_end = efi_map_start + memory_map_size;
1297 efi_desc_size = sizeof(efi_memory_desc_t);
1299 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
1300 if (copy_from_user(&entry, p, sizeof(efi_memory_desc_t))) {
1301 printk ("efi_emulate_set_virtual_address_map: copy_from_user() fault. addr=0x%p\n", p);
1302 return EFI_UNSUPPORTED;
1305 /* skip over non-PAL_CODE memory descriptors; EFI_RUNTIME is included in PAL_CODE. */
1306 if (md->type != EFI_PAL_CODE)
1307 continue;
1309 #define EFI_HYPERCALL_PATCH_TO_VIRT(tgt,call) \
1310 do { \
1311 vfn = (unsigned long *) domain_mpa_to_imva(d, tgt); \
1312 *vfn++ = FW_HYPERCALL_##call##_INDEX * 16UL + md->virt_addr; \
1313 *vfn++ = 0; \
1314 } while (0)
1316 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_time,EFI_GET_TIME);
1317 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_time,EFI_SET_TIME);
1318 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_wakeup_time,EFI_GET_WAKEUP_TIME);
1319 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_wakeup_time,EFI_SET_WAKEUP_TIME);
1320 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_virtual_address_map,EFI_SET_VIRTUAL_ADDRESS_MAP);
1321 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_variable,EFI_GET_VARIABLE);
1322 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_variable,EFI_GET_NEXT_VARIABLE);
1323 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_variable,EFI_SET_VARIABLE);
1324 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_high_mono_count,EFI_GET_NEXT_HIGH_MONO_COUNT);
1325 EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->reset_system,EFI_RESET_SYSTEM);
1327 vfn = (unsigned long *) domain_mpa_to_imva(d, (unsigned long) fpswa_inf->fpswa);
1328 *vfn++ = FW_HYPERCALL_FPSWA_PATCH_INDEX * 16UL + md->virt_addr;
1329 *vfn = 0;
1330 fpswa_inf->fpswa = (void *) (FW_HYPERCALL_FPSWA_ENTRY_INDEX * 16UL + md->virt_addr);
1331 break;
1334 /* The virtual address map has been applied. */
1335 d->arch.sal_data->efi_virt_mode = 1;
1337 return EFI_SUCCESS;
1340 efi_status_t
1341 efi_emulator (struct pt_regs *regs, IA64FAULT *fault)
1343 struct vcpu *v = current;
1344 efi_status_t status;
1346 debugger_event(XEN_IA64_DEBUG_ON_EFI);
1348 *fault = IA64_NO_FAULT;
1350 switch (regs->r2) {
1351 case FW_HYPERCALL_EFI_RESET_SYSTEM:
1353 u8 reason;
1354 unsigned long val = vcpu_get_gr(v,32);
1355 switch (val)
1357 case EFI_RESET_SHUTDOWN:
1358 reason = SHUTDOWN_poweroff;
1359 break;
1360 case EFI_RESET_COLD:
1361 case EFI_RESET_WARM:
1362 default:
1363 reason = SHUTDOWN_reboot;
1364 break;
1366 domain_shutdown (current->domain, reason);
1368 status = EFI_UNSUPPORTED;
1369 break;
1370 case FW_HYPERCALL_EFI_GET_TIME:
1371 status = efi_emulate_get_time (
1372 vcpu_get_gr(v,32),
1373 vcpu_get_gr(v,33),
1374 fault);
1375 break;
1376 case FW_HYPERCALL_EFI_SET_TIME:
1377 status = efi_emulate_set_time (
1378 vcpu_get_gr(v,32),
1379 fault);
1380 break;
1381 case FW_HYPERCALL_EFI_GET_WAKEUP_TIME:
1382 status = efi_emulate_get_wakeup_time (
1383 vcpu_get_gr(v,32),
1384 vcpu_get_gr(v,33),
1385 vcpu_get_gr(v,34),
1386 fault);
1387 break;
1388 case FW_HYPERCALL_EFI_SET_WAKEUP_TIME:
1389 status = efi_emulate_set_wakeup_time (
1390 vcpu_get_gr(v,32),
1391 vcpu_get_gr(v,33),
1392 fault);
1393 break;
1394 case FW_HYPERCALL_EFI_GET_VARIABLE:
1395 status = efi_emulate_get_variable (
1396 vcpu_get_gr(v,32),
1397 vcpu_get_gr(v,33),
1398 vcpu_get_gr(v,34),
1399 vcpu_get_gr(v,35),
1400 vcpu_get_gr(v,36),
1401 fault);
1402 break;
1403 case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE:
1404 status = efi_emulate_get_next_variable (
1405 vcpu_get_gr(v,32),
1406 vcpu_get_gr(v,33),
1407 vcpu_get_gr(v,34),
1408 fault);
1409 break;
1410 case FW_HYPERCALL_EFI_SET_VARIABLE:
1411 status = efi_emulate_set_variable (
1412 vcpu_get_gr(v,32),
1413 vcpu_get_gr(v,33),
1414 vcpu_get_gr(v,34),
1415 vcpu_get_gr(v,35),
1416 vcpu_get_gr(v,36),
1417 fault);
1418 break;
1419 case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP:
1420 status = efi_emulate_set_virtual_address_map (
1421 vcpu_get_gr(v,32),
1422 vcpu_get_gr(v,33),
1423 (u32) vcpu_get_gr(v,34),
1424 (efi_memory_desc_t *) vcpu_get_gr(v,35));
1425 break;
1426 case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT:
1427 // FIXME: need fixes in efi.h from 2.6.9
1428 status = EFI_UNSUPPORTED;
1429 break;
1430 default:
1431 printk("unknown ia64 fw hypercall %lx\n", regs->r2);
1432 status = EFI_UNSUPPORTED;
1435 return status;
1438 void
1439 do_ssc(unsigned long ssc, struct pt_regs *regs)
1441 unsigned long arg0, arg1, arg2, arg3, retval;
1442 char buf[2];
1443 /**/ static int last_fd, last_count; // FIXME FIXME FIXME
1444 /**/ // BROKEN FOR MULTIPLE DOMAINS & SMP
1445 /**/ struct ssc_disk_stat { int fd; unsigned count;} *stat, last_stat;
1447 arg0 = vcpu_get_gr(current,32);
1448 switch(ssc) {
1449 case SSC_PUTCHAR:
1450 buf[0] = arg0;
1451 buf[1] = '\0';
1452 printk(buf);
1453 break;
1454 case SSC_GETCHAR:
1455 retval = ia64_ssc(0,0,0,0,ssc);
1456 vcpu_set_gr(current,8,retval,0);
1457 break;
1458 case SSC_WAIT_COMPLETION:
1459 if (arg0) { // metaphysical address
1461 arg0 = translate_domain_mpaddr(arg0, NULL);
1462 /**/ stat = (struct ssc_disk_stat *)__va(arg0);
1463 ///**/ if (stat->fd == last_fd) stat->count = last_count;
1464 /**/ stat->count = last_count;
1465 //if (last_count >= PAGE_SIZE) printk("ssc_wait: stat->fd=%d,last_fd=%d,last_count=%d\n",stat->fd,last_fd,last_count);
1466 ///**/ retval = ia64_ssc(arg0,0,0,0,ssc);
1467 /**/ retval = 0;
1469 else retval = -1L;
1470 vcpu_set_gr(current,8,retval,0);
1471 break;
1472 case SSC_OPEN:
1473 arg1 = vcpu_get_gr(current,33); // access rights
1474 if (!running_on_sim) {
1475 printk("SSC_OPEN, not implemented on hardware. (ignoring...)\n");
1476 arg0 = 0;
1478 if (arg0) { // metaphysical address
1479 arg0 = translate_domain_mpaddr(arg0, NULL);
1480 retval = ia64_ssc(arg0,arg1,0,0,ssc);
1482 else retval = -1L;
1483 vcpu_set_gr(current,8,retval,0);
1484 break;
1485 case SSC_WRITE:
1486 case SSC_READ:
1487 //if (ssc == SSC_WRITE) printk("DOING AN SSC_WRITE\n");
1488 arg1 = vcpu_get_gr(current,33);
1489 arg2 = vcpu_get_gr(current,34);
1490 arg3 = vcpu_get_gr(current,35);
1491 if (arg2) { // metaphysical address of descriptor
1492 struct ssc_disk_req *req;
1493 unsigned long mpaddr;
1494 long len;
1496 arg2 = translate_domain_mpaddr(arg2, NULL);
1497 req = (struct ssc_disk_req *) __va(arg2);
1498 req->len &= 0xffffffffL; // avoid strange bug
1499 len = req->len;
1500 /**/ last_fd = arg1;
1501 /**/ last_count = len;
1502 mpaddr = req->addr;
1503 //if (last_count >= PAGE_SIZE) printk("do_ssc: read fd=%d, addr=%p, len=%lx ",last_fd,mpaddr,len);
1504 retval = 0;
1505 if ((mpaddr & PAGE_MASK) != ((mpaddr+len-1) & PAGE_MASK)) {
1506 // do partial page first
1507 req->addr = translate_domain_mpaddr(mpaddr, NULL);
1508 req->len = PAGE_SIZE - (req->addr & ~PAGE_MASK);
1509 len -= req->len; mpaddr += req->len;
1510 retval = ia64_ssc(arg0,arg1,arg2,arg3,ssc);
1511 arg3 += req->len; // file offset
1512 /**/ last_stat.fd = last_fd;
1513 /**/ (void)ia64_ssc(__pa(&last_stat),0,0,0,SSC_WAIT_COMPLETION);
1514 //if (last_count >= PAGE_SIZE) printk("ssc(%p,%lx)[part]=%x ",req->addr,req->len,retval);
1516 if (retval >= 0) while (len > 0) {
1517 req->addr = translate_domain_mpaddr(mpaddr, NULL);
1518 req->len = (len > PAGE_SIZE) ? PAGE_SIZE : len;
1519 len -= PAGE_SIZE; mpaddr += PAGE_SIZE;
1520 retval = ia64_ssc(arg0,arg1,arg2,arg3,ssc);
1521 arg3 += req->len; // file offset
1522 // TEMP REMOVED AGAIN arg3 += req->len; // file offset
1523 /**/ last_stat.fd = last_fd;
1524 /**/ (void)ia64_ssc(__pa(&last_stat),0,0,0,SSC_WAIT_COMPLETION);
1525 //if (last_count >= PAGE_SIZE) printk("ssc(%p,%lx)=%x ",req->addr,req->len,retval);
1527 // set it back to the original value
1528 req->len = last_count;
1530 else retval = -1L;
1531 vcpu_set_gr(current,8,retval,0);
1532 //if (last_count >= PAGE_SIZE) printk("retval=%x\n",retval);
1533 break;
1534 case SSC_CONNECT_INTERRUPT:
1535 arg1 = vcpu_get_gr(current,33);
1536 arg2 = vcpu_get_gr(current,34);
1537 arg3 = vcpu_get_gr(current,35);
1538 if (!running_on_sim) {
1539 printk("SSC_CONNECT_INTERRUPT, not implemented on hardware. (ignoring...)\n");
1540 break;
1542 (void)ia64_ssc(arg0,arg1,arg2,arg3,ssc);
1543 break;
1544 case SSC_NETDEV_PROBE:
1545 vcpu_set_gr(current,8,-1L,0);
1546 break;
1547 default:
1548 panic_domain(regs,
1549 "%s: bad ssc code %lx, iip=0x%lx, b0=0x%lx\n",
1550 __func__, ssc, regs->cr_iip, regs->b0);
1551 break;
1553 vcpu_increment_iip(current);