Merge branch 'stable/gntdev' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen

* 'stable/gntdev' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
xen/p2m: Fix module linking error.
xen p2m: clear the old pte when adding a page to m2p_override
xen gntdev: use gnttab_map_refs and gnttab_unmap_refs
xen: introduce gnttab_map_refs and gnttab_unmap_refs
xen p2m: transparently change the p2m mappings in the m2p override
xen/gntdev: Fix circular locking dependency
xen/gntdev: stop using "token" argument
xen: gntdev: move use of GNTMAP_contains_pte next to the map_op
xen: add m2p override mechanism
xen: move p2m handling to separate file
xen/gntdev: add VM_PFNMAP to vma
xen/gntdev: allow usermode to map granted pages
xen: define gnttab_set_map_op/unmap_op

Fix up trivial conflict in drivers/xen/Kconfig

+1408 -371
+13 -3
arch/x86/include/asm/xen/page.h
··· 42 42 extern unsigned long get_phys_to_machine(unsigned long pfn); 43 43 extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn); 44 44 45 + extern int m2p_add_override(unsigned long mfn, struct page *page); 46 + extern int m2p_remove_override(struct page *page); 47 + extern struct page *m2p_find_override(unsigned long mfn); 48 + extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); 49 + 45 50 static inline unsigned long pfn_to_mfn(unsigned long pfn) 46 51 { 47 52 unsigned long mfn; ··· 77 72 if (xen_feature(XENFEAT_auto_translated_physmap)) 78 73 return mfn; 79 74 80 - if (unlikely((mfn >> machine_to_phys_order) != 0)) 81 - return ~0; 82 - 83 75 pfn = 0; 84 76 /* 85 77 * The array access can fail (e.g., device space beyond end of RAM). ··· 84 82 * but we must handle the fault without crashing! 85 83 */ 86 84 __get_user(pfn, &machine_to_phys_mapping[mfn]); 85 + 86 + /* 87 + * If this appears to be a foreign mfn (because the pfn 88 + * doesn't map back to the mfn), then check the local override 89 + * table to see if there's a better pfn to use. 90 + */ 91 + if (get_phys_to_machine(pfn) != mfn) 92 + pfn = m2p_find_override_pfn(mfn, pfn); 87 93 88 94 return pfn; 89 95 }
+2 -1
arch/x86/xen/Makefile
··· 12 12 13 13 obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ 14 14 time.o xen-asm.o xen-asm_$(BITS).o \ 15 - grant-table.o suspend.o platform-pci-unplug.o 15 + grant-table.o suspend.o platform-pci-unplug.o \ 16 + p2m.o 16 17 17 18 obj-$(CONFIG_SMP) += smp.o 18 19 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
-365
arch/x86/xen/mmu.c
··· 173 173 */ 174 174 #define USER_LIMIT ((STACK_TOP_MAX + PGDIR_SIZE - 1) & PGDIR_MASK) 175 175 176 - /* 177 - * Xen leaves the responsibility for maintaining p2m mappings to the 178 - * guests themselves, but it must also access and update the p2m array 179 - * during suspend/resume when all the pages are reallocated. 180 - * 181 - * The p2m table is logically a flat array, but we implement it as a 182 - * three-level tree to allow the address space to be sparse. 183 - * 184 - * Xen 185 - * | 186 - * p2m_top p2m_top_mfn 187 - * / \ / \ 188 - * p2m_mid p2m_mid p2m_mid_mfn p2m_mid_mfn 189 - * / \ / \ / / 190 - * p2m p2m p2m p2m p2m p2m p2m ... 191 - * 192 - * The p2m_mid_mfn pages are mapped by p2m_top_mfn_p. 193 - * 194 - * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the 195 - * maximum representable pseudo-physical address space is: 196 - * P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages 197 - * 198 - * P2M_PER_PAGE depends on the architecture, as a mfn is always 199 - * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to 200 - * 512 and 1024 entries respectively. 201 - */ 202 - 203 - unsigned long xen_max_p2m_pfn __read_mostly; 204 - 205 - #define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long)) 206 - #define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *)) 207 - #define P2M_TOP_PER_PAGE (PAGE_SIZE / sizeof(unsigned long **)) 208 - 209 - #define MAX_P2M_PFN (P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE) 210 - 211 - /* Placeholders for holes in the address space */ 212 - static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE); 213 - static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE); 214 - static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE); 215 - 216 - static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE); 217 - static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE); 218 - static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE); 219 - 220 - RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); 221 - RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); 222 - 223 - static inline unsigned p2m_top_index(unsigned long pfn) 224 - { 225 - BUG_ON(pfn >= MAX_P2M_PFN); 226 - return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE); 227 - } 228 - 229 - static inline unsigned p2m_mid_index(unsigned long pfn) 230 - { 231 - return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE; 232 - } 233 - 234 - static inline unsigned p2m_index(unsigned long pfn) 235 - { 236 - return pfn % P2M_PER_PAGE; 237 - } 238 - 239 - static void p2m_top_init(unsigned long ***top) 240 - { 241 - unsigned i; 242 - 243 - for (i = 0; i < P2M_TOP_PER_PAGE; i++) 244 - top[i] = p2m_mid_missing; 245 - } 246 - 247 - static void p2m_top_mfn_init(unsigned long *top) 248 - { 249 - unsigned i; 250 - 251 - for (i = 0; i < P2M_TOP_PER_PAGE; i++) 252 - top[i] = virt_to_mfn(p2m_mid_missing_mfn); 253 - } 254 - 255 - static void p2m_top_mfn_p_init(unsigned long **top) 256 - { 257 - unsigned i; 258 - 259 - for (i = 0; i < P2M_TOP_PER_PAGE; i++) 260 - top[i] = p2m_mid_missing_mfn; 261 - } 262 - 263 - static void p2m_mid_init(unsigned long **mid) 264 - { 265 - unsigned i; 266 - 267 - for (i = 0; i < P2M_MID_PER_PAGE; i++) 268 - mid[i] = p2m_missing; 269 - } 270 - 271 - static void p2m_mid_mfn_init(unsigned long *mid) 272 - { 273 - unsigned i; 274 - 275 - for (i = 0; i < P2M_MID_PER_PAGE; i++) 276 - mid[i] = virt_to_mfn(p2m_missing); 277 - } 278 - 279 - static void p2m_init(unsigned long *p2m) 280 - { 281 - unsigned i; 282 - 283 - for (i = 0; i < P2M_MID_PER_PAGE; i++) 284 - p2m[i] = INVALID_P2M_ENTRY; 285 - } 286 - 287 - /* 288 - * Build the parallel p2m_top_mfn and p2m_mid_mfn structures 289 - * 290 - * This is called both at boot time, and after resuming from suspend: 291 - * - At boot time we're called very early, and must use extend_brk() 292 - * to allocate memory. 293 - * 294 - * - After resume we're called from within stop_machine, but the mfn 295 - * tree should alreay be completely allocated. 296 - */ 297 - void xen_build_mfn_list_list(void) 298 - { 299 - unsigned long pfn; 300 - 301 - /* Pre-initialize p2m_top_mfn to be completely missing */ 302 - if (p2m_top_mfn == NULL) { 303 - p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE); 304 - p2m_mid_mfn_init(p2m_mid_missing_mfn); 305 - 306 - p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE); 307 - p2m_top_mfn_p_init(p2m_top_mfn_p); 308 - 309 - p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE); 310 - p2m_top_mfn_init(p2m_top_mfn); 311 - } else { 312 - /* Reinitialise, mfn's all change after migration */ 313 - p2m_mid_mfn_init(p2m_mid_missing_mfn); 314 - } 315 - 316 - for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) { 317 - unsigned topidx = p2m_top_index(pfn); 318 - unsigned mididx = p2m_mid_index(pfn); 319 - unsigned long **mid; 320 - unsigned long *mid_mfn_p; 321 - 322 - mid = p2m_top[topidx]; 323 - mid_mfn_p = p2m_top_mfn_p[topidx]; 324 - 325 - /* Don't bother allocating any mfn mid levels if 326 - * they're just missing, just update the stored mfn, 327 - * since all could have changed over a migrate. 328 - */ 329 - if (mid == p2m_mid_missing) { 330 - BUG_ON(mididx); 331 - BUG_ON(mid_mfn_p != p2m_mid_missing_mfn); 332 - p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing_mfn); 333 - pfn += (P2M_MID_PER_PAGE - 1) * P2M_PER_PAGE; 334 - continue; 335 - } 336 - 337 - if (mid_mfn_p == p2m_mid_missing_mfn) { 338 - /* 339 - * XXX boot-time only! We should never find 340 - * missing parts of the mfn tree after 341 - * runtime. extend_brk() will BUG if we call 342 - * it too late. 343 - */ 344 - mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE); 345 - p2m_mid_mfn_init(mid_mfn_p); 346 - 347 - p2m_top_mfn_p[topidx] = mid_mfn_p; 348 - } 349 - 350 - p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p); 351 - mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]); 352 - } 353 - } 354 - 355 - void xen_setup_mfn_list_list(void) 356 - { 357 - BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); 358 - 359 - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = 360 - virt_to_mfn(p2m_top_mfn); 361 - HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn; 362 - } 363 - 364 - /* Set up p2m_top to point to the domain-builder provided p2m pages */ 365 - void __init xen_build_dynamic_phys_to_machine(void) 366 - { 367 - unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list; 368 - unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages); 369 - unsigned long pfn; 370 - 371 - xen_max_p2m_pfn = max_pfn; 372 - 373 - p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE); 374 - p2m_init(p2m_missing); 375 - 376 - p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE); 377 - p2m_mid_init(p2m_mid_missing); 378 - 379 - p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE); 380 - p2m_top_init(p2m_top); 381 - 382 - /* 383 - * The domain builder gives us a pre-constructed p2m array in 384 - * mfn_list for all the pages initially given to us, so we just 385 - * need to graft that into our tree structure. 386 - */ 387 - for (pfn = 0; pfn < max_pfn; pfn += P2M_PER_PAGE) { 388 - unsigned topidx = p2m_top_index(pfn); 389 - unsigned mididx = p2m_mid_index(pfn); 390 - 391 - if (p2m_top[topidx] == p2m_mid_missing) { 392 - unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE); 393 - p2m_mid_init(mid); 394 - 395 - p2m_top[topidx] = mid; 396 - } 397 - 398 - p2m_top[topidx][mididx] = &mfn_list[pfn]; 399 - } 400 - } 401 - 402 - unsigned long get_phys_to_machine(unsigned long pfn) 403 - { 404 - unsigned topidx, mididx, idx; 405 - 406 - if (unlikely(pfn >= MAX_P2M_PFN)) 407 - return INVALID_P2M_ENTRY; 408 - 409 - topidx = p2m_top_index(pfn); 410 - mididx = p2m_mid_index(pfn); 411 - idx = p2m_index(pfn); 412 - 413 - return p2m_top[topidx][mididx][idx]; 414 - } 415 - EXPORT_SYMBOL_GPL(get_phys_to_machine); 416 - 417 - static void *alloc_p2m_page(void) 418 - { 419 - return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT); 420 - } 421 - 422 - static void free_p2m_page(void *p) 423 - { 424 - free_page((unsigned long)p); 425 - } 426 - 427 - /* 428 - * Fully allocate the p2m structure for a given pfn. We need to check 429 - * that both the top and mid levels are allocated, and make sure the 430 - * parallel mfn tree is kept in sync. We may race with other cpus, so 431 - * the new pages are installed with cmpxchg; if we lose the race then 432 - * simply free the page we allocated and use the one that's there. 433 - */ 434 - static bool alloc_p2m(unsigned long pfn) 435 - { 436 - unsigned topidx, mididx; 437 - unsigned long ***top_p, **mid; 438 - unsigned long *top_mfn_p, *mid_mfn; 439 - 440 - topidx = p2m_top_index(pfn); 441 - mididx = p2m_mid_index(pfn); 442 - 443 - top_p = &p2m_top[topidx]; 444 - mid = *top_p; 445 - 446 - if (mid == p2m_mid_missing) { 447 - /* Mid level is missing, allocate a new one */ 448 - mid = alloc_p2m_page(); 449 - if (!mid) 450 - return false; 451 - 452 - p2m_mid_init(mid); 453 - 454 - if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing) 455 - free_p2m_page(mid); 456 - } 457 - 458 - top_mfn_p = &p2m_top_mfn[topidx]; 459 - mid_mfn = p2m_top_mfn_p[topidx]; 460 - 461 - BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p); 462 - 463 - if (mid_mfn == p2m_mid_missing_mfn) { 464 - /* Separately check the mid mfn level */ 465 - unsigned long missing_mfn; 466 - unsigned long mid_mfn_mfn; 467 - 468 - mid_mfn = alloc_p2m_page(); 469 - if (!mid_mfn) 470 - return false; 471 - 472 - p2m_mid_mfn_init(mid_mfn); 473 - 474 - missing_mfn = virt_to_mfn(p2m_mid_missing_mfn); 475 - mid_mfn_mfn = virt_to_mfn(mid_mfn); 476 - if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn) 477 - free_p2m_page(mid_mfn); 478 - else 479 - p2m_top_mfn_p[topidx] = mid_mfn; 480 - } 481 - 482 - if (p2m_top[topidx][mididx] == p2m_missing) { 483 - /* p2m leaf page is missing */ 484 - unsigned long *p2m; 485 - 486 - p2m = alloc_p2m_page(); 487 - if (!p2m) 488 - return false; 489 - 490 - p2m_init(p2m); 491 - 492 - if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing) 493 - free_p2m_page(p2m); 494 - else 495 - mid_mfn[mididx] = virt_to_mfn(p2m); 496 - } 497 - 498 - return true; 499 - } 500 - 501 - /* Try to install p2m mapping; fail if intermediate bits missing */ 502 - bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) 503 - { 504 - unsigned topidx, mididx, idx; 505 - 506 - if (unlikely(pfn >= MAX_P2M_PFN)) { 507 - BUG_ON(mfn != INVALID_P2M_ENTRY); 508 - return true; 509 - } 510 - 511 - topidx = p2m_top_index(pfn); 512 - mididx = p2m_mid_index(pfn); 513 - idx = p2m_index(pfn); 514 - 515 - if (p2m_top[topidx][mididx] == p2m_missing) 516 - return mfn == INVALID_P2M_ENTRY; 517 - 518 - p2m_top[topidx][mididx][idx] = mfn; 519 - 520 - return true; 521 - } 522 - 523 - bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) 524 - { 525 - if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { 526 - BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); 527 - return true; 528 - } 529 - 530 - if (unlikely(!__set_phys_to_machine(pfn, mfn))) { 531 - if (!alloc_p2m(pfn)) 532 - return false; 533 - 534 - if (!__set_phys_to_machine(pfn, mfn)) 535 - return false; 536 - } 537 - 538 - return true; 539 - } 540 - 541 176 unsigned long arbitrary_virt_to_mfn(void *vaddr) 542 177 { 543 178 xmaddr_t maddr = arbitrary_virt_to_machine(vaddr);
+510
arch/x86/xen/p2m.c
··· 1 + /* 2 + * Xen leaves the responsibility for maintaining p2m mappings to the 3 + * guests themselves, but it must also access and update the p2m array 4 + * during suspend/resume when all the pages are reallocated. 5 + * 6 + * The p2m table is logically a flat array, but we implement it as a 7 + * three-level tree to allow the address space to be sparse. 8 + * 9 + * Xen 10 + * | 11 + * p2m_top p2m_top_mfn 12 + * / \ / \ 13 + * p2m_mid p2m_mid p2m_mid_mfn p2m_mid_mfn 14 + * / \ / \ / / 15 + * p2m p2m p2m p2m p2m p2m p2m ... 16 + * 17 + * The p2m_mid_mfn pages are mapped by p2m_top_mfn_p. 18 + * 19 + * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the 20 + * maximum representable pseudo-physical address space is: 21 + * P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages 22 + * 23 + * P2M_PER_PAGE depends on the architecture, as a mfn is always 24 + * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to 25 + * 512 and 1024 entries respectively. 26 + */ 27 + 28 + #include <linux/init.h> 29 + #include <linux/module.h> 30 + #include <linux/list.h> 31 + #include <linux/hash.h> 32 + #include <linux/sched.h> 33 + 34 + #include <asm/cache.h> 35 + #include <asm/setup.h> 36 + 37 + #include <asm/xen/page.h> 38 + #include <asm/xen/hypercall.h> 39 + #include <asm/xen/hypervisor.h> 40 + 41 + #include "xen-ops.h" 42 + 43 + static void __init m2p_override_init(void); 44 + 45 + unsigned long xen_max_p2m_pfn __read_mostly; 46 + 47 + #define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long)) 48 + #define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *)) 49 + #define P2M_TOP_PER_PAGE (PAGE_SIZE / sizeof(unsigned long **)) 50 + 51 + #define MAX_P2M_PFN (P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE) 52 + 53 + /* Placeholders for holes in the address space */ 54 + static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE); 55 + static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE); 56 + static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE); 57 + 58 + static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE); 59 + static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE); 60 + static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE); 61 + 62 + RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); 63 + RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); 64 + 65 + static inline unsigned p2m_top_index(unsigned long pfn) 66 + { 67 + BUG_ON(pfn >= MAX_P2M_PFN); 68 + return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE); 69 + } 70 + 71 + static inline unsigned p2m_mid_index(unsigned long pfn) 72 + { 73 + return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE; 74 + } 75 + 76 + static inline unsigned p2m_index(unsigned long pfn) 77 + { 78 + return pfn % P2M_PER_PAGE; 79 + } 80 + 81 + static void p2m_top_init(unsigned long ***top) 82 + { 83 + unsigned i; 84 + 85 + for (i = 0; i < P2M_TOP_PER_PAGE; i++) 86 + top[i] = p2m_mid_missing; 87 + } 88 + 89 + static void p2m_top_mfn_init(unsigned long *top) 90 + { 91 + unsigned i; 92 + 93 + for (i = 0; i < P2M_TOP_PER_PAGE; i++) 94 + top[i] = virt_to_mfn(p2m_mid_missing_mfn); 95 + } 96 + 97 + static void p2m_top_mfn_p_init(unsigned long **top) 98 + { 99 + unsigned i; 100 + 101 + for (i = 0; i < P2M_TOP_PER_PAGE; i++) 102 + top[i] = p2m_mid_missing_mfn; 103 + } 104 + 105 + static void p2m_mid_init(unsigned long **mid) 106 + { 107 + unsigned i; 108 + 109 + for (i = 0; i < P2M_MID_PER_PAGE; i++) 110 + mid[i] = p2m_missing; 111 + } 112 + 113 + static void p2m_mid_mfn_init(unsigned long *mid) 114 + { 115 + unsigned i; 116 + 117 + for (i = 0; i < P2M_MID_PER_PAGE; i++) 118 + mid[i] = virt_to_mfn(p2m_missing); 119 + } 120 + 121 + static void p2m_init(unsigned long *p2m) 122 + { 123 + unsigned i; 124 + 125 + for (i = 0; i < P2M_MID_PER_PAGE; i++) 126 + p2m[i] = INVALID_P2M_ENTRY; 127 + } 128 + 129 + /* 130 + * Build the parallel p2m_top_mfn and p2m_mid_mfn structures 131 + * 132 + * This is called both at boot time, and after resuming from suspend: 133 + * - At boot time we're called very early, and must use extend_brk() 134 + * to allocate memory. 135 + * 136 + * - After resume we're called from within stop_machine, but the mfn 137 + * tree should alreay be completely allocated. 138 + */ 139 + void xen_build_mfn_list_list(void) 140 + { 141 + unsigned long pfn; 142 + 143 + /* Pre-initialize p2m_top_mfn to be completely missing */ 144 + if (p2m_top_mfn == NULL) { 145 + p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE); 146 + p2m_mid_mfn_init(p2m_mid_missing_mfn); 147 + 148 + p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE); 149 + p2m_top_mfn_p_init(p2m_top_mfn_p); 150 + 151 + p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE); 152 + p2m_top_mfn_init(p2m_top_mfn); 153 + } else { 154 + /* Reinitialise, mfn's all change after migration */ 155 + p2m_mid_mfn_init(p2m_mid_missing_mfn); 156 + } 157 + 158 + for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) { 159 + unsigned topidx = p2m_top_index(pfn); 160 + unsigned mididx = p2m_mid_index(pfn); 161 + unsigned long **mid; 162 + unsigned long *mid_mfn_p; 163 + 164 + mid = p2m_top[topidx]; 165 + mid_mfn_p = p2m_top_mfn_p[topidx]; 166 + 167 + /* Don't bother allocating any mfn mid levels if 168 + * they're just missing, just update the stored mfn, 169 + * since all could have changed over a migrate. 170 + */ 171 + if (mid == p2m_mid_missing) { 172 + BUG_ON(mididx); 173 + BUG_ON(mid_mfn_p != p2m_mid_missing_mfn); 174 + p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing_mfn); 175 + pfn += (P2M_MID_PER_PAGE - 1) * P2M_PER_PAGE; 176 + continue; 177 + } 178 + 179 + if (mid_mfn_p == p2m_mid_missing_mfn) { 180 + /* 181 + * XXX boot-time only! We should never find 182 + * missing parts of the mfn tree after 183 + * runtime. extend_brk() will BUG if we call 184 + * it too late. 185 + */ 186 + mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE); 187 + p2m_mid_mfn_init(mid_mfn_p); 188 + 189 + p2m_top_mfn_p[topidx] = mid_mfn_p; 190 + } 191 + 192 + p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p); 193 + mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]); 194 + } 195 + } 196 + 197 + void xen_setup_mfn_list_list(void) 198 + { 199 + BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); 200 + 201 + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = 202 + virt_to_mfn(p2m_top_mfn); 203 + HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn; 204 + } 205 + 206 + /* Set up p2m_top to point to the domain-builder provided p2m pages */ 207 + void __init xen_build_dynamic_phys_to_machine(void) 208 + { 209 + unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list; 210 + unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages); 211 + unsigned long pfn; 212 + 213 + xen_max_p2m_pfn = max_pfn; 214 + 215 + p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE); 216 + p2m_init(p2m_missing); 217 + 218 + p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE); 219 + p2m_mid_init(p2m_mid_missing); 220 + 221 + p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE); 222 + p2m_top_init(p2m_top); 223 + 224 + /* 225 + * The domain builder gives us a pre-constructed p2m array in 226 + * mfn_list for all the pages initially given to us, so we just 227 + * need to graft that into our tree structure. 228 + */ 229 + for (pfn = 0; pfn < max_pfn; pfn += P2M_PER_PAGE) { 230 + unsigned topidx = p2m_top_index(pfn); 231 + unsigned mididx = p2m_mid_index(pfn); 232 + 233 + if (p2m_top[topidx] == p2m_mid_missing) { 234 + unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE); 235 + p2m_mid_init(mid); 236 + 237 + p2m_top[topidx] = mid; 238 + } 239 + 240 + p2m_top[topidx][mididx] = &mfn_list[pfn]; 241 + } 242 + 243 + m2p_override_init(); 244 + } 245 + 246 + unsigned long get_phys_to_machine(unsigned long pfn) 247 + { 248 + unsigned topidx, mididx, idx; 249 + 250 + if (unlikely(pfn >= MAX_P2M_PFN)) 251 + return INVALID_P2M_ENTRY; 252 + 253 + topidx = p2m_top_index(pfn); 254 + mididx = p2m_mid_index(pfn); 255 + idx = p2m_index(pfn); 256 + 257 + return p2m_top[topidx][mididx][idx]; 258 + } 259 + EXPORT_SYMBOL_GPL(get_phys_to_machine); 260 + 261 + static void *alloc_p2m_page(void) 262 + { 263 + return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT); 264 + } 265 + 266 + static void free_p2m_page(void *p) 267 + { 268 + free_page((unsigned long)p); 269 + } 270 + 271 + /* 272 + * Fully allocate the p2m structure for a given pfn. We need to check 273 + * that both the top and mid levels are allocated, and make sure the 274 + * parallel mfn tree is kept in sync. We may race with other cpus, so 275 + * the new pages are installed with cmpxchg; if we lose the race then 276 + * simply free the page we allocated and use the one that's there. 277 + */ 278 + static bool alloc_p2m(unsigned long pfn) 279 + { 280 + unsigned topidx, mididx; 281 + unsigned long ***top_p, **mid; 282 + unsigned long *top_mfn_p, *mid_mfn; 283 + 284 + topidx = p2m_top_index(pfn); 285 + mididx = p2m_mid_index(pfn); 286 + 287 + top_p = &p2m_top[topidx]; 288 + mid = *top_p; 289 + 290 + if (mid == p2m_mid_missing) { 291 + /* Mid level is missing, allocate a new one */ 292 + mid = alloc_p2m_page(); 293 + if (!mid) 294 + return false; 295 + 296 + p2m_mid_init(mid); 297 + 298 + if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing) 299 + free_p2m_page(mid); 300 + } 301 + 302 + top_mfn_p = &p2m_top_mfn[topidx]; 303 + mid_mfn = p2m_top_mfn_p[topidx]; 304 + 305 + BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p); 306 + 307 + if (mid_mfn == p2m_mid_missing_mfn) { 308 + /* Separately check the mid mfn level */ 309 + unsigned long missing_mfn; 310 + unsigned long mid_mfn_mfn; 311 + 312 + mid_mfn = alloc_p2m_page(); 313 + if (!mid_mfn) 314 + return false; 315 + 316 + p2m_mid_mfn_init(mid_mfn); 317 + 318 + missing_mfn = virt_to_mfn(p2m_mid_missing_mfn); 319 + mid_mfn_mfn = virt_to_mfn(mid_mfn); 320 + if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn) 321 + free_p2m_page(mid_mfn); 322 + else 323 + p2m_top_mfn_p[topidx] = mid_mfn; 324 + } 325 + 326 + if (p2m_top[topidx][mididx] == p2m_missing) { 327 + /* p2m leaf page is missing */ 328 + unsigned long *p2m; 329 + 330 + p2m = alloc_p2m_page(); 331 + if (!p2m) 332 + return false; 333 + 334 + p2m_init(p2m); 335 + 336 + if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing) 337 + free_p2m_page(p2m); 338 + else 339 + mid_mfn[mididx] = virt_to_mfn(p2m); 340 + } 341 + 342 + return true; 343 + } 344 + 345 + /* Try to install p2m mapping; fail if intermediate bits missing */ 346 + bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) 347 + { 348 + unsigned topidx, mididx, idx; 349 + 350 + if (unlikely(pfn >= MAX_P2M_PFN)) { 351 + BUG_ON(mfn != INVALID_P2M_ENTRY); 352 + return true; 353 + } 354 + 355 + topidx = p2m_top_index(pfn); 356 + mididx = p2m_mid_index(pfn); 357 + idx = p2m_index(pfn); 358 + 359 + if (p2m_top[topidx][mididx] == p2m_missing) 360 + return mfn == INVALID_P2M_ENTRY; 361 + 362 + p2m_top[topidx][mididx][idx] = mfn; 363 + 364 + return true; 365 + } 366 + 367 + bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) 368 + { 369 + if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { 370 + BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); 371 + return true; 372 + } 373 + 374 + if (unlikely(!__set_phys_to_machine(pfn, mfn))) { 375 + if (!alloc_p2m(pfn)) 376 + return false; 377 + 378 + if (!__set_phys_to_machine(pfn, mfn)) 379 + return false; 380 + } 381 + 382 + return true; 383 + } 384 + 385 + #define M2P_OVERRIDE_HASH_SHIFT 10 386 + #define M2P_OVERRIDE_HASH (1 << M2P_OVERRIDE_HASH_SHIFT) 387 + 388 + static RESERVE_BRK_ARRAY(struct list_head, m2p_overrides, M2P_OVERRIDE_HASH); 389 + static DEFINE_SPINLOCK(m2p_override_lock); 390 + 391 + static void __init m2p_override_init(void) 392 + { 393 + unsigned i; 394 + 395 + m2p_overrides = extend_brk(sizeof(*m2p_overrides) * M2P_OVERRIDE_HASH, 396 + sizeof(unsigned long)); 397 + 398 + for (i = 0; i < M2P_OVERRIDE_HASH; i++) 399 + INIT_LIST_HEAD(&m2p_overrides[i]); 400 + } 401 + 402 + static unsigned long mfn_hash(unsigned long mfn) 403 + { 404 + return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT); 405 + } 406 + 407 + /* Add an MFN override for a particular page */ 408 + int m2p_add_override(unsigned long mfn, struct page *page) 409 + { 410 + unsigned long flags; 411 + unsigned long pfn; 412 + unsigned long address; 413 + unsigned level; 414 + pte_t *ptep = NULL; 415 + 416 + pfn = page_to_pfn(page); 417 + if (!PageHighMem(page)) { 418 + address = (unsigned long)__va(pfn << PAGE_SHIFT); 419 + ptep = lookup_address(address, &level); 420 + 421 + if (WARN(ptep == NULL || level != PG_LEVEL_4K, 422 + "m2p_add_override: pfn %lx not mapped", pfn)) 423 + return -EINVAL; 424 + } 425 + 426 + page->private = mfn; 427 + page->index = pfn_to_mfn(pfn); 428 + 429 + __set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)); 430 + if (!PageHighMem(page)) 431 + /* Just zap old mapping for now */ 432 + pte_clear(&init_mm, address, ptep); 433 + 434 + spin_lock_irqsave(&m2p_override_lock, flags); 435 + list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); 436 + spin_unlock_irqrestore(&m2p_override_lock, flags); 437 + 438 + return 0; 439 + } 440 + 441 + int m2p_remove_override(struct page *page) 442 + { 443 + unsigned long flags; 444 + unsigned long mfn; 445 + unsigned long pfn; 446 + unsigned long address; 447 + unsigned level; 448 + pte_t *ptep = NULL; 449 + 450 + pfn = page_to_pfn(page); 451 + mfn = get_phys_to_machine(pfn); 452 + if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) 453 + return -EINVAL; 454 + 455 + if (!PageHighMem(page)) { 456 + address = (unsigned long)__va(pfn << PAGE_SHIFT); 457 + ptep = lookup_address(address, &level); 458 + 459 + if (WARN(ptep == NULL || level != PG_LEVEL_4K, 460 + "m2p_remove_override: pfn %lx not mapped", pfn)) 461 + return -EINVAL; 462 + } 463 + 464 + spin_lock_irqsave(&m2p_override_lock, flags); 465 + list_del(&page->lru); 466 + spin_unlock_irqrestore(&m2p_override_lock, flags); 467 + __set_phys_to_machine(pfn, page->index); 468 + 469 + if (!PageHighMem(page)) 470 + set_pte_at(&init_mm, address, ptep, 471 + pfn_pte(pfn, PAGE_KERNEL)); 472 + /* No tlb flush necessary because the caller already 473 + * left the pte unmapped. */ 474 + 475 + return 0; 476 + } 477 + 478 + struct page *m2p_find_override(unsigned long mfn) 479 + { 480 + unsigned long flags; 481 + struct list_head *bucket = &m2p_overrides[mfn_hash(mfn)]; 482 + struct page *p, *ret; 483 + 484 + ret = NULL; 485 + 486 + spin_lock_irqsave(&m2p_override_lock, flags); 487 + 488 + list_for_each_entry(p, bucket, lru) { 489 + if (p->private == mfn) { 490 + ret = p; 491 + break; 492 + } 493 + } 494 + 495 + spin_unlock_irqrestore(&m2p_override_lock, flags); 496 + 497 + return ret; 498 + } 499 + 500 + unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn) 501 + { 502 + struct page *p = m2p_find_override(mfn); 503 + unsigned long ret = pfn; 504 + 505 + if (p) 506 + ret = page_to_pfn(p); 507 + 508 + return ret; 509 + } 510 + EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
+8 -1
drivers/xen/Kconfig
··· 71 71 but will have no xen contents. 72 72 73 73 config XEN_XENBUS_FRONTEND 74 - tristate 74 + tristate 75 + 76 + config XEN_GNTDEV 77 + tristate "userspace grant access device driver" 78 + depends on XEN 79 + select MMU_NOTIFIER 80 + help 81 + Allows userspace processes to use grants. 75 82 76 83 config XEN_PLATFORM_PCI 77 84 tristate "xen platform pci device driver"
+2
drivers/xen/Makefile
··· 9 9 obj-$(CONFIG_XEN_XENCOMM) += xencomm.o 10 10 obj-$(CONFIG_XEN_BALLOON) += balloon.o 11 11 obj-$(CONFIG_XEN_DEV_EVTCHN) += xen-evtchn.o 12 + obj-$(CONFIG_XEN_GNTDEV) += xen-gntdev.o 12 13 obj-$(CONFIG_XENFS) += xenfs/ 13 14 obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o 14 15 obj-$(CONFIG_XEN_PLATFORM_PCI) += xen-platform-pci.o ··· 17 16 obj-$(CONFIG_XEN_DOM0) += pci.o 18 17 19 18 xen-evtchn-y := evtchn.o 19 + xen-gntdev-y := gntdev.o 20 20 21 21 xen-platform-pci-y := platform-pci.o
+665
drivers/xen/gntdev.c
··· 1 + /****************************************************************************** 2 + * gntdev.c 3 + * 4 + * Device for accessing (in user-space) pages that have been granted by other 5 + * domains. 6 + * 7 + * Copyright (c) 2006-2007, D G Murray. 8 + * (c) 2009 Gerd Hoffmann <kraxel@redhat.com> 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program; if not, write to the Free Software 17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 + */ 19 + 20 + #undef DEBUG 21 + 22 + #include <linux/module.h> 23 + #include <linux/kernel.h> 24 + #include <linux/init.h> 25 + #include <linux/miscdevice.h> 26 + #include <linux/fs.h> 27 + #include <linux/mm.h> 28 + #include <linux/mman.h> 29 + #include <linux/mmu_notifier.h> 30 + #include <linux/types.h> 31 + #include <linux/uaccess.h> 32 + #include <linux/sched.h> 33 + #include <linux/spinlock.h> 34 + #include <linux/slab.h> 35 + 36 + #include <xen/xen.h> 37 + #include <xen/grant_table.h> 38 + #include <xen/gntdev.h> 39 + #include <asm/xen/hypervisor.h> 40 + #include <asm/xen/hypercall.h> 41 + #include <asm/xen/page.h> 42 + 43 + MODULE_LICENSE("GPL"); 44 + MODULE_AUTHOR("Derek G. Murray <Derek.Murray@cl.cam.ac.uk>, " 45 + "Gerd Hoffmann <kraxel@redhat.com>"); 46 + MODULE_DESCRIPTION("User-space granted page access driver"); 47 + 48 + static int limit = 1024; 49 + module_param(limit, int, 0644); 50 + MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped at " 51 + "once by a gntdev instance"); 52 + 53 + struct gntdev_priv { 54 + struct list_head maps; 55 + uint32_t used; 56 + uint32_t limit; 57 + /* lock protects maps from concurrent changes */ 58 + spinlock_t lock; 59 + struct mm_struct *mm; 60 + struct mmu_notifier mn; 61 + }; 62 + 63 + struct grant_map { 64 + struct list_head next; 65 + struct gntdev_priv *priv; 66 + struct vm_area_struct *vma; 67 + int index; 68 + int count; 69 + int flags; 70 + int is_mapped; 71 + struct ioctl_gntdev_grant_ref *grants; 72 + struct gnttab_map_grant_ref *map_ops; 73 + struct gnttab_unmap_grant_ref *unmap_ops; 74 + struct page **pages; 75 + }; 76 + 77 + /* ------------------------------------------------------------------ */ 78 + 79 + static void gntdev_print_maps(struct gntdev_priv *priv, 80 + char *text, int text_index) 81 + { 82 + #ifdef DEBUG 83 + struct grant_map *map; 84 + 85 + pr_debug("maps list (priv %p, usage %d/%d)\n", 86 + priv, priv->used, priv->limit); 87 + 88 + list_for_each_entry(map, &priv->maps, next) 89 + pr_debug(" index %2d, count %2d %s\n", 90 + map->index, map->count, 91 + map->index == text_index && text ? text : ""); 92 + #endif 93 + } 94 + 95 + static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) 96 + { 97 + struct grant_map *add; 98 + int i; 99 + 100 + add = kzalloc(sizeof(struct grant_map), GFP_KERNEL); 101 + if (NULL == add) 102 + return NULL; 103 + 104 + add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL); 105 + add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL); 106 + add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL); 107 + add->pages = kzalloc(sizeof(add->pages[0]) * count, GFP_KERNEL); 108 + if (NULL == add->grants || 109 + NULL == add->map_ops || 110 + NULL == add->unmap_ops || 111 + NULL == add->pages) 112 + goto err; 113 + 114 + for (i = 0; i < count; i++) { 115 + add->pages[i] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM); 116 + if (add->pages[i] == NULL) 117 + goto err; 118 + } 119 + 120 + add->index = 0; 121 + add->count = count; 122 + add->priv = priv; 123 + 124 + if (add->count + priv->used > priv->limit) 125 + goto err; 126 + 127 + return add; 128 + 129 + err: 130 + if (add->pages) 131 + for (i = 0; i < count; i++) { 132 + if (add->pages[i]) 133 + __free_page(add->pages[i]); 134 + } 135 + kfree(add->pages); 136 + kfree(add->grants); 137 + kfree(add->map_ops); 138 + kfree(add->unmap_ops); 139 + kfree(add); 140 + return NULL; 141 + } 142 + 143 + static void gntdev_add_map(struct gntdev_priv *priv, struct grant_map *add) 144 + { 145 + struct grant_map *map; 146 + 147 + list_for_each_entry(map, &priv->maps, next) { 148 + if (add->index + add->count < map->index) { 149 + list_add_tail(&add->next, &map->next); 150 + goto done; 151 + } 152 + add->index = map->index + map->count; 153 + } 154 + list_add_tail(&add->next, &priv->maps); 155 + 156 + done: 157 + priv->used += add->count; 158 + gntdev_print_maps(priv, "[new]", add->index); 159 + } 160 + 161 + static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, 162 + int index, int count) 163 + { 164 + struct grant_map *map; 165 + 166 + list_for_each_entry(map, &priv->maps, next) { 167 + if (map->index != index) 168 + continue; 169 + if (map->count != count) 170 + continue; 171 + return map; 172 + } 173 + return NULL; 174 + } 175 + 176 + static struct grant_map *gntdev_find_map_vaddr(struct gntdev_priv *priv, 177 + unsigned long vaddr) 178 + { 179 + struct grant_map *map; 180 + 181 + list_for_each_entry(map, &priv->maps, next) { 182 + if (!map->vma) 183 + continue; 184 + if (vaddr < map->vma->vm_start) 185 + continue; 186 + if (vaddr >= map->vma->vm_end) 187 + continue; 188 + return map; 189 + } 190 + return NULL; 191 + } 192 + 193 + static int gntdev_del_map(struct grant_map *map) 194 + { 195 + int i; 196 + 197 + if (map->vma) 198 + return -EBUSY; 199 + for (i = 0; i < map->count; i++) 200 + if (map->unmap_ops[i].handle) 201 + return -EBUSY; 202 + 203 + map->priv->used -= map->count; 204 + list_del(&map->next); 205 + return 0; 206 + } 207 + 208 + static void gntdev_free_map(struct grant_map *map) 209 + { 210 + int i; 211 + 212 + if (!map) 213 + return; 214 + 215 + if (map->pages) 216 + for (i = 0; i < map->count; i++) { 217 + if (map->pages[i]) 218 + __free_page(map->pages[i]); 219 + } 220 + kfree(map->pages); 221 + kfree(map->grants); 222 + kfree(map->map_ops); 223 + kfree(map->unmap_ops); 224 + kfree(map); 225 + } 226 + 227 + /* ------------------------------------------------------------------ */ 228 + 229 + static int find_grant_ptes(pte_t *pte, pgtable_t token, 230 + unsigned long addr, void *data) 231 + { 232 + struct grant_map *map = data; 233 + unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT; 234 + u64 pte_maddr; 235 + 236 + BUG_ON(pgnr >= map->count); 237 + pte_maddr = arbitrary_virt_to_machine(pte).maddr; 238 + 239 + gnttab_set_map_op(&map->map_ops[pgnr], pte_maddr, 240 + GNTMAP_contains_pte | map->flags, 241 + map->grants[pgnr].ref, 242 + map->grants[pgnr].domid); 243 + gnttab_set_unmap_op(&map->unmap_ops[pgnr], pte_maddr, 244 + GNTMAP_contains_pte | map->flags, 245 + 0 /* handle */); 246 + return 0; 247 + } 248 + 249 + static int map_grant_pages(struct grant_map *map) 250 + { 251 + int i, err = 0; 252 + 253 + pr_debug("map %d+%d\n", map->index, map->count); 254 + err = gnttab_map_refs(map->map_ops, map->pages, map->count); 255 + if (err) 256 + return err; 257 + 258 + for (i = 0; i < map->count; i++) { 259 + if (map->map_ops[i].status) 260 + err = -EINVAL; 261 + map->unmap_ops[i].handle = map->map_ops[i].handle; 262 + } 263 + return err; 264 + } 265 + 266 + static int unmap_grant_pages(struct grant_map *map, int offset, int pages) 267 + { 268 + int i, err = 0; 269 + 270 + pr_debug("map %d+%d [%d+%d]\n", map->index, map->count, offset, pages); 271 + err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages, pages); 272 + if (err) 273 + return err; 274 + 275 + for (i = 0; i < pages; i++) { 276 + if (map->unmap_ops[offset+i].status) 277 + err = -EINVAL; 278 + map->unmap_ops[offset+i].handle = 0; 279 + } 280 + return err; 281 + } 282 + 283 + /* ------------------------------------------------------------------ */ 284 + 285 + static void gntdev_vma_close(struct vm_area_struct *vma) 286 + { 287 + struct grant_map *map = vma->vm_private_data; 288 + 289 + pr_debug("close %p\n", vma); 290 + map->is_mapped = 0; 291 + map->vma = NULL; 292 + vma->vm_private_data = NULL; 293 + } 294 + 295 + static int gntdev_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 296 + { 297 + pr_debug("vaddr %p, pgoff %ld (shouldn't happen)\n", 298 + vmf->virtual_address, vmf->pgoff); 299 + vmf->flags = VM_FAULT_ERROR; 300 + return 0; 301 + } 302 + 303 + static struct vm_operations_struct gntdev_vmops = { 304 + .close = gntdev_vma_close, 305 + .fault = gntdev_vma_fault, 306 + }; 307 + 308 + /* ------------------------------------------------------------------ */ 309 + 310 + static void mn_invl_range_start(struct mmu_notifier *mn, 311 + struct mm_struct *mm, 312 + unsigned long start, unsigned long end) 313 + { 314 + struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); 315 + struct grant_map *map; 316 + unsigned long mstart, mend; 317 + int err; 318 + 319 + spin_lock(&priv->lock); 320 + list_for_each_entry(map, &priv->maps, next) { 321 + if (!map->vma) 322 + continue; 323 + if (!map->is_mapped) 324 + continue; 325 + if (map->vma->vm_start >= end) 326 + continue; 327 + if (map->vma->vm_end <= start) 328 + continue; 329 + mstart = max(start, map->vma->vm_start); 330 + mend = min(end, map->vma->vm_end); 331 + pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", 332 + map->index, map->count, 333 + map->vma->vm_start, map->vma->vm_end, 334 + start, end, mstart, mend); 335 + err = unmap_grant_pages(map, 336 + (mstart - map->vma->vm_start) >> PAGE_SHIFT, 337 + (mend - mstart) >> PAGE_SHIFT); 338 + WARN_ON(err); 339 + } 340 + spin_unlock(&priv->lock); 341 + } 342 + 343 + static void mn_invl_page(struct mmu_notifier *mn, 344 + struct mm_struct *mm, 345 + unsigned long address) 346 + { 347 + mn_invl_range_start(mn, mm, address, address + PAGE_SIZE); 348 + } 349 + 350 + static void mn_release(struct mmu_notifier *mn, 351 + struct mm_struct *mm) 352 + { 353 + struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); 354 + struct grant_map *map; 355 + int err; 356 + 357 + spin_lock(&priv->lock); 358 + list_for_each_entry(map, &priv->maps, next) { 359 + if (!map->vma) 360 + continue; 361 + pr_debug("map %d+%d (%lx %lx)\n", 362 + map->index, map->count, 363 + map->vma->vm_start, map->vma->vm_end); 364 + err = unmap_grant_pages(map, /* offset */ 0, map->count); 365 + WARN_ON(err); 366 + } 367 + spin_unlock(&priv->lock); 368 + } 369 + 370 + struct mmu_notifier_ops gntdev_mmu_ops = { 371 + .release = mn_release, 372 + .invalidate_page = mn_invl_page, 373 + .invalidate_range_start = mn_invl_range_start, 374 + }; 375 + 376 + /* ------------------------------------------------------------------ */ 377 + 378 + static int gntdev_open(struct inode *inode, struct file *flip) 379 + { 380 + struct gntdev_priv *priv; 381 + int ret = 0; 382 + 383 + priv = kzalloc(sizeof(*priv), GFP_KERNEL); 384 + if (!priv) 385 + return -ENOMEM; 386 + 387 + INIT_LIST_HEAD(&priv->maps); 388 + spin_lock_init(&priv->lock); 389 + priv->limit = limit; 390 + 391 + priv->mm = get_task_mm(current); 392 + if (!priv->mm) { 393 + kfree(priv); 394 + return -ENOMEM; 395 + } 396 + priv->mn.ops = &gntdev_mmu_ops; 397 + ret = mmu_notifier_register(&priv->mn, priv->mm); 398 + mmput(priv->mm); 399 + 400 + if (ret) { 401 + kfree(priv); 402 + return ret; 403 + } 404 + 405 + flip->private_data = priv; 406 + pr_debug("priv %p\n", priv); 407 + 408 + return 0; 409 + } 410 + 411 + static int gntdev_release(struct inode *inode, struct file *flip) 412 + { 413 + struct gntdev_priv *priv = flip->private_data; 414 + struct grant_map *map; 415 + int err; 416 + 417 + pr_debug("priv %p\n", priv); 418 + 419 + spin_lock(&priv->lock); 420 + while (!list_empty(&priv->maps)) { 421 + map = list_entry(priv->maps.next, struct grant_map, next); 422 + err = gntdev_del_map(map); 423 + if (WARN_ON(err)) 424 + gntdev_free_map(map); 425 + 426 + } 427 + spin_unlock(&priv->lock); 428 + 429 + mmu_notifier_unregister(&priv->mn, priv->mm); 430 + kfree(priv); 431 + return 0; 432 + } 433 + 434 + static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, 435 + struct ioctl_gntdev_map_grant_ref __user *u) 436 + { 437 + struct ioctl_gntdev_map_grant_ref op; 438 + struct grant_map *map; 439 + int err; 440 + 441 + if (copy_from_user(&op, u, sizeof(op)) != 0) 442 + return -EFAULT; 443 + pr_debug("priv %p, add %d\n", priv, op.count); 444 + if (unlikely(op.count <= 0)) 445 + return -EINVAL; 446 + if (unlikely(op.count > priv->limit)) 447 + return -EINVAL; 448 + 449 + err = -ENOMEM; 450 + map = gntdev_alloc_map(priv, op.count); 451 + if (!map) 452 + return err; 453 + if (copy_from_user(map->grants, &u->refs, 454 + sizeof(map->grants[0]) * op.count) != 0) { 455 + gntdev_free_map(map); 456 + return err; 457 + } 458 + 459 + spin_lock(&priv->lock); 460 + gntdev_add_map(priv, map); 461 + op.index = map->index << PAGE_SHIFT; 462 + spin_unlock(&priv->lock); 463 + 464 + if (copy_to_user(u, &op, sizeof(op)) != 0) { 465 + spin_lock(&priv->lock); 466 + gntdev_del_map(map); 467 + spin_unlock(&priv->lock); 468 + gntdev_free_map(map); 469 + return err; 470 + } 471 + return 0; 472 + } 473 + 474 + static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, 475 + struct ioctl_gntdev_unmap_grant_ref __user *u) 476 + { 477 + struct ioctl_gntdev_unmap_grant_ref op; 478 + struct grant_map *map; 479 + int err = -ENOENT; 480 + 481 + if (copy_from_user(&op, u, sizeof(op)) != 0) 482 + return -EFAULT; 483 + pr_debug("priv %p, del %d+%d\n", priv, (int)op.index, (int)op.count); 484 + 485 + spin_lock(&priv->lock); 486 + map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); 487 + if (map) 488 + err = gntdev_del_map(map); 489 + spin_unlock(&priv->lock); 490 + if (!err) 491 + gntdev_free_map(map); 492 + return err; 493 + } 494 + 495 + static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv, 496 + struct ioctl_gntdev_get_offset_for_vaddr __user *u) 497 + { 498 + struct ioctl_gntdev_get_offset_for_vaddr op; 499 + struct grant_map *map; 500 + 501 + if (copy_from_user(&op, u, sizeof(op)) != 0) 502 + return -EFAULT; 503 + pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr); 504 + 505 + spin_lock(&priv->lock); 506 + map = gntdev_find_map_vaddr(priv, op.vaddr); 507 + if (map == NULL || 508 + map->vma->vm_start != op.vaddr) { 509 + spin_unlock(&priv->lock); 510 + return -EINVAL; 511 + } 512 + op.offset = map->index << PAGE_SHIFT; 513 + op.count = map->count; 514 + spin_unlock(&priv->lock); 515 + 516 + if (copy_to_user(u, &op, sizeof(op)) != 0) 517 + return -EFAULT; 518 + return 0; 519 + } 520 + 521 + static long gntdev_ioctl_set_max_grants(struct gntdev_priv *priv, 522 + struct ioctl_gntdev_set_max_grants __user *u) 523 + { 524 + struct ioctl_gntdev_set_max_grants op; 525 + 526 + if (copy_from_user(&op, u, sizeof(op)) != 0) 527 + return -EFAULT; 528 + pr_debug("priv %p, limit %d\n", priv, op.count); 529 + if (op.count > limit) 530 + return -E2BIG; 531 + 532 + spin_lock(&priv->lock); 533 + priv->limit = op.count; 534 + spin_unlock(&priv->lock); 535 + return 0; 536 + } 537 + 538 + static long gntdev_ioctl(struct file *flip, 539 + unsigned int cmd, unsigned long arg) 540 + { 541 + struct gntdev_priv *priv = flip->private_data; 542 + void __user *ptr = (void __user *)arg; 543 + 544 + switch (cmd) { 545 + case IOCTL_GNTDEV_MAP_GRANT_REF: 546 + return gntdev_ioctl_map_grant_ref(priv, ptr); 547 + 548 + case IOCTL_GNTDEV_UNMAP_GRANT_REF: 549 + return gntdev_ioctl_unmap_grant_ref(priv, ptr); 550 + 551 + case IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR: 552 + return gntdev_ioctl_get_offset_for_vaddr(priv, ptr); 553 + 554 + case IOCTL_GNTDEV_SET_MAX_GRANTS: 555 + return gntdev_ioctl_set_max_grants(priv, ptr); 556 + 557 + default: 558 + pr_debug("priv %p, unknown cmd %x\n", priv, cmd); 559 + return -ENOIOCTLCMD; 560 + } 561 + 562 + return 0; 563 + } 564 + 565 + static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) 566 + { 567 + struct gntdev_priv *priv = flip->private_data; 568 + int index = vma->vm_pgoff; 569 + int count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; 570 + struct grant_map *map; 571 + int err = -EINVAL; 572 + 573 + if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) 574 + return -EINVAL; 575 + 576 + pr_debug("map %d+%d at %lx (pgoff %lx)\n", 577 + index, count, vma->vm_start, vma->vm_pgoff); 578 + 579 + spin_lock(&priv->lock); 580 + map = gntdev_find_map_index(priv, index, count); 581 + if (!map) 582 + goto unlock_out; 583 + if (map->vma) 584 + goto unlock_out; 585 + if (priv->mm != vma->vm_mm) { 586 + printk(KERN_WARNING "Huh? Other mm?\n"); 587 + goto unlock_out; 588 + } 589 + 590 + vma->vm_ops = &gntdev_vmops; 591 + 592 + vma->vm_flags |= VM_RESERVED|VM_DONTCOPY|VM_DONTEXPAND|VM_PFNMAP; 593 + 594 + vma->vm_private_data = map; 595 + map->vma = vma; 596 + 597 + map->flags = GNTMAP_host_map | GNTMAP_application_map; 598 + if (!(vma->vm_flags & VM_WRITE)) 599 + map->flags |= GNTMAP_readonly; 600 + 601 + spin_unlock(&priv->lock); 602 + 603 + err = apply_to_page_range(vma->vm_mm, vma->vm_start, 604 + vma->vm_end - vma->vm_start, 605 + find_grant_ptes, map); 606 + if (err) { 607 + printk(KERN_WARNING "find_grant_ptes() failure.\n"); 608 + return err; 609 + } 610 + 611 + err = map_grant_pages(map); 612 + if (err) { 613 + printk(KERN_WARNING "map_grant_pages() failure.\n"); 614 + return err; 615 + } 616 + 617 + map->is_mapped = 1; 618 + 619 + return 0; 620 + 621 + unlock_out: 622 + spin_unlock(&priv->lock); 623 + return err; 624 + } 625 + 626 + static const struct file_operations gntdev_fops = { 627 + .owner = THIS_MODULE, 628 + .open = gntdev_open, 629 + .release = gntdev_release, 630 + .mmap = gntdev_mmap, 631 + .unlocked_ioctl = gntdev_ioctl 632 + }; 633 + 634 + static struct miscdevice gntdev_miscdev = { 635 + .minor = MISC_DYNAMIC_MINOR, 636 + .name = "xen/gntdev", 637 + .fops = &gntdev_fops, 638 + }; 639 + 640 + /* ------------------------------------------------------------------ */ 641 + 642 + static int __init gntdev_init(void) 643 + { 644 + int err; 645 + 646 + if (!xen_domain()) 647 + return -ENODEV; 648 + 649 + err = misc_register(&gntdev_miscdev); 650 + if (err != 0) { 651 + printk(KERN_ERR "Could not register gntdev device\n"); 652 + return err; 653 + } 654 + return 0; 655 + } 656 + 657 + static void __exit gntdev_exit(void) 658 + { 659 + misc_deregister(&gntdev_miscdev); 660 + } 661 + 662 + module_init(gntdev_init); 663 + module_exit(gntdev_exit); 664 + 665 + /* ------------------------------------------------------------------ */
+46
drivers/xen/grant-table.c
··· 447 447 } 448 448 EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); 449 449 450 + int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, 451 + struct page **pages, unsigned int count) 452 + { 453 + int i, ret; 454 + pte_t *pte; 455 + unsigned long mfn; 456 + 457 + ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count); 458 + if (ret) 459 + return ret; 460 + 461 + for (i = 0; i < count; i++) { 462 + /* m2p override only supported for GNTMAP_contains_pte mappings */ 463 + if (!(map_ops[i].flags & GNTMAP_contains_pte)) 464 + continue; 465 + pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) + 466 + (map_ops[i].host_addr & ~PAGE_MASK)); 467 + mfn = pte_mfn(*pte); 468 + ret = m2p_add_override(mfn, pages[i]); 469 + if (ret) 470 + return ret; 471 + } 472 + 473 + return ret; 474 + } 475 + EXPORT_SYMBOL_GPL(gnttab_map_refs); 476 + 477 + int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, 478 + struct page **pages, unsigned int count) 479 + { 480 + int i, ret; 481 + 482 + ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count); 483 + if (ret) 484 + return ret; 485 + 486 + for (i = 0; i < count; i++) { 487 + ret = m2p_remove_override(pages[i]); 488 + if (ret) 489 + return ret; 490 + } 491 + 492 + return ret; 493 + } 494 + EXPORT_SYMBOL_GPL(gnttab_unmap_refs); 495 + 450 496 static int gnttab_map(unsigned int start_idx, unsigned int end_idx) 451 497 { 452 498 struct gnttab_setup_table setup;
+119
include/xen/gntdev.h
··· 1 + /****************************************************************************** 2 + * gntdev.h 3 + * 4 + * Interface to /dev/xen/gntdev. 5 + * 6 + * Copyright (c) 2007, D G Murray 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License version 2 10 + * as published by the Free Software Foundation; or, when distributed 11 + * separately from the Linux kernel or incorporated into other 12 + * software packages, subject to the following license: 13 + * 14 + * Permission is hereby granted, free of charge, to any person obtaining a copy 15 + * of this source file (the "Software"), to deal in the Software without 16 + * restriction, including without limitation the rights to use, copy, modify, 17 + * merge, publish, distribute, sublicense, and/or sell copies of the Software, 18 + * and to permit persons to whom the Software is furnished to do so, subject to 19 + * the following conditions: 20 + * 21 + * The above copyright notice and this permission notice shall be included in 22 + * all copies or substantial portions of the Software. 23 + * 24 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 30 + * IN THE SOFTWARE. 31 + */ 32 + 33 + #ifndef __LINUX_PUBLIC_GNTDEV_H__ 34 + #define __LINUX_PUBLIC_GNTDEV_H__ 35 + 36 + struct ioctl_gntdev_grant_ref { 37 + /* The domain ID of the grant to be mapped. */ 38 + uint32_t domid; 39 + /* The grant reference of the grant to be mapped. */ 40 + uint32_t ref; 41 + }; 42 + 43 + /* 44 + * Inserts the grant references into the mapping table of an instance 45 + * of gntdev. N.B. This does not perform the mapping, which is deferred 46 + * until mmap() is called with @index as the offset. 47 + */ 48 + #define IOCTL_GNTDEV_MAP_GRANT_REF \ 49 + _IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref)) 50 + struct ioctl_gntdev_map_grant_ref { 51 + /* IN parameters */ 52 + /* The number of grants to be mapped. */ 53 + uint32_t count; 54 + uint32_t pad; 55 + /* OUT parameters */ 56 + /* The offset to be used on a subsequent call to mmap(). */ 57 + uint64_t index; 58 + /* Variable IN parameter. */ 59 + /* Array of grant references, of size @count. */ 60 + struct ioctl_gntdev_grant_ref refs[1]; 61 + }; 62 + 63 + /* 64 + * Removes the grant references from the mapping table of an instance of 65 + * of gntdev. N.B. munmap() must be called on the relevant virtual address(es) 66 + * before this ioctl is called, or an error will result. 67 + */ 68 + #define IOCTL_GNTDEV_UNMAP_GRANT_REF \ 69 + _IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref)) 70 + struct ioctl_gntdev_unmap_grant_ref { 71 + /* IN parameters */ 72 + /* The offset was returned by the corresponding map operation. */ 73 + uint64_t index; 74 + /* The number of pages to be unmapped. */ 75 + uint32_t count; 76 + uint32_t pad; 77 + }; 78 + 79 + /* 80 + * Returns the offset in the driver's address space that corresponds 81 + * to @vaddr. This can be used to perform a munmap(), followed by an 82 + * UNMAP_GRANT_REF ioctl, where no state about the offset is retained by 83 + * the caller. The number of pages that were allocated at the same time as 84 + * @vaddr is returned in @count. 85 + * 86 + * N.B. Where more than one page has been mapped into a contiguous range, the 87 + * supplied @vaddr must correspond to the start of the range; otherwise 88 + * an error will result. It is only possible to munmap() the entire 89 + * contiguously-allocated range at once, and not any subrange thereof. 90 + */ 91 + #define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \ 92 + _IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_gntdev_get_offset_for_vaddr)) 93 + struct ioctl_gntdev_get_offset_for_vaddr { 94 + /* IN parameters */ 95 + /* The virtual address of the first mapped page in a range. */ 96 + uint64_t vaddr; 97 + /* OUT parameters */ 98 + /* The offset that was used in the initial mmap() operation. */ 99 + uint64_t offset; 100 + /* The number of pages mapped in the VM area that begins at @vaddr. */ 101 + uint32_t count; 102 + uint32_t pad; 103 + }; 104 + 105 + /* 106 + * Sets the maximum number of grants that may mapped at once by this gntdev 107 + * instance. 108 + * 109 + * N.B. This must be called before any other ioctl is performed on the device. 110 + */ 111 + #define IOCTL_GNTDEV_SET_MAX_GRANTS \ 112 + _IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_gntdev_set_max_grants)) 113 + struct ioctl_gntdev_set_max_grants { 114 + /* IN parameter */ 115 + /* The maximum number of grants that may be mapped at once. */ 116 + uint32_t count; 117 + }; 118 + 119 + #endif /* __LINUX_PUBLIC_GNTDEV_H__ */
+43 -1
include/xen/grant_table.h
··· 37 37 #ifndef __ASM_GNTTAB_H__ 38 38 #define __ASM_GNTTAB_H__ 39 39 40 - #include <asm/xen/hypervisor.h> 40 + #include <asm/page.h> 41 + 42 + #include <xen/interface/xen.h> 41 43 #include <xen/interface/grant_table.h> 44 + 45 + #include <asm/xen/hypervisor.h> 42 46 #include <asm/xen/grant_table.h> 47 + 48 + #include <xen/features.h> 43 49 44 50 /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ 45 51 #define NR_GRANT_FRAMES 4 ··· 113 107 void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid, 114 108 unsigned long pfn); 115 109 110 + static inline void 111 + gnttab_set_map_op(struct gnttab_map_grant_ref *map, phys_addr_t addr, 112 + uint32_t flags, grant_ref_t ref, domid_t domid) 113 + { 114 + if (flags & GNTMAP_contains_pte) 115 + map->host_addr = addr; 116 + else if (xen_feature(XENFEAT_auto_translated_physmap)) 117 + map->host_addr = __pa(addr); 118 + else 119 + map->host_addr = addr; 120 + 121 + map->flags = flags; 122 + map->ref = ref; 123 + map->dom = domid; 124 + } 125 + 126 + static inline void 127 + gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr, 128 + uint32_t flags, grant_handle_t handle) 129 + { 130 + if (flags & GNTMAP_contains_pte) 131 + unmap->host_addr = addr; 132 + else if (xen_feature(XENFEAT_auto_translated_physmap)) 133 + unmap->host_addr = __pa(addr); 134 + else 135 + unmap->host_addr = addr; 136 + 137 + unmap->handle = handle; 138 + unmap->dev_bus_addr = 0; 139 + } 140 + 116 141 int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, 117 142 unsigned long max_nr_gframes, 118 143 struct grant_entry **__shared); ··· 154 117 unsigned int gnttab_max_grant_frames(void); 155 118 156 119 #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr)) 120 + 121 + int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, 122 + struct page **pages, unsigned int count); 123 + int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, 124 + struct page **pages, unsigned int count); 157 125 158 126 #endif /* __ASM_GNTTAB_H__ */