一.总体说明
二.代码分析
2.1 在arch/i386/mm/init.c-->paging_init-->pagetable_init
-
static void __init pagetable_init (void)
-
{
-
//将ZONE_HIGHMEM部分的页目录表修改一下
-
//执行后vaddr=0xffc00000(物理地址1020M)(虚拟地址4092M)
-
//0xc0101ff0 : 0x00000000 0x00000000 0x00000000 0x00003063
-
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; //执行后vaddr=0xffc00000
-
fixrange_init(vaddr, 0, pgd_base); -->0xc0101ffc处写入0x00003063
-
-
#if CONFIG_HIGHMEM
-
//执行后vaddr=0xfe000000(物理地址992M)(虚地址4064M离4G还有32M),end=996M 虚地址(4064M-4068M之间)
-
//执行后0xc0101fe0 : 0x00004063 0x00000000 0x00000000 0x00000000
-
vaddr = PKMAP_BASE; -->执行后vaddr=0xfe000000
-
fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); -->0xc0101fe0处写入0x00004063
-
-
pgd = swapper_pg_dir + __pgd_offset(vaddr); //vaddr=0xfe000000,其pgd_offset=0x3F8,加法运算时0x3F8*4执行后pgd=0xc0101fe0
-
pmd = pmd_offset(pgd, vaddr); //在pgtable-2level.h中pmd=pgd,所以执行后pmd=0xc0101fe0
-
pte = pte_offset(pmd, vaddr); //pte=0xc0004000
-
pkmap_page_table = pte; //pkmap_pate_talbe=0xc0004000
-
#endif
-
}
完成之后页目录表的内容如下:
-
(gdb) x /1024wx 0xc0101000
-
...
-
0xc0101f50 <swapper_pg_dir+3920>: 0x350001e3 0x354001e3 0x358001e3 0x35c001e3
-
0xc0101f60 <swapper_pg_dir+3936>: 0x360001e3 0x364001e3 0x368001e3 0x36c001e3
-
0xc0101f70 <swapper_pg_dir+3952>: 0x370001e3 0x374001e3 0x378001e3 0x37c001e3
-
0xc0101f80 <swapper_pg_dir+3968>: 0x00000000 0x00000000 0x00000000 0x00000000 -->这部分是用作vmalloc的
-
0xc0101f90 <swapper_pg_dir+3984>: 0x00000000 0x00000000 0x00000000 0x00000000
-
0xc0101fa0 <swapper_pg_dir+4000>: 0x00000000 0x00000000 0x00000000 0x00000000
-
0xc0101fb0 <swapper_pg_dir+4016>: 0x00000000 0x00000000 0x00000000 0x00000000
-
0xc0101fc0 <swapper_pg_dir+4032>: 0x00000000 0x00000000 0x00000000 0x00000000
-
0xc0101fd0 <swapper_pg_dir+4048>: 0x00000000 0x00000000 0x00000000 0x00000000
-
0xc0101fe0 <swapper_pg_dir+4064>: 0x00004063 0x00000000 0x00000000 0x00000000 -->这部分是用作highmem的
-
0xc0101ff0 <swapper_pg_dir+4080>: 0x00000000 0x00000000 0x00000000 0x00003063
2.1 在arch/i386/mm/init.c中L81 paging_init-->kmap_init()
-
//初始化几个变量kmap_vstart=0xffff5000,kmap_pte=0xc0003fd4,kmap_prot=0x163
-
void __init kmap_init(void)
-
{
-
unsigned long kmap_vstart;
-
-
//FIX_KMAP_BEGIN=9, FIXADDR_TOP=0xffffe000(差2个page到4G),kmap_vstart=(FIXADDR_TOP - ((x) << PAGE_SHIFT))
-
kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); //执行后kmap_vstart=0xffff5000
-
kmap_pte = kmap_get_fixmap_pte(kmap_vstart); //执行后kmap_pte=0xc0003fd4
-
-
kmap_prot = PAGE_KERNEL;
-
}
-
2.1 在include/asm/highmem.h中L62
-
static inline void *kmap(struct page *page)
-
{
-
if (in_interrupt())
-
BUG();
-
//这儿传入参数page=0xc1f56f44,highmem_start_page=0xc1ee0010,所以不能返回直接映射
-
if (page < highmem_start_page) //高端内存在page管理区的地址=0xc1000010+0x38000*68=0xc1ee0010
-
return page_address(page); //如果是直接映射的话,返回page->virtual
-
return kmap_high(page);
-
}
如果是直接映射的话,可直接返回page->virtual
-
(gdb) p *(struct page*)0xc1000010
-
$5 = {list = {next = 0xc1000010, prev = 0xc1000010}, mapping = 0x0, index = 0, next_hash = 0x0, count = {counter = 0}, flags = 16384, lru = {next = 0x0, prev = 0x0},
-
wait = {lock = {lock = 1, magic = 3735899821}, task_list = {next = 0xc100003c, prev = 0xc100003c}}, pprev_hash = 0x0, buffers = 0x0, virtual = 0xc0000000, //物理地址0x0
-
zone = 0xc02cf9c0 <contig_page_data>}
-
-
(gdb) p *(struct page*)0xc1000054
-
$8 = {list = {next = 0xc1000054, prev = 0xc1000054}, mapping = 0x0, index = 0, next_hash = 0x0, count = {counter = 0}, flags = 16384, lru = {next = 0x0, prev = 0x0},
-
wait = {lock = {lock = 1, magic = 3735899821}, task_list = {next = 0xc1000080, prev = 0xc1000080}}, pprev_hash = 0x0, buffers = 0x0, virtual = 0xc0001000, //物理地址4096
-
zone = 0xc02cf9c0 <contig_page_data>}
2.1 在mm/highmem.c中L128
-
void *kmap_high(struct page *page)
-
{
-
unsigned long vaddr;
-
spin_lock(&kmap_lock);
-
vaddr = (unsigned long) page->virtual;
-
if (!vaddr)
-
vaddr = map_new_virtual(page);
-
pkmap_count[PKMAP_NR(vaddr)]++; //pkmap_count[1]由1-->2
-
if (pkmap_count[PKMAP_NR(vaddr)] < 2)
-
BUG();
-
spin_unlock(&kmap_lock);
-
return (void*) vaddr; //vaddr=0xfe001000
-
}
下面是参数page的打印
-
(gdb) p *page 的地址=0xc1f56f44
-
$11 = {list = {next = 0xf7daf3bc, prev = 0xf7daf3bc}, mapping = 0xf7daf3bc, index = 0, next_hash = 0x0, count = {counter = 3}, flags = 2113,
-
lru = {next = 0xc1ed562c, prev = 0xc035b42c <inactive_list>}, wait = {lock = {lock = 1, magic = 3735899821}, task_list = {next = 0xc1f56f70, prev = 0xc1f56f70}},
-
pprev_hash = 0xf7e6cc68, buffers = 0xf7db6700, virtual = 0x0, zone = 0xc02cfb18 <contig_page_data+344>}
*(struct zone_struct*)0xc02cf9c0 -->zone_DMA
*(struct zone_struct*)0xC02CFA6C -->zone_Normal
*(struct zone_struct*)0xc02cfb18 --> zone_HighMem
在mm/highmem.c中
-
static inline unsigned long map_new_virtual(struct page *page)
-
{
-
unsigned long vaddr;
-
int count;
-
-
start:
-
count = LAST_PKMAP; //count=1024=0x400
-
/* Find an empty entry */
-
for (;;) {
-
last_pkmap_nr = (last_pkmap_nr + 1) & LAST_PKMAP_MASK; //执行后last_pkmap_nr=1
-
if (!last_pkmap_nr) {
-
flush_all_zero_pkmaps();
-
count = LAST_PKMAP;
-
}
-
if (!pkmap_count[last_pkmap_nr]) //现在数组pkmap_count中都是0
-
break; /* Found a usable entry */
-
if (--count)
-
continue;
-
-
/*
-
* Sleep for somebody else to unmap their entries
-
*/
-
{
-
DECLARE_WAITQUEUE(wait, current);
-
-
current->state = TASK_UNINTERRUPTIBLE;
-
add_wait_queue(&pkmap_map_wait, &wait);
-
spin_unlock(&kmap_lock);
-
schedule();
-
remove_wait_queue(&pkmap_map_wait, &wait);
-
spin_lock(&kmap_lock);
-
-
/* Somebody else might have mapped it while we slept */
-
if (page->virtual)
-
return (unsigned long) page->virtual;
-
-
/* Re-start */
-
goto start;
-
}
-
}
-
//PKMAP_BASE=0xfe000000UL=4064M(离4G有32M)
-
//#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))是从4064M开始依次加1个page
-
vaddr = PKMAP_ADDR(last_pkmap_nr); //执行后vaddr=0xfe001000
-
set_pte(&(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot));
-
-
pkmap_count[last_pkmap_nr] = 1; //last_pkmap_nr=1,pkmap_count[last_pkmap_nr]=1
-
page->virtual = (void *) vaddr; //vaddr0xfe001000
-
-
return vaddr;
-
}
set_pte前后页表项的数据改变:
-
(gdb) x /4wx 0xc0004004= &(pkmap_page_table[last_pkmap_nr])
-
0xc0004004: 0x00000000 0x00000000 0x00000000 0x00000000
-
(gdb) x /4wx 0xc0004004
-
0xc0004004: 0x3fffd163 0x00000000 0x00000000 0x00000000
阅读(1982) | 评论(0) | 转发(0) |