khypervisor  v1
lpae.c
Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines