.. | .. |
---|
69 | 69 | unsigned int nr_handles; |
---|
70 | 70 | }; |
---|
71 | 71 | |
---|
| 72 | +struct map_ring_valloc { |
---|
| 73 | + struct xenbus_map_node *node; |
---|
| 74 | + |
---|
| 75 | + /* Why do we need two arrays? See comment of __xenbus_map_ring */ |
---|
| 76 | + unsigned long addrs[XENBUS_MAX_RING_GRANTS]; |
---|
| 77 | + phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS]; |
---|
| 78 | + |
---|
| 79 | + struct gnttab_map_grant_ref map[XENBUS_MAX_RING_GRANTS]; |
---|
| 80 | + struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS]; |
---|
| 81 | + |
---|
| 82 | + unsigned int idx; |
---|
| 83 | +}; |
---|
| 84 | + |
---|
72 | 85 | static DEFINE_SPINLOCK(xenbus_valloc_lock); |
---|
73 | 86 | static LIST_HEAD(xenbus_valloc_pages); |
---|
74 | 87 | |
---|
75 | 88 | struct xenbus_ring_ops { |
---|
76 | | - int (*map)(struct xenbus_device *dev, |
---|
| 89 | + int (*map)(struct xenbus_device *dev, struct map_ring_valloc *info, |
---|
77 | 90 | grant_ref_t *gnt_refs, unsigned int nr_grefs, |
---|
78 | 91 | void **vaddr); |
---|
79 | 92 | int (*unmap)(struct xenbus_device *dev, void *vaddr); |
---|
.. | .. |
---|
284 | 297 | dev_err(&dev->dev, "%s\n", printf_buffer); |
---|
285 | 298 | |
---|
286 | 299 | path_buffer = kasprintf(GFP_KERNEL, "error/%s", dev->nodename); |
---|
287 | | - if (!path_buffer || |
---|
288 | | - xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer)) |
---|
289 | | - dev_err(&dev->dev, "failed to write error node for %s (%s)\n", |
---|
290 | | - dev->nodename, printf_buffer); |
---|
| 300 | + if (path_buffer) |
---|
| 301 | + xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer); |
---|
291 | 302 | |
---|
292 | 303 | kfree(printf_buffer); |
---|
293 | 304 | kfree(path_buffer); |
---|
.. | .. |
---|
368 | 379 | unsigned int nr_pages, grant_ref_t *grefs) |
---|
369 | 380 | { |
---|
370 | 381 | int err; |
---|
371 | | - int i, j; |
---|
| 382 | + unsigned int i; |
---|
| 383 | + grant_ref_t gref_head; |
---|
| 384 | + |
---|
| 385 | + err = gnttab_alloc_grant_references(nr_pages, &gref_head); |
---|
| 386 | + if (err) { |
---|
| 387 | + xenbus_dev_fatal(dev, err, "granting access to ring page"); |
---|
| 388 | + return err; |
---|
| 389 | + } |
---|
372 | 390 | |
---|
373 | 391 | for (i = 0; i < nr_pages; i++) { |
---|
374 | 392 | unsigned long gfn; |
---|
.. | .. |
---|
378 | 396 | else |
---|
379 | 397 | gfn = virt_to_gfn(vaddr); |
---|
380 | 398 | |
---|
381 | | - err = gnttab_grant_foreign_access(dev->otherend_id, gfn, 0); |
---|
382 | | - if (err < 0) { |
---|
383 | | - xenbus_dev_fatal(dev, err, |
---|
384 | | - "granting access to ring page"); |
---|
385 | | - goto fail; |
---|
386 | | - } |
---|
387 | | - grefs[i] = err; |
---|
| 399 | + grefs[i] = gnttab_claim_grant_reference(&gref_head); |
---|
| 400 | + gnttab_grant_foreign_access_ref(grefs[i], dev->otherend_id, |
---|
| 401 | + gfn, 0); |
---|
388 | 402 | |
---|
389 | 403 | vaddr = vaddr + XEN_PAGE_SIZE; |
---|
390 | 404 | } |
---|
391 | 405 | |
---|
392 | 406 | return 0; |
---|
393 | | - |
---|
394 | | -fail: |
---|
395 | | - for (j = 0; j < i; j++) |
---|
396 | | - gnttab_end_foreign_access_ref(grefs[j], 0); |
---|
397 | | - return err; |
---|
398 | 407 | } |
---|
399 | 408 | EXPORT_SYMBOL_GPL(xenbus_grant_ring); |
---|
400 | 409 | |
---|
.. | .. |
---|
405 | 414 | * error, the device will switch to XenbusStateClosing, and the error will be |
---|
406 | 415 | * saved in the store. |
---|
407 | 416 | */ |
---|
408 | | -int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port) |
---|
| 417 | +int xenbus_alloc_evtchn(struct xenbus_device *dev, evtchn_port_t *port) |
---|
409 | 418 | { |
---|
410 | 419 | struct evtchn_alloc_unbound alloc_unbound; |
---|
411 | 420 | int err; |
---|
.. | .. |
---|
428 | 437 | /** |
---|
429 | 438 | * Free an existing event channel. Returns 0 on success or -errno on error. |
---|
430 | 439 | */ |
---|
431 | | -int xenbus_free_evtchn(struct xenbus_device *dev, int port) |
---|
| 440 | +int xenbus_free_evtchn(struct xenbus_device *dev, evtchn_port_t port) |
---|
432 | 441 | { |
---|
433 | 442 | struct evtchn_close close; |
---|
434 | 443 | int err; |
---|
.. | .. |
---|
437 | 446 | |
---|
438 | 447 | err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); |
---|
439 | 448 | if (err) |
---|
440 | | - xenbus_dev_error(dev, err, "freeing event channel %d", port); |
---|
| 449 | + xenbus_dev_error(dev, err, "freeing event channel %u", port); |
---|
441 | 450 | |
---|
442 | 451 | return err; |
---|
443 | 452 | } |
---|
.. | .. |
---|
454 | 463 | * Map @nr_grefs pages of memory into this domain from another |
---|
455 | 464 | * domain's grant table. xenbus_map_ring_valloc allocates @nr_grefs |
---|
456 | 465 | * pages of virtual address space, maps the pages to that address, and |
---|
457 | | - * sets *vaddr to that address. Returns 0 on success, and GNTST_* |
---|
458 | | - * (see xen/include/interface/grant_table.h) or -ENOMEM / -EINVAL on |
---|
| 466 | + * sets *vaddr to that address. Returns 0 on success, and -errno on |
---|
459 | 467 | * error. If an error is returned, device will switch to |
---|
460 | 468 | * XenbusStateClosing and the error message will be saved in XenStore. |
---|
461 | 469 | */ |
---|
.. | .. |
---|
463 | 471 | unsigned int nr_grefs, void **vaddr) |
---|
464 | 472 | { |
---|
465 | 473 | int err; |
---|
| 474 | + struct map_ring_valloc *info; |
---|
466 | 475 | |
---|
467 | | - err = ring_ops->map(dev, gnt_refs, nr_grefs, vaddr); |
---|
468 | | - /* Some hypervisors are buggy and can return 1. */ |
---|
469 | | - if (err > 0) |
---|
470 | | - err = GNTST_general_error; |
---|
| 476 | + *vaddr = NULL; |
---|
471 | 477 | |
---|
| 478 | + if (nr_grefs > XENBUS_MAX_RING_GRANTS) |
---|
| 479 | + return -EINVAL; |
---|
| 480 | + |
---|
| 481 | + info = kzalloc(sizeof(*info), GFP_KERNEL); |
---|
| 482 | + if (!info) |
---|
| 483 | + return -ENOMEM; |
---|
| 484 | + |
---|
| 485 | + info->node = kzalloc(sizeof(*info->node), GFP_KERNEL); |
---|
| 486 | + if (!info->node) |
---|
| 487 | + err = -ENOMEM; |
---|
| 488 | + else |
---|
| 489 | + err = ring_ops->map(dev, info, gnt_refs, nr_grefs, vaddr); |
---|
| 490 | + |
---|
| 491 | + kfree(info->node); |
---|
| 492 | + kfree(info); |
---|
472 | 493 | return err; |
---|
473 | 494 | } |
---|
474 | 495 | EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc); |
---|
.. | .. |
---|
480 | 501 | grant_ref_t *gnt_refs, |
---|
481 | 502 | unsigned int nr_grefs, |
---|
482 | 503 | grant_handle_t *handles, |
---|
483 | | - phys_addr_t *addrs, |
---|
| 504 | + struct map_ring_valloc *info, |
---|
484 | 505 | unsigned int flags, |
---|
485 | 506 | bool *leaked) |
---|
486 | 507 | { |
---|
487 | | - struct gnttab_map_grant_ref map[XENBUS_MAX_RING_GRANTS]; |
---|
488 | | - struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS]; |
---|
489 | 508 | int i, j; |
---|
490 | | - int err = GNTST_okay; |
---|
491 | 509 | |
---|
492 | 510 | if (nr_grefs > XENBUS_MAX_RING_GRANTS) |
---|
493 | 511 | return -EINVAL; |
---|
494 | 512 | |
---|
495 | 513 | for (i = 0; i < nr_grefs; i++) { |
---|
496 | | - memset(&map[i], 0, sizeof(map[i])); |
---|
497 | | - gnttab_set_map_op(&map[i], addrs[i], flags, gnt_refs[i], |
---|
498 | | - dev->otherend_id); |
---|
| 514 | + gnttab_set_map_op(&info->map[i], info->phys_addrs[i], flags, |
---|
| 515 | + gnt_refs[i], dev->otherend_id); |
---|
499 | 516 | handles[i] = INVALID_GRANT_HANDLE; |
---|
500 | 517 | } |
---|
501 | 518 | |
---|
502 | | - gnttab_batch_map(map, i); |
---|
| 519 | + gnttab_batch_map(info->map, i); |
---|
503 | 520 | |
---|
504 | 521 | for (i = 0; i < nr_grefs; i++) { |
---|
505 | | - if (map[i].status != GNTST_okay) { |
---|
506 | | - err = map[i].status; |
---|
507 | | - xenbus_dev_fatal(dev, map[i].status, |
---|
| 522 | + if (info->map[i].status != GNTST_okay) { |
---|
| 523 | + xenbus_dev_fatal(dev, info->map[i].status, |
---|
508 | 524 | "mapping in shared page %d from domain %d", |
---|
509 | 525 | gnt_refs[i], dev->otherend_id); |
---|
510 | 526 | goto fail; |
---|
511 | 527 | } else |
---|
512 | | - handles[i] = map[i].handle; |
---|
| 528 | + handles[i] = info->map[i].handle; |
---|
513 | 529 | } |
---|
514 | 530 | |
---|
515 | | - return GNTST_okay; |
---|
| 531 | + return 0; |
---|
516 | 532 | |
---|
517 | 533 | fail: |
---|
518 | 534 | for (i = j = 0; i < nr_grefs; i++) { |
---|
519 | 535 | if (handles[i] != INVALID_GRANT_HANDLE) { |
---|
520 | | - memset(&unmap[j], 0, sizeof(unmap[j])); |
---|
521 | | - gnttab_set_unmap_op(&unmap[j], (phys_addr_t)addrs[i], |
---|
| 536 | + gnttab_set_unmap_op(&info->unmap[j], |
---|
| 537 | + info->phys_addrs[i], |
---|
522 | 538 | GNTMAP_host_map, handles[i]); |
---|
523 | 539 | j++; |
---|
524 | 540 | } |
---|
525 | 541 | } |
---|
526 | 542 | |
---|
527 | | - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, j)) |
---|
| 543 | + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, info->unmap, j)) |
---|
528 | 544 | BUG(); |
---|
529 | 545 | |
---|
530 | 546 | *leaked = false; |
---|
531 | 547 | for (i = 0; i < j; i++) { |
---|
532 | | - if (unmap[i].status != GNTST_okay) { |
---|
| 548 | + if (info->unmap[i].status != GNTST_okay) { |
---|
533 | 549 | *leaked = true; |
---|
| 550 | + break; |
---|
| 551 | + } |
---|
| 552 | + } |
---|
| 553 | + |
---|
| 554 | + return -ENOENT; |
---|
| 555 | +} |
---|
| 556 | + |
---|
| 557 | +/** |
---|
| 558 | + * xenbus_unmap_ring |
---|
| 559 | + * @dev: xenbus device |
---|
| 560 | + * @handles: grant handle array |
---|
| 561 | + * @nr_handles: number of handles in the array |
---|
| 562 | + * @vaddrs: addresses to unmap |
---|
| 563 | + * |
---|
| 564 | + * Unmap memory in this domain that was imported from another domain. |
---|
| 565 | + * Returns 0 on success and returns GNTST_* on error |
---|
| 566 | + * (see xen/include/interface/grant_table.h). |
---|
| 567 | + */ |
---|
| 568 | +static int xenbus_unmap_ring(struct xenbus_device *dev, grant_handle_t *handles, |
---|
| 569 | + unsigned int nr_handles, unsigned long *vaddrs) |
---|
| 570 | +{ |
---|
| 571 | + struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS]; |
---|
| 572 | + int i; |
---|
| 573 | + int err; |
---|
| 574 | + |
---|
| 575 | + if (nr_handles > XENBUS_MAX_RING_GRANTS) |
---|
| 576 | + return -EINVAL; |
---|
| 577 | + |
---|
| 578 | + for (i = 0; i < nr_handles; i++) |
---|
| 579 | + gnttab_set_unmap_op(&unmap[i], vaddrs[i], |
---|
| 580 | + GNTMAP_host_map, handles[i]); |
---|
| 581 | + |
---|
| 582 | + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i)) |
---|
| 583 | + BUG(); |
---|
| 584 | + |
---|
| 585 | + err = GNTST_okay; |
---|
| 586 | + for (i = 0; i < nr_handles; i++) { |
---|
| 587 | + if (unmap[i].status != GNTST_okay) { |
---|
| 588 | + xenbus_dev_error(dev, unmap[i].status, |
---|
| 589 | + "unmapping page at handle %d error %d", |
---|
| 590 | + handles[i], unmap[i].status); |
---|
| 591 | + err = unmap[i].status; |
---|
534 | 592 | break; |
---|
535 | 593 | } |
---|
536 | 594 | } |
---|
.. | .. |
---|
538 | 596 | return err; |
---|
539 | 597 | } |
---|
540 | 598 | |
---|
541 | | -struct map_ring_valloc_hvm |
---|
542 | | -{ |
---|
543 | | - unsigned int idx; |
---|
544 | | - |
---|
545 | | - /* Why do we need two arrays? See comment of __xenbus_map_ring */ |
---|
546 | | - phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS]; |
---|
547 | | - unsigned long addrs[XENBUS_MAX_RING_GRANTS]; |
---|
548 | | -}; |
---|
549 | | - |
---|
550 | 599 | static void xenbus_map_ring_setup_grant_hvm(unsigned long gfn, |
---|
551 | 600 | unsigned int goffset, |
---|
552 | 601 | unsigned int len, |
---|
553 | 602 | void *data) |
---|
554 | 603 | { |
---|
555 | | - struct map_ring_valloc_hvm *info = data; |
---|
| 604 | + struct map_ring_valloc *info = data; |
---|
556 | 605 | unsigned long vaddr = (unsigned long)gfn_to_virt(gfn); |
---|
557 | 606 | |
---|
558 | 607 | info->phys_addrs[info->idx] = vaddr; |
---|
.. | .. |
---|
561 | 610 | info->idx++; |
---|
562 | 611 | } |
---|
563 | 612 | |
---|
564 | | -static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev, |
---|
565 | | - grant_ref_t *gnt_ref, |
---|
566 | | - unsigned int nr_grefs, |
---|
567 | | - void **vaddr) |
---|
| 613 | +static int xenbus_map_ring_hvm(struct xenbus_device *dev, |
---|
| 614 | + struct map_ring_valloc *info, |
---|
| 615 | + grant_ref_t *gnt_ref, |
---|
| 616 | + unsigned int nr_grefs, |
---|
| 617 | + void **vaddr) |
---|
568 | 618 | { |
---|
569 | | - struct xenbus_map_node *node; |
---|
| 619 | + struct xenbus_map_node *node = info->node; |
---|
570 | 620 | int err; |
---|
571 | 621 | void *addr; |
---|
572 | 622 | bool leaked = false; |
---|
573 | | - struct map_ring_valloc_hvm info = { |
---|
574 | | - .idx = 0, |
---|
575 | | - }; |
---|
576 | 623 | unsigned int nr_pages = XENBUS_PAGES(nr_grefs); |
---|
577 | 624 | |
---|
578 | | - if (nr_grefs > XENBUS_MAX_RING_GRANTS) |
---|
579 | | - return -EINVAL; |
---|
580 | | - |
---|
581 | | - *vaddr = NULL; |
---|
582 | | - |
---|
583 | | - node = kzalloc(sizeof(*node), GFP_KERNEL); |
---|
584 | | - if (!node) |
---|
585 | | - return -ENOMEM; |
---|
586 | | - |
---|
587 | | - err = alloc_xenballooned_pages(nr_pages, node->hvm.pages); |
---|
| 625 | + err = xen_alloc_unpopulated_pages(nr_pages, node->hvm.pages); |
---|
588 | 626 | if (err) |
---|
589 | 627 | goto out_err; |
---|
590 | 628 | |
---|
591 | 629 | gnttab_foreach_grant(node->hvm.pages, nr_grefs, |
---|
592 | 630 | xenbus_map_ring_setup_grant_hvm, |
---|
593 | | - &info); |
---|
| 631 | + info); |
---|
594 | 632 | |
---|
595 | 633 | err = __xenbus_map_ring(dev, gnt_ref, nr_grefs, node->handles, |
---|
596 | | - info.phys_addrs, GNTMAP_host_map, &leaked); |
---|
| 634 | + info, GNTMAP_host_map, &leaked); |
---|
597 | 635 | node->nr_handles = nr_grefs; |
---|
598 | 636 | |
---|
599 | 637 | if (err) |
---|
.. | .. |
---|
613 | 651 | spin_unlock(&xenbus_valloc_lock); |
---|
614 | 652 | |
---|
615 | 653 | *vaddr = addr; |
---|
| 654 | + info->node = NULL; |
---|
| 655 | + |
---|
616 | 656 | return 0; |
---|
617 | 657 | |
---|
618 | 658 | out_xenbus_unmap_ring: |
---|
619 | 659 | if (!leaked) |
---|
620 | | - xenbus_unmap_ring(dev, node->handles, nr_grefs, info.addrs); |
---|
| 660 | + xenbus_unmap_ring(dev, node->handles, nr_grefs, info->addrs); |
---|
621 | 661 | else |
---|
622 | 662 | pr_alert("leaking %p size %u page(s)", |
---|
623 | 663 | addr, nr_pages); |
---|
624 | 664 | out_free_ballooned_pages: |
---|
625 | 665 | if (!leaked) |
---|
626 | | - free_xenballooned_pages(nr_pages, node->hvm.pages); |
---|
| 666 | + xen_free_unpopulated_pages(nr_pages, node->hvm.pages); |
---|
627 | 667 | out_err: |
---|
628 | | - kfree(node); |
---|
629 | 668 | return err; |
---|
630 | 669 | } |
---|
631 | | - |
---|
632 | | - |
---|
633 | | -/** |
---|
634 | | - * xenbus_map_ring |
---|
635 | | - * @dev: xenbus device |
---|
636 | | - * @gnt_refs: grant reference array |
---|
637 | | - * @nr_grefs: number of grant reference |
---|
638 | | - * @handles: pointer to grant handle to be filled |
---|
639 | | - * @vaddrs: addresses to be mapped to |
---|
640 | | - * @leaked: fail to clean up a failed map, caller should not free vaddr |
---|
641 | | - * |
---|
642 | | - * Map pages of memory into this domain from another domain's grant table. |
---|
643 | | - * xenbus_map_ring does not allocate the virtual address space (you must do |
---|
644 | | - * this yourself!). It only maps in the pages to the specified address. |
---|
645 | | - * Returns 0 on success, and GNTST_* (see xen/include/interface/grant_table.h) |
---|
646 | | - * or -ENOMEM / -EINVAL on error. If an error is returned, device will switch to |
---|
647 | | - * XenbusStateClosing and the first error message will be saved in XenStore. |
---|
648 | | - * Further more if we fail to map the ring, caller should check @leaked. |
---|
649 | | - * If @leaked is not zero it means xenbus_map_ring fails to clean up, caller |
---|
650 | | - * should not free the address space of @vaddr. |
---|
651 | | - */ |
---|
652 | | -int xenbus_map_ring(struct xenbus_device *dev, grant_ref_t *gnt_refs, |
---|
653 | | - unsigned int nr_grefs, grant_handle_t *handles, |
---|
654 | | - unsigned long *vaddrs, bool *leaked) |
---|
655 | | -{ |
---|
656 | | - phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS]; |
---|
657 | | - int i; |
---|
658 | | - |
---|
659 | | - if (nr_grefs > XENBUS_MAX_RING_GRANTS) |
---|
660 | | - return -EINVAL; |
---|
661 | | - |
---|
662 | | - for (i = 0; i < nr_grefs; i++) |
---|
663 | | - phys_addrs[i] = (unsigned long)vaddrs[i]; |
---|
664 | | - |
---|
665 | | - return __xenbus_map_ring(dev, gnt_refs, nr_grefs, handles, |
---|
666 | | - phys_addrs, GNTMAP_host_map, leaked); |
---|
667 | | -} |
---|
668 | | -EXPORT_SYMBOL_GPL(xenbus_map_ring); |
---|
669 | | - |
---|
670 | 670 | |
---|
671 | 671 | /** |
---|
672 | 672 | * xenbus_unmap_ring_vfree |
---|
.. | .. |
---|
687 | 687 | EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree); |
---|
688 | 688 | |
---|
689 | 689 | #ifdef CONFIG_XEN_PV |
---|
690 | | -static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev, |
---|
691 | | - grant_ref_t *gnt_refs, |
---|
692 | | - unsigned int nr_grefs, |
---|
693 | | - void **vaddr) |
---|
| 690 | +static int map_ring_apply(pte_t *pte, unsigned long addr, void *data) |
---|
694 | 691 | { |
---|
695 | | - struct xenbus_map_node *node; |
---|
| 692 | + struct map_ring_valloc *info = data; |
---|
| 693 | + |
---|
| 694 | + info->phys_addrs[info->idx++] = arbitrary_virt_to_machine(pte).maddr; |
---|
| 695 | + return 0; |
---|
| 696 | +} |
---|
| 697 | + |
---|
| 698 | +static int xenbus_map_ring_pv(struct xenbus_device *dev, |
---|
| 699 | + struct map_ring_valloc *info, |
---|
| 700 | + grant_ref_t *gnt_refs, |
---|
| 701 | + unsigned int nr_grefs, |
---|
| 702 | + void **vaddr) |
---|
| 703 | +{ |
---|
| 704 | + struct xenbus_map_node *node = info->node; |
---|
696 | 705 | struct vm_struct *area; |
---|
697 | | - pte_t *ptes[XENBUS_MAX_RING_GRANTS]; |
---|
698 | | - phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS]; |
---|
699 | | - int err = GNTST_okay; |
---|
700 | | - int i; |
---|
701 | | - bool leaked; |
---|
| 706 | + bool leaked = false; |
---|
| 707 | + int err = -ENOMEM; |
---|
702 | 708 | |
---|
703 | | - *vaddr = NULL; |
---|
704 | | - |
---|
705 | | - if (nr_grefs > XENBUS_MAX_RING_GRANTS) |
---|
706 | | - return -EINVAL; |
---|
707 | | - |
---|
708 | | - node = kzalloc(sizeof(*node), GFP_KERNEL); |
---|
709 | | - if (!node) |
---|
| 709 | + area = get_vm_area(XEN_PAGE_SIZE * nr_grefs, VM_IOREMAP); |
---|
| 710 | + if (!area) |
---|
710 | 711 | return -ENOMEM; |
---|
711 | | - |
---|
712 | | - area = alloc_vm_area(XEN_PAGE_SIZE * nr_grefs, ptes); |
---|
713 | | - if (!area) { |
---|
714 | | - kfree(node); |
---|
715 | | - return -ENOMEM; |
---|
716 | | - } |
---|
717 | | - |
---|
718 | | - for (i = 0; i < nr_grefs; i++) |
---|
719 | | - phys_addrs[i] = arbitrary_virt_to_machine(ptes[i]).maddr; |
---|
720 | | - |
---|
| 712 | + if (apply_to_page_range(&init_mm, (unsigned long)area->addr, |
---|
| 713 | + XEN_PAGE_SIZE * nr_grefs, map_ring_apply, info)) |
---|
| 714 | + goto failed; |
---|
721 | 715 | err = __xenbus_map_ring(dev, gnt_refs, nr_grefs, node->handles, |
---|
722 | | - phys_addrs, |
---|
723 | | - GNTMAP_host_map | GNTMAP_contains_pte, |
---|
| 716 | + info, GNTMAP_host_map | GNTMAP_contains_pte, |
---|
724 | 717 | &leaked); |
---|
725 | 718 | if (err) |
---|
726 | 719 | goto failed; |
---|
.. | .. |
---|
733 | 726 | spin_unlock(&xenbus_valloc_lock); |
---|
734 | 727 | |
---|
735 | 728 | *vaddr = area->addr; |
---|
| 729 | + info->node = NULL; |
---|
| 730 | + |
---|
736 | 731 | return 0; |
---|
737 | 732 | |
---|
738 | 733 | failed: |
---|
.. | .. |
---|
741 | 736 | else |
---|
742 | 737 | pr_alert("leaking VM area %p size %u page(s)", area, nr_grefs); |
---|
743 | 738 | |
---|
744 | | - kfree(node); |
---|
745 | 739 | return err; |
---|
746 | 740 | } |
---|
747 | 741 | |
---|
748 | | -static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr) |
---|
| 742 | +static int xenbus_unmap_ring_pv(struct xenbus_device *dev, void *vaddr) |
---|
749 | 743 | { |
---|
750 | 744 | struct xenbus_map_node *node; |
---|
751 | 745 | struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS]; |
---|
.. | .. |
---|
809 | 803 | } |
---|
810 | 804 | |
---|
811 | 805 | static const struct xenbus_ring_ops ring_ops_pv = { |
---|
812 | | - .map = xenbus_map_ring_valloc_pv, |
---|
813 | | - .unmap = xenbus_unmap_ring_vfree_pv, |
---|
| 806 | + .map = xenbus_map_ring_pv, |
---|
| 807 | + .unmap = xenbus_unmap_ring_pv, |
---|
814 | 808 | }; |
---|
815 | 809 | #endif |
---|
816 | 810 | |
---|
817 | | -struct unmap_ring_vfree_hvm |
---|
| 811 | +struct unmap_ring_hvm |
---|
818 | 812 | { |
---|
819 | 813 | unsigned int idx; |
---|
820 | 814 | unsigned long addrs[XENBUS_MAX_RING_GRANTS]; |
---|
.. | .. |
---|
825 | 819 | unsigned int len, |
---|
826 | 820 | void *data) |
---|
827 | 821 | { |
---|
828 | | - struct unmap_ring_vfree_hvm *info = data; |
---|
| 822 | + struct unmap_ring_hvm *info = data; |
---|
829 | 823 | |
---|
830 | 824 | info->addrs[info->idx] = (unsigned long)gfn_to_virt(gfn); |
---|
831 | 825 | |
---|
832 | 826 | info->idx++; |
---|
833 | 827 | } |
---|
834 | 828 | |
---|
835 | | -static int xenbus_unmap_ring_vfree_hvm(struct xenbus_device *dev, void *vaddr) |
---|
| 829 | +static int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr) |
---|
836 | 830 | { |
---|
837 | 831 | int rv; |
---|
838 | 832 | struct xenbus_map_node *node; |
---|
839 | 833 | void *addr; |
---|
840 | | - struct unmap_ring_vfree_hvm info = { |
---|
| 834 | + struct unmap_ring_hvm info = { |
---|
841 | 835 | .idx = 0, |
---|
842 | 836 | }; |
---|
843 | 837 | unsigned int nr_pages; |
---|
.. | .. |
---|
870 | 864 | info.addrs); |
---|
871 | 865 | if (!rv) { |
---|
872 | 866 | vunmap(vaddr); |
---|
873 | | - free_xenballooned_pages(nr_pages, node->hvm.pages); |
---|
| 867 | + xen_free_unpopulated_pages(nr_pages, node->hvm.pages); |
---|
874 | 868 | } |
---|
875 | 869 | else |
---|
876 | 870 | WARN(1, "Leaking %p, size %u page(s)\n", vaddr, nr_pages); |
---|
.. | .. |
---|
878 | 872 | kfree(node); |
---|
879 | 873 | return rv; |
---|
880 | 874 | } |
---|
881 | | - |
---|
882 | | -/** |
---|
883 | | - * xenbus_unmap_ring |
---|
884 | | - * @dev: xenbus device |
---|
885 | | - * @handles: grant handle array |
---|
886 | | - * @nr_handles: number of handles in the array |
---|
887 | | - * @vaddrs: addresses to unmap |
---|
888 | | - * |
---|
889 | | - * Unmap memory in this domain that was imported from another domain. |
---|
890 | | - * Returns 0 on success and returns GNTST_* on error |
---|
891 | | - * (see xen/include/interface/grant_table.h). |
---|
892 | | - */ |
---|
893 | | -int xenbus_unmap_ring(struct xenbus_device *dev, |
---|
894 | | - grant_handle_t *handles, unsigned int nr_handles, |
---|
895 | | - unsigned long *vaddrs) |
---|
896 | | -{ |
---|
897 | | - struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS]; |
---|
898 | | - int i; |
---|
899 | | - int err; |
---|
900 | | - |
---|
901 | | - if (nr_handles > XENBUS_MAX_RING_GRANTS) |
---|
902 | | - return -EINVAL; |
---|
903 | | - |
---|
904 | | - for (i = 0; i < nr_handles; i++) |
---|
905 | | - gnttab_set_unmap_op(&unmap[i], vaddrs[i], |
---|
906 | | - GNTMAP_host_map, handles[i]); |
---|
907 | | - |
---|
908 | | - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i)) |
---|
909 | | - BUG(); |
---|
910 | | - |
---|
911 | | - err = GNTST_okay; |
---|
912 | | - for (i = 0; i < nr_handles; i++) { |
---|
913 | | - if (unmap[i].status != GNTST_okay) { |
---|
914 | | - xenbus_dev_error(dev, unmap[i].status, |
---|
915 | | - "unmapping page at handle %d error %d", |
---|
916 | | - handles[i], unmap[i].status); |
---|
917 | | - err = unmap[i].status; |
---|
918 | | - break; |
---|
919 | | - } |
---|
920 | | - } |
---|
921 | | - |
---|
922 | | - return err; |
---|
923 | | -} |
---|
924 | | -EXPORT_SYMBOL_GPL(xenbus_unmap_ring); |
---|
925 | | - |
---|
926 | 875 | |
---|
927 | 876 | /** |
---|
928 | 877 | * xenbus_read_driver_state |
---|
.. | .. |
---|
943 | 892 | EXPORT_SYMBOL_GPL(xenbus_read_driver_state); |
---|
944 | 893 | |
---|
945 | 894 | static const struct xenbus_ring_ops ring_ops_hvm = { |
---|
946 | | - .map = xenbus_map_ring_valloc_hvm, |
---|
947 | | - .unmap = xenbus_unmap_ring_vfree_hvm, |
---|
| 895 | + .map = xenbus_map_ring_hvm, |
---|
| 896 | + .unmap = xenbus_unmap_ring_hvm, |
---|
948 | 897 | }; |
---|
949 | 898 | |
---|
950 | 899 | void __init xenbus_ring_ops_init(void) |
---|