spdk 建立了一套用户态的 3级页表,来方便在用户态进行虚拟地址到物理地址的转化。
3级页表是:256TiB-> 1GiB -> 2MiB
二级页表容纳 1GB 的地址空间,那么需要占用 1G/2M = 2^9, 也就是 9 bits 的地址位。也就是 [21..29]。
三级页表容纳 256TB 的地址空间,那么需要占用 256 T/1G = 2^18, 也就是 16 bits 的地址位。也就是[30..47]。
dpdk 的内存,以及非dpdk 的内存,例如 vhost-user 来自 qemu的内存都需要经过 spdk_mem_register 来注册到 spdk 的用户态内存页表管理中。
首先来看 spdk_mem_register。
下面的循环翻译虚拟地址对应的页表项是否已经设置(registered)。如果已经注册,那么就返回 EBUSY。
- 386 seg_vaddr = vaddr;
- 387 seg_len = len;
- 388 while (seg_len > 0) {
- 389 reg = spdk_mem_map_translate(g_mem_reg_map, (uint64_t)seg_vaddr, NULL);
- 390 if (reg & REG_MAP_REGISTERED) {
- 391 pthread_mutex_unlock(&g_spdk_mem_map_mutex);
- 392 return -EBUSY;
- 393 }
- 394 seg_vaddr += VALUE_2MB;
- 395 seg_len -= VALUE_2MB;
- 396 }
- 397
下面的循环只是设置对应的页表项为 REG_MAP_REGISTERED,表明已经注册了此段虚拟地址空间。
- 398 seg_vaddr = vaddr;
- 399 seg_len = 0;
- 400 while (len > 0) {
- 401 spdk_mem_map_set_translation(g_mem_reg_map, (ui