Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/common/event_2l.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Event channel port operations.
3
 *
4
 * Copyright (c) 2003-2006, K A Fraser.
5
 *
6
 * This source code is licensed under the GNU General Public License,
7
 * Version 2 or later.  See the file COPYING for more details.
8
 */
9
10
#include <xen/init.h>
11
#include <xen/lib.h>
12
#include <xen/errno.h>
13
#include <xen/sched.h>
14
#include <xen/event.h>
15
16
static void evtchn_2l_set_pending(struct vcpu *v, struct evtchn *evtchn)
17
99.8k
{
18
99.8k
    struct domain *d = v->domain;
19
99.8k
    unsigned int port = evtchn->port;
20
99.8k
21
99.8k
    /*
22
99.8k
     * The following bit operations must happen in strict order.
23
99.8k
     * NB. On x86, the atomic bit operations also act as memory barriers.
24
99.8k
     * There is therefore sufficiently strict ordering for this architecture --
25
99.8k
     * others may require explicit memory barriers.
26
99.8k
     */
27
99.8k
28
99.8k
    if ( test_and_set_bit(port, &shared_info(d, evtchn_pending)) )
29
31
        return;
30
99.8k
31
99.7k
    if ( !test_bit        (port, &shared_info(d, evtchn_mask)) &&
32
99.8k
         !test_and_set_bit(port / BITS_PER_EVTCHN_WORD(d),
33
99.7k
                           &vcpu_info(v, evtchn_pending_sel)) )
34
99.7k
    {
35
99.7k
        vcpu_mark_events_pending(v);
36
99.7k
    }
37
99.7k
38
99.7k
    evtchn_check_pollers(d, port);
39
99.7k
}
40
41
static void evtchn_2l_clear_pending(struct domain *d, struct evtchn *evtchn)
42
0
{
43
0
    clear_bit(evtchn->port, &shared_info(d, evtchn_pending));
44
0
}
45
46
static void evtchn_2l_unmask(struct domain *d, struct evtchn *evtchn)
47
451
{
48
451
    struct vcpu *v = d->vcpu[evtchn->notify_vcpu_id];
49
451
    unsigned int port = evtchn->port;
50
451
51
451
    /*
52
451
     * These operations must happen in strict order. Based on
53
451
     * evtchn_2l_set_pending() above.
54
451
     */
55
451
    if ( test_and_clear_bit(port, &shared_info(d, evtchn_mask)) &&
56
315
         test_bit          (port, &shared_info(d, evtchn_pending)) &&
57
24
         !test_and_set_bit (port / BITS_PER_EVTCHN_WORD(d),
58
451
                            &vcpu_info(v, evtchn_pending_sel)) )
59
24
    {
60
24
        vcpu_mark_events_pending(v);
61
24
    }
62
451
}
63
64
static bool evtchn_2l_is_pending(const struct domain *d, evtchn_port_t port)
65
0
{
66
0
    unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
67
0
68
0
    ASSERT(port < max_ports);
69
0
    return port < max_ports && test_bit(port, &shared_info(d, evtchn_pending));
70
0
}
71
72
static bool evtchn_2l_is_masked(const struct domain *d, evtchn_port_t port)
73
0
{
74
0
    unsigned int max_ports = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
75
0
76
0
    ASSERT(port < max_ports);
77
0
    return port >= max_ports || test_bit(port, &shared_info(d, evtchn_mask));
78
0
}
79
80
static void evtchn_2l_print_state(struct domain *d,
81
                                  const struct evtchn *evtchn)
82
0
{
83
0
    struct vcpu *v = d->vcpu[evtchn->notify_vcpu_id];
84
0
85
0
    printk("%d", !!test_bit(evtchn->port / BITS_PER_EVTCHN_WORD(d),
86
0
                            &vcpu_info(v, evtchn_pending_sel)));
87
0
}
88
89
static const struct evtchn_port_ops evtchn_port_ops_2l =
90
{
91
    .set_pending   = evtchn_2l_set_pending,
92
    .clear_pending = evtchn_2l_clear_pending,
93
    .unmask        = evtchn_2l_unmask,
94
    .is_pending    = evtchn_2l_is_pending,
95
    .is_masked     = evtchn_2l_is_masked,
96
    .print_state   = evtchn_2l_print_state,
97
};
98
99
void evtchn_2l_init(struct domain *d)
100
1
{
101
1
    d->evtchn_port_ops = &evtchn_port_ops_2l;
102
1
    d->max_evtchns = BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d);
103
1
}
104
105
/*
106
 * Local variables:
107
 * mode: C
108
 * c-file-style: "BSD"
109
 * c-basic-offset: 4
110
 * tab-width: 4
111
 * indent-tabs-mode: nil
112
 * End:
113
 */