]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/privilege.c
Update RISCC-V-RV32-SiFive_HiFive1_FreedomStudio project to latest tools and metal...
[freertos] / FreeRTOS / Demo / RISC-V_RV32_SiFive_HiFive1_FreedomStudio / freedom-metal / src / privilege.c
1 /* Copyright 2019 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
3
4 #include <stddef.h>
5
6 #include <metal/privilege.h>
7
8 #define METAL_MSTATUS_MIE_OFFSET        3
9 #define METAL_MSTATUS_MPIE_OFFSET       7
10 #define METAL_MSTATUS_SIE_OFFSET        1
11 #define METAL_MSTATUS_SPIE_OFFSET       5
12 #define METAL_MSTATUS_UIE_OFFSET        0
13 #define METAL_MSTATUS_UPIE_OFFSET       4
14
15 #define METAL_MSTATUS_MPP_OFFSET        11
16 #define METAL_MSTATUS_MPP_MASK          3
17
18 void metal_privilege_drop_to_mode(enum metal_privilege_mode mode,
19                                   struct metal_register_file regfile,
20                                   metal_privilege_entry_point_t entry_point)
21 {
22         uintptr_t mstatus;
23         __asm__ volatile("csrr %0, mstatus" : "=r" (mstatus));
24
25         /* Set xPIE bits based on current xIE bits */
26         if(mstatus && (1 << METAL_MSTATUS_MIE_OFFSET)) {
27                 mstatus |= (1 << METAL_MSTATUS_MPIE_OFFSET);
28         } else {
29                 mstatus &= ~(1 << METAL_MSTATUS_MPIE_OFFSET);
30         }
31         if(mstatus && (1 << METAL_MSTATUS_SIE_OFFSET)) {
32                 mstatus |= (1 << METAL_MSTATUS_SPIE_OFFSET);
33         } else {
34                 mstatus &= ~(1 << METAL_MSTATUS_SPIE_OFFSET);
35         }
36         if(mstatus && (1 << METAL_MSTATUS_UIE_OFFSET)) {
37                 mstatus |= (1 << METAL_MSTATUS_UPIE_OFFSET);
38         } else {
39                 mstatus &= ~(1 << METAL_MSTATUS_UPIE_OFFSET);
40         }
41
42         /* Set MPP to the requested privilege mode */
43         mstatus &= ~(METAL_MSTATUS_MPP_MASK << METAL_MSTATUS_MPP_OFFSET);
44         mstatus |= (mode << METAL_MSTATUS_MPP_OFFSET);
45
46         __asm__ volatile("csrw mstatus, %0" :: "r" (mstatus));
47
48         /* Set the entry point in MEPC */
49         __asm__ volatile("csrw mepc, %0" :: "r" (entry_point));
50
51         /* Set the register file */
52         __asm__ volatile("mv ra, %0" :: "r" (regfile.ra));
53         __asm__ volatile("mv sp, %0" :: "r" (regfile.sp));
54
55         __asm__ volatile("mret");
56 }
57