Home | History | Annotate | Line # | Download | only in pg68k
      1 /*	$NetBSD: pgmmu.h,v 1.1 2026/07/19 01:48:24 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 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_PGMMU_H_
     33 #define	_PG68K_PGMMU_H_
     34 
     35 /*
     36  * Definitions for the Phaethon 1 MMU.
     37  *
     38  * The Phaethon 1 MMU is inspired by the Sun3 MMU (which is itself similar
     39  * to the Sun2 MMU), but has some differences.  Here are the features of
     40  * the Phaethon 1's MMU:
     41  *
     42  * ==> 24 bits of virtual address (16MB, as limited by the 68010) is mapped
     43  *     onto 28 bits (256MB) of physical address.
     44  *
     45  * ==> 64 contexts; kernel accessess all use context 0, leaving 1-63
     46  *     available for user processes.  There is no restriction against
     47  *     using context 0 for user processes, and there is per-page kernel
     48  *     privilege protection in case you do.
     49  *
     50  * ==> 2-level address translation: each context is comprised of 512
     51  *     32KB segments, and each segment is comprised of 8 4KB pages.
     52  *
     53  * ==> A total of 262,144 32-bit Page Map entries.  Because of the 8-entry
     54  *     grouping, there are a total of 32,768 Page Map Entry Groups (PMEGs)
     55  *     shared by all contexts.  Thus, each Segment Map entry is 16 bits
     56  *     (15-bit PMEG index plus a VALID bit).
     57  *
     58  *     This is a key difference from the Sun MMU.  On the Sun MMU, PMEGs
     59  *     were a fairly scarce resource.  Here, there are a lot of them...
     60  *     in fact, enough to fully map the entirety of all 64 contexts
     61  *     (32,768 / 64 == 512).  This implies that we shouldn't burn too
     62  *     much memory on a per-PMEG basis to manage them.
     63  *
     64  * ==> Independent access to the Page Map entries.  This is a key difference
     65  *     from the Sun MMU, which always uses the context register + Segment
     66  *     Map to address Page Map entries.  The Phaethon 1's MMU has an address
     67  *     mux in front of the Page Map, which selects where the Page Map entry
     68  *     index comes from.
     69  *
     70  * ==> Protection on a per-page basis: K (kernel privilege required) and
     71  *     W (writable).
     72  *
     73  * ==> Page Referenced and Modified tracking.
     74  *
     75  * ==> Fast access to the kernel segment map via a dedicated address range
     76  *     for this purpose.
     77  *
     78  * ==> Separate reporting for privilege (user access to kernel-only page)
     79  *     and protection (write access to read-only page) violations, with
     80  *     privilege violation reporting taking priority.
     81  *
     82  * ==> Centralized bus error handling for the whole system, including a
     83  *     a bus cycle watchdog timer.
     84  *
     85  * ==> MMU register access via FC#4.
     86  *
     87  * ==> Separate MMU-enable input signal.  System board logic independent
     88  *     of the MMU is responsible for enabling the MMU post-reset and also
     89  *     dictates address decoding behvior before the MMU is enabled.  On
     90  *     all current implementations (heh), all {User,Super} {Data,Prog}
     91  *     cycles select the system ROM, which is reponsible for configuring
     92  *     and enabling the MMU.
     93  *
     94  * The MMU itself occupies about 1/3 of the board and sits between the CPU
     95  * and the rest of the system.  It is comprised of:
     96  *
     97  *	- A Microchip ATF1508AS-7AX100 7.5ns CPLD, logic written in
     98  *	  in Verilog and synthesized with Yosys.  This runs the bus
     99  *	  cycle state machine, houses the MMU's registers, computes
    100  *	  page faults, and swizzles the control signals for the MMU's
    101  *	  SRAMs.
    102  *	- 1x IS61C3216AL (32K x 16 12ns SRAM) for the SegMap.
    103  *	- 2x AS7C4098A (256K x 16 12ns SRAM) for the PageMap.
    104  *	- 10x 74AHCT157 quad 2-to-1 muxes to mux various address
    105  *	  inputs and outputs.
    106  *	- 3x 74ACHT373 octal transparent latch for the PageMap
    107  *	  index that in retrospect probably weren't necessary.
    108  *	- 6x 74AHCT245 8-bit bus transceivers for CPU data bus
    109  *	  interface to the SegMap and PageMap.
    110  *
    111  * The MMU runs on the main oscillator and generates the system clock
    112  * by dividing the main oscillator by 4.  This is typically a 40MHz
    113  * main oscillator, generating a 10MHz system clock.  No wait states
    114  * are incurred by the MMU.
    115  *
    116  * Address translation:
    117  *
    118  * +---------------+---------------------+
    119  * | Context [5:0] | Segment (VA[23:15]) |
    120  * +---------------+---------------------+--> 15-bit SegMap index --+
    121  *                                                                  |
    122  * +----------------------------------------------------------------+
    123  * |
    124  * +--> SegMap entry contains 15-bit PMEG number --+
    125  *                                                 |
    126  * +-----------------------------------------------+
    127  * |
    128  * +-------------------------+
    129  * |      PageMap index      |
    130  * | (PMEG << 3) | VA[14:12] |
    131  * +-------------------------+--> 18-bit PageMap index --+
    132  *                                                       |
    133  * +-----------------------------------------------------+
    134  * |
    135  * +--> PageMap entry (32-bits) (lower 16 bits are PFN) -----+
    136  *                                                           |
    137  * +---------------------------------------------------------+
    138  * |
    139  * +--> (PFN << 12) | VA[11:1] -> Physical address
    140  *
    141  * Format of a Page Map entry:
    142  *
    143  *  31          28   26         23         20 19 16 15                0
    144  * | V | W | K |  (r)  | R | M | s3 s2 s1 s0 | (r) | Page Frame Number |
    145  * | a   r   e     e     e   o   (software      e
    146  * | l   i   r     s     f   d      defined)    s
    147  * | i   t   n     e     e   i                  e
    148  * | d   e   e     r     r   f                  r
    149  *           l     v     e   i                  v
    150  *                 e     n   e                  e
    151  *                 d     c   d                  d
    152  *                       e
    153  *                       d
    154  */
    155 
    156 #define	PGMMU_NUM_CONTEXTS	64	/* 64 total contexts */
    157 #define	PGMMU_CONTEXT_SUPER	0	/* supervisor is always context 0 */
    158 
    159 #define	PGMMU_PAGE_SHIFT	12	/* 4KB pages */
    160 #define	PGMMU_PAGE_SIZE		(1U << PGMMU_PAGE_SHIFT)
    161 #define	PGMMU_PAGE_OFFSET	(PGMMU_PAGE_SIZE - 1)
    162 #define	PGMMU_PAGE_MASK		(~PGMMU_PAGE_OFFSET)
    163 
    164 #define	PGMMU_NUM_SEGS		512	/* 512 segments per context */
    165 #define	PGMMU_SEG_SHIFT		15	/* 32KB segments */
    166 					/* == 16MB - go go 68010! */
    167 #define	PGMMU_SEG_SIZE		(1U << PGMMU_SEG_SHIFT)
    168 #define	PGMMU_SEG_OFFSET	(PGMMU_SEG_SIZE - 1)
    169 #define	PGMMU_SEG_MASK		(~PGMMU_SEG_OFFSET)
    170 
    171 #define	PGMMU_NUM_PMEGS		32768	/* 32K total Page Map Entry Groups */
    172 #define	PGMMU_PMEG_SHIFT	3	/* 8 PMEs per PMEG */
    173 #define	PGMMU_PMEG_SIZE		(1U << PGMMU_PMEG_SHIFT)
    174 #define	PGMMU_PMEG_OFFSET	(PGMMU_PMEG_SIZE - 1)
    175 #define	PGMMU_NUM_PMES		(PGMMU_NUM_PMEGS << PGMMU_PMEG_SHIFT)
    176 
    177 #define	pgmmu_btos(va)		((vaddr_t)(va) >> PGMMU_SEG_SHIFT)
    178 #define	pgmmu_stob(s)		((vaddr_t)(s) << PGMMU_SEG_SHIFT)
    179 #define	pgmmu_trunc_seg(va)	((vaddr_t)(va) & PGMMU_SEG_MASK)
    180 #define	pgmmu_round_seg(va)	pgmmu_trunc_seg((va) + PGMMU_SEG_OFFSET)
    181 #define	pgmmu_next_seg(va)	pgmmu_round_seg((va) + PGMMU_PAGE_SIZE)
    182 
    183 #define	pgmmu_btop(va)		((vaddr_t)(va) >> PGMMU_PAGE_SHIFT)
    184 #define	pgmmu_ptob(p)		((vaddr_t)(p) << PGMMU_PAGE_SHIFT)
    185 #define	pgmmu_trunc_page(va)	((vaddr_t)(va) & PGMMU_PAGE_MASK)
    186 #define	pgmmu_round_page(va)	pgmmu_trunc_page((va) + PGMMU_PAGE_OFFSET)
    187 
    188 /* Segment Map entry: */
    189 typedef uint16_t sm_entry_t;
    190 #define	SME_PMEG	__BITS(0,14)	/* PMEG for segment */
    191 #define	SME_V		__BIT(15)	/* PMEG is valid */
    192 
    193 /* Page Map entry: */
    194 typedef uint32_t pm_entry_t;
    195 #define	PME_PFN		__BITS(0,15)
    196 	/* 16-19			   reserved */
    197 #define	PME_SW0		__BIT(20)	/* software bit 0 */
    198 #define	PME_SW1		__BIT(21)	/* software bit 1 */
    199 #define	PME_SW2		__BIT(22)	/* software bit 2 */
    200 #define	PME_SW3		__BIT(23)	/* software bit 3 */
    201 #define	PME_M		__BIT(24)	/* modified */
    202 #define	PME_R		__BIT(25)	/* referenced */
    203 	/* 26-28			   reserved */
    204 #define	PME_K		__BIT(29)	/* kernel priv required */
    205 #define	PME_W		__BIT(30)	/* writable page */
    206 #define	PME_V		__BIT(31)	/* valid mapping */
    207 
    208 #define	PME_WIRED	PME_SW0		/* wired mapping */
    209 #define	PME_PVLIST	PME_SW1		/* managed mapping */
    210 
    211 /*
    212  * FC#4 is used by the MMU as "control space".  CPU address bits A3..A1
    213  * are used as a register selector, and the space is decoded like so:
    214  *
    215  *                          selector bits
    216  *                               vvv
    217  *      xxxx.xxxx xxxx.xxxx xxxx.000x   non-MMU control space (ignored)
    218  *      SSSS.SSSS Sxxx.xxxx xxxx.0010   SegMap entry for Context 0
    219  *      SSSS.SSSS Sxxx.xxxx xxxx.0100   SegMap entry (relative to Context Reg)
    220  *      xxxx.xxxx xxxx.xxxx xxxx.0110   Context Register (byte)
    221  *      xxGG.GGGG GGGG.GGGG GEEE.1000   PageMap entry (upper word)
    222  *      xxGG.GGGG GGGG.GGGG GEEE.1010   PageMap entry (lower word)
    223  *        ^^^^^^^^^^^^^^^^^^^|||
    224  *                 PMEG      |||
    225  *                           ^^^
    226  *                    Entry within PMEG
    227  *      xxxx.xxxx xxxx.xxxx xxxx.1100   Bus Error Register (byte)
    228  *      xxxx.xxxx xxxx.xxxx xxxx.1110   (unused; reserved)
    229  */
    230 
    231 #define	PGMMU_CTLSEL_SEGMAP0	(1 << 1)
    232 #define	PGMMU_CTLSEL_SEGMAP	(2 << 1)
    233 #define	PGMMU_CTLSEL_CONTEXT	(3 << 1)
    234 #define	PGMMU_CTLSEL_PAGEMAP_U	(4 << 1)
    235 #define	PGMMU_CTLSEL_PAGEMAP_L	(5 << 1)
    236 #define	PGMMU_CTLSEL_PAGEMAP	PGMMU_CTLSEL_PAGEMAP_U
    237 #define	PGMMU_CTLSEL_BUSERROR	(6 << 1)
    238 
    239 #define	PGMMU_REG_SEGMAP0_ENTRY(va)	\
    240 	(pgmmu_trunc_seg(va) | PGMMU_CTLSEL_SEGMAP0)
    241 
    242 #define	PGMMU_REG_SEGMAP_ENTRY(va)	\
    243 	(pgmmu_trunc_seg(va) | PGMMU_CTLSEL_SEGMAP)
    244 
    245 #define	PGMMU_REG_CONTEXT		\
    246 	PGMMU_CTLSEL_CONTEXT
    247 
    248 #define	PGMMU_REG_PAGEMAP_ENTRY(e)	\
    249 	(((e) << 4) | PGMMU_CTLSEL_PAGEMAP)
    250 
    251 #define	PGMMU_REG_BUSERROR		\
    252 	PGMMU_CTLSEL_BUSERROR
    253 
    254 /*
    255  * Bus Error Register
    256  *
    257  * The Bus Error Register contains the cause of the most recent
    258  * bus error.  It is reset when read; writes are ignored.
    259  */
    260 #define	PGMMU_BERR_INVALID	__BIT(0) /* invalid translation */
    261 #define	PGMMU_BERR_PROT		__BIT(1) /* protection error (ro page) */
    262 #define	PGMMU_BERR_PRIV		__BIT(2) /* privilege error (ko page) */
    263 #define	PGMMU_BERR_TIMEOUT	__BIT(4) /* bus cycle watchdog timed out */
    264 #define	PGMMU_BERR_VME		__BIT(5) /* VMEbus /BERR asserted */
    265 
    266 	/* short-hand for "any MMU page fault type" */
    267 #define	PGMMU_BERR_PAGEFAULT	(PGMMU_BERR_INVALID | \
    268 				 PGMMU_BERR_PROT | \
    269 				 PGMMU_BERR_PRIV)
    270 
    271 #ifdef _KERNEL
    272 #include <hb68k/pg68k/control.h>
    273 
    274 #define	pgmmu_getsme0(va)	\
    275 	control_inw(PGMMU_REG_SEGMAP0_ENTRY(va))
    276 #define	pgmmu_setsme0(va, sme)	\
    277 	control_outw(PGMMU_REG_SEGMAP0_ENTRY(va), (sme))
    278 
    279 #define	pgmmu_getsme(va)	\
    280 	control_inw(PGMMU_REG_SEGMAP_ENTRY(va))
    281 #define	pgmmu_setsme(va, sme)	\
    282 	control_outw(PGMMU_REG_SEGMAP_ENTRY(va), (uint16_t)(sme))
    283 
    284 #define	pgmmu_getcontext()	\
    285 	control_inb(PGMMU_REG_CONTEXT)
    286 #define	pgmmu_setcontext(c)	\
    287 	control_outb(PGMMU_REG_CONTEXT, (uint8_t)(c))
    288 
    289 #define	pgmmu_getpme(e)		\
    290 	control_inl(PGMMU_REG_PAGEMAP_ENTRY(e))
    291 #define	pgmmu_setpme(e, pme)	\
    292 	control_outl(PGMMU_REG_PAGEMAP_ENTRY(e), (pme))
    293 
    294 #define	pgmmu_getberr()		\
    295 	control_inb(PGMMU_REG_BUSERROR)
    296 
    297 #endif /* _KERNEL */
    298 
    299 #endif /* _PG68K_PGMMU_H_ */
    300