ia64/xen-unstable

view xen/common/multicall.c @ 12390:e28beea6d228

[IA64] Fix time services of EFI emulation

This patch serializes the execution of following efi.runtimes.
- GetTime
- SetTime
- GetWakeTime
- SetWakeTime

Linux/ia64 uses similar spinlocks in the EFI RTC driver.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author awilliam@xenbuild.aw
date Fri Nov 10 12:03:19 2006 -0700 (2006-11-10)
parents 36679b74e24a
children c2a82e026497
line source
1 /******************************************************************************
2 * multicall.c
3 */
5 #include <xen/config.h>
6 #include <xen/types.h>
7 #include <xen/lib.h>
8 #include <xen/mm.h>
9 #include <xen/sched.h>
10 #include <xen/event.h>
11 #include <xen/multicall.h>
12 #include <xen/guest_access.h>
13 #include <asm/current.h>
14 #include <asm/hardirq.h>
16 DEFINE_PER_CPU(struct mc_state, mc_state);
18 long
19 do_multicall(
20 XEN_GUEST_HANDLE(multicall_entry_t) call_list, unsigned int nr_calls)
21 {
22 struct mc_state *mcs = &this_cpu(mc_state);
23 unsigned int i;
25 if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
26 {
27 gdprintk(XENLOG_INFO, "Multicall reentry is disallowed.\n");
28 return -EINVAL;
29 }
31 if ( unlikely(!guest_handle_okay(call_list, nr_calls)) )
32 goto fault;
34 for ( i = 0; i < nr_calls; i++ )
35 {
36 if ( hypercall_preempt_check() )
37 goto preempted;
39 if ( unlikely(__copy_from_guest(&mcs->call, call_list, 1)) )
40 goto fault;
42 do_multicall_call(&mcs->call);
44 #ifndef NDEBUG
45 {
46 /*
47 * Deliberately corrupt the contents of the multicall structure.
48 * The caller must depend only on the 'result' field on return.
49 */
50 struct multicall_entry corrupt;
51 memset(&corrupt, 0xAA, sizeof(corrupt));
52 (void)__copy_to_guest(call_list, &corrupt, 1);
53 }
54 #endif
56 if ( unlikely(__copy_field_to_guest(call_list, &mcs->call, result)) )
57 goto fault;
59 if ( test_bit(_MCSF_call_preempted, &mcs->flags) )
60 {
61 /* Copy the sub-call continuation. */
62 (void)__copy_to_guest(call_list, &mcs->call, 1);
63 goto preempted;
64 }
66 guest_handle_add_offset(call_list, 1);
67 }
69 mcs->flags = 0;
70 return 0;
72 fault:
73 mcs->flags = 0;
74 return -EFAULT;
76 preempted:
77 mcs->flags = 0;
78 return hypercall_create_continuation(
79 __HYPERVISOR_multicall, "hi", call_list, nr_calls-i);
80 }
82 /*
83 * Local variables:
84 * mode: C
85 * c-set-style: "BSD"
86 * c-basic-offset: 4
87 * tab-width: 4
88 * indent-tabs-mode: nil
89 * End:
90 */