/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 | | */ |