1 /**
2 ******************************************************************************
3 * @file rv_Sv39.c
4 * @version V1.0
5 * @date
6 * @brief This file is the RISC-V arch c file
7 ******************************************************************************
8 * @attention
9 *
10 * <h2><center>© COPYRIGHT(c) 2021 Bouffalo Lab</center></h2>
11 *
12 * Redistribution and use in source and binary forms, with or without modification,
13 * are permitted provided that the following conditions are met:
14 * 1. Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * 3. Neither the name of Bouffalo Lab nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 ******************************************************************************
35 */
36
37 #include <stdint.h>
38 #include "rv_Sv39.h"
39
40 /** @addtogroup RISCV_ARCH_Driver
41 * @{
42 */
43
44 /** @addtogroup SV39
45 * @{
46 */
47
48 /* allocate 4KB page table buffer */
49 __attribute__((weak))
50 uint64_t *
RV_Sv39_alloc_PageTable_buf(void)51 RV_Sv39_alloc_PageTable_buf(void)
52 {
53 return NULL;
54 }
55
56 /** @defgroup SV39_Public_Functions
57 * @{
58 */
59
60 /******************************************************************************
61 * @brief OSD blend layer configuration
62 *
63 * @param cfg: point to the Page Table Entry.
64 * @param tlb_index: return the TLB index in use if MAP is created directly in TLB.
65 * @param ttb0: the root translation table in memory.
66 *
67 * @return Result of the operation.
68 *
69 *******************************************************************************/
70
RV_Sv39_Create_PageMapping(Sv39_PTE_cfg_t * cfg,uintptr_t * tlb_index,volatile uintptr_t * ttb0)71 int RV_Sv39_Create_PageMapping(Sv39_PTE_cfg_t *cfg, uintptr_t *tlb_index, volatile uintptr_t *ttb0)
72 {
73 uintptr_t smeh, smel, smcir;
74 uintptr_t t0;
75 volatile uint64_t *ttb1 = NULL;
76 volatile uint64_t *ttb2 = NULL;
77
78 if (Sv39_PTE_LOC_JTLB == cfg->where) {
79 t0 = cfg->va;
80 smeh = ((t0 >> 12) << SMEH_VPN_OFFSET) | cfg->size | cfg->asid;
81 __asm volatile("csrw smeh, %0"
82 :
83 : "r"(smeh)
84 : "memory");
85
86 t0 = cfg->pa;
87 smel = cfg->flags | ((t0 >> 12) << PTE_PPN_OFFSET);
88 __asm volatile("csrw smel, %0"
89 :
90 : "r"(smel)
91 : "memory");
92
93 if (cfg->tlb_entry >= SV39_JTLB_ENTRY_CNT) {
94 /* random write */
95 smcir = SMCIR_TLBWR;
96 } else {
97 RV_Sv39_Set_SMIR(cfg->tlb_entry);
98 smcir = SMCIR_TLBWI;
99 }
100
101 smcir |= cfg->asid;
102 RV_Sv39_Set_SMCIR(smcir);
103
104 RV_Sv39_Set_SMCIR(SMCIR_TLBP);
105 t0 = RV_Sv39_Get_SMIR();
106
107 *tlb_index = t0;
108
109 return (t0 & (SMCIR_PF | SMCIR_TF)) ? -1 : 0;
110 } else {
111 /* top level: 1GB */
112 t0 = SV39_VPN2(cfg->va);
113
114 if (!ttb0[t0]) {
115 /* no translation for this 1GB range */
116 if (Sv39_PAGESIZE_1GB == cfg->size) {
117 /* finish map for top level */
118 ttb0[t0] = (SV39_PA2PPN(cfg->pa) << PTE_PPN_OFFSET) |
119 (cfg->flags);
120 return 0;
121 } else {
122 ttb1 = RV_Sv39_alloc_PageTable_buf();
123
124 if (NULL == ttb1) {
125 return -1;
126 }
127
128 __COMPILE_BARRIER();
129 ttb0[t0] = (SV39_PA2PPN((uint64_t)ttb1) << PTE_PPN_OFFSET) |
130 PTE_D | PTE_A |
131 PTE_XWR_NEXT | PTE_V;
132 }
133 } else {
134 /* already mapped, get the next level table pointer */
135 ttb1 = (volatile uint64_t *)SV39_PTE2PA(ttb0[t0]);
136 }
137
138 /* second level: 2MB */
139 t0 = SV39_VPN1(cfg->va);
140
141 if (!ttb1[t0]) {
142 /* no translation for this 2MB range */
143 if (Sv39_PAGESIZE_2MB == cfg->size) {
144 ttb1[t0] = (SV39_PA2PPN(cfg->pa) << PTE_PPN_OFFSET) |
145 (cfg->flags);
146 return 0;
147 } else {
148 ttb2 = RV_Sv39_alloc_PageTable_buf();
149
150 if (NULL == ttb2) {
151 return -1;
152 }
153
154 ttb1[t0] = (SV39_PA2PPN((uint64_t)ttb2) << PTE_PPN_OFFSET) |
155 PTE_D | PTE_A |
156 PTE_XWR_NEXT | PTE_V;
157 }
158 } else {
159 ttb2 = (volatile uint64_t *)SV39_PTE2PA(ttb1[t0]);
160 }
161
162 /* third level: 4KB */
163 t0 = SV39_VPN0(cfg->va);
164 __COMPILE_BARRIER();
165 ttb2[t0] = (SV39_PA2PPN(cfg->pa) << PTE_PPN_OFFSET) |
166 (cfg->flags);
167 }
168
169 /* flush the D cache */
170
171 return 0;
172 }
173
174 /*@} end of group SV39_Public_Functions */
175
176 /*@} end of group SV39 */
177
178 /*@} end of group RISCV_ARCH_Driver */
179