ia64/xen-unstable

view tools/libxc/xc_private.c @ 7959:ff18a169e866

Update the memory_op() hypercall. Add two new subcommands, to
query a domain's current and maximum memory reservation. Also,
XENMEM_maximum_ram_page now returns the max_page directly,
rather than writing through a passed-in pointer.

Also, disable PAE in the default config (accidentally checked
in two changesets ago).

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Nov 21 16:56:39 2005 +0100 (2005-11-21)
parents fe3a892b33b4
children 602aefe7bd48
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 }
219 ret = do_xen_hypercall(xc_handle, &hypercall);
221 switch ( cmd )
222 {
223 case XENMEM_increase_reservation:
224 case XENMEM_decrease_reservation:
225 safe_munlock(reservation, sizeof(*reservation));
226 if ( reservation->extent_start != NULL )
227 safe_munlock(reservation->extent_start,
228 reservation->nr_extents * sizeof(unsigned long));
229 break;
230 }
232 out1:
233 return ret;
234 }
237 long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
238 {
239 dom0_op_t op;
241 op.cmd = DOM0_GETVCPUINFO;
242 op.u.getvcpuinfo.domain = (domid_t)domid;
243 op.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
244 if ( (do_dom0_op(xc_handle, &op) < 0) )
245 {
246 PERROR("Could not get info on domain");
247 return -1;
248 }
249 return op.u.getvcpuinfo.cpu_time;
250 }
253 int xc_get_pfn_list(int xc_handle,
254 uint32_t domid,
255 unsigned long *pfn_buf,
256 unsigned long max_pfns)
257 {
258 dom0_op_t op;
259 int ret;
260 op.cmd = DOM0_GETMEMLIST;
261 op.u.getmemlist.domain = (domid_t)domid;
262 op.u.getmemlist.max_pfns = max_pfns;
263 op.u.getmemlist.buffer = pfn_buf;
266 if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
267 {
268 PERROR("xc_get_pfn_list: pfn_buf mlock failed");
269 return -1;
270 }
272 ret = do_dom0_op(xc_handle, &op);
274 safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long));
276 #if 0
277 #ifdef DEBUG
278 DPRINTF(("Ret for xc_get_pfn_list is %d\n", ret));
279 if (ret >= 0) {
280 int i, j;
281 for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) {
282 fprintf(stderr, "0x%x: ", i);
283 for (j = 0; j < 16; j++)
284 fprintf(stderr, "0x%lx ", pfn_buf[i + j]);
285 fprintf(stderr, "\n");
286 }
287 }
288 #endif
289 #endif
291 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
292 }
294 long xc_get_tot_pages(int xc_handle, uint32_t domid)
295 {
296 dom0_op_t op;
297 op.cmd = DOM0_GETDOMAININFO;
298 op.u.getdomaininfo.domain = (domid_t)domid;
299 return (do_dom0_op(xc_handle, &op) < 0) ?
300 -1 : op.u.getdomaininfo.tot_pages;
301 }
303 int xc_copy_to_domain_page(int xc_handle,
304 uint32_t domid,
305 unsigned long dst_pfn,
306 void *src_page)
307 {
308 void *vaddr = xc_map_foreign_range(
309 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
310 if ( vaddr == NULL )
311 return -1;
312 memcpy(vaddr, src_page, PAGE_SIZE);
313 munmap(vaddr, PAGE_SIZE);
314 return 0;
315 }
317 int xc_clear_domain_page(int xc_handle,
318 uint32_t domid,
319 unsigned long dst_pfn)
320 {
321 void *vaddr = xc_map_foreign_range(
322 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
323 if ( vaddr == NULL )
324 return -1;
325 memset(vaddr, 0, PAGE_SIZE);
326 munmap(vaddr, PAGE_SIZE);
327 return 0;
328 }
330 unsigned long xc_get_filesz(int fd)
331 {
332 uint16_t sig;
333 uint32_t _sz = 0;
334 unsigned long sz;
336 lseek(fd, 0, SEEK_SET);
337 if ( read(fd, &sig, sizeof(sig)) != sizeof(sig) )
338 return 0;
339 sz = lseek(fd, 0, SEEK_END);
340 if ( sig == 0x8b1f ) /* GZIP signature? */
341 {
342 lseek(fd, -4, SEEK_END);
343 if ( read(fd, &_sz, 4) != 4 )
344 return 0;
345 sz = _sz;
346 }
347 lseek(fd, 0, SEEK_SET);
349 return sz;
350 }
352 void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
353 int xch, uint32_t dom, unsigned long *parray,
354 unsigned long vstart)
355 {
356 char *va;
357 unsigned long chunksz, done, pa;
359 for ( done = 0; done < size; done += chunksz )
360 {
361 pa = dst + done - vstart;
362 va = xc_map_foreign_range(
363 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
364 chunksz = size - done;
365 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
366 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
367 memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
368 munmap(va, PAGE_SIZE);
369 }
370 }
372 int xc_dom0_op(int xc_handle, dom0_op_t *op)
373 {
374 return do_dom0_op(xc_handle, op);
375 }
377 int xc_version(int xc_handle, int cmd, void *arg)
378 {
379 int rc, argsize = 0;
381 switch ( cmd )
382 {
383 case XENVER_extraversion:
384 argsize = sizeof(xen_extraversion_t);
385 break;
386 case XENVER_compile_info:
387 argsize = sizeof(xen_compile_info_t);
388 break;
389 case XENVER_capabilities:
390 argsize = sizeof(xen_capabilities_info_t);
391 break;
392 case XENVER_changeset:
393 argsize = sizeof(xen_changeset_info_t);
394 break;
395 case XENVER_platform_parameters:
396 argsize = sizeof(xen_platform_parameters_t);
397 break;
398 }
400 if ( (argsize != 0) && (mlock(arg, argsize) != 0) )
401 {
402 PERROR("Could not lock memory for version hypercall");
403 return -ENOMEM;
404 }
406 rc = do_xen_version(xc_handle, cmd, arg);
408 if ( argsize != 0 )
409 safe_munlock(arg, argsize);
411 return rc;
412 }
414 unsigned long xc_make_page_below_4G(
415 int xc_handle, uint32_t domid, unsigned long mfn)
416 {
417 unsigned long new_mfn;
419 if ( xc_domain_memory_decrease_reservation(
420 xc_handle, domid, 1, 0, &mfn) != 0 )
421 {
422 fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
423 return 0;
424 }
426 if ( xc_domain_memory_increase_reservation(
427 xc_handle, domid, 1, 0, 32, &new_mfn) != 0 )
428 {
429 fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
430 return 0;
431 }
433 return new_mfn;
434 }
436 /*
437 * Local variables:
438 * mode: C
439 * c-set-style: "BSD"
440 * c-basic-offset: 4
441 * tab-width: 4
442 * indent-tabs-mode: nil
443 * End:
444 */