ia64/xen-unstable

view tools/libxc/xc_private.c @ 7800:5aad7e145e50

If /sbin/ isn't in the path, udev rules will erroneously not get
installed.

Signed-off-by: Nivedita Singhvi <niv@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Nov 14 11:05:34 2005 +0100 (2005-11-14)
parents 8928c89a8d0a
children 8ee7df2c18d1
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 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 uint32_t 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 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 privcmd_hypercall_t 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 privcmd_hypercall_t hypercall;
192 struct xen_memory_reservation *reservation = arg;
193 long ret = -EINVAL;
195 hypercall.op = __HYPERVISOR_memory_op;
196 hypercall.arg[0] = (unsigned long)cmd;
197 hypercall.arg[1] = (unsigned long)arg;
199 switch ( cmd )
200 {
201 case XENMEM_increase_reservation:
202 case XENMEM_decrease_reservation:
203 if ( mlock(reservation, sizeof(*reservation)) != 0 )
204 {
205 PERROR("Could not mlock");
206 goto out1;
207 }
208 if ( (reservation->extent_start != NULL) &&
209 (mlock(reservation->extent_start,
210 reservation->nr_extents * sizeof(unsigned long)) != 0) )
211 {
212 PERROR("Could not mlock");
213 safe_munlock(reservation, sizeof(*reservation));
214 goto out1;
215 }
216 break;
217 case XENMEM_maximum_ram_page:
218 if ( mlock(arg, sizeof(unsigned long)) != 0 )
219 {
220 PERROR("Could not mlock");
221 goto out1;
222 }
223 break;
224 }
226 ret = do_xen_hypercall(xc_handle, &hypercall);
228 switch ( cmd )
229 {
230 case XENMEM_increase_reservation:
231 case XENMEM_decrease_reservation:
232 safe_munlock(reservation, sizeof(*reservation));
233 if ( reservation->extent_start != NULL )
234 safe_munlock(reservation->extent_start,
235 reservation->nr_extents * sizeof(unsigned long));
236 break;
237 case XENMEM_maximum_ram_page:
238 safe_munlock(arg, sizeof(unsigned long));
239 break;
240 }
242 out1:
243 return ret;
244 }
247 long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
248 {
249 dom0_op_t op;
251 op.cmd = DOM0_GETVCPUINFO;
252 op.u.getvcpuinfo.domain = (domid_t)domid;
253 op.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
254 if ( (do_dom0_op(xc_handle, &op) < 0) )
255 {
256 PERROR("Could not get info on domain");
257 return -1;
258 }
259 return op.u.getvcpuinfo.cpu_time;
260 }
263 unsigned long xc_get_m2p_start_mfn ( int xc_handle )
264 {
265 unsigned long mfn;
267 if ( ioctl( xc_handle, IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN, &mfn ) < 0 )
268 {
269 perror("xc_get_m2p_start_mfn:");
270 return 0;
271 }
272 return mfn;
273 }
275 int xc_get_pfn_list(int xc_handle,
276 uint32_t domid,
277 unsigned long *pfn_buf,
278 unsigned long max_pfns)
279 {
280 dom0_op_t op;
281 int ret;
282 op.cmd = DOM0_GETMEMLIST;
283 op.u.getmemlist.domain = (domid_t)domid;
284 op.u.getmemlist.max_pfns = max_pfns;
285 op.u.getmemlist.buffer = pfn_buf;
288 if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
289 {
290 PERROR("xc_get_pfn_list: pfn_buf mlock failed");
291 return -1;
292 }
294 ret = do_dom0_op(xc_handle, &op);
296 safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long));
298 #if 0
299 #ifdef DEBUG
300 DPRINTF(("Ret for xc_get_pfn_list is %d\n", ret));
301 if (ret >= 0) {
302 int i, j;
303 for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) {
304 fprintf(stderr, "0x%x: ", i);
305 for (j = 0; j < 16; j++)
306 fprintf(stderr, "0x%lx ", pfn_buf[i + j]);
307 fprintf(stderr, "\n");
308 }
309 }
310 #endif
311 #endif
313 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
314 }
316 long xc_get_tot_pages(int xc_handle, uint32_t domid)
317 {
318 dom0_op_t op;
319 op.cmd = DOM0_GETDOMAININFO;
320 op.u.getdomaininfo.domain = (domid_t)domid;
321 return (do_dom0_op(xc_handle, &op) < 0) ?
322 -1 : op.u.getdomaininfo.tot_pages;
323 }
325 int xc_copy_to_domain_page(int xc_handle,
326 uint32_t domid,
327 unsigned long dst_pfn,
328 void *src_page)
329 {
330 void *vaddr = xc_map_foreign_range(
331 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
332 if ( vaddr == NULL )
333 return -1;
334 memcpy(vaddr, src_page, PAGE_SIZE);
335 munmap(vaddr, PAGE_SIZE);
336 return 0;
337 }
339 int xc_clear_domain_page(int xc_handle,
340 uint32_t domid,
341 unsigned long dst_pfn)
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 memset(vaddr, 0, PAGE_SIZE);
348 munmap(vaddr, PAGE_SIZE);
349 return 0;
350 }
352 unsigned long xc_get_filesz(int fd)
353 {
354 uint16_t sig;
355 uint32_t _sz = 0;
356 unsigned long sz;
358 lseek(fd, 0, SEEK_SET);
359 if ( read(fd, &sig, sizeof(sig)) != sizeof(sig) )
360 return 0;
361 sz = lseek(fd, 0, SEEK_END);
362 if ( sig == 0x8b1f ) /* GZIP signature? */
363 {
364 lseek(fd, -4, SEEK_END);
365 if ( read(fd, &_sz, 4) != 4 )
366 return 0;
367 sz = _sz;
368 }
369 lseek(fd, 0, SEEK_SET);
371 return sz;
372 }
374 void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
375 int xch, uint32_t dom, unsigned long *parray,
376 unsigned long vstart)
377 {
378 char *va;
379 unsigned long chunksz, done, pa;
381 for ( done = 0; done < size; done += chunksz )
382 {
383 pa = dst + done - vstart;
384 va = xc_map_foreign_range(
385 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
386 chunksz = size - done;
387 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
388 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
389 memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
390 munmap(va, PAGE_SIZE);
391 }
392 }
394 int xc_dom0_op(int xc_handle, dom0_op_t *op)
395 {
396 return do_dom0_op(xc_handle, op);
397 }
399 int xc_version(int xc_handle, int cmd, void *arg)
400 {
401 int rc, argsize = 0;
403 switch ( cmd )
404 {
405 case XENVER_extraversion: argsize = sizeof(xen_extraversion_t); break;
406 case XENVER_compile_info: argsize = sizeof(xen_compile_info_t); break;
407 case XENVER_capabilities: argsize = sizeof(xen_capabilities_info_t); break;
408 case XENVER_changeset: argsize = sizeof(xen_changeset_info_t); break;
409 case XENVER_parameters: argsize = sizeof(xen_parameters_info_t); break;
410 }
412 if ( (argsize != 0) && (mlock(arg, argsize) != 0) )
413 {
414 PERROR("Could not lock memory for version hypercall");
415 return -ENOMEM;
416 }
418 rc = do_xen_version(xc_handle, cmd, arg);
420 if ( argsize != 0 )
421 safe_munlock(arg, argsize);
423 return rc;
424 }
426 unsigned long xc_make_page_below_4G(
427 int xc_handle, uint32_t domid, unsigned long mfn)
428 {
429 unsigned long new_mfn;
431 if ( xc_domain_memory_decrease_reservation(
432 xc_handle, domid, 1, 0, &mfn) != 0 )
433 {
434 fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
435 return 0;
436 }
438 if ( xc_domain_memory_increase_reservation(
439 xc_handle, domid, 1, 0, 32, &new_mfn) != 0 )
440 {
441 fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
442 return 0;
443 }
445 return new_mfn;
446 }
448 /*
449 * Local variables:
450 * mode: C
451 * c-set-style: "BSD"
452 * c-basic-offset: 4
453 * tab-width: 4
454 * indent-tabs-mode: nil
455 * End:
456 */