    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

    //! SBI call wrappers

    use core::arch::asm;

    const SBI_CONSOLE_PUTCHAR: usize = 1;
    const SBI_SHUTDOWN: usize = 8;
    // const SBI_SET_TIMER: usize = 0;
    // const SBI_CONSOLE_GETCHAR: usize = 2;
    // const SBI_CLEAR_IPI: usize = 3;
    // const SBI_SEND_IPI: usize = 4;
    // const SBI_REMOTE_FENCE_I: usize = 5;
    // const SBI_REMOTE_SFENCE_VMA: usize = 6;
    // const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7;

    ///  handle SBI call with `which` SBI_id and other arguments
    #[inline(always)]
    fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
        let mut ret;
        unsafe {
            asm!(
                "ecall",
                inlateout("x10") arg0 => ret,
                in("x11") arg1,
                in("x12") arg2,
                in("x17") which,
            );
        }
        ret
    }

    /// use sbi call to putchar in console (qemu uart handler)
    pub fn console_putchar(c: usize) {
        sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0);
    }

    /// use sbi call to getchar from console (qemu uart handler)
    // pub fn console_getchar() -> usize {
    //     sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0)
    // }

    /// use sbi call to shutdown the kernel
    pub fn shutdown() -> ! {
        sbi_call(SBI_SHUTDOWN, 0, 0, 0);
        panic!("It should shutdown!");
    }