root/sys/arch/m68k/include/pmap_68k.h
/*      $NetBSD: pmap_68k.h,v 1.21 2026/07/15 04:58:26 thorpej Exp $    */

/*-     
 * Copyright (c) 2025 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */             

/* 
 * Copyright (c) 1987 Carnegie-Mellon University
 * Copyright (c) 1991, 1993
 *      The Regents of the University of California.  All rights reserved.
 * 
 * This code is derived from software contributed to Berkeley by
 * the Systems Programming Group of the University of Utah Computer 
 * Science Department.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *                       
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *      @(#)pmap.h      8.1 (Berkeley) 6/10/93
 */   

#ifndef _M68K_PMAP_68K_H_
#define _M68K_PMAP_68K_H_

#if defined(_KERNEL)

#if !defined(_MODULE)

#include <sys/rbtree.h>
#include <sys/queue.h>

#include <m68k/mmu_51.h>
#include <m68k/mmu_40.h>

#include <sys/kcore.h>
#include <m68k/kcore.h>

typedef unsigned int    pt_entry_t;

#define NPTEPG          (PAGE_SIZE / (sizeof(pt_entry_t)))

TAILQ_HEAD(pmap_ptpage_list, pmap_ptpage);
LIST_HEAD(pmap_pv_list, pv_entry);

struct pmap {
        struct pmap_table *pm_lev1map;  /* level 1 table */
        paddr_t            pm_lev1pa;   /* PA of level 1 table */
        uint16_t           pm_refcnt;   /* reference count */
        uint16_t           pm_busy;     /* "busy" (currently loaded in
                                           to MMU, or involved in
                                           some pmap operation) count */

        struct pmap_table *pm_pt_cache; /* most recently used leaf table */

        /* Red-Black tree that contains the active tables. */
        struct rb_tree     pm_tables;   /* lev1map not in here */

        /* Page table pages for segment and leaf tables. */
        struct pmap_ptpage_list pm_ptpages[2];

        struct pmap_pv_list pm_pvlist;  /* all associated P->V entries */

        struct pmap_statistics pm_stats;/* statistics */
};

/*
 * One entry per P->V mapping of a managed page.
 *
 * N.B. We want to keep this structure's size to be a multiple of
 * 8; we want to align them to 8 bytes in order to be able to use
 * the lower 3 bits of the pv_entry list head for page attributes.
 */
struct pv_entry {
/* 0*/  struct pv_entry     *pv_next;   /* link on page list */
/* 4*/  LIST_ENTRY(pv_entry) pv_pmlist; /* link on pmap list */
/*12*/  pmap_t               pv_pmap;   /* pmap that contains mapping */
/*16*/  vaddr_t              pv_vf;     /* virtual address + flags */
/*20*/  struct pmap_table   *pv_pt;     /* table that contains the PTE */
/*24*/
};

/* Upper bits of pv_vf contain the virtual address */
#define PV_VA(pv)       ((pv)->pv_vf & ~PAGE_MASK)

/* Lower bits of pv_vf contain flags */
#define PV_F_CI_VAC     __BIT(0)        /* mapping CI due to VAC alias */
#define PV_F_CI_USR     __BIT(1)        /* mapping CI due to user request */

/*
 * This describes an individual table used by the MMU.  Depending on
 * the MMU configuration, there may be more than one table per physical
 * page.
 *
 * For leaf (page) and inner segment tables, pt_st points to the
 * segment table one level up in the tree that maps it, and pt_stidx
 * is the index into that segment table.  pt_st also serves as a
 * proxy for whether or not the table has been inserted into the
 * table lookup tree.  For the level-1 table, pt_st is NULL and
 * that table is not inserted into the lookup tree.
 */
struct pmap_table {
        struct pmap_ptpage *pt_ptpage;
        pt_entry_t         *pt_entries;
        struct pmap_table  *pt_st;
        unsigned short      pt_holdcnt;
        unsigned short      pt_stidx;
        unsigned int        pt_key;
        union {
                LIST_ENTRY(pmap_table) pt_freelist;
                struct rb_node         pt_node;
        };
};

/*
 * This describes a page table page, which contains one or more MMU tables.
 * It's variable length, and the table descriptors are allocated along with.
 */
struct pmap_ptpage {
        TAILQ_ENTRY(pmap_ptpage)  ptp_list;
        LIST_HEAD(, pmap_table)   ptp_freelist;
        struct vm_page           *ptp_pg;
        unsigned int              ptp_vpagenum : 23,
                                  ptp_freecnt : 8,
                                  ptp_segtab : 1;
        struct pmap_table         ptp_tables[];
};

