Chinaunix首页 | 论坛 | 博客
  • 博客访问: 610090
  • 博文数量: 197
  • 博客积分: 7001
  • 博客等级: 大校
  • 技术积分: 2155
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-24 00:29
文章分类

全部博文(197)

文章存档

2022年(1)

2019年(2)

2015年(1)

2012年(100)

2011年(69)

2010年(14)

2007年(3)

2005年(7)

分类: 虚拟化

2012-04-22 22:01:33

balloon的概念来自下面的经典论文

Carl Waldspurger. in Proceedings of the 5th Symposium on Operating Systems Design and Implementation, 2002

简而言之,balloon就是VMM打入guest的一个探子,通常以驱动方式存在,当guest空闲内存比较多时,通过吹气球inflat,让balloon申请若干内存,然后转给VMM。当guest load比较重,可以放气deflat,让VMM塞给balloon若干内存,然后balloon释放给guestLinux 3.0已经包含了balloon for Xen的实现。

OVERVIEW

balloon的状态由描述,该结构在balloon_init函数中初始化。

struct { //in xen/balloon.h

       /* We aim for 'current allocation' == 'target allocation'. */

       unsigned long current_pages;  //guest当前实际mfn数目

       unsigned long ;   //balloon期待guest拥有的mfn数目

       /* Number of pages in high- and low-memory balloons. guest中被剥夺mfn的页面*/

       unsigned long balloon_low; 

       unsigned long balloon_high;

       unsigned long schedule_delay;

       unsigned long max_schedule_delay;

       unsigned long retry_count;

       unsigned long max_retry_count;

};

工作队列负责具体的操作,实际处理函数balloon_process根据target_pages值决定充气还是放气。外围代码通过调用balloon_set_new_target驱动balloon_worker

static DECLARE_DELAYED_WORK(, );

 

balloon的外围代码在linux 3.0/drivers/xen/xen-balloon.c中,一个是xenstore的节点memory/target设置watch,另一个是在guestsysfs文件系统创建子目录xen_memory,该子目录下有几个文件读/balloon_stats的状态

核心操作inflatdeflat

主要代码

increase_reservation 对应放气,增加guest的内存。

decrease_reservation对应吹气,减少guest的内存。

 

/* List of , threaded through the mem_map array. ballooned_pages的页面都是有struct page结构,但是其对应的mfn已经被xen回收了

*/

static LIST_HEAD();

 

static enum bp_state increase_reservation(unsigned long nr_pages)

{

       int rc;

       unsigned long  pfn, i;

       struct page   *page;

       struct xen_memory_reservation reservation = {

              .address_bits = 0,

              .extent_order = 0,

              .domid        = DOMID_SELF

       };

      

   /*下面的先取得若干page结构,然后通过超级调用populate_physmapxen给这些page分配mfn,但是实际并不是如此,返回的mfn放在列表中,但是并没有和开始传递进去的各个page绑定起来,也就是前面传进去的参数只有reservation.nr_extents = nr_pages; 才有作用,page传进去似乎是浪费(只有XENMEMF_populate_on_demand标记传进去page才有作用 fix me)。

*/

 

       page = balloon_first_page();

       for (i = 0; i < nr_pages; i++) {

              if (!page) {

                     nr_pages = i;

                     break;

              }

              frame_list[i] = page_to_pfn(page);

              page = balloon_next_page(page);

       }

       set_xen_guest_handle(reservation.extent_start, );

      

       rc = HYPERVISOR_memory_op(, &reservation);

      

  //将部分pageballooned pages摘除,和frame_list中取得的mfn绑定,包括P2M

//,最后guest使用

       for (i = 0; i < rc; i++) {

              page = balloon_retrieve(false);

 

              pfn = page_to_pfn(page);

              set_phys_to_machine(pfn, );// 更新P2M

 

              /* Link back into the page tables if not highmem. */

              if (xen_pv_domain() && !PageHighMem(page)) {

                     int ret;

                     ret = HYPERVISOR_update_va_mapping(//更新guest的页表

                            (unsigned long)__va(pfn << PAGE_SHIFT),

                            mfn_pte(frame_list[i], PAGE_KERNEL),

                            0);

              }

 

              /* Relinquish the page back to the allocator. */

              ClearPageReserved(page);

              init_page_count(page);

              ;// 释放给guest使用

       }

       balloon_stats.current_pages += rc;

       return BP_DONE;

}

 

static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)

{

       enum bp_state state = BP_DONE;

       unsigned long  pfn, i;

       struct page   *page;

       int ret;

       struct xen_memory_reservation reservation = {

              .address_bits = 0,

              .extent_order = 0,

              .domid        = DOMID_SELF

       };

 

       for (i = 0; i < nr_pages; i++) {

              if ((page = alloc_page(gfp)) == NULL) {//guest申请页面

                     nr_pages = i;

                     state = BP_EAGAIN;

                     break;

              }

              pfn = page_to_pfn(page);

              frame_list[i] = pfn_to_mfn(pfn);//取得对应的mfn

 

              scrub_page(page); //为安全起见(可以挪到另一个guest使用),清0

 

              if (xen_pv_domain() && !PageHighMem(page)) {

                     ret = HYPERVISOR_update_va_mapping(//将页表项清0

                            (unsigned long)__va(pfn << PAGE_SHIFT),

                            __pte_ma(0), 0);

                }

 

       }

 

       /* Ensure that ballooned highmem pages don't have kmaps. */

       kmap_flush_unused();

       flush_tlb_all();

 

       /* No more mappings: invalidate P2M and add to balloon. */

       for (i = 0; i < nr_pages; i++) {

              pfn = mfn_to_pfn(frame_list[i]);

              __set_phys_to_machine(pfn, INVALID_P2M_ENTRY);

              balloon_append(pfn_to_page(pfn));//page加入ballooned_pages链表

       }

 

       set_xen_guest_handle(reservation.extent_start, frame_list);

       reservation.nr_extents   = nr_pages;

    //mfn转给Xen

       ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);

       balloon_stats.current_pages -= nr_pages;

       return state;

}

alloc_xenballooned_pagesfree_xenballooned_pages接口

[Xen-devel] Re: [PATCH 2/3] xen-balloon: Add interface to retrieve ballooned pages

Pages that have been ballooned are useful for other Xen drivers doing grant table actions, because these pages have valid struct page/PFNs but have no valid MFN so are available for remapping.

Xen的支持

do_memory_op中的 XENMEM_increase_reservationXENMEM_decrease_reservationincrease_reservation是利用alloc_domheap_pagesXen中获取物理页面,而decrease_reservation 是调用guest_remove_pageguest回收页面。

阅读(2786) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

十七岁的回忆2012-04-26 18:15:32

- -这个很不错啊,楼主的帖子的值得学习