关于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
},
...
中断, softirq, tasklet的区别 2017-01-18
1. 中断流程
假定 CONFIGMULTIIRQHANDLER=y, handlearchirq 为 gichandle_irq.
linux-3.10.86/arch/arm/kernel/setup.c
__irq_svc @entry-armv.S
| |--svc_entry 保存spsr_<exception> 到r5
| |--irq_handler
| | |--handle_arch_irq => gic_handle_irq
| | | |--irq_find_mapping 完成 an hw irq number到a linux irq的转换
| | | |--handle_IRQ(irqnr, regs) if not IPI
| | | | |--generic_handle_irq -> generic_handle_irq_desc -> handle_fasteoi_irq
| | | | | |--raw_spin_lock(&desc->lock);
| | | | | |--handle_irq_event
| | | | | | |--raw_spin_unlock(&desc->lock);
| | | | | | |--handle_irq_event_percpu -> action->handler
| | | | | | |--raw_spin_lock(&desc->lock);
| | | | | |--chip->irq_eoi
| | | | | |--raw_spin_unlock(&desc->lock);
| | | | |--irq_exit(); 这里中断还是禁用的吗? 答:是的, ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
| | | | | |--WARN_ON_ONCE(!irqs_disabled());
| | | | | |--if( ... ) invoke_softirq()
| | | | | | |--do_softirq -> __do_softirq
| | | | | | | |--local_irq_enable //修改CPSR I bit, 打开中断
| | | | | | | |--h->action(h)
| | | | | | | |--local_irq_disable //这里为何又禁止中断???
| | | | |--set_irq_regs(old_regs) 这里开启中断? 答:不是.
| |--svc_exit r5, irq = 1 @entry-header.S
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中断处理过程中寄存器的保存 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
SLUB 04:tid 2017-01-14
1. tid
linux-3.10.86/include/linux/slub_def.h
struct kmem_cache_cpu {
...
unsigned long tid; /* Globally unique transaction id */
..
};
linux-3.10.86/mm/slub.c
#ifdef CONFIG_PREEMPT
/*
* Calculate the next globally unique transaction for disambiguiation
* during cmpxchg. The transactions start with the cpu number and are then
* incremented by CONFIG_NR_CPUS.
问题:一次不是加1, 而是加CONFIGNRCPUS, 为啥?
答:这个设计是为了让任何时刻每个cpu的tid值都不一样.
不过上面的注释有点老, 因为实际并不是加CONFIGNRCPUS, 而是TID_STEP.