1/*	$NetBSD: pte.h,v 1.27 2020/08/22 15:34:51 skrll Exp $	*/
  2
  3/*-
  4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
  5 * All rights reserved.
  6 *
  7 * This code is derived from software contributed to The NetBSD Foundation
  8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
  9 * NASA Ames Research Center.
 10 *
 11 * Redistribution and use in source and binary forms, with or without
 12 * modification, are permitted provided that the following conditions
 13 * are met:
 14 * 1. Redistributions of source code must retain the above copyright
 15 *    notice, this list of conditions and the following disclaimer.
 16 * 2. Redistributions in binary form must reproduce the above copyright
 17 *    notice, this list of conditions and the following disclaimer in the
 18 *    documentation and/or other materials provided with the distribution.
 19 *
 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 30 * POSSIBILITY OF SUCH DAMAGE.
 31 */
 32
 33/*
 34 * Copyright 1996 The Board of Trustees of The Leland Stanford
 35 * Junior University. All Rights Reserved.
 36 *
 37 * Permission to use, copy, modify, and distribute this
 38 * software and its documentation for any purpose and without
 39 * fee is hereby granted, provided that the above copyright
 40 * notice appear in all copies.  Stanford University
 41 * makes no representations about the suitability of this
 42 * software for any purpose.  It is provided "as is" without
 43 * express or implied warranty.
 44 */
 45
 46#ifndef  __MIPS_PTE_H__
 47#define	 __MIPS_PTE_H__
 48
 49#include <mips/mips1_pte.h>
 50#include <mips/mips3_pte.h>
 51
 52#define	PG_ASID	0x000000ff	/* Address space ID */
 53
 54#ifndef _LOCORE
 55#ifndef __BSD_PTENTRY_T__
 56#define	__BSD_PTENTRY_T__
 57typedef uint32_t pt_entry_t;
 58#define	PRIxPTE		PRIx32
 59#endif
 60
 61/*
 62 * Macros/inline functions to hide PTE format differences.
 63 */
 64
 65#define	mips_pg_nv_bit()	(MIPS1_PG_NV)	/* same on mips1 and mips3 */
 66
 67
 68bool pmap_is_page_ro_p(struct pmap *pmap, vaddr_t, uint32_t);
 69
 70
 71/* MIPS1-only */
 72#if defined(MIPS1) && !defined(MIPS3_PLUS)
 73#define	mips_pg_v(entry)	((entry) & MIPS1_PG_V)
 74#define	mips_pg_wired(entry)	((entry) & MIPS1_PG_WIRED)
 75
 76#define	mips_pg_m_bit()		(MIPS1_PG_D)
 77#define	mips_pg_rw_bit()	(MIPS1_PG_RW)	/* no RW bits for mips1 */
 78#define	mips_pg_ro_bit()	(MIPS1_PG_RO)
 79#define	mips_pg_ropage_bit()	(MIPS1_PG_RO)	/* XXX not MIPS1_PG_ROPAGE? */
 80#define	mips_pg_rwpage_bit()	(MIPS1_PG_RWPAGE)
 81#define	mips_pg_rwncpage_bit()	(MIPS1_PG_RWNCPAGE)
 82#define	mips_pg_cwpage_bit()	(MIPS1_PG_CWPAGE)
 83#define	mips_pg_cwncpage_bit()	(MIPS1_PG_CWNCPAGE)
 84#define	mips_pg_global_bit()	(MIPS1_PG_G)
 85#define	mips_pg_wired_bit()	(MIPS1_PG_WIRED)
 86
 87#define	pte_to_paddr(pte)	MIPS1_PTE_TO_PADDR((pte))
 88#define	PAGE_IS_RDONLY(pte, va)	MIPS1_PAGE_IS_RDONLY((pte), (va))
 89
 90#define	mips_tlbpfn_to_paddr(x)		mips1_tlbpfn_to_paddr((vaddr_t)(x))
 91#define	mips_paddr_to_tlbpfn(x)		mips1_paddr_to_tlbpfn((x))
 92#endif /* mips1 */
 93
 94
 95/* MIPS3 (or greater) only */
 96#if !defined(MIPS1) && defined(MIPS3_PLUS)
 97#define	mips_pg_v(entry)	((entry) & MIPS3_PG_V)
 98#define	mips_pg_wired(entry)	((entry) & MIPS3_PG_WIRED)
 99