/*
 * This structure describes regions to be statically allocated / mapped by
 * pmap_boostrap1().  This is used for the fixed regions that everyone
 * gets (kernel text / data / bss / symbols, lwp0 u-area, msgbuf address,
 * etc.) as well as any additional static regions (device areas, etc.) that
 * need to be mapped (with KVA space) or reserved (because they're mapped
 * with TT registers).
 *
 * Some notes:
 *
 * - Virtual addresses are allocated and stored in the variable pointed
 *   to by pmbm_vaddr_ptr, **unless** the PMBM_F_KEEPOUT or PMBM_F_FIXEDVA
 *   flags are set, in which case the pmbm_vaddr field indicates a range
 *   that kernel virtual space should keep out of (PMBM_F_KEEPOUT - usually
 *   because it's mapped by Transparent Translation registers) or that is
 *   used for a fixed-VA special mapping (PMBM_F_FIXEDVA).
 *
 * - If the PMBM_F_VAONLY flag is set, only VA space will be allocated,
 *   no mapping will be entered in the space.
 *
 * N.B. PMBM_F_KEEPOUT VA regions are assumed to lie beyond the normal
 * kernel virtual address space.  The maximum kernel virtual address will
 * be clamped to ensure that it never grows into the lowest of these regions.
 *
 * pmap_bootstrap1() makes no effort to ensure there are PTs backing any
 * PMBM_F_FIXEDVA range.  It is assumed that any fixed VA mapping will
 * occur within an already-provisioned VA range.
 *
 * All regions will be rounded / aligned to page boundaries.
 *
 * This list is terminated by placing a (vaddr_t)-1 in the pmbm_vaddr
 * field.
 *
 * N.B. IF YOU CHANGE THIS STRUCTURE, AUDIT ALL DECLS OF machine_bootmap[].
 */
struct pmap_bootmap {
        union {
                vaddr_t         pmbm_vaddr;
                vaddr_t *       pmbm_vaddr_ptr;
        };
        paddr_t                 pmbm_paddr;
        size_t                  pmbm_size;
        int                     pmbm_flags;
};

#define PMBM_F_VAONLY   __BIT(0)
#define PMBM_F_FIXEDVA  __BIT(1)
#define PMBM_F_KEEPOUT  __BIT(2)
#define PMBM_F_CI       __BIT(3)        /* cache-inhibited mapping */
#define PMBM_F_CWT      __BIT(4)        /* write-through cacheable mapping */
#define PMBM_F_RO       __BIT(5)        /* read-only mapping */

/*
 * Abstract definitions for PTE bits / fields.  C code will compile-time-
 * assert the equivalencies that we assume.
 *
 * N.B. assumes exclusive use of short descriptors on 68851.
 */
#define PTE_VALID       PTE40_RESIDENT  /* == DT51_PAGE */
#define PTE_WP          PTE40_W         /* == PTE51_WP */
#define PTE_M           PTE40_M         /* == PTE51_M */
#define PTE_U           PTE40_U         /* == PTE51_U */
#define PTE_PVLIST      PTE40_G         /* unused on '51, don't use PFLUSHxN */
#define PTE_WIRED       PTE40_UR        /* unused on '51 */

/*
 * PTE40_CM overlaps with PTE51_CI and PTE51_L (which we don't use).
 */
#define PTE_CMASK       PTE40_CM

/*
 * Critical bits that, when changed (see pmap_changebit()), require
 * invalidation of the ATC.
 */
#define PTE_CRIT_BITS   (PTE_WP | PTE_CMASK)

/*
 * Root Pointer attributes for Supervisor and User modes.
 *
 * Supervisor:
 * - No index limit (Lower limit == 0)
 * - Points to Short format descriptor table.
 * - Shared Globally
 *
 * User:
 * - No index limit (Lower limit == 0)
 * - Points to Short format descriptor table.
 */
#define MMU51_SRP_BITS  (DTE51_LOWER | DTE51_SG | DT51_SHORT)
#define MMU51_CRP_BITS  (DTE51_LOWER |            DT51_SHORT)

