khypervisor
v1
|
00001 #ifndef __LPAE_H__ 00002 #define __LPAE_H__ 00003 #include <arch_types.h> 00004 00005 #define LPAE_PAGE_SHIFT 12 00006 #define LPAE_PAGE_SIZE (1<<LPAE_PAGE_SHIFT) 00007 #define LPAE_PAGE_MASK (0xFFF) 00008 00009 #define LPAE_BLOCK_L2_SHIFT 21 00010 #define LPAE_BLOCK_L2_SIZE (1<<LPAE_BLOCK_L2_SHIFT) 00011 #define LPAE_BLOCK_L2_MASK (0x1FFFFF) 00012 00013 /* 00014 * Attribute Indexes. 00015 * 00016 * These are valid in the AttrIndx[2:0] field of an LPAE stage 1 page 00017 * table entry. They are indexes into the bytes of the MAIR* 00018 * registers, as defined above. 00019 * 00020 */ 00021 #define ATTR_IDX_UNCACHED 0x0 00022 #define ATTR_IDX_BUFFERABLE 0x1 00023 #define ATTR_IDX_WRITETHROUGH 0x2 00024 #define ATTR_IDX_WRITEBACK 0x3 00025 #define ATTR_IDX_DEV_SHARED 0x4 00026 #define ATTR_IDX_WRITEALLOC 0x7 00027 #define ATTR_IDX_DEV_NONSHARED DEV_SHARED 00028 #define ATTR_IDX_DEV_WC BUFFERABLE 00029 #define ATTR_IDX_DEV_CACHED WRITEBACK 00030 00031 /****************************************************************************** 00032 * ARMv7-A LPAE pagetables: 3-level trie, mapping 40-bit input to 00033 * 40-bit output addresses. Tables at all levels have 512 64-bit entries 00034 * (i.e. are 4Kb long). 00035 * 00036 * The bit-shuffling that has the permission bits in branch nodes in a 00037 * different place from those in leaf nodes seems to be to allow linear 00038 * pagetable tricks. If we're not doing that then the set of permission 00039 * bits that's not in use in a given node type can be used as 00040 * extra software-defined bits. */ 00041 00042 typedef struct { 00043 /* These are used in all kinds of entry. */ 00044 unsigned long valid:1; /* Valid mapping */ 00045 unsigned long table:1; /* == 1 in 4k map entries too */ 00046 00047 /* These ten bits are only used in Block entries and are ignored 00048 * in Table entries. */ 00049 unsigned long ai:3; /* Attribute Index */ 00050 unsigned long ns:1; /* Not-Secure */ 00051 unsigned long user:1; /* User-visible */ 00052 unsigned long ro:1; /* Read-Only */ 00053 unsigned long sh:2; /* Shareability */ 00054 unsigned long af:1; /* Access Flag */ 00055 unsigned long ng:1; /* Not-Global */ 00056 00057 /* The base address must be appropriately aligned for Block entries */ 00058 unsigned long base:28; /* Base address of block or next table */ 00059 unsigned long sbz:12; /* Must be zero */ 00060 00061 /* These seven bits are only used in Block entries and are ignored 00062 * in Table entries. */ 00063 unsigned long hint:1; /* In a block of 16 contiguous entries */ 00064 unsigned long pxn:1; /* Privileged-XN */ 00065 unsigned long xn:1; /* eXecute-Never */ 00066 unsigned long avail:4; /* Ignored by hardware */ 00067 00068 /* These 5 bits are only used in Table entries and are ignored in 00069 * Block entries */ 00070 unsigned long pxnt:1; /* Privileged-XN */ 00071 unsigned long xnt:1; /* eXecute-Never */ 00072 unsigned long apt:2; /* Access Permissions */ 00073 unsigned long nst:1; /* Not-Secure */ 00074 } __attribute__((__packed__)) lpae_pt_t; 00075 00076 /* The p2m tables have almost the same layout, but some of the permission 00077 * and cache-control bits are laid out differently (or missing) */ 00078 typedef struct { 00079 /* These are used in all kinds of entry. */ 00080 unsigned long valid:1; /* Valid mapping */ 00081 unsigned long table:1; /* == 1 in 4k map entries too */ 00082 00083 /* These ten bits are only used in Block entries and are ignored 00084 * in Table entries. */ 00085 unsigned long mattr:4; /* Memory Attributes */ 00086 unsigned long read:1; /* Read access */ 00087 unsigned long write:1; /* Write access */ 00088 unsigned long sh:2; /* Shareability */ 00089 unsigned long af:1; /* Access Flag */ 00090 unsigned long sbz4:1; 00091 00092 /* The base address must be appropriately aligned for Block entries */ 00093 unsigned long base:28; /* Base address of block or next table */ 00094 unsigned long sbz3:12; 00095 00096 /* These seven bits are only used in Block entries and are ignored 00097 * in Table entries. */ 00098 unsigned long hint:1; /* In a block of 16 contiguous entries */ 00099 unsigned long sbz2:1; 00100 unsigned long xn:1; /* eXecute-Never */ 00101 unsigned long avail:4; /* Ignored by hardware */ 00102 00103 unsigned long sbz1:5; 00104 } __attribute__((__packed__)) lpae_p2m_t; 00105 00106 00107 /* 00108 * Walk is the common bits of p2m and pt entries which are needed to 00109 * simply walk the table (e.g. for debug). 00110 */ 00111 typedef struct { 00112 /* These are used in all kinds of entry. */ 00113 unsigned long valid:1; /* Valid mapping */ 00114 unsigned long table:1; /* == 1 in 4k map entries too */ 00115 00116 unsigned long pad2:10; 00117 00118 /* The base address must be appropriately aligned for Block entries */ 00119 unsigned long base:28; /* Base address of block or next table */ 00120 00121 unsigned long pad1:24; 00122 } __attribute__((__packed__)) lpae_walk_t; 00123 00124 typedef union { 00125 uint64_t bits; 00126 lpae_pt_t pt; 00127 lpae_p2m_t p2m; 00128 lpae_walk_t walk; 00129 } lpaed_t; 00130 00131 typedef enum { 00132 LPAED_STAGE2_MEMATTR_SO = 0x0, /* Strongly Ordered */ 00133 LPAED_STAGE2_MEMATTR_DM = 0x1, /* Device memory */ 00134 LPAED_STAGE2_MEMATTR_NORMAL_ONC = 0x4, /* Outer Non-cacheable */ 00135 LPAED_STAGE2_MEMATTR_NORMAL_OWT = 0x8, 00136 LPAED_STAGE2_MEMATTR_NORMAL_OWB = 0xC, 00137 LPAED_STAGE2_MEMATTR_NORMAL_INC = 0x1, 00138 LPAED_STAGE2_MEMATTR_NORMAL_IWT = 0x2, 00139 LPAED_STAGE2_MEMATTR_NORMAL_IWB = 0x3, 00140 } lpaed_stage2_memattr_t; 00141 00142 lpaed_t hvmm_mm_lpaed_l1_block( uint64_t pa, uint8_t attr_idx ); 00143 lpaed_t hvmm_mm_lpaed_l2_block( uint64_t pa, lpaed_stage2_memattr_t mattr ); 00144 lpaed_t hvmm_mm_lpaed_l1_table( uint64_t pa); 00145 lpaed_t hvmm_mm_lpaed_l2_table( uint64_t pa); 00146 lpaed_t hvmm_mm_lpaed_l3_table( uint64_t pa, uint8_t attr_idx, uint8_t valid ); 00147 void lpaed_stage1_conf_l3_table( lpaed_t *ttbl3, uint64_t baddr, uint8_t valid ); 00148 void lpaed_stage1_disable_l3_table( lpaed_t *ttbl2 ); 00149 void lpaed_stage2_map_page( lpaed_t *pte, uint64_t pa, lpaed_stage2_memattr_t mattr ); 00150 void lpaed_stage2_conf_l1_table( lpaed_t *ttbl1, uint64_t baddr, uint8_t valid ); 00151 void lpaed_stage2_conf_l2_table( lpaed_t *ttbl2, uint64_t baddr, uint8_t valid ); 00152 void lpaed_stage2_enable_l2_table( lpaed_t *ttbl2 ); 00153 void lpaed_stage2_disable_l2_table( lpaed_t *ttbl2 ); 00154 00155 #endif