khypervisor
v1
|
00001 #include "lpae.h" 00002 00003 #include <log/print.h> 00004 #include <log/uart_print.h> 00005 00006 /* Long-descriptor translation table format */ 00007 #define TTBL_L1_OUTADDR_MASK 0x000000FFEC000000ULL 00008 #define TTBL_L2_OUTADDR_MASK 0x000000FFFFE00000ULL 00009 #define TTBL_L3_OUTADDR_MASK 0x000000FFFFFFF000ULL 00010 00011 #define TTBL_L1_TABADDR_MASK 0x000000FFFFFFF000ULL 00012 #define TTBL_L2_TABADDR_MASK 0x000000FFFFFFF000ULL 00013 00014 /* Level 2 Block, 2MB, entry in LPAE Descriptor format for the given physical address */ 00015 lpaed_t hvmm_mm_lpaed_l2_block( uint64_t pa, lpaed_stage2_memattr_t mattr ) 00016 { 00017 /* lpae.c */ 00018 lpaed_t lpaed; 00019 00020 // Valid Block Entry 00021 lpaed.pt.valid = 1; 00022 lpaed.pt.table = 0; 00023 00024 lpaed.bits &= ~TTBL_L2_OUTADDR_MASK; 00025 lpaed.bits |= pa & TTBL_L2_OUTADDR_MASK; 00026 lpaed.p2m.sbz3 = 0; 00027 00028 // Lower block attributes 00029 lpaed.p2m.mattr = mattr & 0x0F; 00030 lpaed.p2m.read = 1; // Read/Write 00031 lpaed.p2m.write = 1; 00032 lpaed.p2m.sh = 0; // Non-shareable 00033 lpaed.p2m.af = 1; // Access Flag set to 1? 00034 lpaed.p2m.sbz4 = 0; 00035 00036 // Upper block attributes 00037 lpaed.p2m.hint = 0; 00038 lpaed.p2m.sbz2 = 0; 00039 lpaed.p2m.xn = 0; // eXecute Never = 0 00040 00041 lpaed.p2m.sbz1 = 0; 00042 00043 return lpaed; 00044 } 00045 00046 /* Level 1 Block, 1GB, entry in LPAE Descriptor format for the given physical address */ 00047 lpaed_t hvmm_mm_lpaed_l1_block( uint64_t pa, uint8_t attr_idx ) 00048 { 00049 /* lpae.c */ 00050 lpaed_t lpaed; 00051 00052 printh( "[mm] hvmm_mm_lpaed_l1_block:\n\r" ); 00053 printh( " pa:"); uart_print_hex64(pa); printh("\n\r"); 00054 printh( " attr_idx:"); uart_print_hex32((uint32_t) attr_idx); printh("\n\r"); 00055 00056 // Valid Block Entry 00057 lpaed.pt.valid = 1; 00058 lpaed.pt.table = 0; 00059 00060 lpaed.bits &= ~TTBL_L1_OUTADDR_MASK; 00061 lpaed.bits |= pa & TTBL_L1_OUTADDR_MASK; 00062 lpaed.pt.sbz = 0; 00063 00064 // Lower block attributes 00065 lpaed.pt.ai = attr_idx; 00066 lpaed.pt.ns = 1; // Allow Non-secure access 00067 lpaed.pt.user = 1; 00068 lpaed.pt.ro = 0; 00069 lpaed.pt.sh = 2; // Outher Shareable 00070 lpaed.pt.af = 1; // Access Flag set to 1? 00071 lpaed.pt.ng = 1; 00072 00073 // Upper block attributes 00074 lpaed.pt.hint = 0; 00075 lpaed.pt.pxn = 0; 00076 lpaed.pt.xn = 0; // eXecute Never = 0 00077 return lpaed; 00078 } 00079 00080 00081 void lpaed_stage2_conf_l1_table( lpaed_t *ttbl1, uint64_t baddr, uint8_t valid ) 00082 { 00083 ttbl1->pt.valid = valid ? 1 : 0; 00084 ttbl1->pt.table = valid ? 1 : 0; 00085 ttbl1->bits &= ~TTBL_L1_TABADDR_MASK; 00086 ttbl1->bits |= baddr & TTBL_L1_TABADDR_MASK; 00087 } 00088 00089 void lpaed_stage2_conf_l2_table( lpaed_t *ttbl2, uint64_t baddr, uint8_t valid ) 00090 { 00091 ttbl2->pt.valid = valid ? 1 : 0; 00092 ttbl2->pt.table = valid ? 1 : 0; 00093 ttbl2->bits &= ~TTBL_L2_TABADDR_MASK; 00094 ttbl2->bits |= baddr & TTBL_L2_TABADDR_MASK; 00095 } 00096 00097 void lpaed_stage2_enable_l2_table( lpaed_t *ttbl2 ) 00098 { 00099 ttbl2->pt.valid = 1; 00100 ttbl2->pt.table = 1; 00101 } 00102 void lpaed_stage2_disable_l2_table( lpaed_t *ttbl2 ) 00103 { 00104 ttbl2->pt.valid = 0; 00105 } 00106 00107 void lpaed_stage2_map_page( lpaed_t *pte, uint64_t pa, lpaed_stage2_memattr_t mattr ) 00108 { 00109 00110 pte->pt.valid = 1; 00111 pte->pt.table = 1; 00112 00113 pte->bits &= ~TTBL_L3_OUTADDR_MASK; 00114 pte->bits |= pa & TTBL_L3_OUTADDR_MASK; 00115 pte->p2m.sbz3 = 0; 00116 00117 // Lower block attributes 00118 pte->p2m.mattr = mattr & 0x0F; 00119 pte->p2m.read = 1; // Read/Write 00120 pte->p2m.write = 1; 00121 pte->p2m.sh = 0; // Non-shareable 00122 pte->p2m.af = 1; // Access Flag set to 1? 00123 pte->p2m.sbz4 = 0; 00124 00125 // Upper block attributes 00126 pte->p2m.hint = 0; 00127 pte->p2m.sbz2 = 0; 00128 pte->p2m.xn = 0; // eXecute Never = 0 00129 00130 pte->p2m.sbz1 = 0; 00131 } 00132 00133 /* Level 1 Table, 1GB, each entry refer level2 page table */ 00134 lpaed_t hvmm_mm_lpaed_l1_table( uint64_t pa ) 00135 { 00136 lpaed_t lpaed; 00137 00138 // Valid Table Entry 00139 lpaed.pt.valid = 1; 00140 lpaed.pt.table = 1; 00141 00142 // Next-level table address [39:12] 00143 lpaed.bits &= ~TTBL_L1_TABADDR_MASK; 00144 lpaed.bits |= pa & TTBL_L1_TABADDR_MASK; 00145 00146 // UNK/SBZP [51:40] 00147 lpaed.pt.sbz = 0; 00148 00149 lpaed.pt.pxnt = 0; // PXN limit for subsequent levels of lookup 00150 lpaed.pt.xnt = 0; // XN limit for subsequent levels of lookup 00151 lpaed.pt.apt = 0; // Access permissions limit for subsequent levels of lookup 00152 lpaed.pt.nst = 1; // Table address is in the Non-secure physical address space 00153 00154 return lpaed; 00155 } 00156 00157 /* Level 2 Table, 2MB, each entry refer level3 page table.*/ 00158 lpaed_t hvmm_mm_lpaed_l2_table( uint64_t pa ) 00159 { 00160 lpaed_t lpaed; 00161 00162 // Valid Table Entry 00163 lpaed.pt.valid = 1; 00164 lpaed.pt.table = 1; 00165 00166 // Next-level table address [39:12] 00167 lpaed.bits &= ~TTBL_L2_TABADDR_MASK; 00168 lpaed.bits |= pa & TTBL_L2_TABADDR_MASK; 00169 00170 // UNK/SBZP [51:40] 00171 lpaed.pt.sbz = 0; 00172 00173 lpaed.pt.pxnt = 0; // PXN limit for subsequent levels of lookup 00174 lpaed.pt.xnt = 0; // XN limit for subsequent levels of lookup 00175 lpaed.pt.apt = 0; // Access permissions limit for subsequent levels of lookup 00176 lpaed.pt.nst = 1; // Table address is in the Non-secure physical address space 00177 00178 return lpaed; 00179 } 00180 00181 /* Level 3 Table, each entry refer 4KB physical address */ 00182 lpaed_t hvmm_mm_lpaed_l3_table( uint64_t pa, uint8_t attr_idx, uint8_t valid ) 00183 { 00184 lpaed_t lpaed; 00185 00186 // Valid Table Entry 00187 lpaed.pt.valid = valid; 00188 lpaed.pt.table = 1; 00189 00190 // 4KB physical address [39:12] 00191 lpaed.bits &= ~TTBL_L3_OUTADDR_MASK; 00192 lpaed.bits |= pa & TTBL_L3_OUTADDR_MASK; 00193 00194 // UNK/SBZP [51:40] 00195 lpaed.pt.sbz = 0; 00196 00197 //Lower page attributes 00198 lpaed.pt.ai = attr_idx; 00199 lpaed.pt.ns = 1; // Allow Non-secure access 00200 lpaed.pt.user = 1; 00201 lpaed.pt.ro = 0; 00202 lpaed.pt.sh = 2; // Outher Shareable 00203 lpaed.pt.af = 1; // Access Flag set to 1? 00204 lpaed.pt.ng = 1; 00205 00206 // Upper page attributes 00207 lpaed.pt.hint = 0; 00208 lpaed.pt.pxn = 0; 00209 lpaed.pt.xn = 0; // eXecute Never = 0 00210 00211 return lpaed; 00212 } 00213 00214 void lpaed_stage1_conf_l3_table( lpaed_t *ttbl3, uint64_t baddr, uint8_t valid ) 00215 { 00216 ttbl3->pt.valid = valid ? 1 : 0; 00217 ttbl3->bits &= ~TTBL_L3_OUTADDR_MASK; 00218 ttbl3->bits |= baddr & TTBL_L3_OUTADDR_MASK; 00219 } 00220 00221 void lpaed_stage1_disable_l3_table( lpaed_t *ttbl3 ) 00222 { 00223 ttbl3->pt.valid = 0; 00224 }