QEMU分页机制分析

原创 2012年03月26日 17:47:35

1 qemu页面层次划分

qemu通过定义一些宏灵活地进行分页,首先由宏TARGET_PAGE_BITS(12)确定页的大小,然后根据目标机的物理地址空间和宿主机的字长确定P_L1_BITS和V_L1_BITS,从而使得剩余部分可以被L2_BITS均分。那么如何确定P_L1_BITS和V_L1_BITS的值呢?先看下面两个宏定义:
/* The bits remaining after N lower levels of page tables. */
#define P_L1_BITS_REM \
((TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS)
#define V_L1_BITS_REM \
((L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS)
这两个宏确定了按照L2_BITS大小均分后剩余的bit数。

再看P_L1_BITS的定义,它取决于P_L1_BITS_REM的大小,这么做得目的就是既能保证除去L1层之后,剩余长度的页面可以按照L2_BITS大小均分,也避免了L1页面尺寸太小,降低了访问效率。
/* Size of the L1 page table. Avoid silly small sizes. */
#if P_L1_BITS_REM < 4
#define P_L1_BITS (P_L1_BITS_REM + L2_BITS)
#else
#define P_L1_BITS P_L1_BITS_REM
#endif

V_L1_BITS定义的思想与P_L1_BITS完全一致,如下:
#if V_L1_BITS_REM < 4
#define V_L1_BITS (V_L1_BITS_REM + L2_BITS)
#else
#define V_L1_BITS V_L1_BITS_REM
#endif

P_L1_SHIFT和V_L1_SHIFT分别表示除去L1层与页宽后剩余的物理空间与虚拟地址宽度。从P_L1_BITS与V_L1_BITS定义不难看出这两个宏模L2_BITS的值恰好为0。
#define P_L1_SHIFT (TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - P_L1_BITS)
#define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS)

2 页的查找与分配

这里以虚拟页的查找与分配为例进行说明,L1层采用静态分配,最底层是指向PageDesc的指针。

static void *l1_map[V_L1_SIZE];
static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
{//假如页地址为addr,参数index为addr >> TARGET_PAGE_BITS
//参数alloc非零时表示待查找的页不存在时动态进行分配,否则返回NULL
PageDesc *pd;
void **lp;
int i;

...
/* Level 1. Always allocated. *///找出indexL1层对应的位置
lp = l1_map + ((index >> V_L1_SHIFT) & (V_L1_SIZE - 1));

/* Level 2..N-1. *///最底层页面分配的是PageDesc元素,所以需单独处理
for (i = V_L1_SHIFT / L2_BITS - 1; i > 0; i--) {
void **p = *lp;

if (p == NULL) {
if (!alloc) {
return NULL;
}
ALLOC(p, sizeof(void *) * L2_SIZE);
*lp = p;
}

lp = p + ((index >> (i * L2_BITS)) & (L2_SIZE - 1));
}

pd = *lp;
if (pd == NULL) {
if (!alloc) {
return NULL;
}
ALLOC(pd, sizeof(PageDesc) * L2_SIZE);//动态分配最底层页面
*lp = pd;
}

#undef ALLOC
//返回最底层页面相应位置的PageDesc指针
return pd + (index & (L2_SIZE - 1));
}

下面举例说明一下,假设L1_MAP_ADDR_SPACE_BITS为32,那么
V_L1_BITS_REM=((L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS)=0.
V_L1_BITS=L2_BITS
V_L1_SHIFT=(L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS)=10
调用page_find_alloc函数时,如果参数alloc非零,其中的for循环不会执行,因为
i = V_L1_SHIFT / L2_BITS - 1=0,不满足i>0的条件。
这时我们可以看到32位虚地址空间的页共分配了两层,第一层大小为2^10,其内容是指向下一层的指针;第二层大小也为2^10,其内容是PageDesc;

qemu的这种实现方法可以兼容各种长度的宿主与目标机长度,程序代码不用做任何修改。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Linux内核源码分析--内存管理(一、分页机制)

最开始的地方是在head汇编中,如果看boot中那三个汇编的应该记得(那三个汇编还是比较重要的)。首先是分页机制,在CR0的第31位(PG位)置1表示开启分页机制,顺便也介绍下其他几个控制寄存器:CR...

windows分页机制

  • 2013-09-07 12:06
  • 644KB
  • 下载

Mysql limit 分页机制和优化实例

Mysql limit 常用于分页等操作,对于页面展示来说,一旦数据量上升,分页查询的性能问题就会非常需要关注,下面给出几种 limit性能分析和实例。

80386内存分页机制

  • 2010-06-24 16:44
  • 316KB
  • 下载

《一个操作系统的实现》读书笔记--第三章--分页机制

1、逻辑地址、线性地址和物理地址 2、分页管理机制 3、PDE、PTE、cr3 4、如何初始化页目录表与页表 一、逻辑地址、线性地址和物理地址 1、在未开启分页机制情况下 2、在开启分页...

内存管理-分页机制

  • 2014-10-10 21:17
  • 486KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)