ia64/xen-unstable

annotate 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
rev   line source
mjw@1623 1 /******************************************************************************
mjw@1623 2 * xc_private.c
mjw@1623 3 *
mjw@1623 4 * Helper functions for the rest of the library.
mjw@1623 5 */
mjw@1623 6
mafetter@3434 7 #include <zlib.h>
mjw@1623 8 #include "xc_private.h"
kaf24@6486 9 #include <xen/memory.h>
mjw@1623 10
iap10@2325 11 void *xc_map_foreign_batch(int xc_handle, u32 dom, int prot,
kaf24@1645 12 unsigned long *arr, int num )
mjw@1623 13 {
mjw@1623 14 privcmd_mmapbatch_t ioctlx;
mjw@1623 15 void *addr;
kaf24@1645 16 addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0);
rusty@4866 17 if ( addr == MAP_FAILED )
rusty@4866 18 return NULL;
rusty@4866 19
rusty@4866 20 ioctlx.num=num;
rusty@4866 21 ioctlx.dom=dom;
rusty@4866 22 ioctlx.addr=(unsigned long)addr;
rusty@4866 23 ioctlx.arr=arr;
rusty@4866 24 if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx ) < 0 )
mjw@1623 25 {
kaf24@5543 26 int saved_errno = errno;
rusty@4866 27 perror("XXXXXXXX");
kaf24@5543 28 (void)munmap(addr, num*PAGE_SIZE);
kaf24@5543 29 errno = saved_errno;
rusty@4866 30 return NULL;
mjw@1623 31 }
mjw@1623 32 return addr;
mjw@1623 33
mjw@1623 34 }
mjw@1623 35
mjw@1623 36 /*******************/
mjw@1623 37
iap10@2325 38 void *xc_map_foreign_range(int xc_handle, u32 dom,
kaf24@1645 39 int size, int prot,
kaf24@1645 40 unsigned long mfn )
mjw@1623 41 {
mjw@1623 42 privcmd_mmap_t ioctlx;
mjw@1623 43 privcmd_mmap_entry_t entry;
mjw@1623 44 void *addr;
kaf24@1645 45 addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
rusty@4866 46 if ( addr == MAP_FAILED )
rusty@4866 47 return NULL;
rusty@4866 48
rusty@4866 49 ioctlx.num=1;
rusty@4866 50 ioctlx.dom=dom;
rusty@4866 51 ioctlx.entry=&entry;
rusty@4866 52 entry.va=(unsigned long) addr;
rusty@4866 53 entry.mfn=mfn;
rusty@4866 54 entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT;
rusty@4866 55 if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) < 0 )
mjw@1623 56 {
kaf24@5543 57 int saved_errno = errno;
kaf24@5543 58 (void)munmap(addr, size);
kaf24@5543 59 errno = saved_errno;
rusty@4866 60 return NULL;
mjw@1623 61 }
mjw@1623 62 return addr;
mjw@1623 63 }
mjw@1623 64
mjw@1623 65 /*******************/
mjw@1623 66
mjw@1623 67 /* NB: arr must be mlock'ed */
cl349@6404 68 int xc_get_pfn_type_batch(int xc_handle,
cl349@6404 69 u32 dom, int num, unsigned long *arr)
mjw@1623 70 {
mjw@1623 71 dom0_op_t op;
mjw@1623 72 op.cmd = DOM0_GETPAGEFRAMEINFO2;
mjw@1623 73 op.u.getpageframeinfo2.domain = (domid_t)dom;
mjw@1623 74 op.u.getpageframeinfo2.num = num;
mjw@1623 75 op.u.getpageframeinfo2.array = arr;
mjw@1623 76 return do_dom0_op(xc_handle, &op);
mjw@1623 77 }
mjw@1623 78
mjw@1623 79 #define GETPFN_ERR (~0U)
mjw@1623 80 unsigned int get_pfn_type(int xc_handle,
mjw@1623 81 unsigned long mfn,
mjw@1623 82 u32 dom)
mjw@1623 83 {
mjw@1623 84 dom0_op_t op;
mjw@1623 85 op.cmd = DOM0_GETPAGEFRAMEINFO;
mjw@1623 86 op.u.getpageframeinfo.pfn = mfn;
mjw@1623 87 op.u.getpageframeinfo.domain = (domid_t)dom;
mjw@1623 88 if ( do_dom0_op(xc_handle, &op) < 0 )
mjw@1623 89 {
mjw@1623 90 PERROR("Unexpected failure when getting page frame info!");
mjw@1623 91 return GETPFN_ERR;
mjw@1623 92 }
mjw@1623 93 return op.u.getpageframeinfo.type;
mjw@1623 94 }
mjw@1623 95
cl349@6404 96 int xc_mmuext_op(
cl349@6404 97 int xc_handle,
cl349@6404 98 struct mmuext_op *op,
cl349@6404 99 unsigned int nr_ops,
cl349@6404 100 domid_t dom)
kaf24@4388 101 {
cl349@6404 102 privcmd_hypercall_t hypercall;
cl349@6404 103 long ret = -EINVAL;
kaf24@4388 104
cl349@6404 105 hypercall.op = __HYPERVISOR_mmuext_op;
cl349@6404 106 hypercall.arg[0] = (unsigned long)op;
cl349@6404 107 hypercall.arg[1] = (unsigned long)nr_ops;
cl349@6404 108 hypercall.arg[2] = (unsigned long)0;
cl349@6404 109 hypercall.arg[3] = (unsigned long)dom;
kaf24@4388 110
cl349@6404 111 if ( mlock(op, nr_ops*sizeof(*op)) != 0 )
cl349@6404 112 {
cl349@6404 113 PERROR("Could not lock memory for Xen hypercall");
cl349@6404 114 goto out1;
cl349@6404 115 }
kaf24@4388 116
cl349@6404 117 if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
cl349@6404 118 {
iap10@6698 119 fprintf(stderr, "Dom_mmuext operation failed (rc=%ld errno=%d)-- need to"
cl349@6404 120 " rebuild the user-space tool set?\n",ret,errno);
cl349@6404 121 }
mjw@1623 122
cl349@6404 123 safe_munlock(op, nr_ops*sizeof(*op));
cl349@6404 124
cl349@6404 125 out1:
cl349@6404 126 return ret;
cl349@6404 127 }
cl349@6404 128
cl349@6404 129 static int flush_mmu_updates(int xc_handle, xc_mmu_t *mmu)
mjw@1623 130 {
mjw@1623 131 int err = 0;
mjw@1623 132 privcmd_hypercall_t hypercall;
mjw@1623 133
kaf24@4388 134 if ( mmu->idx == 0 )
mjw@1623 135 return 0;
mjw@1623 136
mjw@1623 137 hypercall.op = __HYPERVISOR_mmu_update;
mjw@1623 138 hypercall.arg[0] = (unsigned long)mmu->updates;
mjw@1623 139 hypercall.arg[1] = (unsigned long)mmu->idx;
mjw@1623 140 hypercall.arg[2] = 0;
kaf24@4388 141 hypercall.arg[3] = mmu->subject;
mjw@1623 142
mjw@1623 143 if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 )
mjw@1623 144 {
cl349@5333 145 PERROR("flush_mmu_updates: mmu updates mlock failed");
mjw@1623 146 err = 1;
mjw@1623 147 goto out;
mjw@1623 148 }
mjw@1623 149
mjw@1623 150 if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
mjw@1623 151 {
mjw@1623 152 ERROR("Failure when submitting mmu updates");
mjw@1623 153 err = 1;
mjw@1623 154 }
mjw@1623 155
kaf24@4388 156 mmu->idx = 0;
kaf24@5543 157
kaf24@5543 158 safe_munlock(mmu->updates, sizeof(mmu->updates));
mjw@1623 159
mjw@1623 160 out:
mjw@1623 161 return err;
mjw@1623 162 }
mjw@1623 163
cl349@6404 164 xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom)
mjw@1623 165 {
cl349@6404 166 xc_mmu_t *mmu = malloc(sizeof(xc_mmu_t));
mjw@1623 167 if ( mmu == NULL )
mjw@1623 168 return mmu;
kaf24@4388 169 mmu->idx = 0;
mjw@1623 170 mmu->subject = dom;
mjw@1623 171 return mmu;
mjw@1623 172 }
mjw@1623 173
cl349@6404 174 int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
iap10@6698 175 unsigned long long ptr, unsigned long long val)
mjw@1623 176 {
mjw@1623 177 mmu->updates[mmu->idx].ptr = ptr;
mjw@1623 178 mmu->updates[mmu->idx].val = val;
mjw@1623 179
mjw@1623 180 if ( ++mmu->idx == MAX_MMU_UPDATES )
mjw@1623 181 return flush_mmu_updates(xc_handle, mmu);
mjw@1623 182
mjw@1623 183 return 0;
mjw@1623 184 }
mjw@1623 185
cl349@6404 186 int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu)
mjw@1623 187 {
mjw@1623 188 return flush_mmu_updates(xc_handle, mmu);
mjw@1623 189 }
mjw@1623 190
kaf24@6486 191 int xc_memory_op(int xc_handle,
kaf24@6486 192 int cmd,
kaf24@6486 193 void *arg)
cl349@6404 194 {
cl349@6404 195 privcmd_hypercall_t hypercall;
kaf24@6486 196 struct xen_memory_reservation *reservation = arg;
cl349@6404 197 long ret = -EINVAL;
cl349@6404 198
kaf24@6486 199 hypercall.op = __HYPERVISOR_memory_op;
kaf24@6486 200 hypercall.arg[0] = (unsigned long)cmd;
kaf24@6486 201 hypercall.arg[1] = (unsigned long)arg;
cl349@6404 202
kaf24@6486 203 switch ( cmd )
cl349@6404 204 {
kaf24@6486 205 case XENMEM_increase_reservation:
kaf24@6486 206 case XENMEM_decrease_reservation:
kaf24@6486 207 if ( mlock(reservation, sizeof(*reservation)) != 0 )
kaf24@6486 208 {
kaf24@6486 209 PERROR("Could not mlock");
kaf24@6486 210 goto out1;
kaf24@6486 211 }
kaf24@6486 212 if ( (reservation->extent_start != NULL) &&
kaf24@6486 213 (mlock(reservation->extent_start,
kaf24@6486 214 reservation->nr_extents * sizeof(unsigned long)) != 0) )
kaf24@6486 215 {
kaf24@6486 216 PERROR("Could not mlock");
kaf24@6486 217 safe_munlock(reservation, sizeof(*reservation));
kaf24@6486 218 goto out1;
kaf24@6486 219 }
kaf24@6486 220 break;
kaf24@6486 221 case XENMEM_maximum_ram_page:
kaf24@6486 222 if ( mlock(arg, sizeof(unsigned long)) != 0 )
kaf24@6486 223 {
kaf24@6486 224 PERROR("Could not mlock");
kaf24@6486 225 goto out1;
kaf24@6486 226 }
kaf24@6486 227 break;
cl349@6404 228 }
cl349@6404 229
cl349@6404 230 if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
cl349@6404 231 {
iap10@6698 232 fprintf(stderr, "hypercall failed (rc=%ld errno=%d)-- need to"
cl349@6404 233 " rebuild the user-space tool set?\n",ret,errno);
cl349@6404 234 }
cl349@6404 235
kaf24@6486 236 switch ( cmd )
kaf24@6486 237 {
kaf24@6486 238 case XENMEM_increase_reservation:
kaf24@6486 239 case XENMEM_decrease_reservation:
kaf24@6486 240 safe_munlock(reservation, sizeof(*reservation));
kaf24@6486 241 if ( reservation->extent_start != NULL )
kaf24@6486 242 safe_munlock(reservation->extent_start,
kaf24@6486 243 reservation->nr_extents * sizeof(unsigned long));
kaf24@6486 244 break;
kaf24@6486 245 case XENMEM_maximum_ram_page:
kaf24@6486 246 safe_munlock(arg, sizeof(unsigned long));
kaf24@6486 247 break;
kaf24@6486 248 }
cl349@6404 249
cl349@6404 250 out1:
cl349@6404 251 return ret;
cl349@6404 252 }
cl349@6404 253
mjw@1623 254
mafetter@3435 255 long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
mjw@1623 256 {
mjw@1623 257 dom0_op_t op;
mjw@1623 258
cl349@4849 259 op.cmd = DOM0_GETVCPUCONTEXT;
cl349@4849 260 op.u.getvcpucontext.domain = (domid_t)domid;
kaf24@4882 261 op.u.getvcpucontext.vcpu = (u16)vcpu;
kaf24@4882 262 op.u.getvcpucontext.ctxt = NULL;
cl349@4849 263 if ( (do_dom0_op(xc_handle, &op) < 0) )
mjw@1623 264 {
mjw@1623 265 PERROR("Could not get info on domain");
mjw@1623 266 return -1;
mjw@1623 267 }
cl349@4849 268 return op.u.getvcpucontext.cpu_time;
mjw@1623 269 }
mjw@1623 270
mjw@1623 271
iap10@2124 272 unsigned long xc_get_m2p_start_mfn ( int xc_handle )
iap10@2124 273 {
iap10@2124 274 unsigned long mfn;
iap10@2124 275
iap10@2124 276 if ( ioctl( xc_handle, IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN, &mfn ) < 0 )
iap10@2124 277 {
iap10@2124 278 perror("xc_get_m2p_start_mfn:");
iap10@2124 279 return 0;
iap10@2124 280 }
iap10@2124 281 return mfn;
iap10@2124 282 }
iap10@2124 283
mafetter@3434 284 int xc_get_pfn_list(int xc_handle,
mafetter@3434 285 u32 domid,
mafetter@3434 286 unsigned long *pfn_buf,
mafetter@3434 287 unsigned long max_pfns)
mafetter@3434 288 {
mafetter@3434 289 dom0_op_t op;
mafetter@3434 290 int ret;
mafetter@3434 291 op.cmd = DOM0_GETMEMLIST;
mafetter@3434 292 op.u.getmemlist.domain = (domid_t)domid;
mafetter@3434 293 op.u.getmemlist.max_pfns = max_pfns;
mafetter@3434 294 op.u.getmemlist.buffer = pfn_buf;
iap10@2124 295
iap10@2124 296
mafetter@3434 297 if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
mafetter@3434 298 {
cl349@5333 299 PERROR("xc_get_pfn_list: pfn_buf mlock failed");
mafetter@3434 300 return -1;
mafetter@3434 301 }
mafetter@3434 302
mafetter@3434 303 ret = do_dom0_op(xc_handle, &op);
mafetter@3434 304
kaf24@5543 305 safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long));
mafetter@3434 306
mafetter@3434 307 #if 0
mafetter@3434 308 #ifdef DEBUG
mafetter@3434 309 DPRINTF(("Ret for xc_get_pfn_list is %d\n", ret));
mafetter@3434 310 if (ret >= 0) {
mafetter@3434 311 int i, j;
mafetter@3434 312 for (i = 0; i < op.u.getmemlist.num_pfns; i += 16) {
mafetter@3434 313 fprintf(stderr, "0x%x: ", i);
mafetter@3434 314 for (j = 0; j < 16; j++)
mafetter@3434 315 fprintf(stderr, "0x%lx ", pfn_buf[i + j]);
mafetter@3434 316 fprintf(stderr, "\n");
mafetter@3434 317 }
mafetter@3434 318 }
mafetter@3434 319 #endif
mafetter@3434 320 #endif
mafetter@3434 321
mafetter@3434 322 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
mafetter@3434 323 }
mafetter@3434 324
kaf24@5930 325 #ifdef __ia64__
kaf24@5930 326 int xc_ia64_get_pfn_list(int xc_handle,
kaf24@5930 327 u32 domid,
kaf24@5930 328 unsigned long *pfn_buf,
kaf24@5930 329 unsigned int start_page,
kaf24@5930 330 unsigned int nr_pages)
kaf24@5930 331 {
kaf24@5930 332 dom0_op_t op;
kaf24@5930 333 int ret;
kaf24@5930 334
kaf24@5930 335 op.cmd = DOM0_GETMEMLIST;
kaf24@5930 336 op.u.getmemlist.domain = (domid_t)domid;
kaf24@5930 337 op.u.getmemlist.max_pfns = ((unsigned long)start_page << 32) | nr_pages;
kaf24@5930 338 op.u.getmemlist.buffer = pfn_buf;
kaf24@5930 339
kaf24@5930 340 if ( mlock(pfn_buf, nr_pages * sizeof(unsigned long)) != 0 )
kaf24@5930 341 {
kaf24@5930 342 PERROR("Could not lock pfn list buffer");
kaf24@5930 343 return -1;
kaf24@5930 344 }
kaf24@5930 345
kaf24@5930 346 /* XXX Hack to put pages in TLB, hypervisor should be able to handle this */
kaf24@5930 347 memset(pfn_buf, 0, nr_pages * sizeof(unsigned long));
kaf24@5930 348 ret = do_dom0_op(xc_handle, &op);
kaf24@5930 349
kaf24@5930 350 (void)munlock(pfn_buf, nr_pages * sizeof(unsigned long));
kaf24@5930 351
kaf24@5930 352 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
kaf24@5930 353 }
kaf24@5930 354 #endif
kaf24@5930 355
mafetter@3434 356 long xc_get_tot_pages(int xc_handle, u32 domid)
mafetter@3434 357 {
mafetter@3434 358 dom0_op_t op;
mafetter@3434 359 op.cmd = DOM0_GETDOMAININFO;
mafetter@3434 360 op.u.getdomaininfo.domain = (domid_t)domid;
mafetter@3434 361 return (do_dom0_op(xc_handle, &op) < 0) ?
mafetter@3434 362 -1 : op.u.getdomaininfo.tot_pages;
mafetter@3434 363 }
mafetter@3434 364
mafetter@3434 365 int xc_copy_to_domain_page(int xc_handle,
mafetter@3434 366 u32 domid,
mafetter@3434 367 unsigned long dst_pfn,
mafetter@3434 368 void *src_page)
mafetter@3434 369 {
mafetter@3434 370 void *vaddr = xc_map_foreign_range(
mafetter@3434 371 xc_handle, domid, PAGE_SIZE, PROT_WRITE, dst_pfn);
mafetter@3434 372 if ( vaddr == NULL )
mafetter@3434 373 return -1;
mafetter@3434 374 memcpy(vaddr, src_page, PAGE_SIZE);
mafetter@3434 375 munmap(vaddr, PAGE_SIZE);
mafetter@3434 376 return 0;
mafetter@3434 377 }
mafetter@3434 378
mafetter@3434 379 unsigned long xc_get_filesz(int fd)
mafetter@3434 380 {
mafetter@3434 381 u16 sig;
mafetter@3434 382 u32 _sz = 0;
mafetter@3434 383 unsigned long sz;
mafetter@3434 384
mafetter@3434 385 lseek(fd, 0, SEEK_SET);
kaf24@3876 386 if ( read(fd, &sig, sizeof(sig)) != sizeof(sig) )
kaf24@3876 387 return 0;
mafetter@3434 388 sz = lseek(fd, 0, SEEK_END);
mafetter@3434 389 if ( sig == 0x8b1f ) /* GZIP signature? */
mafetter@3434 390 {
mafetter@3434 391 lseek(fd, -4, SEEK_END);
kaf24@3876 392 if ( read(fd, &_sz, 4) != 4 )
kaf24@3876 393 return 0;
mafetter@3434 394 sz = _sz;
mafetter@3434 395 }
mafetter@3434 396 lseek(fd, 0, SEEK_SET);
mafetter@3434 397
mafetter@3434 398 return sz;
mafetter@3434 399 }
mafetter@3434 400
mafetter@3434 401 void xc_map_memcpy(unsigned long dst, char *src, unsigned long size,
mafetter@3434 402 int xch, u32 dom, unsigned long *parray,
mafetter@3434 403 unsigned long vstart)
mafetter@3434 404 {
mafetter@3434 405 char *va;
mafetter@3434 406 unsigned long chunksz, done, pa;
mafetter@3434 407
mafetter@3434 408 for ( done = 0; done < size; done += chunksz )
mafetter@3434 409 {
mafetter@3434 410 pa = dst + done - vstart;
mafetter@3434 411 va = xc_map_foreign_range(
mafetter@3434 412 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
mafetter@3434 413 chunksz = size - done;
mafetter@3434 414 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
mafetter@3434 415 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
mafetter@3434 416 memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
mafetter@3434 417 munmap(va, PAGE_SIZE);
mafetter@3434 418 }
mafetter@3434 419 }
kaf24@5318 420
kaf24@5318 421 int xc_dom0_op(int xc_handle, dom0_op_t *op)
kaf24@5318 422 {
kaf24@5318 423 return do_dom0_op(xc_handle, op);
kaf24@5318 424 }
vh249@6567 425
vh249@6567 426 int xc_version(int xc_handle, int cmd, void *arg)
vh249@6567 427 {
vh249@6567 428 return do_xen_version(xc_handle, cmd, arg);
vh249@6567 429 }
iap10@6706 430
iap10@6706 431 unsigned long xc_make_page_below_4G(int xc_handle, u32 domid,
iap10@6706 432 unsigned long mfn)
iap10@6706 433 {
iap10@6706 434 unsigned long new_mfn;
iap10@6706 435 if ( xc_domain_memory_decrease_reservation(
iap10@6706 436 xc_handle, domid, 1, 0, &mfn ) != 1 )
iap10@6706 437 {
iap10@6706 438 fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
iap10@6706 439 return 0;
iap10@6706 440 }
iap10@6706 441 if ( xc_domain_memory_increase_reservation( xc_handle, domid, 1, 0, 32, &new_mfn ) != 1 )
iap10@6706 442 {
iap10@6706 443 fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
iap10@6706 444 return 0;
iap10@6706 445 }
iap10@6706 446 return new_mfn;
iap10@6706 447 }