arm linux演艺(十一)
2012-12-12
xiangye
标签: ARM

长篇连载--arm linux演艺---第十一回

上回我们说到在paging_init中分配了三个页:

zero_page=0xc0000000

bad page=0xc0001000

bad_table=0xc0002000

但是奇怪的很,在更新的linux代码中只分配了一个zero_page,而且在源代码中找不到zero_page,用在什么地方了,大家讨论讨论吧。

paging_init的主要工作是在

void __init memtable_init(struct meminfo *mi)

中完成的,为系统内存创建页表:

meminfo结构如下:

struct meminfo {

int nr_banks;

unsigned long end;

struct {

unsigned long start;

unsigned long size;

int node;

} bank[NR_BANKS];

};

是用来纪录系统中的内存区段的,因为在嵌入式系统中并不是所有的内存都能映射,例如sdram只有64m,flash 32m,而且不见得是连续的,所以用meminfo纪录这些区段。

void __init memtable_init(struct meminfo *mi)

{

struct map_desc *init_maps, *p, *q;

unsigned long address = 0;

int i;

其中map_desc定义为:

struct map_desc {

unsigned long virtual;

unsigned long physical;

unsigned long length;

int domain:4, //页表的domain

prot_read:1, //保护标志

prot_write:1, //写保护标志

cacheable:1, //是否cache

bufferable:1, //是否用write buffer

last:1; //空

};init_maps

map_desc是区段及其属性的定义,属性位的意义请参考ARM MMU的介绍。

下面对meminfo的区段进行遍历,同时填写init_maps中的各项内容:

for (i = 0; i < mi->nr_banks; i++) {

if (mi->bank[i].size == 0)

continue;

p->physical = mi->bank[i].start;

p->virtual = __phys_to_virt(p->physical);

p->length = mi->bank[i].size;

p->domain = DOMAIN_KERNEL;

p->prot_read = 0;

p->prot_write = 1;

p->cacheable = 1; //可以CACHE

p->bufferable = 1; //使用write buffer

p ++; //下一个区段

}

如果系统有flash,

#ifdef FLUSH_BASE

p->physical = FLUSH_BASE_PHYS;

p->virtual = FLUSH_BASE;

p->length = PGDIR_SIZE;

p->domain = DOMAIN_KERNEL;

p->prot_read = 1;

p->prot_write = 0;

p->cacheable = 1;

p->bufferable = 1;

p ++;

#endif

其中的prot_read和prot_write是用来设置页表的domain的,

下面就是逐个区段建立页表:

q = init_maps;

do {

if (address < q->virtual || q == p) {

clear_mapping(address);

address += PGDIR_SIZE;

} else {

create_mapping(q);

address = q->virtual + q->length;

address = (address + PGDIR_SIZE - 1) & PGDIR_MASK;

q ++;

}

} while (address != 0);

arm linux 第十一回完

可能会用到的工具/仪表
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号