/*
 * Our abstract definition of a "segment" is "that which points to the
 * leaf tables".  On the 2-level configuration, that's the level 1 table,
 * and on the 3-level configuration, that's the level 2 table.
 *
 * This is the logical address layout:
 *
 * 2-level 4KB/page: l1,l2,page    == 10,10,12  (HP MMU compatible)
 * 2-level 8KB/page: l1,l2,page    ==  8,11,13
 * 3-level 4KB/page: l1,l2,l3,page == 7,7,6,12
 * 3-level 8KB/page: l1,l2,l3,page == 7,7,5,13
 *
 * The 2-level l2 size is chosen per the number of page table entries
 * per page, to use one whole page for PTEs per one segment table entry.
 *
 * The 3-level layout is defined by the 68040/68060 hardware, and is not
 * configurable (other than chosen page size).  If '851 / '030 chooses
 * to use the 3-level layout, it is specifically configured to be compatible
 * with the 68040.
 */
                                                         /*  8KB /  4KB  */
#define LA2L_L2_NBITS   (PAGE_SHIFT - 2)                 /*   11 /   10  */
#define LA2L_L2_COUNT   __BIT(LA2L_L2_NBITS)             /* 2048 / 1024  */
#define LA2L_L2_SHIFT   PAGE_SHIFT                       /*   13 /   12  */
#define LA2L_L1_NBITS   (32 - LA2L_L2_NBITS - PAGE_SHIFT)/*    8 /   10  */
#define LA2L_L1_COUNT   __BIT(LA2L_L1_NBITS)             /*  256 / 1024  */
#define LA2L_L1_SHIFT   (LA2L_L2_NBITS + PAGE_SHIFT)     /*   24 /   22  */

#define LA2L_L1_MASK    (__BITS(0,(LA2L_L1_NBITS - 1)) << LA2L_L1_SHIFT)
#define LA2L_L2_MASK    (__BITS(0,(LA2L_L2_NBITS - 1)) << LA2L_L2_SHIFT)

#define LA2L_RI(va)     __SHIFTOUT((va), LA2L_L1_MASK)  /* root index */
#define LA2L_PGI(va)    __SHIFTOUT((va), LA2L_L2_MASK)  /* page index */

#define MMU51_TCR_BITS  (TCR51_E | TCR51_SRE |                          \
                         __SHIFTIN(PAGE_SHIFT, TCR51_PS) |              \
                         __SHIFTIN(LA2L_L1_NBITS, TCR51_TIA) |          \
                         __SHIFTIN(LA2L_L2_NBITS, TCR51_TIB))

#define MMU51_3L_TCR_BITS (TCR51_E | TCR51_SRE |                        \
                        __SHIFTIN(PAGE_SHIFT, TCR51_PS) |               \
                        __SHIFTIN(LA40_L1_NBITS, TCR51_TIA) |           \
                        __SHIFTIN(LA40_L2_NBITS, TCR51_TIB) |           \
                        __SHIFTIN(LA40_L3_NBITS, TCR51_TIC))

#define MMU40_TCR_BITS  (TCR40_E |                                      \
                         __SHIFTIN(PAGE_SHIFT - 12, TCR40_P))

/* SEG1SHIFT3L is for the "upper" segment on the 3-level configuration */
#define SEGSHIFT2L      (LA2L_L1_SHIFT)                 /*   24 /   22  */
#define SEGSHIFT3L      (LA40_L2_SHIFT)                 /*   18 /   18  */
#define SEG1SHIFT3L     (LA40_L1_SHIFT)                 /*   25 /   25  */

/* NBSEG13L is for the "upper" segment on the 3-level configuration */
#define NBSEG2L         __BIT(SEGSHIFT2L)
#define NBSEG3L         __BIT(SEGSHIFT3L)
#define NBSEG13L        __BIT(SEG1SHIFT3L)

#define SEGOFSET2L      (NBSEG2L - 1)
#define SEGOFSET3L      (NBSEG3L - 1)
#define SEG1OFSET3L     (NBSEG13L - 1)

#define pmap_trunc_seg_2L(va)   (((vaddr_t)(va)) & ~SEGOFSET2L)
#define pmap_round_seg_2L(va)   (pmap_trunc_seg_2L((vaddr_t)(va) + SEGOFSET2L))
#define pmap_seg_offset_2L(va)  (((vaddr_t)(va)) & SEGOFSET2L)

#define pmap_trunc_seg_3L(va)   (((vaddr_t)(va)) & ~SEGOFSET3L)
#define pmap_round_seg_3L(va)   (pmap_trunc_seg_3L((vaddr_t)(va) + SEGOFSET3L))
#define pmap_seg_offset_3L(va)  (((vaddr_t)(va)) & SEGOFSET3L)

