direct-io.hg

view tools/libxc/xc_private.c @ 8736:8aeb417387ca

Fix some more pfn/mfn/gmfn/gpfn inconsistencies. Fix some direct
uses of max_page variable to use the mfn_valid() predicate.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 02 12:18:28 2006 +0100 (2006-02-02)
parents 1db05e589fa0
children 0d10fac28427
line source
1 /******************************************************************************
2 * xc_private.c
3 *
4 * Helper functions for the rest of the library.
5 */
7 #include <zlib.h>
8 #include "xc_private.h"
9 #include <xen/memory.h>
11 void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
12 unsigned long *arr, int num )
13 {
14 privcmd_mmapbatch_t ioctlx;
15 void *addr;
16 addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0);
17 if ( addr == MAP_FAILED )
18 return NULL;
20 ioctlx.num=num;
21 ioctlx.dom=dom;
22 ioctlx.addr=(unsigned long)addr;
23 ioctlx.arr=arr;
24 if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx ) < 0 )
25 {
26 int saved_errno = errno;
27 perror("XXXXXXXX");
28 (void)munmap(addr, num*PAGE_SIZE);
29 errno = saved_errno;
30 return NULL;
31 }
32 return addr;
34 }
36 /*******************/
38 void *xc_map_foreign_range(int xc_handle, uint32_t dom,
39 int size, int prot,
40 unsigned long mfn )
41 {
42 privcmd_mmap_t ioctlx;
43 privcmd_mmap_entry_t entry;
44 void *addr;
45 addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
46 if ( addr == MAP_FAILED )
47 return NULL;
49 ioctlx.num=1;
50 ioctlx.dom=dom;
51 ioctlx.entry=&entry;
52 entry.va=(unsigned long) addr;
53 entry.mfn=mfn;
54 entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT;
55 if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) < 0 )
56 {
57 int saved_errno = errno;
58 (void)munmap(addr, size);
59 errno = saved_errno;
60 return NULL;
61 }
62 return addr;
63 }
65 /*******************/
67 /* NB: arr must be mlock'ed */
68 int xc_get_pfn_type_batch(int xc_handle,
69 uint32_t dom, int num, unsigned long *arr)
70 {
71 DECLARE_DOM0_OP;
72 op.cmd = DOM0_GETPAGEFRAMEINFO2;
73 op.u.getpageframeinfo2.domain = (domid_t)dom;
74 op.u.getpageframeinfo2.num = num;
75 op.u.getpageframeinfo2.array = arr;
76 return do_dom0_op(xc_handle, &op);
77 }
79 #define GETPFN_ERR (~0U)
80 unsigned int get_pfn_type(int xc_handle,
81 unsigned long mfn,
82 uint32_t dom)
83 {
84 DECLARE_DOM0_OP;
85 op.cmd = DOM0_GETPAGEFRAMEINFO;
86 op.u.getpageframeinfo.mfn = mfn;
87 op.u.getpageframeinfo.domain = (domid_t)dom;
88 if ( do_dom0_op(xc_handle, &op) < 0 )
89 {
90 PERROR("Unexpected failure when getting page frame info!");
91 return GETPFN_ERR;
92 }
93 return op.u.getpageframeinfo.type;
94 }
96 int xc_mmuext_op(
97 int xc_handle,
98 struct mmuext_op *op,
99 unsigned int nr_ops,
100 domid_t dom)
101 {
102 DECLARE_HYPERCALL;
103 long ret = -EINVAL;
105 hypercall.op = __HYPERVISOR_mmuext_op;
106 hypercall.arg[0] = (unsigned long)op;
107 hypercall.arg[1] = (unsigned long)nr_ops;
108 hypercall.arg[2] = (unsigned long)0;
109 hypercall.arg[3] = (unsigned long)dom;
111 if ( mlock(op, nr_ops*sizeof(*op)) != 0 )
112 {
113 PERROR("Could not lock memory for Xen hypercall");
114 goto out1;
115 }
117 ret = do_xen_hypercall(xc_handle, &hypercall);
119 safe_munlock(op, nr_ops*sizeof(*op));
121 out1:
122 return ret;
123 }
125 static int flush_mmu_updates(int xc_handle, xc_mmu_t *mmu)
126 {
127 int err = 0;
128 DECLARE_HYPERCALL;
130 if ( mmu->idx == 0 )
131 return 0;
133 hypercall.op = __HYPERVISOR_mmu_update;
134 hypercall.arg[0] = (unsigned long)mmu->updates;
135 hypercall.arg[1] = (unsigned long)mmu->idx;
136 hypercall.arg[2] = 0;
137 hypercall.arg[3] = mmu->subject;
139 if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 )
140 {
141 PERROR("flush_mmu_updates: mmu updates mlock failed");
142 err = 1;
143 goto out;
144 }
146 if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
147 {
148 ERROR("Failure when submitting mmu updates");
149 err = 1;
150 }
152 mmu->idx = 0;
154 safe_munlock(mmu->updates, sizeof(mmu->updates));
156 out:
157 return err;
158 }
160 xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom)
161 {
162 xc_mmu_t *mmu = malloc(sizeof(xc_mmu_t));
163 if ( mmu == NULL )
164 return mmu;
165 mmu->idx = 0;
166 mmu->subject = dom;
167 return mmu;
168 }
170 int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
171 unsigned long long ptr, unsigned long long val)
172 {
173 mmu->updates[mmu->idx].ptr = ptr;
174 mmu->updates[mmu->idx].val = val;
176 if ( ++mmu->idx == MAX_MMU_UPDATES )
177 return flush_mmu_updates(xc_handle, mmu);
179 return 0;
180 }
182 int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu)
183 {
184 return flush_mmu_updates(xc_handle, mmu);
185 }
187 int xc_memory_op(int xc_handle,
188 int cmd,
189 void *arg)
190 {
191 DECLARE_HYPERCALL;
192 struct xen_memory_reservation *reservation = arg;
193 struct xen_machphys_mfn_list *xmml = arg;
194 long ret = -EINVAL;
196 hypercall.op = __HYPERVISOR_memory_op;
197 hypercall.arg[0] = (unsigned long)cmd;
198 hypercall.arg[1] = (unsigned long)arg;
200 switch ( cmd )
201 {
202 case XENMEM_increase_reservation:
203 case XENMEM_decrease_reservation:
204 case XENMEM_populate_physmap:
205 if ( mlock(reservation, sizeof(*reservation)) != 0 )
206 {
207 PERROR("Could not mlock");
208 goto out1;
209 }
210 if ( (reservation->extent_start != NULL) &&
211 (mlock(reservation->extent_start,
212 reservation->nr_extents * sizeof(unsigned long)) != 0) )
213 {
214 PERROR("Could not mlock");
215 safe_munlock(reservation, sizeof(*reservation));
216 goto out1;
217 }
218 break;
219 case XENMEM_machphys_mfn_list:
220 if ( mlock(xmml, sizeof(*xmml)) != 0 )
221 {
222 PERROR("Could not mlock");
223 goto out1;
224 }
225 if ( mlock(xmml->extent_start,
226 xmml->max_extents * sizeof(unsigned long)) != 0 )
227 {
228 PERROR("Could not mlock");
229 safe_munlock(xmml, sizeof(*xmml));
230 goto out1;
231 }
232 break;
233 case XENMEM_reserved_phys_area:
234 if ( mlock(arg, sizeof(struct xen_reserved_phys_area)) )
235 {
236 PERROR("Could not mlock");
237 goto out1;
238 }
239 break;
240 }
242 ret = do_xen_hypercall(xc_handle, &hypercall);
244 switch ( cmd )
245 {
246 case XENMEM_increase_reservation:
247 case XENMEM_decrease_reservation:
248 case XENMEM_populate_physmap:
249 safe_munlock(reservation, sizeof(*reservation));
250 if ( reservation->extent_start != NULL )
251 safe_munlock(reservation->extent_start,
252 reservation->nr_extents * sizeof(unsigned long));
253 break;
254 case XENMEM_machphys_mfn_list:
255 safe_munlock(xmml, sizeof(*xmml));
256 safe_munlock(xmml->extent_start,
257 xmml->max_extents * sizeof(unsigned long));
258 break;
259 case XENMEM_reserved_phys_area:
260 safe_munlock(arg, sizeof(struct xen_reserved_phys_area));
261 break;
262 }
264 out1:
265 return ret;
266 }
269 long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
270 {
271 DECLARE_DOM0_OP;
273 op.cmd = DOM0_GETVCPUINFO;
274 op.u.getvcpuinfo.domain = (domid_t)domid;
275 op.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
276 if ( (do_dom0_op(xc_handle, &op) < 0) )
277 {
278 PERROR("Could not get info on domain");
279 return -1;
280 }
281 return op.u.getvcpuinfo.cpu_time;
282 }
285 int xc_get_pfn_list(int xc_handle,
286 uint32_t domid,
287 unsigned long *pfn_buf,
288 unsigned long max_pfns)
289 {
290 DECLARE_DOM0_OP;
291 int ret;
292 op.cmd = DOM0_GETMEMLIST;
293 op.u.getmemlist.domain = (domid_t)domid;
294 op.u.getmemlist.max_pfns = max_pfns;
295 op.u.getmemlist.buffer = pfn_buf;
297 #ifdef VALGRIND
298 memset(pfn_buf, 0, max_pfns * sizeof(unsigned long));
299 #endif
301 if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
302 {
303 PERROR("xc_get_pfn_list: pfn_buf mlock failed");
304 return -1;
305 }
307 ret = do_dom0_op(xc_handle, &op);
309 safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long));
311 #if 0
312 #ifdef DEBUG
313 DPRINTF(("Ret for xc_get_pfn_list is %d\n", ret));
314 if (ret >= 0) {
315 int i, j;
316 for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) {
317 fprintf(stderr, "0x%x: ", i);
318 for (j = 0; j < 16; j++)
319 fprintf(stderr, "0x%lx ", pfn_buf[i + j]);
320 fprintf(stderr, "\n");
321 }
322 }
323 #endif
324 #endif
326 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
327 }
329 long xc_get_tot_pages(int xc_handle, uint32_t domid)
330 {
331 DECLARE_DOM0_OP;
332 op.cmd = DOM0_GETDOMAININFO;
333 op.u.getdomaininfo.domain = (domid_t)domid;
334 return (do_dom0_op(xc_handle, &op) < 0) ?
335 -1 : op.u.getdomaininfo.tot_pages;
336 }
338 int xc_copy_to_domain_page(int xc_handle,
339 uint32_t domid,
340 unsigned long dst_pfn,
341 void *src_page)
342 {
343 void *vaddr = xc_map_foreign_range(
344 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
345 if ( vaddr == NULL )
346 return -1;
347 memcpy(vaddr, src_page, PAGE_SIZE);
348 munmap(vaddr, PAGE_SIZE);
349 return 0;
350 }
352 int xc_clear_domain_page(int xc_handle,
353 uint32_t domid,
354 unsigned long dst_pfn)
355 {
356 void *vaddr = xc_map_foreign_range(
357 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
358 if ( vaddr == NULL )
359 return -1;
360 memset(vaddr, 0, PAGE_SIZE);
361 munmap(vaddr, PAGE_SIZE);
362 return 0;
363 }
365 unsigned long xc_get_filesz(int fd)
366 {
367 uint16_t sig;
368 uint32_t _sz = 0;
369 unsigned long sz;
371 lseek(fd, 0, SEEK_SET);
372 if ( read(fd, &sig, sizeof(sig)) != sizeof(sig) )
373 return 0;
374 sz = lseek(fd, 0, SEEK_END);
375 if ( sig == 0x8b1f ) /* GZIP signature? */
376 {
377 lseek(fd, -4, SEEK_END);
378 if ( read(fd, &_sz, 4) != 4 )
379 return 0;
380 sz = _sz;
381 }
382 lseek(fd, 0, SEEK_SET);
384 return sz;
385 }
387 void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
388 int xch, uint32_t dom, unsigned long *parray,
389 unsigned long vstart)
390 {
391 char *va;
392 unsigned long chunksz, done, pa;
394 for ( done = 0; done < size; done += chunksz )
395 {
396 pa = dst + done - vstart;
397 va = xc_map_foreign_range(
398 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
399 chunksz = size - done;
400 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
401 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
402 memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
403 munmap(va, PAGE_SIZE);
404 }
405 }
407 int xc_dom0_op(int xc_handle, dom0_op_t *op)
408 {
409 return do_dom0_op(xc_handle, op);
410 }
412 int xc_version(int xc_handle, int cmd, void *arg)
413 {
414 int rc, argsize = 0;
416 switch ( cmd )
417 {
418 case XENVER_extraversion:
419 argsize = sizeof(xen_extraversion_t);
420 break;
421 case XENVER_compile_info:
422 argsize = sizeof(xen_compile_info_t);
423 break;
424 case XENVER_capabilities:
425 argsize = sizeof(xen_capabilities_info_t);
426 break;
427 case XENVER_changeset:
428 argsize = sizeof(xen_changeset_info_t);
429 break;
430 case XENVER_platform_parameters:
431 argsize = sizeof(xen_platform_parameters_t);
432 break;
433 }
435 if ( (argsize != 0) && (mlock(arg, argsize) != 0) )
436 {
437 PERROR("Could not lock memory for version hypercall");
438 return -ENOMEM;
439 }
441 #ifdef VALGRIND
442 if (argsize != 0)
443 memset(arg, 0, argsize);
444 #endif
446 rc = do_xen_version(xc_handle, cmd, arg);
448 if ( argsize != 0 )
449 safe_munlock(arg, argsize);
451 return rc;
452 }
454 unsigned long xc_make_page_below_4G(
455 int xc_handle, uint32_t domid, unsigned long mfn)
456 {
457 unsigned long new_mfn;
459 if ( xc_domain_memory_decrease_reservation(
460 xc_handle, domid, 1, 0, &mfn) != 0 )
461 {
462 fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
463 return 0;
464 }
466 if ( xc_domain_memory_increase_reservation(
467 xc_handle, domid, 1, 0, 32, &new_mfn) != 0 )
468 {
469 fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
470 return 0;
471 }
473 return new_mfn;
474 }
476 /*
477 * Local variables:
478 * mode: C
479 * c-set-style: "BSD"
480 * c-basic-offset: 4
481 * tab-width: 4
482 * indent-tabs-mode: nil
483 * End:
484 */