ia64/xen-unstable

view tools/libxc/xc_private.c @ 6435:b4b3f6be5226

merge?
author cl349@firebug.cl.cam.ac.uk
date Thu Aug 25 17:27:49 2005 +0000 (2005-08-25)
parents 0610add7c3fe fdfd511768a3
children 8799d14bef77 9312a3e8a6f8 112d44270733
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"
10 void *xc_map_foreign_batch(int xc_handle, u32 dom, int prot,
11 unsigned long *arr, int num )
12 {
13 privcmd_mmapbatch_t ioctlx;
14 void *addr;
15 addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0);
16 if ( addr == MAP_FAILED )
17 return NULL;
19 ioctlx.num=num;
20 ioctlx.dom=dom;
21 ioctlx.addr=(unsigned long)addr;
22 ioctlx.arr=arr;
23 if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx ) < 0 )
24 {
25 int saved_errno = errno;
26 perror("XXXXXXXX");
27 (void)munmap(addr, num*PAGE_SIZE);
28 errno = saved_errno;
29 return NULL;
30 }
31 return addr;
33 }
35 /*******************/
37 void *xc_map_foreign_range(int xc_handle, u32 dom,
38 int size, int prot,
39 unsigned long mfn )
40 {
41 privcmd_mmap_t ioctlx;
42 privcmd_mmap_entry_t entry;
43 void *addr;
44 addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
45 if ( addr == MAP_FAILED )
46 return NULL;
48 ioctlx.num=1;
49 ioctlx.dom=dom;
50 ioctlx.entry=&entry;
51 entry.va=(unsigned long) addr;
52 entry.mfn=mfn;
53 entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT;
54 if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) < 0 )
55 {
56 int saved_errno = errno;
57 (void)munmap(addr, size);
58 errno = saved_errno;
59 return NULL;
60 }
61 return addr;
62 }
64 /*******************/
66 /* NB: arr must be mlock'ed */
67 int xc_get_pfn_type_batch(int xc_handle,
68 u32 dom, int num, unsigned long *arr)
69 {
70 dom0_op_t op;
71 op.cmd = DOM0_GETPAGEFRAMEINFO2;
72 op.u.getpageframeinfo2.domain = (domid_t)dom;
73 op.u.getpageframeinfo2.num = num;
74 op.u.getpageframeinfo2.array = arr;
75 return do_dom0_op(xc_handle, &op);
76 }
78 #define GETPFN_ERR (~0U)
79 unsigned int get_pfn_type(int xc_handle,
80 unsigned long mfn,
81 u32 dom)
82 {
83 dom0_op_t op;
84 op.cmd = DOM0_GETPAGEFRAMEINFO;
85 op.u.getpageframeinfo.pfn = mfn;
86 op.u.getpageframeinfo.domain = (domid_t)dom;
87 if ( do_dom0_op(xc_handle, &op) < 0 )
88 {
89 PERROR("Unexpected failure when getting page frame info!");
90 return GETPFN_ERR;
91 }
92 return op.u.getpageframeinfo.type;
93 }
95 int xc_mmuext_op(
96 int xc_handle,
97 struct mmuext_op *op,
98 unsigned int nr_ops,
99 domid_t dom)
100 {
101 privcmd_hypercall_t hypercall;
102 long ret = -EINVAL;
104 hypercall.op = __HYPERVISOR_mmuext_op;
105 hypercall.arg[0] = (unsigned long)op;
106 hypercall.arg[1] = (unsigned long)nr_ops;
107 hypercall.arg[2] = (unsigned long)0;
108 hypercall.arg[3] = (unsigned long)dom;
110 if ( mlock(op, nr_ops*sizeof(*op)) != 0 )
111 {
112 PERROR("Could not lock memory for Xen hypercall");
113 goto out1;
114 }
116 if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
117 {
118 fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
119 " rebuild the user-space tool set?\n",ret,errno);
120 }
122 safe_munlock(op, nr_ops*sizeof(*op));
124 out1:
125 return ret;
126 }
128 static int flush_mmu_updates(int xc_handle, xc_mmu_t *mmu)
129 {
130 int err = 0;
131 privcmd_hypercall_t hypercall;
133 if ( mmu->idx == 0 )
134 return 0;
136 hypercall.op = __HYPERVISOR_mmu_update;
137 hypercall.arg[0] = (unsigned long)mmu->updates;
138 hypercall.arg[1] = (unsigned long)mmu->idx;
139 hypercall.arg[2] = 0;
140 hypercall.arg[3] = mmu->subject;
142 if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 )
143 {
144 PERROR("flush_mmu_updates: mmu updates mlock failed");
145 err = 1;
146 goto out;
147 }
149 if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
150 {
151 ERROR("Failure when submitting mmu updates");
152 err = 1;
153 }
155 mmu->idx = 0;
157 safe_munlock(mmu->updates, sizeof(mmu->updates));
159 out:
160 return err;
161 }
163 xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom)
164 {
165 xc_mmu_t *mmu = malloc(sizeof(xc_mmu_t));
166 if ( mmu == NULL )
167 return mmu;
168 mmu->idx = 0;
169 mmu->subject = dom;
170 return mmu;
171 }
173 int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
174 unsigned long ptr, unsigned long val)
175 {
176 mmu->updates[mmu->idx].ptr = ptr;
177 mmu->updates[mmu->idx].val = val;
179 if ( ++mmu->idx == MAX_MMU_UPDATES )
180 return flush_mmu_updates(xc_handle, mmu);
182 return 0;
183 }
185 int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu)
186 {
187 return flush_mmu_updates(xc_handle, mmu);
188 }
190 int xc_dom_mem_op(int xc_handle,
191 unsigned int memop,
192 unsigned int *extent_list,
193 unsigned int nr_extents,
194 unsigned int extent_order,
195 domid_t domid)
196 {
197 privcmd_hypercall_t hypercall;
198 long ret = -EINVAL;
200 hypercall.op = __HYPERVISOR_dom_mem_op;
201 hypercall.arg[0] = (unsigned long)memop;
202 hypercall.arg[1] = (unsigned long)extent_list;
203 hypercall.arg[2] = (unsigned long)nr_extents;
204 hypercall.arg[3] = (unsigned long)extent_order;
205 hypercall.arg[4] = (unsigned long)domid;
207 if ( (extent_list != NULL) &&
208 (mlock(extent_list, nr_extents*sizeof(unsigned long)) != 0) )
209 {
210 PERROR("Could not lock memory for Xen hypercall");
211 goto out1;
212 }
214 if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
215 {
216 fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
217 " rebuild the user-space tool set?\n",ret,errno);
218 }
220 if ( extent_list != NULL )
221 safe_munlock(extent_list, nr_extents*sizeof(unsigned long));
223 out1:
224 return ret;
225 }
228 long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
229 {
230 dom0_op_t op;
232 op.cmd = DOM0_GETVCPUCONTEXT;
233 op.u.getvcpucontext.domain = (domid_t)domid;
234 op.u.getvcpucontext.vcpu = (u16)vcpu;
235 op.u.getvcpucontext.ctxt = NULL;
236 if ( (do_dom0_op(xc_handle, &op) < 0) )
237 {
238 PERROR("Could not get info on domain");
239 return -1;
240 }
241 return op.u.getvcpucontext.cpu_time;
242 }
245 unsigned long xc_get_m2p_start_mfn ( int xc_handle )
246 {
247 unsigned long mfn;
249 if ( ioctl( xc_handle, IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN, &mfn ) < 0 )
250 {
251 perror("xc_get_m2p_start_mfn:");
252 return 0;
253 }
254 return mfn;
255 }
257 int xc_get_pfn_list(int xc_handle,
258 u32 domid,
259 unsigned long *pfn_buf,
260 unsigned long max_pfns)
261 {
262 dom0_op_t op;
263 int ret;
264 op.cmd = DOM0_GETMEMLIST;
265 op.u.getmemlist.domain = (domid_t)domid;
266 op.u.getmemlist.max_pfns = max_pfns;
267 op.u.getmemlist.buffer = pfn_buf;
270 if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
271 {
272 PERROR("xc_get_pfn_list: pfn_buf mlock failed");
273 return -1;
274 }
276 ret = do_dom0_op(xc_handle, &op);
278 safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long));
280 #if 0
281 #ifdef DEBUG
282 DPRINTF(("Ret for xc_get_pfn_list is %d\n", ret));
283 if (ret >= 0) {
284 int i, j;
285 for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) {
286 fprintf(stderr, "0x%x: ", i);
287 for (j = 0; j < 16; j++)
288 fprintf(stderr, "0x%lx ", pfn_buf[i + j]);
289 fprintf(stderr, "\n");
290 }
291 }
292 #endif
293 #endif
295 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
296 }
298 #ifdef __ia64__
299 int xc_ia64_get_pfn_list(int xc_handle,
300 u32 domid,
301 unsigned long *pfn_buf,
302 unsigned int start_page,
303 unsigned int nr_pages)
304 {
305 dom0_op_t op;
306 int ret;
308 op.cmd = DOM0_GETMEMLIST;
309 op.u.getmemlist.domain = (domid_t)domid;
310 op.u.getmemlist.max_pfns = ((unsigned long)start_page << 32) | nr_pages;
311 op.u.getmemlist.buffer = pfn_buf;
313 if ( mlock(pfn_buf, nr_pages * sizeof(unsigned long)) != 0 )
314 {
315 PERROR("Could not lock pfn list buffer");
316 return -1;
317 }
319 /* XXX Hack to put pages in TLB, hypervisor should be able to handle this */
320 memset(pfn_buf, 0, nr_pages * sizeof(unsigned long));
321 ret = do_dom0_op(xc_handle, &op);
323 (void)munlock(pfn_buf, nr_pages * sizeof(unsigned long));
325 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
326 }
327 #endif
329 long xc_get_tot_pages(int xc_handle, u32 domid)
330 {
331 dom0_op_t op;
332 op.cmd = DOM0_GETDOMAININFO;
333 op.u.getdomaininfo.domain = (domid_t)domid;
334 return (do_dom0_op(xc_handle, &op) < 0) ?
335 -1 : op.u.getdomaininfo.tot_pages;
336 }
338 int xc_copy_to_domain_page(int xc_handle,
339 u32 domid,
340 unsigned long dst_pfn,
341 void *src_page)
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 memcpy(vaddr, src_page, PAGE_SIZE);
348 munmap(vaddr, PAGE_SIZE);
349 return 0;
350 }
352 unsigned long xc_get_filesz(int fd)
353 {
354 u16 sig;
355 u32 _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, u32 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 }