#define pmap_trunc_seg1_3L(va)  (((vaddr_t)(va)) & ~SEG1OFSET3L)
#define pmap_round_seg1_3L(va)  (pmap_trunc_seg1_3L((vaddr_t)(va)+ SEG1OFSET3L))
#define pmap_seg1_offset_3L(va) (((vaddr_t)(va)) & SEG1OFSET3L)

/*
 * pmap-specific data store in the vm_page structure.
 *
 * We keep the U/M attrs in the lower 2 bits of the list head
 * pointer.  This is possible because both the U and M bits are
 * adjacent; we just need to shift them down 3 bit positions.
 *
 * Assumes that PV entries will be 4-byte aligned, but the allocator
 * guarantees this for us.
 */
#define __HAVE_VM_PAGE_MD
struct vm_page_md {
        uintptr_t pvh_listx;            /* pv_entry list + attrs */
};

#define PVH_UM_SHIFT    3
#define PVH_UM_MASK     __BITS(0,1)
#define PVH_CI          __BIT(2)
#define PVH_ATTR_MASK   (PVH_UM_MASK | PVH_CI)
#define PVH_PV_MASK     (~PVH_ATTR_MASK)

#define VM_MDPAGE_INIT(pg)                                      \
do {                                                            \
        (pg)->mdpage.pvh_listx = 0;                             \
} while (/*CONSTCOND*/0)

#define VM_MDPAGE_PVS(pg)                                       \
        ((struct pv_entry *)((pg)->mdpage.pvh_listx & (uintptr_t)PVH_PV_MASK))

#define VM_MDPAGE_HEAD_PVP(pg)                                  \
        ((struct pv_entry **)&(pg)->mdpage.pvh_listx)

#define VM_MDPAGE_SETPVP(pvp, pv)                               \
do {                                                            \
        /*                                                      \
         * The page attributes are in the lower two bits of     \
         * the first PV pointer.  Rather than comparing the     \
         * address and branching, we just always preserve what  \
         * might be there (either the attribute bits or zero    \
         * bits).                                               \
         */                                                     \
        *(pvp) = (struct pv_entry *)                            \
            ((uintptr_t)(pv) |                                  \
             (((uintptr_t)(*(pvp))) & (uintptr_t)PVH_ATTR_MASK));\
} while (/*CONSTCOND*/0)

#define VM_MDPAGE_UM(pg)                                        \
        (((pg)->mdpage.pvh_listx & PVH_UM_MASK) << PVH_UM_SHIFT)

#define VM_MDPAGE_ADD_UM(pg, a)                                 \
do {                                                            \
        (pg)->mdpage.pvh_listx |=                               \
            ((a) >> PVH_UM_SHIFT) & PVH_UM_MASK;                \
} while (/*CONSTCOND*/0)

#define VM_MDPAGE_SET_UM(pg, v)                                 \
do {                                                            \
        (pg)->mdpage.pvh_listx =                                \
            ((pg)->mdpage.pvh_listx & ~PVH_UM_MASK) |           \
            (((v) >> PVH_UM_SHIFT) & PVH_UM_MASK);              \
} while (/*CONSTCOND*/0)

#define VM_MDPAGE_SET_CI(pg)                                    \
do {                                                            \
        (pg)->mdpage.pvh_listx |= PVH_CI;                       \
} while (/*CONSTCOND*/0)

#define VM_MDPAGE_CLR_CI(pg)                                    \
do {                                                            \
        (pg)->mdpage.pvh_listx &= ~PVH_CI;                      \
} while (/*CONSTCOND*/0)

#define VM_MDPAGE_CI_P(pg)                                      \
        ((pg)->mdpage.pvh_listx & PVH_CI)

#define pmap_copy(dp, sp, da, l, sa)    __nothing

#define pmap_resident_count(pmap)       ((pmap)->pm_stats.resident_count)
#define pmap_wired_count(pmap)          ((pmap)->pm_stats.wired_count)

#define PMAP_GROWKERNEL                 /* enable pmap_growkernel() */

void    pmap_procwr(struct proc *, vaddr_t, size_t);
#define PMAP_NEED_PROCWR

/*
 * pmap_bootstrap1() is called before the MMU is turned on.
 * pmap_bootstrap2() is called after.
 */
paddr_t pmap_bootstrap1(paddr_t/*nextpa*/, paddr_t/*reloff*/);
void *  pmap_bootstrap2(void);

/*
 * Variant of pmap_extract() that returns additional information about
 * the mapping.  Used by bus_dma(9).
 */
