1 /* $OpenBSD: mem.c,v 1.10 2024/12/30 02:46:00 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 1998-2004 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 /* 29 * Copyright (c) 1991,1992,1994, The University of Utah and 30 * the Computer Systems Laboratory (CSL). All rights reserved. 31 * 32 * Subject to your agreements with CMU, 33 * permission to use, copy, modify and distribute this software and its 34 * documentation is hereby granted, provided that both the copyright 35 * notice and this permission notice appear in all copies of the 36 * software, derivative works or modified versions, and any portions 37 * thereof, and that both notices appear in supporting documentation. 38 * 39 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS 40 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF 41 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 42 * 43 * CSL requests users of this software to return to csl-dist@cs.utah.edu any 44 * improvements that they make and grant CSL redistribution rights. 45 * 46 * Utah $Hdr: mem.c 1.9 94/12/16$ 47 */ 48 /* 49 * Mach Operating System 50 * Copyright (c) 1992 Carnegie Mellon University 51 * All Rights Reserved. 52 * 53 * Permission to use, copy, modify and distribute this software and its 54 * documentation is hereby granted, provided that both the copyright 55 * notice and this permission notice appear in all copies of the 56 * software, derivative works or modified versions, and any portions 57 * thereof, and that both notices appear in supporting documentation. 58 * 59 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 60 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 61 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 62 * 63 * Carnegie Mellon requests users of this software to return to 64 * 65 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 66 * School of Computer Science 67 * Carnegie Mellon University 68 * Pittsburgh PA 15213-3890 69 * 70 * any improvements or extensions that they make and grant Carnegie Mellon 71 * the rights to redistribute these changes. 72 */ 73 74 #include <sys/param.h> 75 #include <sys/systm.h> 76 #include <sys/buf.h> 77 #include <sys/filio.h> 78 #include <sys/malloc.h> 79 #include <sys/proc.h> 80 #include <sys/uio.h> 81 #include <sys/device.h> 82 #include <sys/errno.h> 83 #include <sys/ioctl.h> 84 #include <sys/atomic.h> 85 86 #include <uvm/uvm_extern.h> 87 88 #include <machine/conf.h> 89 #include <machine/bus.h> 90 #include <machine/iomod.h> 91 #include <machine/autoconf.h> 92 #include <machine/pmap.h> 93 94 #include <hppa/dev/cpudevs.h> 95 #include <hppa/dev/viper.h> 96 97 #define VIPER_HPA 0xfffbf000 98 99 /* registers on the PCXL2 MIOC */ 100 struct l2_mioc { 101 u_int32_t pad[0x20]; /* 0x000 */ 102 u_int32_t mioc_control; /* 0x080 MIOC control bits */ 103 u_int32_t mioc_status; /* 0x084 MIOC status bits */ 104 u_int32_t pad1[6]; /* 0x088 */ 105 u_int32_t sltcv; /* 0x0a0 L2 cache control */ 106 #define SLTCV_AVWL 0x00002000 /* extra cycle for addr valid write low */ 107 #define SLTCV_UP4COUT 0x00001000 /* update cache on CPU castouts */ 108 #define SLTCV_EDCEN 0x08000000 /* enable error correction */ 109 #define SLTCV_EDTAG 0x10000000 /* enable diagtag */ 110 #define SLTCV_CHKTP 0x20000000 /* enable parity checking */ 111 #define SLTCV_LOWPWR 0x40000000 /* low power mode */ 112 #define SLTCV_ENABLE 0x80000000 /* enable L2 cache */ 113 #define SLTCV_BITS "\020\15avwl\16up4cout\24edcen\25edtag\26chktp\27lowpwr\30l2ena" 114 u_int32_t tagmask; /* 0x0a4 L2 cache tag mask */ 115 u_int32_t diagtag; /* 0x0a8 L2 invalidates tag */ 116 u_int32_t sltestat; /* 0x0ac L2 last logged tag read */ 117 u_int32_t slteadd; /* 0x0b0 L2 pa of -- " -- */ 118 u_int32_t pad2[3]; /* 0x0b4 */ 119 u_int32_t mtcv; /* 0x0c0 MIOC timings */ 120 u_int32_t ref; /* 0x0cc MIOC refresh timings */ 121 u_int32_t pad3[4]; /* 0x0d0 */ 122 u_int32_t mderradd; /* 0x0e0 addr of most evil mem error */ 123 u_int32_t pad4; /* 0x0e4 */ 124 u_int32_t dmaerr; /* 0x0e8 addr of most evil dma error */ 125 u_int32_t dioerr; /* 0x0ec addr of most evil dio error */ 126 u_int32_t gsc_timeout; /* 0x0f0 1-compl of GSC timeout delay */ 127 u_int32_t hidmamem; /* 0x0f4 amount of phys mem installed */ 128 u_int32_t pad5[2]; /* 0x0f8 */ 129 u_int32_t memcomp[16]; /* 0x100 memory address comparators */ 130 u_int32_t memmask[16]; /* 0x140 masks for -- " -- */ 131 u_int32_t memtest; /* 0x180 test address decoding */ 132 u_int32_t pad6[0xf]; /* 0x184 */ 133 u_int32_t outchk; /* 0x1c0 address decoding output */ 134 u_int32_t pad7[0x168]; /* 0x200 */ 135 u_int32_t gsc15x_config; /* 0x7a0 writev enable */ 136 }; 137 138 struct mem_softc { 139 struct device sc_dev; 140 141 volatile struct vi_trs *sc_vp; 142 volatile struct l2_mioc *sc_l2; 143 }; 144 145 int memmatch(struct device *, void *, void *); 146 void memattach(struct device *, struct device *, void *); 147 148 const struct cfattach mem_ca = { 149 sizeof(struct mem_softc), memmatch, memattach 150 }; 151 152 struct cfdriver mem_cd = { 153 NULL, "mem", DV_DULL 154 }; 155 156 caddr_t zeropage; 157 158 int 159 memmatch(struct device *parent, void *cfdata, void *aux) 160 { 161 struct confargs *ca = aux; 162 163 if (ca->ca_type.iodc_type != HPPA_TYPE_MEMORY || 164 ca->ca_type.iodc_sv_model != HPPA_MEMORY_PDEP) 165 return 0; 166 167 return 1; 168 } 169 170 void 171 memattach(struct device *parent, struct device *self, void *aux) 172 { 173 struct pdc_iodc_minit pdc_minit PDC_ALIGNMENT; 174 struct mem_softc *sc = (struct mem_softc *)self; 175 struct confargs *ca = aux; 176 int err; 177 178 printf (":"); 179 180 /* XXX check if we are dealing w/ Viper */ 181 if (ca->ca_hpa == (hppa_hpa_t)VIPER_HPA) { 182 183 sc->sc_vp = (struct vi_trs *) 184 &((struct iomod *)ca->ca_hpa)->priv_trs; 185 186 printf(" viper rev %x,", sc->sc_vp->vi_status.hw_rev); 187 188 /* XXX other values seem to blow it up */ 189 if (sc->sc_vp->vi_status.hw_rev == 0) { 190 u_int32_t vic; 191 int s, settimeout; 192 193 switch (cpu_hvers) { 194 case HPPA_BOARD_HP705: 195 case HPPA_BOARD_HP710: 196 case HPPA_BOARD_HP715_33: 197 case HPPA_BOARD_HP715S_33: 198 case HPPA_BOARD_HP715T_33: 199 case HPPA_BOARD_HP715_50: 200 case HPPA_BOARD_HP715S_50: 201 case HPPA_BOARD_HP715T_50: 202 case HPPA_BOARD_HP715_75: 203 case HPPA_BOARD_HP720: 204 case HPPA_BOARD_HP725_50: 205 case HPPA_BOARD_HP725_75: 206 case HPPA_BOARD_HP730_66: 207 case HPPA_BOARD_HP750_66: 208 settimeout = 1; 209 break; 210 default: 211 settimeout = 0; 212 break; 213 } 214 if (sc->sc_dev.dv_cfdata->cf_flags & 1) 215 settimeout = !settimeout; 216 217 #ifdef DEBUG 218 printf(" ctrl %b", VI_CTRL, VI_CTRL_BITS); 219 #endif 220 s = splhigh(); 221 vic = VI_CTRL; 222 vic &= ~VI_CTRL_CORE_DEN; 223 vic &= ~VI_CTRL_SGC0_DEN; 224 vic &= ~VI_CTRL_SGC1_DEN; 225 vic |= VI_CTRL_EISA_DEN; 226 vic |= VI_CTRL_CORE_PRF; 227 228 if (settimeout && (vic & VI_CTRL_VSC_TOUT) == 0) 229 vic |= (850 << 19); /* clks */ 230 231 sc->sc_vp->vi_control = vic; 232 233 __asm volatile("stwas %1, 0(%0)" 234 :: "r" (&VI_CTRL), "r" (vic) : "memory"); 235 splx(s); 236 #ifdef DEBUG 237 printf (" >> %b,", vic, VI_CTRL_BITS); 238 #endif 239 } else { 240 /* set at least VI_CTRL_EISA_DEN ? */ 241 } 242 } else 243 sc->sc_vp = NULL; 244 245 if ((err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_NINIT, 246 &pdc_minit, ca->ca_hpa, PAGE0->imm_spa_size)) < 0) 247 pdc_minit.max_spa = PAGE0->imm_max_mem; 248 249 printf(" size %d", pdc_minit.max_spa / (1024*1024)); 250 if (pdc_minit.max_spa % (1024*1024)) 251 printf(".%d", pdc_minit.max_spa % (1024*1024)); 252 printf("MB"); 253 254 /* L2 cache controller is a part of the memory controller on PCXL2 */ 255 if (cpu_type == hpcxl2) { 256 sc->sc_l2 = (struct l2_mioc *)ca->ca_hpa; 257 #ifdef DEBUG 258 printf(", sltcv %b", sc->sc_l2->sltcv, SLTCV_BITS); 259 #endif 260 /* sc->sc_l2->sltcv |= SLTCV_UP4COUT; */ 261 if (sc->sc_l2->sltcv & SLTCV_ENABLE) { 262 u_int32_t tagmask = sc->sc_l2->tagmask >> 20; 263 264 printf(", %dMB L2 cache", tagmask + 1); 265 } 266 } 267 268 printf("\n"); 269 } 270 271 void 272 viper_setintrwnd(u_int32_t mask) 273 { 274 struct mem_softc *sc; 275 276 sc = mem_cd.cd_devs[0]; 277 278 if (sc->sc_vp) 279 sc->sc_vp->vi_intrwd = mask; 280 } 281 282 void 283 viper_eisa_en(void) 284 { 285 struct mem_softc *sc; 286 287 sc = mem_cd.cd_devs[0]; 288 if (sc->sc_vp) { 289 u_int32_t vic; 290 int s; 291 292 s = splhigh(); 293 vic = VI_CTRL; 294 vic &= ~VI_CTRL_EISA_DEN; 295 sc->sc_vp->vi_control = vic; 296 __asm volatile("stwas %1, 0(%0)" 297 :: "r" (&VI_CTRL), "r" (vic) : "memory"); 298 splx(s); 299 } 300 } 301 302 int 303 mmopen(dev_t dev, int flag, int ioflag, struct proc *p) 304 { 305 extern int allowkmem; 306 307 switch (minor(dev)) { 308 case 0: 309 case 1: 310 if ((int)atomic_load_int(&securelevel) <= 0 || 311 atomic_load_int(&allowkmem)) 312 break; 313 return (EPERM); 314 case 2: 315 case 12: 316 break; 317 default: 318 return (ENXIO); 319 } 320 return (0); 321 } 322 323 int 324 mmclose(dev_t dev, int flag, int mode, struct proc *p) 325 { 326 return (0); 327 } 328 329 int 330 mmrw(dev_t dev, struct uio *uio, int flags) 331 { 332 struct iovec *iov; 333 vaddr_t v, o; 334 int error = 0; 335 size_t c; 336 337 while (uio->uio_resid > 0 && error == 0) { 338 iov = uio->uio_iov; 339 if (iov->iov_len == 0) { 340 uio->uio_iov++; 341 uio->uio_iovcnt--; 342 if (uio->uio_iovcnt < 0) 343 panic("mmrw"); 344 continue; 345 } 346 switch (minor(dev)) { 347 348 case 0: /* /dev/mem */ 349 350 /* If the address isn't in RAM, bail. */ 351 v = uio->uio_offset; 352 if (atop(v) > physmem) { 353 error = EFAULT; 354 /* this will break us out of the loop */ 355 continue; 356 } 357 c = ptoa(physmem) - v; 358 c = ulmin(c, uio->uio_resid); 359 error = uiomove((caddr_t)v, c, uio); 360 break; 361 362 case 1: /* /dev/kmem */ 363 v = uio->uio_offset; 364 o = v & PGOFSET; 365 c = ulmin(uio->uio_resid, PAGE_SIZE - o); 366 if (atop(v) > physmem && !uvm_kernacc((caddr_t)v, 367 c, (uio->uio_rw == UIO_READ) ? B_READ : B_WRITE)) { 368 error = EFAULT; 369 /* this will break us out of the loop */ 370 continue; 371 } 372 error = uiomove((caddr_t)v, c, uio); 373 break; 374 375 case 2: /* /dev/null */ 376 if (uio->uio_rw == UIO_WRITE) 377 uio->uio_resid = 0; 378 return (0); 379 380 case 12: /* /dev/zero */ 381 /* Write to /dev/zero is ignored. */ 382 if (uio->uio_rw == UIO_WRITE) { 383 uio->uio_resid = 0; 384 return (0); 385 } 386 /* 387 * On the first call, allocate and zero a page 388 * of memory for use with /dev/zero. 389 */ 390 if (zeropage == NULL) 391 zeropage = malloc(PAGE_SIZE, M_TEMP, 392 M_WAITOK | M_ZERO); 393 c = ulmin(iov->iov_len, PAGE_SIZE); 394 error = uiomove(zeropage, c, uio); 395 break; 396 397 default: 398 return (ENXIO); 399 } 400 } 401 402 return (error); 403 } 404 405 paddr_t 406 mmmmap(dev_t dev, off_t off, int prot) 407 { 408 if (minor(dev) != 0) 409 return (-1); 410 411 /* 412 * Allow access only in RAM. 413 */ 414 #if 0 415 if (off < ptoa(firstusablepage) || 416 off >= ptoa(lastusablepage + 1)) 417 return (-1); 418 #endif 419 return (off); 420 } 421 422 int 423 mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 424 { 425 switch (cmd) { 426 case FIOASYNC: 427 /* handled by fd layer */ 428 return 0; 429 } 430 431 return (ENOTTY); 432 } 433