arm linux的ASID (Address Space ID) 2017-01-18
来自本人的旧博客 http://blog.163.com/awaken_ing/blog/static/1206131972015112011286335
平台:ARM Versatile Express for Cortex-A9 (ARMv7)
# CONFIGARMLPAE is not set, 也就是使用Short-descriptor格式, ASID存储在CONTEXTIDR的低8 bit:
31 7 0
+-------------------------+-----------+
| PROCID | ASID |
+-------------------------+-----------+
页表项中 nG == 1时, 这个页表项信息就是 non-global, 或者说 process-specific, 对应的TLB中就会有ASID信息, 执行虚拟地址到物理地址转换时, ASID也需要参与该过程.
用户地址空间的页表才会设置nG标志 (内核地址的一部分地址范围使用TLB lockdown比较合适): linux-3.10.86/arch/arm/include/asm/pgtable.h
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pteval)
{
...
if (addr < TASK_SIZE && pte_present_user(pteval)) {
...
ext |= PTE_EXT_NG;
}
...
set_pte_ext(ptep, pteval, ext);
}
set_pte_at -> set_pte_ext -> cpu_v7_set_pte_ext
从create_mapping()看arm linux的页表 2017-01-18
来自本人的旧博客 http://blog.163.com/awaken_ing/blog/static/120613197201571932454226
createmapping会调用到allocinitpte(), 进而调用setpte_ext()
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
这里qemu模拟的versatilepb ARM Versatile/PB (ARM926EJ-S) ARMv5TEJ
所以setpteext(pte, pfnpte(pfn, _pgprot(type->prot_pte)), 0);
就是
cpuarm926setpteext (pte, pfnpte(pfn, _pgprot(type->prot_pte)), 0);
/*
* cpu_arm926_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*/
.align 5
ENTRY(cpu_arm926_set_pte_ext)
#ifdef CONFIG_MMU
armv3_set_pte_ext
mov r0, r0
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif
mov pc, lr
arm linux中断处理过程中寄存器的保存 2017-01-18
来自本人的旧博客 http://blog.163.com/awaken_ing/blog/static/1206131972015839465987
模式 usr exception svc
-----|----|--------------------------------|---------------------------------------------------
函数 vector_\name: usr_entry:
对应的汇编语句:
+----------------+ 0 +------------------+ ------------------------
高地址 |spsr_<exception>| | r0 | str r1, [sp]
| | 4 +------------------+ ----------------------
^ +----------------+ | r1 |
| | | | |
| |lr_<exception> | | . |
| | | | . | stmib sp, {r1 - r12}
| +----------------+ | . |
| | | |
低地址 | r0 | | r12 |
| | | |
+----------------+ 52 +------------------+ ----------------------
struct stack | sp_usr |
| |
56 +------------------+ stmdb r0, {sp, lr}^
| lr_usr |
| |
60 +------------------+ ---------------------
| lr_<exception> |
| |
64 +------------------+
| spsr_<exception> | stmia r0, {r2 - r4}
| |
68 +------------------+
| -1 |
| |
72 +------------------+ -----------------------
struct pt_regs
arm linux的iounmap()如何处理主页表(master page table)的同步 2017-01-18
来自本人的旧博客: http://blog.163.com/awaken_ing/blog/static/120613197201510308269773
1. 背景
平台为qemu ARM Versatile/PB (ARM926EJ-S) ARMv5TEJ, UP
我们知道进程的内核地址空间的页表 和 swapperpgdir 进行同步, 在进程创建时, do_fork()会拷贝一级页表.
2. 问题
vmalloc() area发生异常, 由dotranslationfault()处理, 处理的是一级页表无效的情况, 处理方法: If the init_task's first level page tables contains the relevant entry, we copy the it to this task.
可以猜想, vmalloc区域的页表是 两级页表(低两位D1D0为0b01), 而不是section (D1D0为0b10)
打印vmalloc区域的对应的页表, 可以看到 D1D0 既有0b01(指向二级页表), 也有0b10(无需二级页表) 的.
从cat /proc/vmallocinfo可知, 可知0b10不是由vmalloc()引发的页表创建, 而是ioremap(). (这里并不是说ioremap创建的都是section)
虚拟地址0xc9000000开始对应的一级页表entry
关于arm linux的map_io 2017-01-18
文来自本人的旧博客 http://blog.163.com/awaken_ing/blog/static/1206131972016226674429
1. 主要流程
平台:versatilepb ARM Versatile/PB (ARM926EJ-S) 内核版本2.6.35.7
paging_init
|--devicemaps_init
| |--from VMALLOC_END, pmd_clear(pmd_off_k(addr))
| |--mdesc->map_io() => versatile_map_io
| | |--iotable_init
| | | |--create_mapping
2. 为何是 MT_DEVICE
linux-2.6.35.7/arch/arm/mach-versatile/core.c
void __init versatile_map_io(void)
{
iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));
}
static struct map_desc versatile_io_desc[] __initdata = {
{
...
.type = MT_DEVICE
},
...