100#define	mips_pg_m_bit()		(MIPS3_PG_D)
101#define	mips_pg_rw_bit()	(MIPS3_PG_D)
102#define	mips_pg_ro_bit()	(MIPS3_PG_RO)
103#define	mips_pg_ropage_bit()	(MIPS3_PG_ROPAGE)
104#define	mips_pg_rwpage_bit()	(MIPS3_PG_RWPAGE)
105#define	mips_pg_rwncpage_bit()	(MIPS3_PG_RWNCPAGE)
106#define	mips_pg_cwpage_bit()	(MIPS3_PG_CWPAGE)
107#define	mips_pg_cwncpage_bit()	(MIPS3_PG_CWNCPAGE)
108#define	mips_pg_global_bit()	(MIPS3_PG_G)
109#define	mips_pg_wired_bit()	(MIPS3_PG_WIRED)
110
111#define	pte_to_paddr(pte)	MIPS3_PTE_TO_PADDR((pte))
112#define	PAGE_IS_RDONLY(pte, va)	MIPS3_PAGE_IS_RDONLY((pte), (va))
113
114#define	mips_tlbpfn_to_paddr(x)		mips3_tlbpfn_to_paddr((vaddr_t)(x))
115#define	mips_paddr_to_tlbpfn(x)		mips3_paddr_to_tlbpfn((x))
116#endif /* mips3 */
117
118/* MIPS1 and MIPS3 (or greater) */
119#if defined(MIPS1) && defined(MIPS3_PLUS)
120
121static __inline bool
122    mips_pg_v(uint32_t entry),
123    mips_pg_wired(uint32_t entry),
124    PAGE_IS_RDONLY(uint32_t pte, vaddr_t va);
125
126static __inline uint32_t
127    mips_pg_wired_bit(void) __pure,
128    mips_pg_m_bit(void) __pure,
129    mips_pg_ro_bit(void) __pure,
130    mips_pg_rw_bit(void) __pure,
131    mips_pg_ropage_bit(void) __pure,
132    mips_pg_cwpage_bit(void) __pure,
133    mips_pg_rwpage_bit(void) __pure,
134    mips_pg_global_bit(void) __pure;
135static __inline paddr_t pte_to_paddr(pt_entry_t pte) __pure;
136static __inline bool PAGE_IS_RDONLY(uint32_t pte, vaddr_t va) __pure;
137
138static __inline paddr_t mips_tlbpfn_to_paddr(uint32_t pfn) __pure;
139static __inline uint32_t mips_paddr_to_tlbpfn(paddr_t pa) __pure;
140
141
142static __inline bool
143mips_pg_v(uint32_t entry)
144{
145	if (MIPS_HAS_R4K_MMU)
146		return (entry & MIPS3_PG_V) != 0;
147	return (entry & MIPS1_PG_V) != 0;
148}
149
150static __inline bool
151mips_pg_wired(uint32_t entry)
152{
153	if (MIPS_HAS_R4K_MMU)
154		return (entry & MIPS3_PG_WIRED) != 0;
155	return (entry & MIPS1_PG_WIRED) != 0;
156}
157
158static __inline uint32_t
159mips_pg_m_bit(void)
160{
161	if (MIPS_HAS_R4K_MMU)
162		return (MIPS3_PG_D);
163	return (MIPS1_PG_D);
164}
165
166static __inline unsigned int
167mips_pg_ro_bit(void)
168{
169	if (MIPS_HAS_R4K_MMU)
170		return (MIPS3_PG_RO);
171	return (MIPS1_PG_RO);
172}
173
174static __inline unsigned int
175mips_pg_rw_bit(void)
176{
177	if (MIPS_HAS_R4K_MMU)
178		return (MIPS3_PG_D);
179	return (MIPS1_PG_RW);
180}
181
182static __inline unsigned int
183mips_pg_ropage_bit(void)
184{
185	if (MIPS_HAS_R4K_MMU)
186		return (MIPS3_PG_ROPAGE);
187	return (MIPS1_PG_RO);
188}
189
190static __inline unsigned int
191mips_pg_rwpage_bit(void)
192{
193	if (MIPS_HAS_R4K_MMU)
194		return (MIPS3_PG_RWPAGE);
195	return (MIPS1_PG_RWPAGE);
196}
197
198static __inline unsigned int
199mips_pg_cwpage_bit(void)
200{
201	if (MIPS_HAS_R4K_MMU)
202		return (MIPS3_PG_CWPAGE);
203	return (MIPS1_PG_CWPAGE);
204}
205
206
207static __inline unsigned int
208mips_pg_global_bit(void)
209{
210	if (MIPS_HAS_R4K_MMU)
211		return (MIPS3_PG_G);
212	return (MIPS1_PG_G);
213}
214
215static __inline unsigned int
216mips_pg_wired_bit(void)
217{
218	if (MIPS_HAS_R4K_MMU)
219		return (MIPS3_PG_WIRED);
220	return (MIPS1_PG_WIRED);
221}
222
223static __inline paddr_t
224pte_to_paddr(pt_entry_t pte)
225{
226	if (MIPS_HAS_R4K_MMU)
227		return (MIPS3_PTE_TO_PADDR(pte));
228	return (MIPS1_PTE_TO_PADDR(pte));
229}
230
231static __inline bool
232PAGE_IS_RDONLY(uint32_t pte, vaddr_t va)
233{
234	if (MIPS_HAS_R4K_MMU)
235		return (MIPS3_PAGE_IS_RDONLY(pte, va));
236	return (MIPS1_PAGE_IS_RDONLY(pte, va));
237}
238
239static __inline paddr_t
240mips_tlbpfn_to_paddr(uint32_t pfn)
241{
242	if (MIPS_HAS_R4K_MMU)
243		return (mips3_tlbpfn_to_paddr(pfn));
244	return (mips1_tlbpfn_to_paddr(pfn));
245}
246
247static __inline uint32_t
248mips_paddr_to_tlbpfn(paddr_t pa)
249{
250	if (MIPS_HAS_R4K_MMU)
251		return (mips3_paddr_to_tlbpfn(pa));
252	return (mips1_paddr_to_tlbpfn(pa));
253}
254#endif
255
256#endif /* ! _LOCORE */
257
258#if defined(_KERNEL) && !defined(_LOCORE)
259#define	MIPS_MMU(X)	(MIPS_HAS_R4K_MMU ? MIPS3_##X : MIPS1_##X)
260static inline bool
261pte_valid_p(pt_entry_t pte)
262{
263	return (pte & MIPS_MMU(PG_V)) != 0;
264}
265
266static inline bool
267pte_modified_p(pt_entry_t pte)
268{
269	return (pte & MIPS_MMU(PG_D)) != 0;
270}
271
272static inline bool
273pte_global_p(pt_entry_t pte)
274{
275	return (pte & MIPS_MMU(PG_G)) != 0;
276}
277
278static inline bool
279pte_wired_p(pt_entry_t pte)
280{
281	return (pte & MIPS_MMU(PG_WIRED)) != 0;
282}
283
284static inline pt_entry_t
285pte_wire_entry(pt_entry_t pte)
286{
287	return pte | MIPS_MMU(PG_WIRED);
288}
289
290static inline pt_entry_t
291pte_unwire_entry(pt_entry_t pte)
292{
293	return pte & ~MIPS_MMU(PG_WIRED);
294}
295
296static inline uint32_t
297pte_value(pt_entry_t pte)
298{
299	return pte;
300}
301
302static inline bool
303pte_readonly_p(pt_entry_t pte)
304{
305	return (pte & MIPS_MMU(PG_RO)) != 0;
306}
307
308static inline bool
309pte_cached_p(pt_entry_t pte)
310{
311	if (MIPS_HAS_R4K_MMU) {
312		return MIPS3_PG_TO_CCA(pte) == MIPS3_PG_TO_CCA(mips_options.mips3_pg_cached);
313	} else {
314		return (pte & MIPS1_PG_N) == 0;
315	}
316}
317
318static inline bool
319pte_deferred_exec_p(pt_entry_t pte)
320{
321	return false;
322}
323
324static inline pt_entry_t
325pte_nv_entry(bool kernel_p)
326{
327	__CTASSERT(MIPS1_PG_NV == MIPS3_PG_NV);
328	__CTASSERT(MIPS1_PG_NV == 0);
329	return (kernel_p && MIPS_HAS_R4K_MMU) ? MIPS3_PG_G : 0;
330}
331
332static inline pt_entry_t
333pte_prot_downgrade(pt_entry_t pte, vm_prot_t prot)
334{
335	const uint32_t ro_bit = MIPS_MMU(PG_RO);
336	const uint32_t rw_bit = MIPS_MMU(PG_D);
337
338	return (pte & ~(ro_bit|rw_bit))
339	    | ((prot & VM_PROT_WRITE) ? rw_bit : ro_bit);
340}
341
342static inline pt_entry_t
343pte_prot_nowrite(pt_entry_t pte)
344{
345	return pte & ~MIPS_MMU(PG_D);
346}
347
348static inline pt_entry_t
349pte_cached_change(pt_entry_t pte, bool cached)
350{
351	if (MIPS_HAS_R4K_MMU) {
352		pte &= ~MIPS3_PG_CACHEMODE;
353		pte |= (cached ? MIPS3_PG_CACHED : MIPS3_PG_UNCACHED);
354	}
355	return pte;
356}
357
358static inline void
359pte_set(pt_entry_t *ptep, pt_entry_t pte)
360{
361	*ptep = pte;
362}
363
364#ifdef __PMAP_PRIVATE
365struct vm_page_md;
366
367static inline pt_entry_t
368pte_make_kenter_pa(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
369    u_int flags)
370{
371	pt_entry_t pte;
372	if (MIPS_HAS_R4K_MMU) {
373		pte = mips3_paddr_to_tlbpfn(pa)
374		    | ((prot & VM_PROT_WRITE) ? MIPS3_PG_D : MIPS3_PG_RO)
375		    | ((flags & PMAP_NOCACHE) ? MIPS3_PG_UNCACHED : MIPS3_PG_CACHED)
376		    | MIPS3_PG_WIRED | MIPS3_PG_V | MIPS3_PG_G;
377	} else {
378		pte = mips1_paddr_to_tlbpfn(pa)
379		    | ((prot & VM_PROT_WRITE) ? MIPS1_PG_D : MIPS1_PG_RO)
380		    | ((flags & PMAP_NOCACHE) ? MIPS1_PG_N : 0)
381		    | MIPS1_PG_WIRED | MIPS1_PG_V | MIPS1_PG_G;
382	}
383	return pte;
384}
385
386static inline pt_entry_t
387pte_make_enter(paddr_t pa, const struct vm_page_md *mdpg, vm_prot_t prot,
388    u_int flags, bool is_kernel_pmap_p)
389{
390	pt_entry_t pte;
391#if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
392	const bool cached = (flags & PMAP_NOCACHE) == 0
393	    && (pa & PGC_NOCACHE) == 0;
394	const bool prefetch = (pa & PGC_PREFETCH) != 0;
395
396	pa &= ~(PGC_NOCACHE|PGC_PREFETCH);
397#endif
398
399#if defined(cobalt) || defined(newsmips) || defined(pmax) /* otherwise ok */
400	/* this is not error in general. */
401	KASSERTMSG((pa & 0x80000000) == 0, "%#"PRIxPADDR, pa);
402#endif
403
404	if (mdpg != NULL) {
405		if ((prot & VM_PROT_WRITE) == 0) {
406			/*
407			 * If page is not yet referenced, we could emulate this
408			 * by not setting the page valid, and setting the
409			 * referenced status in the TLB fault handler, similar
410			 * to how page modified status is done for UTLBmod
411			 * exceptions.
412			 */
413			pte = mips_pg_ropage_bit();
414#if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
415		} else if (cached == false) {
416			if (VM_PAGEMD_MODIFIED_P(mdpg)) {
417				pte = mips_pg_rwncpage_bit();
418			} else {
419				pte = mips_pg_cwncpage_bit();
420			}
421#endif
422		} else {
423			if (VM_PAGEMD_MODIFIED_P(mdpg)) {
424				pte = mips_pg_rwpage_bit();
425			} else {
426				pte = mips_pg_cwpage_bit();
427			}
428		}
429	} else if (MIPS_HAS_R4K_MMU) {
430		/*
431		 * Assumption: if it is not part of our managed memory
432		 * then it must be device memory which may be volatile.
433		 */
434		u_int cca = PMAP_CCA_FOR_PA(pa);
435#if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
436		if (prefetch)
437			cca = mips_options.mips3_cca_devmem;
438#endif
439		pte = MIPS3_PG_IOPAGE(cca) & ~MIPS3_PG_G;
440	} else if (prot & VM_PROT_WRITE) {
441		pte = MIPS1_PG_N | MIPS1_PG_D;
442	} else {
443		pte = MIPS1_PG_N | MIPS1_PG_RO;
444	}
445
446	if (MIPS_HAS_R4K_MMU) {
447		pte |= mips3_paddr_to_tlbpfn(pa)
448		    | (is_kernel_pmap_p ? MIPS3_PG_G : 0);
449	} else {
450		pte |= mips1_paddr_to_tlbpfn(pa)
451		    | MIPS1_PG_V
452		    | (is_kernel_pmap_p ? MIPS1_PG_G : 0);
453	}
454
455	return pte;
456}
457#endif /* __PMAP_PRIVATE */
458
459#endif	/* defined(_KERNEL) && !defined(_LOCORE) */
460#endif /* __MIPS_PTE_H__ */