18ab2f5ecSMark Murray /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 48ab2f5ecSMark Murray * Copyright (c) 2004 Mark R V Murray 58ab2f5ecSMark Murray * All rights reserved. 68ab2f5ecSMark Murray * 78ab2f5ecSMark Murray * Redistribution and use in source and binary forms, with or without 88ab2f5ecSMark Murray * modification, are permitted provided that the following conditions 98ab2f5ecSMark Murray * are met: 108ab2f5ecSMark Murray * 1. Redistributions of source code must retain the above copyright 118ab2f5ecSMark Murray * notice, this list of conditions and the following disclaimer 128ab2f5ecSMark Murray * in this position and unchanged. 138ab2f5ecSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 148ab2f5ecSMark Murray * notice, this list of conditions and the following disclaimer in the 158ab2f5ecSMark Murray * documentation and/or other materials provided with the distribution. 168ab2f5ecSMark Murray * 178ab2f5ecSMark Murray * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 188ab2f5ecSMark Murray * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 198ab2f5ecSMark Murray * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 208ab2f5ecSMark Murray * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 218ab2f5ecSMark Murray * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 228ab2f5ecSMark Murray * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 238ab2f5ecSMark Murray * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 248ab2f5ecSMark Murray * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258ab2f5ecSMark Murray * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 268ab2f5ecSMark Murray * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278ab2f5ecSMark Murray * 288ab2f5ecSMark Murray */ 298ab2f5ecSMark Murray 308ab2f5ecSMark Murray #include <sys/cdefs.h> 318ab2f5ecSMark Murray __FBSDID("$FreeBSD$"); 328ab2f5ecSMark Murray 338ab2f5ecSMark Murray #include <sys/param.h> 348ab2f5ecSMark Murray #include <sys/conf.h> 358ab2f5ecSMark Murray #include <sys/fcntl.h> 362d838cd8SMark Johnston #include <sys/ioccom.h> 378ab2f5ecSMark Murray #include <sys/kernel.h> 388ab2f5ecSMark Murray #include <sys/lock.h> 398ab2f5ecSMark Murray #include <sys/malloc.h> 402fea6431SJung-uk Kim #include <sys/memrange.h> 418ab2f5ecSMark Murray #include <sys/module.h> 428ab2f5ecSMark Murray #include <sys/mutex.h> 43c71e3362SJamie Gritton #include <sys/priv.h> 448ab2f5ecSMark Murray #include <sys/proc.h> 458ab2f5ecSMark Murray #include <sys/signalvar.h> 468ab2f5ecSMark Murray #include <sys/systm.h> 478ab2f5ecSMark Murray #include <sys/uio.h> 488ab2f5ecSMark Murray 498ab2f5ecSMark Murray #include <vm/vm.h> 502d838cd8SMark Johnston #include <vm/vm_param.h> 518ab2f5ecSMark Murray #include <vm/pmap.h> 522d838cd8SMark Johnston #include <vm/vm_map.h> 532d838cd8SMark Johnston #include <vm/vm_object.h> 542d838cd8SMark Johnston #include <vm/vm_page.h> 552d838cd8SMark Johnston #include <vm/vm_phys.h> 568ab2f5ecSMark Murray 578ab2f5ecSMark Murray #include <machine/memdev.h> 588ab2f5ecSMark Murray 598ab2f5ecSMark Murray static struct cdev *memdev, *kmemdev; 608ab2f5ecSMark Murray 612d838cd8SMark Johnston static d_ioctl_t memioctl; 622d838cd8SMark Johnston 638ab2f5ecSMark Murray static struct cdevsw mem_cdevsw = { 648ab2f5ecSMark Murray .d_version = D_VERSION, 658f4548ffSKonstantin Belousov .d_flags = D_MEM, 668ab2f5ecSMark Murray .d_open = memopen, 678ab2f5ecSMark Murray .d_read = memrw, 688ab2f5ecSMark Murray .d_write = memrw, 698ab2f5ecSMark Murray .d_ioctl = memioctl, 708ab2f5ecSMark Murray .d_mmap = memmmap, 718ab2f5ecSMark Murray .d_name = "mem", 728ab2f5ecSMark Murray }; 738ab2f5ecSMark Murray 748ab2f5ecSMark Murray /* ARGSUSED */ 758ab2f5ecSMark Murray int 768ab2f5ecSMark Murray memopen(struct cdev *dev __unused, int flags, int fmt __unused, 778ab2f5ecSMark Murray struct thread *td) 788ab2f5ecSMark Murray { 798ab2f5ecSMark Murray int error = 0; 808ab2f5ecSMark Murray 81c71e3362SJamie Gritton if (flags & FREAD) 82c71e3362SJamie Gritton error = priv_check(td, PRIV_KMEM_READ); 83c71e3362SJamie Gritton if (flags & FWRITE) { 84c71e3362SJamie Gritton if (error == 0) 85c71e3362SJamie Gritton error = priv_check(td, PRIV_KMEM_WRITE); 86c71e3362SJamie Gritton if (error == 0) 878ab2f5ecSMark Murray error = securelevel_gt(td->td_ucred, 0); 88c71e3362SJamie Gritton } 898ab2f5ecSMark Murray 908ab2f5ecSMark Murray return (error); 918ab2f5ecSMark Murray } 928ab2f5ecSMark Murray 932d838cd8SMark Johnston static int 942d838cd8SMark Johnston memioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, 952d838cd8SMark Johnston struct thread *td) 962d838cd8SMark Johnston { 972d838cd8SMark Johnston vm_map_t map; 982d838cd8SMark Johnston vm_map_entry_t entry; 992d838cd8SMark Johnston struct mem_extract *me; 1002d838cd8SMark Johnston int error; 1012d838cd8SMark Johnston 1022d838cd8SMark Johnston error = 0; 1032d838cd8SMark Johnston switch (cmd) { 1042d838cd8SMark Johnston case MEM_EXTRACT_PADDR: 1052d838cd8SMark Johnston me = (struct mem_extract *)data; 1062d838cd8SMark Johnston 1072d838cd8SMark Johnston map = &td->td_proc->p_vmspace->vm_map; 1082d838cd8SMark Johnston vm_map_lock_read(map); 1092d838cd8SMark Johnston if (vm_map_lookup_entry(map, me->me_vaddr, &entry)) { 1102d838cd8SMark Johnston me->me_paddr = pmap_extract( 1112d838cd8SMark Johnston &td->td_proc->p_vmspace->vm_pmap, me->me_vaddr); 1122d838cd8SMark Johnston if (me->me_paddr != 0) { 1132d838cd8SMark Johnston me->me_state = ME_STATE_MAPPED; 114*431fb8abSMark Johnston me->me_domain = vm_phys_domain(me->me_paddr); 1152d838cd8SMark Johnston } else { 1162d838cd8SMark Johnston me->me_state = ME_STATE_VALID; 1172d838cd8SMark Johnston } 1182d838cd8SMark Johnston } else { 1192d838cd8SMark Johnston me->me_state = ME_STATE_INVALID; 1202d838cd8SMark Johnston } 1212d838cd8SMark Johnston vm_map_unlock_read(map); 1222d838cd8SMark Johnston break; 1232d838cd8SMark Johnston default: 1242d838cd8SMark Johnston error = memioctl_md(dev, cmd, data, flags, td); 1252d838cd8SMark Johnston break; 1262d838cd8SMark Johnston } 1272d838cd8SMark Johnston return (error); 1282d838cd8SMark Johnston } 1292d838cd8SMark Johnston 1308ab2f5ecSMark Murray /* ARGSUSED */ 1318ab2f5ecSMark Murray static int 1328ab2f5ecSMark Murray mem_modevent(module_t mod __unused, int type, void *data __unused) 1338ab2f5ecSMark Murray { 1348ab2f5ecSMark Murray switch(type) { 1358ab2f5ecSMark Murray case MOD_LOAD: 1368ab2f5ecSMark Murray if (bootverbose) 1378ab2f5ecSMark Murray printf("mem: <memory>\n"); 1382fea6431SJung-uk Kim mem_range_init(); 1398ab2f5ecSMark Murray memdev = make_dev(&mem_cdevsw, CDEV_MINOR_MEM, 1408ab2f5ecSMark Murray UID_ROOT, GID_KMEM, 0640, "mem"); 1418ab2f5ecSMark Murray kmemdev = make_dev(&mem_cdevsw, CDEV_MINOR_KMEM, 1428ab2f5ecSMark Murray UID_ROOT, GID_KMEM, 0640, "kmem"); 1438ab2f5ecSMark Murray break; 1448ab2f5ecSMark Murray 1458ab2f5ecSMark Murray case MOD_UNLOAD: 1462fea6431SJung-uk Kim mem_range_destroy(); 1478ab2f5ecSMark Murray destroy_dev(memdev); 1488ab2f5ecSMark Murray destroy_dev(kmemdev); 1498ab2f5ecSMark Murray break; 1508ab2f5ecSMark Murray 1518ab2f5ecSMark Murray case MOD_SHUTDOWN: 1528ab2f5ecSMark Murray break; 1538ab2f5ecSMark Murray 1548ab2f5ecSMark Murray default: 1558ab2f5ecSMark Murray return(EOPNOTSUPP); 1568ab2f5ecSMark Murray } 1578ab2f5ecSMark Murray 1588ab2f5ecSMark Murray return (0); 1598ab2f5ecSMark Murray } 1608ab2f5ecSMark Murray 1618ab2f5ecSMark Murray DEV_MODULE(mem, mem_modevent, NULL); 162ce46e205SMark Murray MODULE_VERSION(mem, 1); 163