Home | History | Annotate | Line # | Download | only in include
pte.h revision 1.1.22.2
      1  1.1.22.2    martin /* $NetBSD: pte.h,v 1.1.22.2 2020/04/08 14:07:50 martin Exp $ */
      2       1.1      matt /*-
      3       1.1      matt  * Copyright (c) 2014 The NetBSD Foundation, Inc.
      4       1.1      matt  * All rights reserved.
      5       1.1      matt  *
      6       1.1      matt  * This code is derived from software contributed to The NetBSD Foundation
      7       1.1      matt  * by Matt Thomas of 3am Software Foundry.
      8       1.1      matt  *
      9       1.1      matt  * Redistribution and use in source and binary forms, with or without
     10       1.1      matt  * modification, are permitted provided that the following conditions
     11       1.1      matt  * are met:
     12       1.1      matt  * 1. Redistributions of source code must retain the above copyright
     13       1.1      matt  *    notice, this list of conditions and the following disclaimer.
     14       1.1      matt  * 2. Redistributions in binary form must reproduce the above copyright
     15       1.1      matt  *    notice, this list of conditions and the following disclaimer in the
     16       1.1      matt  *    documentation and/or other materials provided with the distribution.
     17       1.1      matt  *
     18       1.1      matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     19       1.1      matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     20       1.1      matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     21       1.1      matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     22       1.1      matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23       1.1      matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24       1.1      matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25       1.1      matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26       1.1      matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27       1.1      matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28       1.1      matt  * POSSIBILITY OF SUCH DAMAGE.
     29       1.1      matt  */
     30       1.1      matt 
     31       1.1      matt #ifndef _RISCV_PTE_H_
     32       1.1      matt #define _RISCV_PTE_H_
     33       1.1      matt 
     34       1.1      matt //
     35       1.1      matt // RV32 page table entry (4 GB VA space)
     36       1.1      matt //   [31..22] = PPN[1]
     37       1.1      matt //   [21..12] = PPN[0]
     38       1.1      matt //   [11.. 9] = software
     39       1.1      matt //
     40       1.1      matt // RV64 page table entry (4 TB VA space)
     41       1.1      matt //   [64..43] = 0
     42       1.1      matt //   [42..33] = PPN[2]
     43       1.1      matt //   [32..23] = PPN[1]
     44       1.1      matt //   [22..13] = PPN[0]
     45       1.1      matt //   [12.. 9] = software
     46       1.1      matt //
     47       1.1      matt // Common to both:
     48       1.1      matt //   [8] = SX
     49       1.1      matt //   [7] = SW
     50       1.1      matt //   [6] = SR
     51       1.1      matt //   [5] = UX
     52       1.1      matt //   [4] = UW
     53       1.1      matt //   [3] = UR
     54       1.1      matt //   [2] = G
     55       1.1      matt //   [1] = T
     56       1.1      matt //   [0] = V
     57       1.1      matt //
     58       1.1      matt 
     59       1.1      matt #define NPTEPG		(1 + __BITS(9, 0))	// PTEs per Page
     60       1.1      matt #define NSEGPG		NPTEPG
     61       1.1      matt #define NPDEPG		NPTEPG
     62       1.1      matt #ifdef _LP64
     63       1.1      matt #define PTE_PPN		__BITS(63, 13)	// Physical Page Number
     64       1.1      matt #define	PTE_PPN0	__BITS(42, 33)	// 1K 8-byte SDEs / PAGE
     65       1.1      matt #define	PTE_PPN1	__BITS(32, 23)	// 1K 8-byte PDEs / PAGE
     66       1.1      matt #define	PTE_PPN2	__BITS(22, 13)	// 1K 8-byte PTEs / PAGE
     67       1.1      matt typedef __uint64_t pt_entry_t;
     68       1.1      matt typedef __uint64_t pd_entry_t;
     69       1.1      matt #define atomic_cas_pte	atomic_cas_64
     70       1.1      matt #define atomic_cas_pde	atomic_cas_64
     71       1.1      matt #else
     72       1.1      matt #define PTE_PPN		__BITS(31, 12)	// Physical Page Number
     73       1.1      matt #define	PTE_PPN0	__BITS(31, 22)	// 1K 4-byte PDEs / PAGE
     74       1.1      matt #define	PTE_PPN1	__BITS(21, 12)	// 1K 4-byte PTEs / PAGE
     75       1.1      matt typedef __uint32_t pt_entry_t;
     76       1.1      matt typedef __uint32_t pd_entry_t;
     77       1.1      matt #define atomic_cas_pte	atomic_cas_32
     78       1.1      matt #define atomic_cas_pde	atomic_cas_32
     79       1.1      matt #endif
     80       1.1      matt 
     81       1.1      matt // These only mean something to NetBSD
     82       1.1      matt #define	PTE_NX		__BIT(11)	// Unexecuted
     83       1.1      matt #define	PTE_NW		__BIT(10)	// Unmodified
     84       1.1      matt #define	PTE_WIRED	__BIT(9)	// Do Not Delete
     85       1.1      matt 
     86       1.1      matt // These are hardware defined bits
     87       1.1      matt #define	PTE_SX		__BIT(8)	// Supervisor eXecute
     88       1.1      matt #define	PTE_SW		__BIT(7)	// Supervisor Write
     89       1.1      matt #define	PTE_SR		__BIT(6)	// Supervisor Read
     90       1.1      matt #define	PTE_UX		__BIT(5)	// User eXecute
     91       1.1      matt #define	PTE_UW		__BIT(4)	// User Write
     92       1.1      matt #define	PTE_UR		__BIT(3)	// User Read
     93       1.1      matt #define	PTE_G		__BIT(2)	// Global
     94       1.1      matt #define	PTE_T		__BIT(1)	// "Transit" (non-leaf)
     95       1.1      matt #define	PTE_V		__BIT(0)	// Valid
     96       1.1      matt 
     97       1.1      matt static inline bool
     98       1.1      matt pte_valid_p(pt_entry_t pte)
     99       1.1      matt {
    100       1.1      matt 	return (pte & PTE_V) != 0;
    101       1.1      matt }
    102       1.1      matt 
    103       1.1      matt static inline bool
    104       1.1      matt pte_wired_p(pt_entry_t pte)
    105       1.1      matt {
    106       1.1      matt 	return (pte & PTE_WIRED) != 0;
    107       1.1      matt }
    108       1.1      matt 
    109       1.1      matt static inline bool
    110       1.1      matt pte_modified_p(pt_entry_t pte)
    111       1.1      matt {
    112       1.1      matt 	return (pte & PTE_NW) == 0 && (pte & (PTE_UW|PTE_SW)) != 0;
    113       1.1      matt }
    114       1.1      matt 
    115       1.1      matt static inline bool
    116       1.1      matt pte_cached_p(pt_entry_t pte)
    117       1.1      matt {
    118       1.1      matt 	return true;
    119       1.1      matt }
    120       1.1      matt 
    121       1.1      matt static inline bool
    122       1.1      matt pte_deferred_exec_p(pt_entry_t pte)
    123       1.1      matt {
    124       1.1      matt 	return (pte & PTE_NX) != 0;
    125       1.1      matt }
    126       1.1      matt 
    127       1.1      matt static inline pt_entry_t
    128       1.1      matt pte_wire_entry(pt_entry_t pte)
    129       1.1      matt {
    130       1.1      matt 	return pte | PTE_WIRED;
    131       1.1      matt }
    132  1.1.22.2    martin 
    133  1.1.22.2    martin static inline pt_entry_t
    134       1.1      matt pte_unwire_entry(pt_entry_t pte)
    135       1.1      matt {
    136       1.1      matt 	return pte & ~PTE_WIRED;
    137       1.1      matt }
    138       1.1      matt 
    139       1.1      matt static inline paddr_t
    140       1.1      matt pte_to_paddr(pt_entry_t pte)
    141       1.1      matt {
    142       1.1      matt 	return pte & ~PAGE_MASK;
    143       1.1      matt }
    144       1.1      matt 
    145       1.1      matt static inline pt_entry_t
    146       1.1      matt pte_nv_entry(bool kernel_p)
    147       1.1      matt {
    148       1.1      matt 	return kernel_p ? PTE_G : 0;
    149       1.1      matt }
    150       1.1      matt 
    151       1.1      matt static inline pt_entry_t
    152       1.1      matt pte_prot_nowrite(pt_entry_t pte)
    153       1.1      matt {
    154       1.1      matt 	return pte & ~(PTE_NW|PTE_SW|PTE_UW);
    155       1.1      matt }
    156       1.1      matt 
    157       1.1      matt static inline pt_entry_t
    158       1.1      matt pte_prot_downgrade(pt_entry_t pte, vm_prot_t newprot)
    159       1.1      matt {
    160       1.1      matt 	pte &= ~(PTE_NW|PTE_SW|PTE_UW);
    161       1.1      matt 	if ((newprot & VM_PROT_EXECUTE) == 0)
    162       1.1      matt 		pte &= ~(PTE_NX|PTE_SX|PTE_UX);
    163       1.1      matt 	return pte;
    164       1.1      matt }
    165       1.1      matt 
    166       1.1      matt static inline pt_entry_t
    167       1.1      matt pte_prot_bits(struct vm_page_md *mdpg, vm_prot_t prot, bool kernel_p)
    168       1.1      matt {
    169       1.1      matt 	KASSERT(prot & VM_PROT_READ);
    170       1.1      matt 	pt_entry_t pt_entry = PTE_SR | (kernel_p ? 0 : PTE_UR);
    171       1.1      matt 	if (prot & VM_PROT_EXECUTE) {
    172       1.1      matt 		if (mdpg != NULL && !VM_PAGEMD_EXECPAGE_P(mdpg))
    173       1.1      matt 			pt_entry |= PTE_NX;
    174       1.1      matt 		else
    175       1.1      matt 			pt_entry |= kernel_p ? PTE_SX : PTE_UX;
    176       1.1      matt 	}
    177       1.1      matt 	if (prot & VM_PROT_WRITE) {
    178       1.1      matt 		if (mdpg != NULL && !VM_PAGEMD_MODIFIED_P(mdpg))
    179       1.1      matt 			pt_entry |= PTE_NW;
    180       1.1      matt 		else
    181       1.1      matt 			pt_entry |= PTE_SW | (kernel_p ? 0 : PTE_UW);
    182       1.1      matt 	}
    183       1.1      matt 	return pt_entry;
    184       1.1      matt }
    185       1.1      matt 
    186       1.1      matt static inline pt_entry_t
    187       1.1      matt pte_flag_bits(struct vm_page_md *mdpg, int flags, bool kernel_p)
    188       1.1      matt {
    189       1.1      matt #if 0
    190       1.1      matt 	if (__predict_false(flags & PMAP_NOCACHE)) {
    191       1.1      matt 		if (__predict_true(mdpg != NULL)) {
    192       1.1      matt 			return pte_nocached_bits();
    193       1.1      matt 		} else {
    194       1.1      matt 			return pte_ionocached_bits();
    195       1.1      matt 		}
    196       1.1      matt 	} else {
    197       1.1      matt 		if (__predict_false(mdpg != NULL)) {
    198       1.1      matt 			return pte_cached_bits();
    199       1.1      matt 		} else {
    200       1.1      matt 			return pte_iocached_bits();
    201       1.1      matt 		}
    202       1.1      matt 	}
    203       1.1      matt #else
    204       1.1      matt 	return 0;
    205       1.1      matt #endif
    206       1.1      matt }
    207       1.1      matt 
    208       1.1      matt static inline pt_entry_t
    209       1.1      matt pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
    210       1.1      matt 	int flags, bool kernel_p)
    211       1.1      matt {
    212       1.1      matt 	pt_entry_t pte = (pt_entry_t) pa & ~PAGE_MASK;
    213       1.1      matt 
    214       1.1      matt 	pte |= pte_flag_bits(mdpg, flags, kernel_p);
    215       1.1      matt 	pte |= pte_prot_bits(mdpg, prot, kernel_p);
    216       1.1      matt 
    217       1.1      matt 	if (mdpg == NULL && VM_PAGEMD_REFERENCED_P(mdpg))
    218       1.1      matt 		pte |= PTE_V;
    219       1.1      matt 
    220       1.1      matt 	return pte;
    221       1.1      matt }
    222       1.1      matt 
    223       1.1      matt static inline pt_entry_t
    224       1.1      matt pte_make_kenter_pa(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
    225       1.1      matt 	int flags)
    226       1.1      matt {
    227       1.1      matt 	pt_entry_t pte = (pt_entry_t) pa & ~PAGE_MASK;
    228       1.1      matt 
    229       1.1      matt 	pte |= PTE_WIRED | PTE_V;
    230       1.1      matt 	pte |= pte_flag_bits(NULL, flags, true);
    231       1.1      matt 	pte |= pte_prot_bits(NULL, prot, true); /* pretend unmanaged */
    232       1.1      matt 
    233       1.1      matt 	return pte;
    234       1.1      matt }
    235       1.1      matt 
    236       1.1      matt static inline void
    237       1.1      matt pte_set(pt_entry_t *ptep, pt_entry_t pte)
    238       1.1      matt {
    239       1.1      matt 	*ptep = pte;
    240       1.1      matt }
    241       1.1      matt 
    242       1.1      matt static inline paddr_t
    243       1.1      matt pte_pde_to_paddr(pd_entry_t pde)
    244       1.1      matt {
    245       1.1      matt 	return pde & ~PAGE_MASK;
    246       1.1      matt }
    247       1.1      matt 
    248       1.1      matt static inline pd_entry_t
    249       1.1      matt pte_pde_cas(pd_entry_t *pdep, pd_entry_t opde, pt_entry_t npde)
    250       1.1      matt {
    251       1.1      matt #ifdef MULTIPROCESSOR
    252       1.1      matt #ifdef _LP64
    253       1.1      matt 	return atomic_cas_64(pdep, opde, npde);
    254       1.1      matt #else
    255       1.1      matt 	return atomic_cas_32(pdep, opde, npde);
    256       1.1      matt #endif
    257       1.1      matt #else
    258       1.1      matt 	*pdep = npde;
    259       1.1      matt 	return 0;
    260       1.1      matt #endif
    261       1.1      matt }
    262  1.1.22.1  christos 
    263  1.1.22.1  christos static inline pt_entry_t
    264  1.1.22.1  christos pte_value(pt_entry_t pte)
    265  1.1.22.1  christos {
    266  1.1.22.1  christos 	return pte;
    267  1.1.22.1  christos }
    268  1.1.22.1  christos 
    269       1.1      matt #endif /* _RISCV_PTE_H_ */
    270