mem.c revision 268194
1/*-
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department, and code derived from software contributed to
9 * Berkeley by William Jolitz.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 *	from: Utah $Hdr: mem.c 1.13 89/10/08$
36 *	from: @(#)mem.c	7.2 (Berkeley) 5/9/91
37 */
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: stable/10/sys/ia64/ia64/mem.c 268194 2014-07-02 23:12:56Z marcel $");
41
42/*
43 * Memory special file
44 */
45
46#include <sys/param.h>
47#include <sys/conf.h>
48#include <sys/fcntl.h>
49#include <sys/kernel.h>
50#include <sys/malloc.h>
51#include <sys/memrange.h>
52#include <sys/systm.h>
53#include <sys/uio.h>
54#include <machine/efi.h>
55
56#include <vm/vm.h>
57#include <vm/pmap.h>
58#include <vm/vm_extern.h>
59
60#include <machine/memdev.h>
61
62struct mem_range_softc mem_range_softc;
63
64static int
65mem_phys2virt(vm_offset_t offset, int prot, void **ptr, u_long *limit)
66{
67	struct efi_md *md;
68
69	if (prot & ~(VM_PROT_READ | VM_PROT_WRITE))
70		return (EPERM);
71
72	md = efi_md_find(offset);
73	if (md == NULL)
74		return (EFAULT);
75
76	if (md->md_type == EFI_MD_TYPE_BAD)
77		return (EIO);
78
79	*ptr = (void *)((md->md_attr & EFI_MD_ATTR_WB)
80	    ? IA64_PHYS_TO_RR7(offset) : IA64_PHYS_TO_RR6(offset));
81	*limit = (md->md_pages * EFI_PAGE_SIZE) - (offset - md->md_phys);
82	return (0);
83}
84
85/* ARGSUSED */
86int
87memrw(struct cdev *dev, struct uio *uio, int flags)
88{
89	struct iovec *iov;
90	off_t ofs;
91	vm_offset_t addr;
92	void *ptr;
93	u_long limit;
94	int count, error, phys, rw;
95
96	error = 0;
97	rw = (uio->uio_rw == UIO_READ) ? VM_PROT_READ : VM_PROT_WRITE;
98
99	while (uio->uio_resid > 0 && !error) {
100		iov = uio->uio_iov;
101		if (iov->iov_len == 0) {
102			uio->uio_iov++;
103			uio->uio_iovcnt--;
104			if (uio->uio_iovcnt < 0)
105				panic("memrw");
106			continue;
107		}
108
109		ofs = uio->uio_offset;
110
111		phys = (dev2unit(dev) == CDEV_MINOR_MEM) ? 1 : 0;
112		if (phys == 0 && ofs >= IA64_RR_BASE(6)) {
113			ofs = IA64_RR_MASK(ofs);
114			phys++;
115		}
116
117		if (phys) {
118			error = mem_phys2virt(ofs, rw, &ptr, &limit);
119			if (error)
120				return (error);
121
122			count = min(uio->uio_resid, limit);
123			error = uiomove(ptr, count, uio);
124		} else {
125			ptr = (void *)ofs;
126			count = iov->iov_len;
127
128			/*
129			 * Make sure that all of the pages are currently
130			 * resident so that we don't create any zero-fill
131			 * pages.
132			 */
133			limit = round_page(ofs + count);
134			addr = trunc_page(ofs);
135			if (addr < VM_MAXUSER_ADDRESS)
136				return (EINVAL);
137			for (; addr < limit; addr += PAGE_SIZE) {
138				if (pmap_kextract(addr) == 0)
139					return (EFAULT);
140			}
141			if (!kernacc(ptr, count, rw))
142				return (EFAULT);
143			error = uiomove(ptr, count, uio);
144		}
145		/* else panic! */
146	}
147	return (error);
148}
149
150/*
151 * allow user processes to MMAP some memory sections
152 * instead of going through read/write
153 */
154int
155memmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
156    int prot, vm_memattr_t *memattr)
157{
158	void *ptr;
159	u_long limit;
160	int error;
161
162	/*
163	 * /dev/mem is the only one that makes sense through this
164	 * interface.  For /dev/kmem any physaddr we return here
165	 * could be transient and hence incorrect or invalid at
166	 * a later time.
167	 */
168	if (dev2unit(dev) != CDEV_MINOR_MEM)
169		return (ENXIO);
170
171	error = mem_phys2virt(offset, prot, &ptr, &limit);
172	if (error)
173		return (error);
174
175	*paddr = offset;
176	*memattr = ((uintptr_t)ptr >= IA64_RR_BASE(7)) ?
177	    VM_MEMATTR_WRITE_BACK : VM_MEMATTR_UNCACHEABLE;
178	return (0);
179}
180