ARM Linux (S3C6410架构…
来源:互联网 发布:家居设计软件有哪些 编辑:程序博客网 时间:2024/03/29 20:30
ARM Linux的访问权限控制
ARM1176JZF-S处理器为访问权限控制定义了两个层次:第一层是"域"(Domain)的访问类型,第二层是页或者段的"读写权限"(AccessPermission)。具体来说,过程是这样的:
1.
对于每一个域所对应的两个bit,访问类型设置方法如下:
[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定义了一个类型为structmem_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 3
arch/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]
内存空间和三种域的对应关系如下:
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 register
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
b __turn_mmu_on
ENDPROC(__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]
- ARM Linux (S3C6410架构…
- ARM Linux (S3C6410架构…
- ARM Linux (S3C6410架构…
- ARM Linux (S3C6410架构…
- ARM Linux 3.x的设备树…
- ARM Linux 3.x的设备树…
- arm-linux-ranlib:command no…
- arm-linux-g++; comman…
- Arm linux 启动流程
- Arm linux 启动流程
- arm-linux-gcc 4.3.3 Illegal inst…
- arm-linux-gcc 4.3.3 Illegal inst…
- s3c6410 PCB 布线建议(S3C64…
- ARM1176JZF-S/S3C6410 内存地…
- Linux Kernel SMP …
- Linux Kernel SMP …
- Linux Kernel SMP …
- Linux Kernel SMP …
- ARM1176JZF-S/S3C6410处理器的操作…
- ARM Linux系统中的用户栈与内核栈
- 数据摘要算法的测试效率(SHA、MD5和CRC32)
- POJ 2195 - Going Home 更新最小费用最大流模板..整合成结构体...
- ARM Linux (S3C6410架构…
- ARM Linux (S3C6410架构…
- jQuery一个元素绑定多个相同事件的解决
- ARM1176JZF-S/S3C6410处理器的异常…
- 简单工厂模式/Simple Factory
- 工厂方法模式/Factory Method
- 抽象工厂模式/Abstract Factory
- 单例模式/Singleton
- 建造模式/Builder
- 原型模式/Prototype