debuggers.hg

view xen/common/multicall.c @ 3726:88957a238191

bitkeeper revision 1.1159.1.544 (4207248crq3YxiyLWjUehtHv_Yd3tg)

Merge tempest.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xeno.bk
into tempest.cl.cam.ac.uk:/local/scratch/smh22/xen-unstable.bk
author smh22@tempest.cl.cam.ac.uk
date Mon Feb 07 08:19:24 2005 +0000 (2005-02-07)
parents d31d480dee1d 4294cfa9fad3
children f5f2757b3aa2
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
2 /******************************************************************************
3 * multicall.c
4 */
6 #include <xen/config.h>
7 #include <xen/types.h>
8 #include <xen/lib.h>
9 #include <xen/mm.h>
10 #include <xen/perfc.h>
11 #include <xen/sched.h>
12 #include <xen/event.h>
13 #include <xen/multicall.h>
15 struct mc_state mc_state[NR_CPUS];
17 long do_multicall(multicall_entry_t *call_list, unsigned int nr_calls)
18 {
19 struct mc_state *mcs = &mc_state[smp_processor_id()];
20 unsigned int i;
22 if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
23 {
24 DPRINTK("Multicall reentry is disallowed.\n");
25 return -EINVAL;
26 }
28 if ( unlikely(!array_access_ok(VERIFY_WRITE, call_list,
29 nr_calls, sizeof(*call_list))) )
30 {
31 DPRINTK("Bad memory range %p for %u*%u bytes.\n",
32 call_list, nr_calls, 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], sizeof(*call_list));
43 goto fault;
44 }
46 do_multicall_call(&mcs->call);
48 if ( unlikely(__put_user(mcs->call.args[5], &call_list[i].args[5])) )
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 hypercall_create_continuation(
71 __HYPERVISOR_multicall, 2, &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 }