1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use {
crate::{
hypercall,
platform::util::{init_events, synch_clear_bit, synch_set_bit},
println, SHARED_INFO,
},
xen_sys::{
__HYPERVISOR_event_channel_op, evtchn_bind_virq_t, evtchn_port_t, EVTCHNOP_bind_virq,
},
};
pub const NUM_EVENT_PORTS: usize = 1024;
pub static mut EVENT_ACTIONS: [EventAction; NUM_EVENT_PORTS] = [EventAction {
handler: DEFAULT_HANDLER,
data: 0,
count: 0,
}; NUM_EVENT_PORTS];
pub static DEFAULT_HANDLER: fn(evtchn_port_t, *mut u8, *mut u8) =
|port, _, _| log::warn!("received event on port {}", port);
#[derive(Clone, Copy, Debug)]
pub struct EventAction {
handler: fn(evtchn_port_t, *mut u8, *mut u8),
data: usize,
count: u32,
}
pub fn init() {
for i in 0..unsafe { EVENT_ACTIONS.len() as u32 } {
mask_event_channel(i);
}
init_events();
unsafe { *SHARED_INFO }.vcpu_info[0].evtchn_upcall_mask = 0;
}
pub fn do_event(port: evtchn_port_t) {
unsafe {
EVENT_ACTIONS[port as usize].count += 1;
(EVENT_ACTIONS[port as usize].handler)(port, core::ptr::null_mut(), core::ptr::null_mut())
}
}
pub fn bind_event_channel(
port: evtchn_port_t,
handler: fn(evtchn_port_t, *mut u8, *mut u8),
data: usize,
) {
let idx = port as usize;
if unsafe { EVENT_ACTIONS[idx].handler != DEFAULT_HANDLER } {
println!(
"Warning: handler for port {} already registered, replacing",
port,
);
}
unsafe {
EVENT_ACTIONS[idx].data = data;
EVENT_ACTIONS[idx].count = 0;
EVENT_ACTIONS[idx].handler = handler;
}
unmask_event_channel(port);
}
pub fn bind_virq(
virq: u32,
handler: fn(evtchn_port_t, *mut u8, *mut u8),
data: usize,
) -> evtchn_port_t {
let mut op = evtchn_bind_virq_t {
virq,
vcpu: 0,
port: 0,
};
event_channel_op(EVTCHNOP_bind_virq, &mut op as *mut _ as u64);
bind_event_channel(op.port, handler, data);
op.port
}
pub fn mask_event_channel(port: evtchn_port_t) {
unsafe { synch_set_bit(port.into(), &mut (*SHARED_INFO).evtchn_mask[0]) }
}
pub fn unmask_event_channel(port: evtchn_port_t) {
unsafe { synch_clear_bit(port.into(), &mut (*SHARED_INFO).evtchn_mask[0]) }
}
pub fn clear_event_channel(port: evtchn_port_t) {
unsafe { synch_clear_bit(port.into(), &mut (*SHARED_INFO).evtchn_pending[0]) }
}
pub fn event_channel_op(cmd: u32, op_ptr: u64) {
unsafe { hypercall!(__HYPERVISOR_event_channel_op, cmd, op_ptr) }
.expect("Event channel operation failed");
}