direct-io.hg

view xen/common/multicall.c @ 5517:10e9028c8e3d

bitkeeper revision 1.1718.1.10 (42b7b19aqOS_1M8I4pIOFjiTPYWV-g)

Merge bk://xenbits.xensource.com/xen-unstable.bk
into spot.cl.cam.ac.uk:C:/Documents and Settings/iap10/xen-unstable.bk
author iap10@spot.cl.cam.ac.uk
date Tue Jun 21 06:20:10 2005 +0000 (2005-06-21)
parents b51e4b4608f9
children 37e9c9cd6c14 dfaf788ab18c b2f4823b6ff0
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/perfc.h>
10 #include <xen/sched.h>
11 #include <xen/event.h>
12 #include <xen/multicall.h>
13 #include <asm/current.h>
14 #include <asm/hardirq.h>
16 struct mc_state mc_state[NR_CPUS];
18 long do_multicall(multicall_entry_t *call_list, unsigned int nr_calls)
19 {
20 struct mc_state *mcs = &mc_state[smp_processor_id()];
21 unsigned int i;
23 if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
24 {
25 DPRINTK("Multicall reentry is disallowed.\n");
26 return -EINVAL;
27 }
29 if ( unlikely(!array_access_ok(call_list, nr_calls, sizeof(*call_list))) )
30 {
31 DPRINTK("Bad memory range %p for %u*%u bytes.\n",
32 call_list, nr_calls, (unsigned int)sizeof(*call_list));
33 goto fault;
34 }
36 for ( i = 0; i < nr_calls; i++ )
37 {
38 if ( unlikely(__copy_from_user(&mcs->call, &call_list[i],
39 sizeof(*call_list))) )
40 {
41 DPRINTK("Error copying from user range %p for %u bytes.\n",
42 &call_list[i], (unsigned int)sizeof(*call_list));
43 goto fault;
44 }
46 do_multicall_call(&mcs->call);
48 if ( unlikely(__put_user(mcs->call.result, &call_list[i].result)) )
49 {
50 DPRINTK("Error writing result back to multicall block.\n");
51 goto fault;
52 }
54 if ( hypercall_preempt_check() )
55 {
56 /*
57 * Copy the sub-call continuation if it was preempted.
58 * Otherwise skip over the sub-call entirely.
59 */
60 if ( !test_bit(_MCSF_call_preempted, &mcs->flags) )
61 i++;
62 else
63 (void)__copy_to_user(&call_list[i], &mcs->call,
64 sizeof(*call_list));
66 /* Only create a continuation if there is work left to be done. */
67 if ( i < nr_calls )
68 {
69 mcs->flags = 0;
70 return hypercall2_create_continuation(
71 __HYPERVISOR_multicall, &call_list[i], nr_calls-i);
72 }
73 }
74 }
76 mcs->flags = 0;
77 return 0;
79 fault:
80 mcs->flags = 0;
81 return -EFAULT;
82 }
84 /*
85 * Local variables:
86 * mode: C
87 * c-set-style: "BSD"
88 * c-basic-offset: 4
89 * tab-width: 4
90 * indent-tabs-mode: nil
91 * End:
92 */