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