diff options
-rw-r--r-- | drivers/xen/balloon.c | 147 |
1 files changed, 3 insertions, 144 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index cdec2d843e4c..fff987b10e0f 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
@@ -226,9 +226,8 @@ static int increase_reservation(unsigned long nr_pages) | |||
226 | } | 226 | } |
227 | 227 | ||
228 | set_xen_guest_handle(reservation.extent_start, frame_list); | 228 | set_xen_guest_handle(reservation.extent_start, frame_list); |
229 | reservation.nr_extents = nr_pages; | 229 | reservation.nr_extents = nr_pages; |
230 | rc = HYPERVISOR_memory_op( | 230 | rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); |
231 | XENMEM_populate_physmap, &reservation); | ||
232 | if (rc < nr_pages) { | 231 | if (rc < nr_pages) { |
233 | if (rc > 0) { | 232 | if (rc > 0) { |
234 | int ret; | 233 | int ret; |
@@ -236,7 +235,7 @@ static int increase_reservation(unsigned long nr_pages) | |||
236 | /* We hit the Xen hard limit: reprobe. */ | 235 | /* We hit the Xen hard limit: reprobe. */ |
237 | reservation.nr_extents = rc; | 236 | reservation.nr_extents = rc; |
238 | ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, | 237 | ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, |
239 | &reservation); | 238 | &reservation); |
240 | BUG_ON(ret != rc); | 239 | BUG_ON(ret != rc); |
241 | } | 240 | } |
242 | if (rc >= 0) | 241 | if (rc >= 0) |
@@ -464,130 +463,6 @@ static void balloon_exit(void) | |||
464 | 463 | ||
465 | module_exit(balloon_exit); | 464 | module_exit(balloon_exit); |
466 | 465 | ||
467 | static void balloon_update_driver_allowance(long delta) | ||
468 | { | ||
469 | unsigned long flags; | ||
470 | |||
471 | spin_lock_irqsave(&balloon_lock, flags); | ||
472 | balloon_stats.driver_pages += delta; | ||
473 | spin_unlock_irqrestore(&balloon_lock, flags); | ||
474 | } | ||
475 | |||
476 | static int dealloc_pte_fn( | ||
477 | pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) | ||
478 | { | ||
479 | unsigned long mfn = pte_mfn(*pte); | ||
480 | int ret; | ||
481 | struct xen_memory_reservation reservation = { | ||
482 | .nr_extents = 1, | ||
483 | .extent_order = 0, | ||
484 | .domid = DOMID_SELF | ||
485 | }; | ||
486 | set_xen_guest_handle(reservation.extent_start, &mfn); | ||
487 | set_pte_at(&init_mm, addr, pte, __pte_ma(0ull)); | ||
488 | set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY); | ||
489 | ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation); | ||
490 | BUG_ON(ret != 1); | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static struct page **alloc_empty_pages_and_pagevec(int nr_pages) | ||
495 | { | ||
496 | unsigned long vaddr, flags; | ||
497 | struct page *page, **pagevec; | ||
498 | int i, ret; | ||
499 | |||
500 | pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL); | ||
501 | if (pagevec == NULL) | ||
502 | return NULL; | ||
503 | |||
504 | for (i = 0; i < nr_pages; i++) { | ||
505 | page = pagevec[i] = alloc_page(GFP_KERNEL); | ||
506 | if (page == NULL) | ||
507 | goto err; | ||
508 | |||
509 | vaddr = (unsigned long)page_address(page); | ||
510 | |||
511 | scrub_page(page); | ||
512 | |||
513 | spin_lock_irqsave(&balloon_lock, flags); | ||
514 | |||
515 | if (xen_feature(XENFEAT_auto_translated_physmap)) { | ||
516 | unsigned long gmfn = page_to_pfn(page); | ||
517 | struct xen_memory_reservation reservation = { | ||
518 | .nr_extents = 1, | ||
519 | .extent_order = 0, | ||
520 | .domid = DOMID_SELF | ||
521 | }; | ||
522 | set_xen_guest_handle(reservation.extent_start, &gmfn); | ||
523 | ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, | ||
524 | &reservation); | ||
525 | if (ret == 1) | ||
526 | ret = 0; /* success */ | ||
527 | } else { | ||
528 | ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE, | ||
529 | dealloc_pte_fn, NULL); | ||
530 | } | ||
531 | |||
532 | if (ret != 0) { | ||
533 | spin_unlock_irqrestore(&balloon_lock, flags); | ||
534 | __free_page(page); | ||
535 | goto err; | ||
536 | } | ||
537 | |||
538 | totalram_pages = --balloon_stats.current_pages; | ||
539 | |||
540 | spin_unlock_irqrestore(&balloon_lock, flags); | ||
541 | } | ||
542 | |||
543 | out: | ||
544 | schedule_work(&balloon_worker); | ||
545 | flush_tlb_all(); | ||
546 | return pagevec; | ||
547 | |||
548 | err: | ||
549 | spin_lock_irqsave(&balloon_lock, flags); | ||
550 | while (--i >= 0) | ||
551 | balloon_append(pagevec[i]); | ||
552 | spin_unlock_irqrestore(&balloon_lock, flags); | ||
553 | kfree(pagevec); | ||
554 | pagevec = NULL; | ||
555 | goto out; | ||
556 | } | ||
557 | |||
558 | static void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages) | ||
559 | { | ||
560 | unsigned long flags; | ||
561 | int i; | ||
562 | |||
563 | if (pagevec == NULL) | ||
564 | return; | ||
565 | |||
566 | spin_lock_irqsave(&balloon_lock, flags); | ||
567 | for (i = 0; i < nr_pages; i++) { | ||
568 | BUG_ON(page_count(pagevec[i]) != 1); | ||
569 | balloon_append(pagevec[i]); | ||
570 | } | ||
571 | spin_unlock_irqrestore(&balloon_lock, flags); | ||
572 | |||
573 | kfree(pagevec); | ||
574 | |||
575 | schedule_work(&balloon_worker); | ||
576 | } | ||
577 | |||
578 | static void balloon_release_driver_page(struct page *page) | ||
579 | { | ||
580 | unsigned long flags; | ||
581 | |||
582 | spin_lock_irqsave(&balloon_lock, flags); | ||
583 | balloon_append(page); | ||
584 | balloon_stats.driver_pages--; | ||
585 | spin_unlock_irqrestore(&balloon_lock, flags); | ||
586 | |||
587 | schedule_work(&balloon_worker); | ||
588 | } | ||
589 | |||
590 | |||
591 | #define BALLOON_SHOW(name, format, args...) \ | 466 | #define BALLOON_SHOW(name, format, args...) \ |
592 | static ssize_t show_##name(struct sys_device *dev, \ | 467 | static ssize_t show_##name(struct sys_device *dev, \ |
593 | struct sysdev_attribute *attr, \ | 468 | struct sysdev_attribute *attr, \ |
@@ -691,20 +566,4 @@ static int register_balloon(struct sys_device *sysdev) | |||
691 | return error; | 566 | return error; |
692 | } | 567 | } |
693 | 568 | ||
694 | static void unregister_balloon(struct sys_device *sysdev) | ||
695 | { | ||
696 | int i; | ||
697 | |||
698 | sysfs_remove_group(&sysdev->kobj, &balloon_info_group); | ||
699 | for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) | ||
700 | sysdev_remove_file(sysdev, balloon_attrs[i]); | ||
701 | sysdev_unregister(sysdev); | ||
702 | sysdev_class_unregister(&balloon_sysdev_class); | ||
703 | } | ||
704 | |||
705 | static void balloon_sysfs_exit(void) | ||
706 | { | ||
707 | unregister_balloon(&balloon_sysdev); | ||
708 | } | ||
709 | |||
710 | MODULE_LICENSE("GPL"); | 569 | MODULE_LICENSE("GPL"); |