您的位置 首页 电源

ARM Linux (S3C6410架构/2.6.35内核)的内存映射(五)

ARMLinux的访问权限控制ARM1176JZF-S处理器为访问权限控制定义了两个层次:第一层是域(Domain)的访问类型,第二层是页或者段的读写权…

ARM Linux的拜访权限操控

ARM1176JZF-S处理器为拜访权限操控界说了两个层次:榜首层是”域”(Domain)的拜访类型,第二层是页或许段的”读写权限”(Access Permission)。具体来说,进程是这样的:

1.在ARM处理器中,MMU将整个存储空间分红最多16个域,记作D0~D15,每个域对应必定的存储区域,该区域具有相同的拜访操控特点。每个域的拜访权限分别由CP15的C3寄存器中的两位来设定,c3寄存器的巨细为32bits,刚好能够设置16个域的拜访权限。

Bits 31, 30 29, 28 27, 26 25, 24 23, 22 21, 20 19, 18 17, 16 15, 14 13, 12 11, 10 9, 8 7, 6 5, 4 3, 2 1, 0
Domain D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0

关于每一个域所对应的两个bit,拜访类型设置办法如下:

拜访类型 意义
0b00 无拜访权限 此刻拜访该域将发生拜访失效
0b01 用户(client) 依据CP15的C1操控寄存器中的R和S位以及页表中地址改换条目中的拜访权限操控位AP来确认是否答应各种体系作业形式的存储拜访
0b10 保存 运用该值会发生不行预知的成果
0b11 管理者(Manager) 不考虑CP15的C1操控寄存器中的R和S位以及页表中地址改换条目中的拜访权限操控位AP,在这种情况下不论体系作业在特权形式仍是用户形式都不会发生拜访失效
2. 假如域的拜访类型是0b01的话,下面就进入第二层。所拜访内存页或段的权限还要依据CP15的C1寄存器中的R和S位以及页/段表项中的拜访权限操控位AP(X)来决议。
APX AP[1:0] 特权形式拜访权限 用户形式拜访权限
0 b00 制止拜访;S=1,R=0或S=0,R=1时只读 制止拜访;S=1,R=0时只读
0 b01 读写 制止拜访
0 b10 读写 只读
0 b11 读写 读写
1 b00 保存 保存
1 b01 只读 制止拜访
1 b10 只读 只读
1 b11 只读 只读
[8]参阅ARM1176JZF-S Revision: r0p7->6.5.2 Access permissions
下面看一下Linux是怎么完成的。
在谈到create_mapping之前,有必要阐明一下Linux是怎么完成对页面的拜访操控的。
Linux运用结构体mem_type来界说不同的内存映射类型(arch/arm/mm/mm.h),不同的映射类型界说了不同的拜访权限:
[c]struct mem_type {unsigned int prot_pte;unsigned int prot_l1;unsigned int prot_sect;unsigned int domain;};[/c] 

其间处成员意义如下:
prot_pte代表页表项的拜访操控权,pte即第二级映射表项(页表项)。
prot_l1代表段表项的拜访操控位,l1即榜首级映射表项(段表项/主页表项)。
prot_sect代表主页表(留意,不是主页表项)的拜访操控位和内存域。
domain代表所属的内存域。
关于ARM处理器,Linux界说了一个类型为struct mem_type的部分静态数组(arch/arm/mm/mmu.c)。依据不同的映射类型,界说了不同的拜访权限。

[c]static struct mem_type mem_types[] = {[MT_DEVICE] = { .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |L_PTE_SHARED,.prot_l1 = PMD_TYPE_TABLE,.prot_sect = PROT_SECT_DEVICE | PMD_SECT_S,.domain = DOMAIN_IO,},[MT_DEVICE_NONSHARED] = { .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_NONSHARED,.prot_l1 = PMD_TYPE_TABLE,.prot_sect = PROT_SECT_DEVICE,.domain = DOMAIN_IO,},[MT_DEVICE_CACHED] = { .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_CACHED,.prot_l1 = PMD_TYPE_TABLE,.prot_sect = PROT_SECT_DEVICE | PMD_SECT_WB,.domain = DOMAIN_IO,},[MT_DEVICE_WC] = { .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_WC,.prot_l1 = PMD_TYPE_TABLE,.prot_sect = PROT_SECT_DEVICE,.domain = DOMAIN_IO,},[MT_UNCACHED] = {.prot_pte = PROT_PTE_DEVICE,.prot_l1 = PMD_TYPE_TABLE,.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,.domain = DOMAIN_IO,},[MT_CACHECLEAN] = {.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,.domain = DOMAIN_KERNEL,},[MT_MINICLEAN] = {.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_MINICACHE,.domain = DOMAIN_KERNEL,},[MT_LOW_VECTORS] = {.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |L_PTE_EXEC,.prot_l1 = PMD_TYPE_TABLE,.domain = DOMAIN_USER,},[MT_HIGH_VECTORS] = {.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |L_PTE_USER | L_PTE_EXEC,.prot_l1 = PMD_TYPE_TABLE,.domain = DOMAIN_USER,},[MT_MEMORY] = {.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,.domain = DOMAIN_KERNEL,},[MT_ROM] = {.prot_sect = PMD_TYPE_SECT,.domain = DOMAIN_KERNEL,},[MT_MEMORY_NONCACHED] = {.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,.domain = DOMAIN_KERNEL,},};[/c] 

