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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
extern crate alloc;

use super::Context;
use crate::asm::smc;
use crate::rmi;
use crate::rmi::error::Error;
use crate::Monitor;

use alloc::boxed::Box;
use alloc::collections::btree_map::BTreeMap;
use alloc::collections::vec_deque::VecDeque;
use spin::mutex::Mutex;

pub type Handler = Box<dyn Fn(&[usize], &mut [usize], &Monitor) -> Result<(), Error>>;

pub struct Mainloop {
    pub queue: Mutex<VecDeque<Context>>, // TODO: we need a more realistic queue considering multi-core environments if needed
    pub on_event: BTreeMap<usize, Handler>,
}

impl Mainloop {
    pub fn new() -> Self {
        Self {
            queue: Mutex::new(VecDeque::new()),
            on_event: BTreeMap::new(),
        }
    }

    #[cfg(not(kani))]
    fn add_event_handlers(&mut self) {
        rmi::features::set_event_handler(self);
        rmi::gpt::set_event_handler(self);
        rmi::realm::set_event_handler(self);
        rmi::rec::set_event_handler(self);
        rmi::rtt::set_event_handler(self);
        rmi::version::set_event_handler(self);
    }
    #[cfg(kani)]
    fn add_event_handlers(&mut self) {
        #[cfg(feature = "mc_rmi_features")]
        rmi::features::set_event_handler(self);
        #[cfg(any(
            feature = "mc_rmi_granule_delegate",
            feature = "mc_rmi_granule_undelegate"
        ))]
        rmi::gpt::set_event_handler(self);
    }

    #[cfg(not(kani))]
    pub fn boot_complete(&mut self) {
        let mut ctx = Context::new(rmi::BOOT_COMPLETE);
        ctx.init_arg(&[rmi::BOOT_SUCCESS]);

        self.add_event_handlers();
        self.dispatch(ctx);
    }
    #[cfg(kani)]
    // DIFF: `symbolic` parameter is added to pass symbolic input
    pub fn boot_complete(&mut self, symbolic: [usize; 8]) {
        let mut ctx = Context::new(rmi::BOOT_COMPLETE);
        ctx.init_arg(&[rmi::BOOT_SUCCESS]);

        self.add_event_handlers();
        self.dispatch(ctx, symbolic);
    }

    #[cfg(not(kani))]
    pub fn dispatch(&self, ctx: Context) {
        let ret = smc(ctx.cmd(), ctx.arg_slice());
        let cmd = ret[0];

        rmi::constraint::validate(
            cmd,
            |arg_num, ret_num| {
                let mut ctx = Context::new(cmd);
                ctx.init_arg(&ret[1..arg_num]);
                ctx.resize_ret(ret_num);
                self.queue.lock().push_back(ctx);
            },
            || {
                let ctx = Context::new(rmi::NOT_SUPPORTED_YET);
                self.queue.lock().push_back(ctx);
            },
        );
    }
    #[cfg(kani)]
    // DIFF: `symbolic` parameter is added to pass symbolic input
    pub fn dispatch(&self, ctx: Context, symbolic: [usize; 8]) {
        let _ret = smc(ctx.cmd(), ctx.arg_slice());
        let ret = symbolic;
        let cmd = ret[0];

        rmi::constraint::validate(
            cmd,
            |arg_num, ret_num| {
                let mut ctx = Context::new(cmd);
                ctx.init_arg(&ret[1..arg_num]);
                ctx.resize_ret(ret_num);
                self.queue.lock().push_back(ctx);
            },
            || {
                let ctx = Context::new(rmi::NOT_SUPPORTED_YET);
                self.queue.lock().push_back(ctx);
            },
        );
    }

    #[cfg(not(kani))]
    pub fn run(&self, monitor: &Monitor) {
        loop {
            let mut ctx = self.queue.lock().pop_front().unwrap(); // TODO: remove unwrap here, by introducing a more realistic queue
            if self.on_event.is_empty() {
                panic!("There is no registered event handler.");
            }

            match self.on_event.get(&ctx.cmd) {
                Some(handler) => {
                    ctx.do_rmi(|arg, ret| handler(arg, ret, monitor));
                }
                None => {
                    error!("Not registered event: {:X}", ctx.cmd);
                    ctx.init_arg(&[rmi::RET_FAIL]);
                }
            };

            ctx.cmd = rmi::REQ_COMPLETE;
            self.dispatch(ctx);
        }
    }
    #[cfg(kani)]
    // DIFF: infinite loop is removed
    //       return value is added to track output
    pub fn run(&self, monitor: &Monitor) -> [usize; 5] {
        let mut ctx = self.queue.lock().pop_front().unwrap();

        if self.on_event.is_empty() {
            panic!("There is no registered event handler.");
        }

        match self.on_event.get(&ctx.cmd()) {
            Some(handler) => ctx.do_rmi(|arg, ret| handler(arg, ret, monitor)),
            None => {
                assert!(false);
                error!("Not registered event: {:X}", ctx.cmd());
                ctx.init_arg(&[rmi::RET_FAIL]);

                return [0; 5]; // this is a bogus statement to meet the return type
            }
        }
    }

    pub fn add_event_handler(&mut self, code: usize, handler: Handler) {
        self.on_event.insert(code, handler);
    }
}