ia64/xen-unstable

view tools/libxc/xc_private.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 3233e7ecfa9f
children 619e3d6f01b3 3133e64d0462
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, u32 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, u32 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 u32 dom, int num, unsigned long *arr)
70 {
71 dom0_op_t 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 u32 dom)
83 {
84 dom0_op_t op;
85 op.cmd = DOM0_GETPAGEFRAMEINFO;
86 op.u.getpageframeinfo.pfn = 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 privcmd_hypercall_t 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 if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
118 {
119 fprintf(stderr, "Dom_mmuext operation failed (rc=%ld errno=%d)-- need to"
120 " rebuild the user-space tool set?\n",ret,errno);
121 }
123 safe_munlock(op, nr_ops*sizeof(*op));
125 out1:
126 return ret;
127 }
129 static int flush_mmu_updates(int xc_handle, xc_mmu_t *mmu)
130 {
131 int err = 0;
132 privcmd_hypercall_t hypercall;
134 if ( mmu->idx == 0 )
135 return 0;
137 hypercall.op = __HYPERVISOR_mmu_update;
138 hypercall.arg[0] = (unsigned long)mmu->updates;
139 hypercall.arg[1] = (unsigned long)mmu->idx;
140 hypercall.arg[2] = 0;
141 hypercall.arg[3] = mmu->subject;
143 if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 )
144 {
145 PERROR("flush_mmu_updates: mmu updates mlock failed");
146 err = 1;
147 goto out;
148 }
150 if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
151 {
152 ERROR("Failure when submitting mmu updates");
153 err = 1;
154 }
156 mmu->idx = 0;
158 safe_munlock(mmu->updates, sizeof(mmu->updates));
160 out:
161 return err;
162 }
164 xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom)
165 {
166 xc_mmu_t *mmu = malloc(sizeof(xc_mmu_t));
167 if ( mmu == NULL )
168 return mmu;
169 mmu->idx = 0;
170 mmu->subject = dom;
171 return mmu;
172 }
174 int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
175 unsigned long long ptr, unsigned long long val)
176 {
177 mmu->updates[mmu->idx].ptr = ptr;
178 mmu->updates[mmu->idx].val = val;
180 if ( ++mmu->idx == MAX_MMU_UPDATES )
181 return flush_mmu_updates(xc_handle, mmu);
183 return 0;
184 }
186 int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu)
187 {
188 return flush_mmu_updates(xc_handle, mmu);
189 }
191 int xc_memory_op(int xc_handle,
192 int cmd,
193 void *arg)
194 {
195 privcmd_hypercall_t hypercall;
196 struct xen_memory_reservation *reservation = arg;
197 long ret = -EINVAL;
199 hypercall.op = __HYPERVISOR_memory_op;
200 hypercall.arg[0] = (unsigned long)cmd;
201 hypercall.arg[1] = (unsigned long)arg;
203 switch ( cmd )
204 {
205 case XENMEM_increase_reservation:
206 case XENMEM_decrease_reservation:
207 if ( mlock(reservation, sizeof(*reservation)) != 0 )
208 {
209 PERROR("Could not mlock");
210 goto out1;
211 }
212 if ( (reservation->extent_start != NULL) &&
213 (mlock(reservation->extent_start,
214 reservation->nr_extents * sizeof(unsigned long)) != 0) )
215 {
216 PERROR("Could not mlock");
217 safe_munlock(reservation, sizeof(*reservation));
218 goto out1;
219 }
220 break;
221 case XENMEM_maximum_ram_page:
222 if ( mlock(arg, sizeof(unsigned long)) != 0 )
223 {
224 PERROR("Could not mlock");
225 goto out1;
226 }
227 break;
228 }
230 if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
231 {
232 fprintf(stderr, "hypercall failed (rc=%ld errno=%d)-- need to"
233 " rebuild the user-space tool set?\n",ret,errno);
234 }
236 switch ( cmd )
237 {
238 case XENMEM_increase_reservation:
239 case XENMEM_decrease_reservation:
240 safe_munlock(reservation, sizeof(*reservation));
241 if ( reservation->extent_start != NULL )
242 safe_munlock(reservation->extent_start,
243 reservation->nr_extents * sizeof(unsigned long));
244 break;
245 case XENMEM_maximum_ram_page:
246 safe_munlock(arg, sizeof(unsigned long));
247 break;
248 }
250 out1:
251 return ret;
252 }
255 long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
256 {
257 dom0_op_t op;
259 op.cmd = DOM0_GETVCPUCONTEXT;
260 op.u.getvcpucontext.domain = (domid_t)domid;
261 op.u.getvcpucontext.vcpu = (u16)vcpu;
262 op.u.getvcpucontext.ctxt = NULL;
263 if ( (do_dom0_op(xc_handle, &op) < 0) )
264 {
265 PERROR("Could not get info on domain");
266 return -1;
267 }
268 return op.u.getvcpucontext.cpu_time;
269 }
272 unsigned long xc_get_m2p_start_mfn ( int xc_handle )
273 {
274 unsigned long mfn;
276 if ( ioctl( xc_handle, IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN, &mfn ) < 0 )
277 {
278 perror("xc_get_m2p_start_mfn:");
279 return 0;
280 }
281 return mfn;
282 }
284 int xc_get_pfn_list(int xc_handle,
285 u32 domid,
286 unsigned long *pfn_buf,
287 unsigned long max_pfns)
288 {
289 dom0_op_t op;
290 int ret;
291 op.cmd = DOM0_GETMEMLIST;
292 op.u.getmemlist.domain = (domid_t)domid;
293 op.u.getmemlist.max_pfns = max_pfns;
294 op.u.getmemlist.buffer = pfn_buf;
297 if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
298 {
299 PERROR("xc_get_pfn_list: pfn_buf mlock failed");
300 return -1;
301 }
303 ret = do_dom0_op(xc_handle, &op);
305 safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long));
307 #if 0
308 #ifdef DEBUG
309 DPRINTF(("Ret for xc_get_pfn_list is %d\n", ret));
310 if (ret >= 0) {
311 int i, j;
312 for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) {
313 fprintf(stderr, "0x%x: ", i);
314 for (j = 0; j < 16; j++)
315 fprintf(stderr, "0x%lx ", pfn_buf[i + j]);
316 fprintf(stderr, "\n");
317 }
318 }
319 #endif
320 #endif
322 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
323 }
325 #ifdef __ia64__
326 int xc_ia64_get_pfn_list(int xc_handle,
327 u32 domid,
328 unsigned long *pfn_buf,
329 unsigned int start_page,
330 unsigned int nr_pages)
331 {
332 dom0_op_t op;
333 int ret;
335 op.cmd = DOM0_GETMEMLIST;
336 op.u.getmemlist.domain = (domid_t)domid;
337 op.u.getmemlist.max_pfns = ((unsigned long)start_page << 32) | nr_pages;
338 op.u.getmemlist.buffer = pfn_buf;
340 if ( mlock(pfn_buf, nr_pages * sizeof(unsigned long)) != 0 )
341 {
342 PERROR("Could not lock pfn list buffer");
343 return -1;
344 }
346 /* XXX Hack to put pages in TLB, hypervisor should be able to handle this */
347 memset(pfn_buf, 0, nr_pages * sizeof(unsigned long));
348 ret = do_dom0_op(xc_handle, &op);
350 (void)munlock(pfn_buf, nr_pages * sizeof(unsigned long));
352 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
353 }
355 long xc_get_max_pages(int xc_handle, u32 domid)
356 {
357 dom0_op_t op;
358 op.cmd = DOM0_GETDOMAININFO;
359 op.u.getdomaininfo.domain = (domid_t)domid;
360 return (do_dom0_op(xc_handle, &op) < 0) ?
361 -1 : op.u.getdomaininfo.max_pages;
362 }
363 #endif
365 long xc_get_tot_pages(int xc_handle, u32 domid)
366 {
367 dom0_op_t op;
368 op.cmd = DOM0_GETDOMAININFO;
369 op.u.getdomaininfo.domain = (domid_t)domid;
370 return (do_dom0_op(xc_handle, &op) < 0) ?
371 -1 : op.u.getdomaininfo.tot_pages;
372 }
374 int xc_copy_to_domain_page(int xc_handle,
375 u32 domid,
376 unsigned long dst_pfn,
377 void *src_page)
378 {
379 void *vaddr = xc_map_foreign_range(
380 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
381 if ( vaddr == NULL )
382 return -1;
383 memcpy(vaddr, src_page, PAGE_SIZE);
384 munmap(vaddr, PAGE_SIZE);
385 return 0;
386 }
388 unsigned long xc_get_filesz(int fd)
389 {
390 u16 sig;
391 u32 _sz = 0;
392 unsigned long sz;
394 lseek(fd, 0, SEEK_SET);
395 if ( read(fd, &sig, sizeof(sig)) != sizeof(sig) )
396 return 0;
397 sz = lseek(fd, 0, SEEK_END);
398 if ( sig == 0x8b1f ) /* GZIP signature? */
399 {
400 lseek(fd, -4, SEEK_END);
401 if ( read(fd, &_sz, 4) != 4 )
402 return 0;
403 sz = _sz;
404 }
405 lseek(fd, 0, SEEK_SET);
407 return sz;
408 }
410 void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
411 int xch, u32 dom, unsigned long *parray,
412 unsigned long vstart)
413 {
414 char *va;
415 unsigned long chunksz, done, pa;
417 for ( done = 0; done < size; done += chunksz )
418 {
419 pa = dst + done - vstart;
420 va = xc_map_foreign_range(
421 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
422 chunksz = size - done;
423 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
424 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
425 memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
426 munmap(va, PAGE_SIZE);
427 }
428 }
430 int xc_dom0_op(int xc_handle, dom0_op_t *op)
431 {
432 return do_dom0_op(xc_handle, op);
433 }
435 int xc_version(int xc_handle, int cmd, void *arg)
436 {
437 int rc, argsize = 0;
439 switch ( cmd )
440 {
441 case XENVER_extraversion: argsize = sizeof(xen_extraversion_t); break;
442 case XENVER_compile_info: argsize = sizeof(xen_compile_info_t); break;
443 case XENVER_capabilities: argsize = sizeof(xen_capabilities_info_t); break;
444 case XENVER_changeset: argsize = sizeof(xen_changeset_info_t); break;
445 case XENVER_parameters: argsize = sizeof(xen_parameters_info_t); break;
446 }
448 if ( (argsize != 0) && (mlock(arg, argsize) != 0) )
449 {
450 PERROR("Could not lock memory for version hypercall");
451 return -ENOMEM;
452 }
454 rc = do_xen_version(xc_handle, cmd, arg);
456 if ( argsize != 0 )
457 safe_munlock(arg, argsize);
459 return rc;
460 }
462 unsigned long xc_make_page_below_4G(
463 int xc_handle, u32 domid, unsigned long mfn)
464 {
465 unsigned long new_mfn;
467 if ( xc_domain_memory_decrease_reservation(
468 xc_handle, domid, 1, 0, &mfn) != 0 )
469 {
470 fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
471 return 0;
472 }
474 if ( xc_domain_memory_increase_reservation(
475 xc_handle, domid, 1, 0, 32, &new_mfn) != 0 )
476 {
477 fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
478 return 0;
479 }
481 return new_mfn;
482 }