1 /* $NetBSD: pte.h,v 1.6 2011/06/30 00:52:59 matt Exp $ */ 2 /*- 3 * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects 8 * Agency and which was developed by Matt Thomas of 3am Software Foundry. 9 * 10 * This material is based upon work supported by the Defense Advanced Research 11 * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under 12 * Contract No. N66001-09-C-2073. 13 * Approved for Public Release, Distribution Unlimited 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #ifndef _POWERPC_BOOKE_PTE_H_ 38 #define _POWERPC_BOOKE_PTE_H_ 39 40 #ifndef _LOCORE 41 #ifndef __BSD_PT_ENTRY_T 42 #define __BSD_PT_ENTRY_T __uint32_t 43 typedef __BSD_PT_ENTRY_T pt_entry_t; 44 #endif 45 #endif 46 47 #include <powerpc/booke/spr.h> 48 49 /* 50 * The PTE format is software and must be translated into the various portions 51 * X W R are separted by single bits so that they can map to the MAS2 bits 52 * UX/UW/UR or SX/SW/SR by a mask and a shift. 53 */ 54 #define PTE_IO (PTE_I|PTE_G|PTE_xW|PTE_xR) 55 #define PTE_DEFAULT (PTE_M|PTE_xX|PTE_xW|PTE_xR) 56 #define PTE_MAS3_MASK (MAS3_RPN|MAS3_U2|MAS3_U0) 57 #define PTE_MAS2_MASK (MAS2_WIMGE) 58 #define PTE_RPN_MASK MAS3_RPN /* MAS3[RPN] */ 59 #define PTE_RWX_MASK (PTE_xX|PTE_xW|PTE_xR) 60 #define PTE_WIRED (MAS3_U0 << 2) /* page is wired (PTE only) */ 61 #define PTE_xX (MAS3_U0 << 1) /* MAS2[UX] | MAS2[SX] */ 62 #define PTE_UNSYNCED MAS3_U0 /* page needs isync */ 63 #define PTE_xW MAS3_U1 /* MAS2[UW] | MAS2[SW] */ 64 #define PTE_UNMODIFIED MAS3_U2 /* page is unmodified */ 65 #define PTE_xR MAS3_U3 /* MAS2[UR] | MAS2[SR] */ 66 #define PTE_RWX_SHIFT 6 67 #define PTE_UNUSED 0x00000020 68 #define PTE_WIMGE_MASK MAS2_WIMGE 69 #define PTE_WIG (PTE_W|PTE_I|PTE_G) 70 #define PTE_W MAS2_W /* Write-through */ 71 #define PTE_I MAS2_I /* cache-Inhibited */ 72 #define PTE_M MAS2_M /* Memory coherence */ 73 #define PTE_G MAS2_G /* Guarded */ 74 #define PTE_E MAS2_E /* [Little] Endian */ 75 76 #ifndef _LOCORE 77 #ifdef _KERNEL 78 79 static inline bool 80 pte_cached_p(pt_entry_t pt_entry) 81 { 82 return (pt_entry & PTE_I) == 0; 83 } 84 85 static inline bool 86 pte_modified_p(pt_entry_t pt_entry) 87 { 88 return (pt_entry & (PTE_UNMODIFIED|PTE_xW)) == PTE_xW; 89 } 90 91 static inline bool 92 pte_valid_p(pt_entry_t pt_entry) 93 { 94 return pt_entry != 0; 95 } 96 97 static inline bool 98 pte_exec_p(pt_entry_t pt_entry) 99 { 100 return (pt_entry & PTE_xX) != 0; 101 } 102 103 static inline bool 104 pte_deferred_exec_p(pt_entry_t pt_entry) 105 { 106 //return (pt_entry & (PTE_xX|PTE_UNSYNCED)) == (PTE_xX|PTE_UNSYNCED); 107 return (pt_entry & PTE_UNSYNCED) == PTE_UNSYNCED; 108 } 109 110 static inline bool 111 pte_wired_p(pt_entry_t pt_entry) 112 { 113 return (pt_entry & PTE_WIRED) != 0; 114 } 115 116 static inline pt_entry_t 117 pte_nv_entry(bool kernel) 118 { 119 return 0; 120 } 121 122 static inline paddr_t 123 pte_to_paddr(pt_entry_t pt_entry) 124 { 125 return (paddr_t)(pt_entry & PTE_RPN_MASK); 126 } 127 128 static inline pt_entry_t 129 pte_ionocached_bits(void) 130 { 131 return PTE_I|PTE_G; 132 } 133 134 static inline pt_entry_t 135 pte_iocached_bits(void) 136 { 137 return PTE_G; 138 } 139 140 static inline pt_entry_t 141 pte_nocached_bits(void) 142 { 143 return PTE_M|PTE_I; 144 } 145 146 static inline pt_entry_t 147 pte_cached_bits(void) 148 { 149 return PTE_M; 150 } 151 152 static inline pt_entry_t 153 pte_cached_change(pt_entry_t pt_entry, bool cached) 154 { 155 return (pt_entry & ~PTE_I) | (cached ? 0 : PTE_I); 156 } 157 158 static inline pt_entry_t 159 pte_wire_entry(pt_entry_t pt_entry) 160 { 161 return pt_entry | PTE_WIRED; 162 } 163 164 static inline pt_entry_t 165 pte_unwire_entry(pt_entry_t pt_entry) 166 { 167 return pt_entry & ~PTE_WIRED; 168 } 169 170 static inline pt_entry_t 171 pte_prot_nowrite(pt_entry_t pt_entry) 172 { 173 return pt_entry & ~(PTE_xW|PTE_UNMODIFIED); 174 } 175 176 static inline pt_entry_t 177 pte_prot_downgrade(pt_entry_t pt_entry, vm_prot_t newprot) 178 { 179 pt_entry &= ~(PTE_xW|PTE_UNMODIFIED); 180 if ((newprot & VM_PROT_EXECUTE) == 0) 181 pt_entry &= ~(PTE_xX|PTE_UNSYNCED); 182 return pt_entry; 183 } 184 185 static inline pt_entry_t 186 pte_prot_bits(struct vm_page_md *mdpg, vm_prot_t prot) 187 { 188 KASSERT(prot & VM_PROT_READ); 189 pt_entry_t pt_entry = PTE_xR; 190 if (prot & VM_PROT_EXECUTE) { 191 #if 0 192 pt_entry |= PTE_xX; 193 if (mdpg != NULL && !VM_PAGEMD_EXECPAGE_P(mdpg)) 194 pt_entry |= PTE_UNSYNCED; 195 #elif 1 196 if (mdpg != NULL && !VM_PAGEMD_EXECPAGE_P(mdpg)) 197 pt_entry |= PTE_UNSYNCED; 198 else 199 pt_entry |= PTE_xX; 200 #else 201 pt_entry |= PTE_UNSYNCED; 202 #endif 203 } 204 if (prot & VM_PROT_WRITE) { 205 pt_entry |= PTE_xW; 206 if (mdpg != NULL && !VM_PAGEMD_MODIFIED_P(mdpg)) 207 pt_entry |= PTE_UNMODIFIED; 208 } 209 return pt_entry; 210 } 211 212 static inline pt_entry_t 213 pte_flag_bits(struct vm_page_md *mdpg, int flags) 214 { 215 if (__predict_false(flags & PMAP_NOCACHE)) { 216 if (__predict_true(mdpg != NULL)) { 217 return pte_nocached_bits(); 218 } else { 219 return pte_ionocached_bits(); 220 } 221 } else { 222 if (__predict_false(mdpg != NULL)) { 223 return pte_cached_bits(); 224 } else { 225 return pte_iocached_bits(); 226 } 227 } 228 } 229 230 static inline pt_entry_t 231 pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot, 232 int flags, bool kernel) 233 { 234 pt_entry_t pt_entry = (pt_entry_t) pa & PTE_RPN_MASK; 235 236 pt_entry |= pte_flag_bits(mdpg, flags); 237 pt_entry |= pte_prot_bits(mdpg, prot); 238 239 return pt_entry; 240 } 241 242 static inline pt_entry_t 243 pte_make_kenter_pa(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot, 244 int flags) 245 { 246 pt_entry_t pt_entry = (pt_entry_t) pa & PTE_RPN_MASK; 247 248 pt_entry |= PTE_WIRED; 249 pt_entry |= pte_flag_bits(mdpg, flags); 250 pt_entry |= pte_prot_bits(NULL, prot); /* pretend unmanaged */ 251 252 return pt_entry; 253 } 254 #endif /* _KERNEL */ 255 #endif /* !_LOCORE */ 256 257 #endif /* !_POWERPC_BOOKE_PTE_H_ */ 258