ia64/xen-unstable

view tools/libxc/xc_private.c @ 6707:3bde4219c681

manual merge
author iap10@freefall.cl.cam.ac.uk
date Thu Sep 08 17:40:37 2005 +0000 (2005-09-08)
parents 5db85ba1c4e0 f0d728001aaa
children aa0990ef260f
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 }
354 #endif
356 long xc_get_tot_pages(int xc_handle, u32 domid)
357 {
358 dom0_op_t op;
359 op.cmd = DOM0_GETDOMAININFO;
360 op.u.getdomaininfo.domain = (domid_t)domid;
361 return (do_dom0_op(xc_handle, &op) < 0) ?
362 -1 : op.u.getdomaininfo.tot_pages;
363 }
365 int xc_copy_to_domain_page(int xc_handle,
366 u32 domid,
367 unsigned long dst_pfn,
368 void *src_page)
369 {
370 void *vaddr = xc_map_foreign_range(
371 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
372 if ( vaddr == NULL )
373 return -1;
374 memcpy(vaddr, src_page, PAGE_SIZE);
375 munmap(vaddr, PAGE_SIZE);
376 return 0;
377 }
379 unsigned long xc_get_filesz(int fd)
380 {
381 u16 sig;
382 u32 _sz = 0;
383 unsigned long sz;
385 lseek(fd, 0, SEEK_SET);
386 if ( read(fd, &sig, sizeof(sig)) != sizeof(sig) )
387 return 0;
388 sz = lseek(fd, 0, SEEK_END);
389 if ( sig == 0x8b1f ) /* GZIP signature? */
390 {
391 lseek(fd, -4, SEEK_END);
392 if ( read(fd, &_sz, 4) != 4 )
393 return 0;
394 sz = _sz;
395 }
396 lseek(fd, 0, SEEK_SET);
398 return sz;
399 }
401 void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
402 int xch, u32 dom, unsigned long *parray,
403 unsigned long vstart)
404 {
405 char *va;
406 unsigned long chunksz, done, pa;
408 for ( done = 0; done < size; done += chunksz )
409 {
410 pa = dst + done - vstart;
411 va = xc_map_foreign_range(
412 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
413 chunksz = size - done;
414 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
415 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
416 memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
417 munmap(va, PAGE_SIZE);
418 }
419 }
421 int xc_dom0_op(int xc_handle, dom0_op_t *op)
422 {
423 return do_dom0_op(xc_handle, op);
424 }
426 int xc_version(int xc_handle, int cmd, void *arg)
427 {
428 return do_xen_version(xc_handle, cmd, arg);
429 }
431 unsigned long xc_make_page_below_4G(int xc_handle, u32 domid,
432 unsigned long mfn)
433 {
434 unsigned long new_mfn;
435 if ( xc_domain_memory_decrease_reservation(
436 xc_handle, domid, 1, 0, &mfn ) != 1 )
437 {
438 fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
439 return 0;
440 }
441 if ( xc_domain_memory_increase_reservation( xc_handle, domid, 1, 0, 32, &new_mfn ) != 1 )
442 {
443 fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
444 return 0;
445 }
446 return new_mfn;
447 }