본문 바로가기

Programming/Linux_Kernel

virtual address to physical address (64bit linux)

linux 64bit 에서 page address 변환에 대해서

한눈에 보기 쉽게 그려보았습니다.


사용할때는 꼭 출처를 명시해 주기 바랍니다.







        pde64_table = (pde64_t *)__va(BASE_TO_PAGE_ADDR(pdpe64_table->pd_base_addr) + (PDE64_INDEX(fault_addr)*sizeof(pde64_t)));
	if(!pde64_table->present) {
		uintptr_t tmp_pte64_table;
		tmp_pte64_table = (uintptr_t)petmem_smart_alloc_pages(map, (uintptr_t)NULL, (pte64_t *)NULL);
		memset((void *)__va(tmp_pte64_table), 0, PAGE_SIZE_4KB);
		pde64_table->present = 1;
		pde64_table->writable = 1;
		pde64_table->user_page = 1;
		pde64_table->pt_base_addr = PAGE_TO_BASE_ADDR(tmp_pte64_table);
	}
	pte64_table = (pte64_t *)__va(BASE_TO_PAGE_ADDR(pde64_table->pt_base_addr) + (PTE64_INDEX(fault_addr)*sizeof(pte64_t)));

		uintptr_t alloc_physical_memory;
		alloc_physical_memory = (uintptr_t)(petmem_smart_alloc_pages(map, fault_addr, pte64_table));
		memset((void *)__va(alloc_physical_memory), 0, PAGE_SIZE_4KB);
		pte64_table->present = 1;
		pte64_table->writable = 1;
		pte64_table->user_page = 1;
		pte64_table->page_base_addr = PAGE_TO_BASE_ADDR_4KB(alloc_physical_memory);

	printk_debug("alloc physical addr : 0x%lx\n", (uintptr_t)(BASE_TO_PAGE_ADDR_4KB(pte64_table->page_base_addr) + PAGE_OFFSET_4KB(fault_addr)) ); // fault_addr == virtuall address
/* Gets the base address needed for a Page Table entry */
#define PAGE_TO_BASE_ADDR(x) ((x) >> 12)
#define PAGE_TO_BASE_ADDR_4KB(x) ((x) >> 12)
#define PAGE_TO_BASE_ADDR_2MB(x) ((x) >> 21)
#define PAGE_TO_BASE_ADDR_4MB(x) ((x) >> 22)
#define PAGE_TO_BASE_ADDR_1GB(x) ((x) >> 30)

#define BASE_TO_PAGE_ADDR(x) (((uintptr_t)x) << 12)
#define BASE_TO_PAGE_ADDR_4KB(x) (((uintptr_t)x) << 12)
#define BASE_TO_PAGE_ADDR_2MB(x) (((uintptr_t)x) << 21)
#define BASE_TO_PAGE_ADDR_4MB(x) (((uintptr_t)x) << 22)
#define BASE_TO_PAGE_ADDR_1GB(x) (((uintptr_t)x) << 30)
/* *** */


//#define PAGE_OFFSET(x) ((x) & 0xfff)
#define PAGE_OFFSET_4KB(x) ((x) & 0xfff)
#define PAGE_OFFSET_2MB(x) ((x) & 0x1fffff)
#define PAGE_OFFSET_4MB(x) ((x) & 0x3fffff)
#define PAGE_OFFSET_1GB(x) ((x) & 0x3fffffff)

#define PAGE_POWER 12
#define PAGE_POWER_4KB 12
#define PAGE_POWER_2MB 21
#define PAGE_POWER_4MB 22
#define PAGE_POWER_1GB 30

// We shift instead of mask because we don't know the address size
#define PAGE_ADDR(x) (((x) >> PAGE_POWER) << PAGE_POWER)
#define PAGE_ADDR_4KB(x) (((x) >> PAGE_POWER_4KB) << PAGE_POWER_4KB)
#define PAGE_ADDR_2MB(x) (((x) >> PAGE_POWER_2MB) << PAGE_POWER_2MB)
#define PAGE_ADDR_4MB(x) (((x) >> PAGE_POWER_4MB) << PAGE_POWER_4MB)
#define PAGE_ADDR_1GB(x) (((x) >> PAGE_POWER_1GB) << PAGE_POWER_1GB)

virtual-memory-example-source-code.tar.bz2




'Programming > Linux_Kernel' 카테고리의 다른 글

sleep and delay in linux kernel  (0) 2015.03.22
uevent 사용하기  (0) 2015.03.21
File System의 개요  (0) 2014.05.12
mmap 을 이용한 process memory mapping  (0) 2014.04.25
linux 에서 page cache(페이지 캐쉬)란?  (0) 2014.04.24