体系中界说了多个映射类型,最常用的是MT_MEMORY,它对应RAM;MT_DEVICE则对应了其他I/O设备,应用于ioremap;MT_ROM对应于ROM;MT_LOW_VECTORS对应0地址开端的向量;MT_HIGH_VECTORS对应高地址开端的向量,它有vector_base宏决议。

[c]arch/arm/include/asm/io.h#define MT_DEVICE               0#define MT_DEVICE_NONSHARED     1#define MT_DEVICE_CACHED        2#define MT_DEVICE_WC            3arch/arm/include/asm/mach/map.h#define MT_UNCACHED             4#define MT_CACHECLEAN           5#define MT_MINICLEAN            6#define MT_LOW_VECTORS          7#define MT_HIGH_VECTORS         8#define MT_MEMORY               9#define MT_ROM                  10[/c] 

虽然ARM界说了16种不同的域,可是Linux只运用其间的三种:D0 ~ D2 (arch/arm/include/asm/domain.h)

[c]#define DOMAIN_KERNEL   0#define DOMAIN_TABLE    0#define DOMAIN_USER     1#define DOMAIN_IO       2[/c] 

内存空间和三种域的对应联系如下:

内存空间
设备空间 DOMAIN_IO
内部高速SRAM空间/内部MINI Cache空间 DOMAIN_KERNEL
RAM内存空间/ROM内存空间 DOMAIN_KERNEL
高低端中断向量空间 DOMAIN_USER


ARM处理器为每一个域界说了四种不两只的拜访类型(0b00 ~ 0x11),Linux运用其间的三种(0b10不必),宏界说如下:
arch/arm/include/asm/domain.h

[c]#define DOMAIN_NOACCESS 0#define DOMAIN_CLIENT   1#define DOMAIN_MANAGER  3[/c] 

Linux在体系引导设置MMU时初始化c3寄存器来完成对内存域的拜访操控。其间对DOMAIN_USER,DOMAIN_KERNEL和DOMAIN_TABLE均设置DOMAIN_MANAGER权限;对DOMAIN_IO设置DOMAIN_CLIENT权限。
arch/arm/include/asm/domain.h

[c]#define domain_val(dom,type)    ((type) << (2*(dom)))arch/arm/kernel/head.S......mov     r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \domain_val(DOMAIN_IO, DOMAIN_CLIENT))mcr     p15, 0, r5, c3, c0, 0           @ load domain access registermcr     p15, 0, r4, c2, c0, 0           @ load page table pointerb       __turn_mmu_onENDPROC(__enable_mmu)[/c] 

在体系的引导进程中对这3个域的拜访操控位并不是原封不动的,它供给了一个名为modify_domain的宏来修正域拜访操控位。体系在setup_arch中调用early_trap_init后,DOMAIN_USER的权限位将被设置成DOMAIN_CLIENT。
arch/arm/include/asm/domain.h

[c]#define set_domain(x)                                   \do {                                            \__asm__ __volatile__(                           \"mcr    p15, 0, %0, c3, c0      @ set domain"   \: : "r" (x));                                 \isb();                                          \} while (0)#define modify_domain(dom,type)                                 \do {                                                    \struct thread_info *thread = current_thread_info();     \unsigned int domain = thread->cpu_domain;               \domain &= ~domain_val(dom, DOMAIN_MANAGER);             \thread->cpu_domain = domain | domain_val(dom, type);    \set_domain(thread->cpu_domain);                         \} while (0)[/c] 

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/dianyuan/277069.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部