direct-io.hg

view tools/libxc/xc_private.c @ 8686:c0a0f4db5ab1

Create a block of reserved PFNs in shadow translate mode guests, and
move the shared info and grant table pfns into that block. This
allows us to remove the get_gnttablist dom0 op, and simplifies the
domain creation code slightly. Having the reserved block managed by
Xen may also make it slightly easier to handle the case where the
grant table needs to be extended at run time.

Suggested-by: kaf24
Signed-off-by: Steven Smith, sos22@cam.ac.uk
author sos22@douglas.cl.cam.ac.uk
date Thu Jan 26 19:40:13 2006 +0100 (2006-01-26)
parents cc9bb3e0e348
children 1db05e589fa0
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.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 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 if ( mlock(reservation, sizeof(*reservation)) != 0 )
205 {
206 PERROR("Could not mlock");
207 goto out1;
208 }
209 if ( (reservation->extent_start != NULL) &&
210 (mlock(reservation->extent_start,
211 reservation->nr_extents * sizeof(unsigned long)) != 0) )
212 {
213 PERROR("Could not mlock");
214 safe_munlock(reservation, sizeof(*reservation));
215 goto out1;
216 }
217 break;
218 case XENMEM_machphys_mfn_list:
219 if ( mlock(xmml, sizeof(*xmml)) != 0 )
220 {
221 PERROR("Could not mlock");
222 goto out1;
223 }
224 if ( mlock(xmml->extent_start,
225 xmml->max_extents * sizeof(unsigned long)) != 0 )
226 {
227 PERROR("Could not mlock");
228 safe_munlock(xmml, sizeof(*xmml));
229 goto out1;
230 }
231 break;
232 }
234 ret = do_xen_hypercall(xc_handle, &hypercall);
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_machphys_mfn_list:
246 safe_munlock(xmml, sizeof(*xmml));
247 safe_munlock(xmml->extent_start,
248 xmml->max_extents * sizeof(unsigned long));
249 break;
250 }
252 out1:
253 return ret;
254 }
257 long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
258 {
259 DECLARE_DOM0_OP;
261 op.cmd = DOM0_GETVCPUINFO;
262 op.u.getvcpuinfo.domain = (domid_t)domid;
263 op.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
264 if ( (do_dom0_op(xc_handle, &op) < 0) )
265 {
266 PERROR("Could not get info on domain");
267 return -1;
268 }
269 return op.u.getvcpuinfo.cpu_time;
270 }
273 int xc_get_pfn_list(int xc_handle,
274 uint32_t domid,
275 unsigned long *pfn_buf,
276 unsigned long max_pfns)
277 {
278 DECLARE_DOM0_OP;
279 int ret;
280 op.cmd = DOM0_GETMEMLIST;
281 op.u.getmemlist.domain = (domid_t)domid;
282 op.u.getmemlist.max_pfns = max_pfns;
283 op.u.getmemlist.buffer = pfn_buf;
285 #ifdef VALGRIND
286 memset(pfn_buf, 0, max_pfns * sizeof(unsigned long));
287 #endif
289 if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
290 {
291 PERROR("xc_get_pfn_list: pfn_buf mlock failed");
292 return -1;
293 }
295 ret = do_dom0_op(xc_handle, &op);
297 safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long));
299 #if 0
300 #ifdef DEBUG
301 DPRINTF(("Ret for xc_get_pfn_list is %d\n", ret));
302 if (ret >= 0) {
303 int i, j;
304 for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) {
305 fprintf(stderr, "0x%x: ", i);
306 for (j = 0; j < 16; j++)
307 fprintf(stderr, "0x%lx ", pfn_buf[i + j]);
308 fprintf(stderr, "\n");
309 }
310 }
311 #endif
312 #endif
314 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
315 }
317 long xc_get_tot_pages(int xc_handle, uint32_t domid)
318 {
319 DECLARE_DOM0_OP;
320 op.cmd = DOM0_GETDOMAININFO;
321 op.u.getdomaininfo.domain = (domid_t)domid;
322 return (do_dom0_op(xc_handle, &op) < 0) ?
323 -1 : op.u.getdomaininfo.tot_pages;
324 }
326 int xc_copy_to_domain_page(int xc_handle,
327 uint32_t domid,
328 unsigned long dst_pfn,
329 void *src_page)
330 {
331 void *vaddr = xc_map_foreign_range(
332 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
333 if ( vaddr == NULL )
334 return -1;
335 memcpy(vaddr, src_page, PAGE_SIZE);
336 munmap(vaddr, PAGE_SIZE);
337 return 0;
338 }
340 int xc_clear_domain_page(int xc_handle,
341 uint32_t domid,
342 unsigned long dst_pfn)
343 {
344 void *vaddr = xc_map_foreign_range(
345 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
346 if ( vaddr == NULL )
347 return -1;
348 memset(vaddr, 0, PAGE_SIZE);
349 munmap(vaddr, PAGE_SIZE);
350 return 0;
351 }
353 unsigned long xc_get_filesz(int fd)
354 {
355 uint16_t sig;
356 uint32_t _sz = 0;
357 unsigned long sz;
359 lseek(fd, 0, SEEK_SET);
360 if ( read(fd, &sig, sizeof(sig)) != sizeof(sig) )
361 return 0;
362 sz = lseek(fd, 0, SEEK_END);
363 if ( sig == 0x8b1f ) /* GZIP signature? */
364 {
365 lseek(fd, -4, SEEK_END);
366 if ( read(fd, &_sz, 4) != 4 )
367 return 0;
368 sz = _sz;
369 }
370 lseek(fd, 0, SEEK_SET);
372 return sz;
373 }
375 void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
376 int xch, uint32_t dom, unsigned long *parray,
377 unsigned long vstart)
378 {
379 char *va;
380 unsigned long chunksz, done, pa;
382 for ( done = 0; done < size; done += chunksz )
383 {
384 pa = dst + done - vstart;
385 va = xc_map_foreign_range(
386 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
387 chunksz = size - done;
388 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
389 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
390 memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
391 munmap(va, PAGE_SIZE);
392 }
393 }
395 int xc_dom0_op(int xc_handle, dom0_op_t *op)
396 {
397 return do_dom0_op(xc_handle, op);
398 }
400 int xc_version(int xc_handle, int cmd, void *arg)
401 {
402 int rc, argsize = 0;
404 switch ( cmd )
405 {
406 case XENVER_extraversion:
407 argsize = sizeof(xen_extraversion_t);
408 break;
409 case XENVER_compile_info:
410 argsize = sizeof(xen_compile_info_t);
411 break;
412 case XENVER_capabilities:
413 argsize = sizeof(xen_capabilities_info_t);
414 break;
415 case XENVER_changeset:
416 argsize = sizeof(xen_changeset_info_t);
417 break;
418 case XENVER_platform_parameters:
419 argsize = sizeof(xen_platform_parameters_t);
420 break;
421 }
423 if ( (argsize != 0) && (mlock(arg, argsize) != 0) )
424 {
425 PERROR("Could not lock memory for version hypercall");
426 return -ENOMEM;
427 }
429 #ifdef VALGRIND
430 if (argsize != 0)
431 memset(arg, 0, argsize);
432 #endif
434 rc = do_xen_version(xc_handle, cmd, arg);
436 if ( argsize != 0 )
437 safe_munlock(arg, argsize);
439 return rc;
440 }
442 unsigned long xc_make_page_below_4G(
443 int xc_handle, uint32_t domid, unsigned long mfn)
444 {
445 unsigned long new_mfn;
447 if ( xc_domain_memory_decrease_reservation(
448 xc_handle, domid, 1, 0, &mfn) != 0 )
449 {
450 fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
451 return 0;
452 }
454 if ( xc_domain_memory_increase_reservation(
455 xc_handle, domid, 1, 0, 32, &new_mfn) != 0 )
456 {
457 fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
458 return 0;
459 }
461 return new_mfn;
462 }
464 /*
465 * Local variables:
466 * mode: C
467 * c-set-style: "BSD"
468 * c-basic-offset: 4
469 * tab-width: 4
470 * indent-tabs-mode: nil
471 * End:
472 */