152
153 if (ddi_copyin(umme, mme, sizeof (*mme), mode)) {
154 error = EFAULT;
155 break;
156 }
157
158 DTRACE_XPV3(mmap__entry, ulong_t, mme->va, ulong_t, mme->mfn,
159 ulong_t, mme->npages);
160
161 if (mme->mfn == MFN_INVALID) {
162 error = EINVAL;
163 break;
164 }
165
166 addr = (caddr_t)mme->va;
167
168 /*
169 * Find the segment we want to mess with, then add
170 * the mfn range to the segment.
171 */
172 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
173 if ((seg = as_findseg(as, addr, 0)) == NULL ||
174 addr + mmu_ptob(mme->npages) > seg->s_base + seg->s_size)
175 error = EINVAL;
176 else
177 error = segmf_add_mfns(seg, addr,
178 mme->mfn, mme->npages, mmc->dom);
179 AS_LOCK_EXIT(as, &as->a_lock);
180
181 if (error != 0)
182 break;
183 }
184
185 done:
186 DTRACE_XPV1(mmap__end, int, error);
187
188 return (error);
189 }
190
191 /*
192 * Set up the address range to map to an array of mfns in
193 * a foreign domain. Used in the following way:
194 *
195 * privcmd_mmap_batch_t p;
196 *
197 * addr = mmap(NULL, size, prot, MAP_SHARED, fd, 0);
198 * p.num = number of pages
199 * p.dom = domid
202 * ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &p);
203 */
204 /*ARGSUSED2*/
205 static int
206 do_privcmd_mmapbatch(void *uarg, int mode, cred_t *cr)
207 {
208 privcmd_mmapbatch_t __mmapbatch, *mmb = &__mmapbatch;
209 struct as *as = curproc->p_as;
210 struct seg *seg;
211 int i, error = 0;
212 caddr_t addr;
213 ulong_t *ulp;
214
215 if (ddi_copyin(uarg, mmb, sizeof (*mmb), mode))
216 return (EFAULT);
217
218 DTRACE_XPV3(mmapbatch__start, domid_t, mmb->dom, int, mmb->num,
219 caddr_t, mmb->addr);
220
221 addr = (caddr_t)mmb->addr;
222 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
223 if ((seg = as_findseg(as, addr, 0)) == NULL ||
224 addr + ptob(mmb->num) > seg->s_base + seg->s_size) {
225 error = EINVAL;
226 goto done;
227 }
228
229 for (i = 0, ulp = mmb->arr;
230 i < mmb->num; i++, addr += PAGESIZE, ulp++) {
231 mfn_t mfn;
232
233 if (fulword(ulp, &mfn) != 0) {
234 error = EFAULT;
235 break;
236 }
237
238 if (mfn == MFN_INVALID) {
239 /*
240 * This mfn is invalid and should not be added to
241 * segmf, as we'd only cause an immediate EFAULT when
242 * we tried to fault it in.
243 */
244 mfn |= XEN_DOMCTL_PFINFO_XTAB;
245 continue;
246 }
247
248 if (segmf_add_mfns(seg, addr, mfn, 1, mmb->dom) == 0)
249 continue;
250
251 /*
252 * Tell the process that this MFN could not be mapped, so it
253 * won't later try to access it.
254 */
255 mfn |= XEN_DOMCTL_PFINFO_XTAB;
256 if (sulword(ulp, mfn) != 0) {
257 error = EFAULT;
258 break;
259 }
260 }
261
262 done:
263 AS_LOCK_EXIT(as, &as->a_lock);
264
265 DTRACE_XPV3(mmapbatch__end, int, error, struct seg *, seg, caddr_t,
266 mmb->addr);
267
268 return (error);
269 }
270
271 /*ARGSUSED*/
272 static int
273 privcmd_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval)
274 {
275 if (secpolicy_xvm_control(cr))
276 return (EPERM);
277
278 /*
279 * Everything is a -native- data type.
280 */
281 if ((mode & FMODELS) != FNATIVE)
282 return (EOVERFLOW);
283
|
152
153 if (ddi_copyin(umme, mme, sizeof (*mme), mode)) {
154 error = EFAULT;
155 break;
156 }
157
158 DTRACE_XPV3(mmap__entry, ulong_t, mme->va, ulong_t, mme->mfn,
159 ulong_t, mme->npages);
160
161 if (mme->mfn == MFN_INVALID) {
162 error = EINVAL;
163 break;
164 }
165
166 addr = (caddr_t)mme->va;
167
168 /*
169 * Find the segment we want to mess with, then add
170 * the mfn range to the segment.
171 */
172 AS_LOCK_ENTER(as, RW_READER);
173 if ((seg = as_findseg(as, addr, 0)) == NULL ||
174 addr + mmu_ptob(mme->npages) > seg->s_base + seg->s_size)
175 error = EINVAL;
176 else
177 error = segmf_add_mfns(seg, addr,
178 mme->mfn, mme->npages, mmc->dom);
179 AS_LOCK_EXIT(as);
180
181 if (error != 0)
182 break;
183 }
184
185 done:
186 DTRACE_XPV1(mmap__end, int, error);
187
188 return (error);
189 }
190
191 /*
192 * Set up the address range to map to an array of mfns in
193 * a foreign domain. Used in the following way:
194 *
195 * privcmd_mmap_batch_t p;
196 *
197 * addr = mmap(NULL, size, prot, MAP_SHARED, fd, 0);
198 * p.num = number of pages
199 * p.dom = domid
202 * ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &p);
203 */
204 /*ARGSUSED2*/
205 static int
206 do_privcmd_mmapbatch(void *uarg, int mode, cred_t *cr)
207 {
208 privcmd_mmapbatch_t __mmapbatch, *mmb = &__mmapbatch;
209 struct as *as = curproc->p_as;
210 struct seg *seg;
211 int i, error = 0;
212 caddr_t addr;
213 ulong_t *ulp;
214
215 if (ddi_copyin(uarg, mmb, sizeof (*mmb), mode))
216 return (EFAULT);
217
218 DTRACE_XPV3(mmapbatch__start, domid_t, mmb->dom, int, mmb->num,
219 caddr_t, mmb->addr);
220
221 addr = (caddr_t)mmb->addr;
222 AS_LOCK_ENTER(as, RW_READER);
223 if ((seg = as_findseg(as, addr, 0)) == NULL ||
224 addr + ptob(mmb->num) > seg->s_base + seg->s_size) {
225 error = EINVAL;
226 goto done;
227 }
228
229 for (i = 0, ulp = mmb->arr;
230 i < mmb->num; i++, addr += PAGESIZE, ulp++) {
231 mfn_t mfn;
232
233 if (fulword(ulp, &mfn) != 0) {
234 error = EFAULT;
235 break;
236 }
237
238 if (mfn == MFN_INVALID) {
239 /*
240 * This mfn is invalid and should not be added to
241 * segmf, as we'd only cause an immediate EFAULT when
242 * we tried to fault it in.
243 */
244 mfn |= XEN_DOMCTL_PFINFO_XTAB;
245 continue;
246 }
247
248 if (segmf_add_mfns(seg, addr, mfn, 1, mmb->dom) == 0)
249 continue;
250
251 /*
252 * Tell the process that this MFN could not be mapped, so it
253 * won't later try to access it.
254 */
255 mfn |= XEN_DOMCTL_PFINFO_XTAB;
256 if (sulword(ulp, mfn) != 0) {
257 error = EFAULT;
258 break;
259 }
260 }
261
262 done:
263 AS_LOCK_EXIT(as);
264
265 DTRACE_XPV3(mmapbatch__end, int, error, struct seg *, seg, caddr_t,
266 mmb->addr);
267
268 return (error);
269 }
270
271 /*ARGSUSED*/
272 static int
273 privcmd_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval)
274 {
275 if (secpolicy_xvm_control(cr))
276 return (EPERM);
277
278 /*
279 * Everything is a -native- data type.
280 */
281 if ((mode & FMODELS) != FNATIVE)
282 return (EOVERFLOW);
283
|