source: trunk/packages/xen-3.1/xen-3.1/xen/common/multicall.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 2.3 KB
Line 
1/******************************************************************************
2 * multicall.c
3 */
4
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 <xen/perfc.h>
14#include <asm/current.h>
15#include <asm/hardirq.h>
16
17#ifndef COMPAT
18DEFINE_PER_CPU(struct mc_state, mc_state);
19typedef long ret_t;
20#endif
21
22ret_t
23do_multicall(
24    XEN_GUEST_HANDLE(multicall_entry_t) call_list, unsigned int nr_calls)
25{
26    struct mc_state *mcs = &this_cpu(mc_state);
27    unsigned int     i;
28
29    if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
30    {
31        gdprintk(XENLOG_INFO, "Multicall reentry is disallowed.\n");
32        return -EINVAL;
33    }
34
35    if ( unlikely(!guest_handle_okay(call_list, nr_calls)) )
36        goto fault;
37
38    for ( i = 0; i < nr_calls; i++ )
39    {
40        if ( hypercall_preempt_check() )
41            goto preempted;
42
43        if ( unlikely(__copy_from_guest(&mcs->call, call_list, 1)) )
44            goto fault;
45
46        do_multicall_call(&mcs->call);
47
48#ifndef NDEBUG
49        {
50            /*
51             * Deliberately corrupt the contents of the multicall structure.
52             * The caller must depend only on the 'result' field on return.
53             */
54            struct multicall_entry corrupt;
55            memset(&corrupt, 0xAA, sizeof(corrupt));
56            (void)__copy_to_guest(call_list, &corrupt, 1);
57        }
58#endif
59
60        if ( unlikely(__copy_field_to_guest(call_list, &mcs->call, result)) )
61            goto fault;
62
63        if ( test_bit(_MCSF_call_preempted, &mcs->flags) )
64        {
65            /* Copy the sub-call continuation. */
66            (void)__copy_to_guest(call_list, &mcs->call, 1);
67            goto preempted;
68        }
69
70        guest_handle_add_offset(call_list, 1);
71    }
72
73    perfc_incr(calls_to_multicall);
74    perfc_add(calls_from_multicall, nr_calls);
75    mcs->flags = 0;
76    return 0;
77
78 fault:
79    perfc_incr(calls_to_multicall);
80    mcs->flags = 0;
81    return -EFAULT;
82
83 preempted:
84    perfc_add(calls_from_multicall, i);
85    mcs->flags = 0;
86    return hypercall_create_continuation(
87        __HYPERVISOR_multicall, "hi", call_list, nr_calls-i);
88}
89
90/*
91 * Local variables:
92 * mode: C
93 * c-set-style: "BSD"
94 * c-basic-offset: 4
95 * tab-width: 4
96 * indent-tabs-mode: nil
97 * End:
98 */
Note: See TracBrowser for help on using the repository browser.