分类: 虚拟化
2012-04-22 22:01:33
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释放给guest。Linux 3.0已经包含了balloon for Xen的实现。
OVERVIEWballoon的状态由描述,该结构在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,另一个是在guest的sysfs文件系统创建子目录xen_memory,该子目录下有几个文件读/写balloon_stats的状态
核心操作inflat和deflat主要代码中
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_physmap让xen给这些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);
//将部分page从ballooned 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_pages和free_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_reservation和XENMEM_decrease_reservation。increase_reservation是利用alloc_domheap_pages从Xen中获取物理页面,而decrease_reservation 是调用guest_remove_page从guest回收页面。