bool    pmap_extract_info(pmap_t, vaddr_t, paddr_t *, int *);

/*
 * Functions to determine if a VA/PA range is a static mapping created
 * by pmap_bootstrap1(), for the benefit of bus_space(9).
 */
extern struct pmap_bootmap machine_bootmap[];
bool    pmap_pa_has_static_mapping(paddr_t, size_t, vm_prot_t,
            vaddr_t *, int *);
bool    pmap_va_is_static_mapping(vaddr_t, size_t);

/* Kernel debugger support functions. */
struct pmap_db_write_text_context {
        vaddr_t         pgva;
        pt_entry_t *    ptep;
        pt_entry_t      opte;
};
bool    pmap_db_write_text_enter(vaddr_t, struct pmap_db_write_text_context *);
void    pmap_db_write_text_exit(struct pmap_db_write_text_context *);

/*
 * Functions exported for compatibility with the Hibler pmap, where
 * these are needed by other shared m68k code.
 *
 * XXX Clean this up eventually.
 */
pt_entry_t *            pmap_kernel_pte(vaddr_t);

paddr_t         vtophys(vaddr_t);

extern char *   vmmap;
extern void *   msgbufaddr;

/* Support functions for HP MMU. */
void    pmap_init_vac(size_t);
void    pmap_prefer(vaddr_t, vaddr_t *, int);
/* PMAP_PREFER() defined in <machine/pmap.h> on machines were it's needed. */

/*
 * pmap hook for trap()'s page fault handler.  We don't need to
 * do anything special, so it just goes to uvm_fault().
 */
#define pmap_fault(m, v, t)     uvm_fault((m), (v), (t))

/* Kernel crash dump support. */
phys_ram_seg_t *        pmap_init_kcore_hdr(cpu_kcore_hdr_t *);

/*
 * pmap_bootstrap1() may need to relocate global references, and perform
 * VA <-> PA conversions.  These macros facilitate these conversions, and
 * can be overridden in <machine/pmap.h> before including <m68k/pmap_68k.h>
 * if needed.
 *
 * The first two macros are specifically for converting addresses within
 * the confines of pmap_bootstrap1().  We may be running with the MMU off
 * (and either VA==PA or VA!=PA) or with the MMU on with some mappings.
 * The default ones are suitable for the "MMU off" case with the relocation
 * offset passed in the "reloff" variable.
 *
 * - PMAP_BOOTSTRAP_RELOC_GLOB() -- relocate a global reference in order
 *   to access it during bootstrap.
 *
 * - PMAP_BOOTSTRAP_RELOC_PA() -- relocate a physical address in order to
 *   access it during bootstrap.
 *
 * The next two macros are intended to convert kernel virtual <-> physical
 * addresses that will be used in the context of the running kernel once
 * the MMU is enabled and running on the kernel's ultimate mappings:
 *
 * - PMAP_BOOTSTRAP_VA_TO_PA() -- convert a kernel virtual address to
 *   a physical address using linear relocation.
 *
 * - PMAP_BOOTSTRAP_PA_TO_VA() -- and vice versa.
 */
#ifndef PMAP_BOOTSTRAP_RELOC_GLOB
#define PMAP_BOOTSTRAP_RELOC_GLOB(va)                                   \
        ((((vaddr_t)(va)) - VM_MIN_KERNEL_ADDRESS) + reloff)
#endif

#ifndef PMAP_BOOTSTRAP_RELOC_PA
#define PMAP_BOOTSTRAP_RELOC_PA(pa)                                     \
        ((vaddr_t)(pa))
#endif

#ifndef PMAP_BOOTSTRAP_VA_TO_PA
#define PMAP_BOOTSTRAP_VA_TO_PA(va)                                     \
        ((((vaddr_t)(va)) - VM_MIN_KERNEL_ADDRESS) + reloff)
#endif

#ifndef PMAP_BOOTSTRAP_PA_TO_VA
#define PMAP_BOOTSTRAP_PA_TO_VA(pa)                                     \
        (VM_MIN_KERNEL_ADDRESS + (((paddr_t)(pa)) - reloff))
#endif

#endif /* ! _MODULE */

/*
 * Some pmap(9) API macros should be defined here for module(7).
 * Luckily, all m68k pmap implementations behave this way. (see PR/54869)
 */
#define pmap_update(pmap)               __nothing

#endif /* _KERNEL */

#endif /* _M68K_PMAP_68K_H_ */