Home | History | Annotate | Line # | Download | only in pg68k
      1 /*	$NetBSD: pmap_pgmmu.h,v 1.1 2026/07/19 01:48:24 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2025, 2026 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.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #ifndef _PG68K_PMAP_PGMMU_H_
     33 #define	_PG68K_PMAP_PGMMU_H_
     34 
     35 #if defined(_KERNEL)
     36 
     37 #if !defined(_MODULE)
     38 
     39 #include <sys/queue.h>
     40 
     41 #include <hb68k/pg68k/pgmmu.h>
     42 
     43 #include <sys/kcore.h>
     44 #include <m68k/kcore.h>
     45 
     46 /*
     47  * Description of a pmap's MMU context.  In addition to the context
     48  * number, we also keep track of how many mappings we have in each
     49  * PMEG we have allocated so we know when we can free them back.
     50  *
     51  * The number of these context structures is limited to the total
     52  * number of contexts the MMU can handle.
     53  */
     54 struct pmap_context {
     55 	unsigned int ctx_num;
     56 	union {
     57 		struct pmap_context *ctx_next;
     58 		uint8_t ctx_segrefs[PGMMU_NUM_SEGS];
     59 	};
     60 };
     61 
     62 /*
     63  * This MMU is used in relatively resource-constrained machines,
     64  * so we aim to keep this structure as small as possible.
     65  */
     66 struct pmap {
     67 	TAILQ_ENTRY(pmap)      pm_list;		/* link on global list */
     68 	struct pmap_context   *pm_context;	/* current context */
     69 	uint16_t               pm_refcnt;	/* reference count */
     70 	uint16_t               pm_busy;		/* "busy" (currently loaded in
     71 						   to MMU, or involved in
     72 						   some pmap operation) count */
     73 	/*
     74 	 * N.B. we also used wired_count internally to identify
     75 	 * potential victims of resource theft.
     76 	 */
     77 	struct pmap_statistics pm_stats;	/* statistics */
     78 };
     79 
     80 /*
     81  * One entry per P->V mapping of a managed page.
     82  *
     83  * N.B. We want to keep this structure's size to be a multiple of
     84  * 8; we want to align them to 8 bytes in order to be able to use
     85  * the lower 3 bits of the pv_entry list head for page attributes.
     86  */
     87 struct pv_entry {
     88 /* 0*/	struct pv_entry *pv_next;	/* link on page list */
     89 /* 4*/	pmap_t           pv_pmap;	/* pmap that contains mapping */
     90 /* 8*/	vaddr_t          pv_vf;		/* virtual address + flags */
     91 /*12*/	unsigned int     pv_pmeg;	/* PMEG that maps this VA */
     92 /*16*/
     93 };
     94 
     95 /* Upper bits of pv_vf contain the virtual address */
     96 #define	PV_VA(pv)	((pv)->pv_vf & ~PAGE_MASK)
     97 
     98 /*
     99  * pmap-specific data store in the vm_page structure.
    100  *
    101  * We keep the Mod/Ref attrs in the lower 2 bits of the list head
    102  * pointer.  This is possible because both the Mod and Ref bits are
    103  * adjacent; we just need to shift them down 24 bit positions.
    104  *
    105  * Assumes that PV entries will be 4-byte aligned, but the allocator
    106  * guarantees this for us.
    107  */
    108 #define	__HAVE_VM_PAGE_MD
    109 struct vm_page_md {
    110 	uintptr_t pvh_listx;		/* pv_entry list + attrs */
    111 };
    112 
    113 #define	PVH_MR_SHIFT	24
    114 #define	PVH_MR_MASK	__BITS(0,1)
    115 #define	PVH_ATTR_MASK	PVH_MR_MASK
    116 #define	PVH_PV_MASK	(~PVH_ATTR_MASK)
    117 
    118 #define	VM_MDPAGE_INIT(pg)					\
    119 do {								\
    120 	(pg)->mdpage.pvh_listx = 0;				\
    121 } while (/*CONSTCOND*/0)
    122 
    123 #define	VM_MDPAGE_PVS(pg)					\
    124 	((struct pv_entry *)((pg)->mdpage.pvh_listx & (uintptr_t)PVH_PV_MASK))
    125 
    126 #define	VM_MDPAGE_HEAD_PVP(pg)					\
    127 	((struct pv_entry **)&(pg)->mdpage.pvh_listx)
    128 
    129 #define	VM_MDPAGE_SETPVP(pvp, pv)				\
    130 do {								\
    131 	/*							\
    132 	 * The page attributes are in the lower two bits of	\
    133 	 * the first PV pointer.  Rather than comparing the	\
    134 	 * address and branching, we just always preserve what	\
    135 	 * might be there (either the attribute bits or zero	\
    136 	 * bits).						\
    137 	 */							\
    138 	*(pvp) = (struct pv_entry *)				\
    139 	    ((uintptr_t)(pv) |					\
    140 	     (((uintptr_t)(*(pvp))) & (uintptr_t)PVH_ATTR_MASK));\
    141 } while (/*CONSTCOND*/0)
    142 
    143 #define	VM_MDPAGE_MR(pg)					\
    144 	(((pg)->mdpage.pvh_listx & PVH_MR_MASK) << PVH_MR_SHIFT)
    145 
    146 #define	VM_MDPAGE_ADD_MR(pg, a)					\
    147 do {								\
    148 	(pg)->mdpage.pvh_listx |=				\
    149 	    ((a) >> PVH_MR_SHIFT) & PVH_MR_MASK;		\
    150 } while (/*CONSTCOND*/0)
    151 
    152 #define	VM_MDPAGE_SET_MR(pg, v)					\
    153 do {								\
    154 	(pg)->mdpage.pvh_listx =				\
    155 	    ((pg)->mdpage.pvh_listx & ~PVH_MR_MASK) |		\
    156 	    (((v) >> PVH_MR_SHIFT) & PVH_MR_MASK);		\
    157 } while (/*CONSTCOND*/0)
    158 
    159 #define	pmap_copy(dp, sp, da, l, sa)	__nothing
    160 
    161 #define	pmap_resident_count(pmap)	((pmap)->pm_stats.resident_count)
    162 #define	pmap_wired_count(pmap)		((pmap)->pm_stats.wired_count)
    163 
    164 /*
    165  * pmap_bootstrap1() is called before the MMU is turned on (well, for
    166  * this MMU, it's always on...)
    167  * pmap_bootstrap2() is called after.
    168  */
    169 paddr_t	pmap_bootstrap1(paddr_t/*nextpa*/, paddr_t/*reloff*/);
    170 void *	pmap_bootstrap2(void);
    171 
    172 /*
    173  * Variant of pmap_extract() that returns additional information about
    174  * the mapping.  Used by bus_dma(9).
    175  */
    176 bool	pmap_extract_info(pmap_t, vaddr_t, paddr_t *, int *);
    177 
    178 /*
    179  * pmap hook for trap()'s page fault handler.  We don't need to
    180  * do anything special, so it just goes to uvm_fault().
    181  */
    182 #define	pmap_fault(m, v, t)	uvm_fault((m), (v), (t))
    183 
    184 /*
    185  * Functions to determine if a VA/PA range is a static mapping created
    186  * by pmap_bootstrap1(), for the benefit of bus_space(9).
    187  */
    188 bool	pmap_pa_has_static_mapping(paddr_t, size_t, vm_prot_t,
    189 	    vaddr_t *, int *);
    190 bool	pmap_va_is_static_mapping(vaddr_t, size_t);
    191 
    192 /* Kernel debugger support functions. */
    193 struct pmap_db_write_text_context {
    194 	unsigned int	pmeidx;
    195 	pm_entry_t	opme;
    196 };
    197 bool	pmap_db_write_text_enter(vaddr_t, struct pmap_db_write_text_context *);
    198 void	pmap_db_write_text_exit(struct pmap_db_write_text_context *);
    199 
    200 /*
    201  * Functions exported for compatibility with the Hibler pmap, where
    202  * these are needed by other shared m68k code.
    203  *
    204  * XXX Clean this up eventually.
    205  */
    206 
    207 paddr_t		vtophys(vaddr_t);
    208 
    209 extern char *	vmmap;
    210 extern void *	msgbufaddr;
    211 
    212 /* Kernel crash dump support. */
    213 phys_ram_seg_t *	pmap_init_kcore_hdr(cpu_kcore_hdr_t *);
    214 
    215 /*
    216  * pmap_bootstrap1() may need to relocate global references, and perform
    217  * VA <-> PA conversions.  We don't need to do anything for these accesses
    218  * on this MMU, because the MMU is always on.
    219  */
    220 #undef PMAP_BOOTSTRAP_RELOC_GLOB
    221 #define	PMAP_BOOTSTRAP_RELOC_GLOB(va)	(va)
    222 
    223 #undef PMAP_BOOTSTRAP_RELOC_PA
    224 #define	PMAP_BOOTSTRAP_RELOC_PA(pa)	(pa)
    225 
    226 #undef PMAP_BOOTSTRAP_VA_TO_PA
    227 #define	PMAP_BOOTSTRAP_VA_TO_PA(va)	(va)
    228 
    229 #undef PMAP_BOOTSTRAP_PA_TO_VA
    230 #define	PMAP_BOOTSTRAP_PA_TO_VA(pa)	(pa)
    231 
    232 #endif /* _MODULE */
    233 
    234 /*
    235  * Some pmap(9) API macros should be defined here for module(7).
    236  * Luckily, all m68k pmap implementations behave this way. (see PR/54869)
    237  */
    238 #define	pmap_update(pmap)		__nothing
    239 
    240 #endif /* _KERNEL */
    241 
    242 #endif /* _PG68K_PMAP_PGMMU_H_ */
    243