Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / compat / darwin / darwin_mman.c
blob276b95c97acb44e38e13511b20c146ca009559ab
1 /* $NetBSD: darwin_mman.c,v 1.30 2009/01/11 02:45:47 christos Exp $ */
3 /*-
4 * Copyright (c) 2002, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus.
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: darwin_mman.c,v 1.30 2009/01/11 02:45:47 christos Exp $");
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/signal.h>
40 #include <sys/mount.h>
41 #include <sys/proc.h>
42 #include <sys/fcntl.h>
43 #include <sys/file.h>
44 #include <sys/filedesc.h>
45 #include <sys/vnode.h>
46 #include <sys/exec.h>
48 #include <sys/syscallargs.h>
50 #include <compat/sys/signal.h>
52 #include <compat/mach/mach_types.h>
53 #include <compat/mach/mach_vm.h>
55 #include <compat/darwin/darwin_types.h>
56 #include <compat/darwin/darwin_audit.h>
57 #include <compat/darwin/darwin_syscallargs.h>
59 int
60 darwin_sys_load_shared_file(struct lwp *l, const struct darwin_sys_load_shared_file_args *uap, register_t *retval)
62 /* {
63 syscallarg(char *) filename;
64 syscallarg(void *) addr;
65 syscallarg(u_long) len;
66 syscallarg(void **) base;
67 syscallarg(int) count:
68 syscallarg(mach_sf_mapping_t *) mappings;
69 syscallarg(int *) flags;
70 } */
71 struct file *fp;
72 struct vnode *vp = NULL;
73 vaddr_t base;
74 struct proc *p = l->l_proc;
75 int flags;
76 char *filename;
77 mach_sf_mapping_t *mapp = NULL;
78 size_t maplen;
79 struct sys_open_args open_cup;
80 struct sys_close_args close_cup;
81 register_t fdc;
82 int fd;
83 int i;
84 int error;
85 vaddr_t max_addr, addr;
86 size_t len;
87 vaddr_t uaddr;
88 int need_relocation;
89 struct exec_vmcmd evc;
91 filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
92 if ((error = copyin(SCARG(uap, filename), filename, MAXPATHLEN)) != 0)
93 goto bad1;
95 if ((error = copyin(SCARG(uap, base), &base, sizeof(base))) != 0)
96 goto bad1;
98 if ((error = copyin(SCARG(uap, flags), &flags, sizeof(base))) != 0)
99 goto bad1;
101 #ifdef DEBUG_DARWIN
102 DPRINTF(("darwin_sys_load_shared_file: filename = %p ",
103 SCARG(uap, filename)));
104 DPRINTF(("addr = %p len = 0x%08lx base = %p ",
105 SCARG(uap, addr), SCARG(uap, len), SCARG(uap, base)));
106 DPRINTF(("count = %d mappings = %p flags = %p ",
107 SCARG(uap, count), SCARG(uap, mappings), SCARG(uap, flags)));
108 DPRINTF(("*base = 0x%08lx *flags = %d filename=`%s'\n",
109 base, flags, filename));
110 #endif
112 SCARG(&open_cup, path) = SCARG(uap, filename);
113 SCARG(&open_cup, flags) = O_RDONLY;
114 SCARG(&open_cup, mode) = 0;
115 if ((error = sys_open(l, &open_cup, &fdc)) != 0)
116 goto bad1;
118 fd = (int)fdc;
119 fp = fd_getfile(fd);
120 if (fp == NULL) {
121 error = EBADF;
122 goto bad1point5;
124 vp = fp->f_data;
125 vref(vp);
127 if (SCARG(uap, count) < 0 ||
128 SCARG(uap, count) > PAGE_SIZE / sizeof(*mapp)) {
129 error = EINVAL;
130 goto bad2;
132 maplen = SCARG(uap, count) * sizeof(*mapp);
133 mapp = malloc(maplen, M_TEMP, M_WAITOK);
135 if ((error = copyin(SCARG(uap, mappings), mapp, maplen)) != 0)
136 goto bad2;
138 #ifdef DEBUG_DARWIN
139 for (i = 0; i < SCARG(uap, count); i++) {
140 DPRINTF(("mapp[%d].mapping_offset = 0x%08lx\n",
141 i, mapp[i].mapping_offset));
142 DPRINTF(("mapp[%d].size = 0x%08lx\n", i, (long)mapp[i].size));
143 DPRINTF(("mapp[%d].file_offset = 0x%08lx\n",
144 i, mapp[i].file_offset));
145 DPRINTF(("mapp[%d].protection = %d\n",
146 i, mapp[i].protection));
147 DPRINTF(("mapp[%d].cksum = %ld\n", i, mapp[i].cksum));
149 #endif
151 /* Check if we can load at the default addresses */
152 need_relocation = 0;
153 vm_map_lock(&p->p_vmspace->vm_map);
154 for (i = 0; i < SCARG(uap, count); i++)
155 if ((uvm_map_findspace(&p->p_vmspace->vm_map,
156 base + mapp[i].mapping_offset, mapp[i].size,
157 &uaddr, NULL, 0, 0, UVM_FLAG_FIXED)) == NULL)
158 need_relocation = 1;
159 vm_map_unlock(&p->p_vmspace->vm_map);
161 /* If we cannot, we need a relocation */
162 if (need_relocation) {
163 DPRINTF(("Relocating\n"));
164 /* Compute the length of the region enclosing all sections */
165 max_addr = 0;
166 for (i = 0; i < SCARG(uap, count); i++) {
167 addr = (vaddr_t)(mapp[i].mapping_offset
168 + base + mapp[i].size);
169 if (addr > max_addr)
170 max_addr = addr;
172 len = max_addr - base;
173 DPRINTF(("base = 0x%08lx max_addr = 0x%08lx len = 0x%08x\n",
174 base, max_addr, len));
176 /* Find some place to map this region */
177 vm_map_lock(&p->p_vmspace->vm_map);
178 if ((uvm_map_findspace(&p->p_vmspace->vm_map, base,
179 len, &uaddr, NULL, 0, PAGE_SIZE, 0)) == NULL) {
180 DPRINTF(("Impossible to find some space\n"));
181 vm_map_unlock(&p->p_vmspace->vm_map);
182 error = ENOMEM;
183 goto bad2;
185 vm_map_unlock(&p->p_vmspace->vm_map);
187 /* Update the base address */
188 base = uaddr;
189 DPRINTF(("New base address: base = 0x%08lx\n", base));
192 /* Do the actual mapping */
193 for (i = 0; i < SCARG(uap, count); i++) {
194 memset(&evc, 0, sizeof(evc));
195 evc.ev_addr = base + mapp[i].mapping_offset;
196 evc.ev_len = mapp[i].size;
197 evc.ev_prot = mapp[i].protection & VM_PROT_ALL;
198 evc.ev_flags = 0;
199 if (mapp[i].protection & MACH_VM_PROT_ZF)
200 evc.ev_proc = vmcmd_map_zero;
201 else
202 evc.ev_proc = vmcmd_map_readvn;
203 evc.ev_offset = mapp[i].file_offset;
204 evc.ev_vp = vp;
206 DPRINTF(("map section %d: start = 0x%08lx, len = 0x%08lx\n",
207 i, evc.ev_addr, evc.ev_len));
209 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
210 if ((error = (*evc.ev_proc)(l, &evc)) != 0) {
211 VOP_UNLOCK(vp, 0);
212 DPRINTF(("Failed\n"));
213 goto bad2;
215 VOP_UNLOCK(vp, 0);
216 DPRINTF(("Success\n"));
218 bad2:
219 if (mapp)
220 free(mapp, M_TEMP);
221 vrele(vp);
222 fd_putfile(fd);
223 bad1point5:
224 SCARG(&close_cup, fd) = fd;
225 if ((error = sys_close(l, &close_cup, retval)) != 0)
226 goto bad1;
228 if ((error = copyout(&base, SCARG(uap, base), sizeof(base))) != 0)
229 goto bad1;
231 if ((error = copyout(&flags, SCARG(uap, flags), sizeof(base))) != 0)
232 goto bad1;
233 bad1:
234 free(filename, M_TEMP);
236 return error;