qemu观察arm linux启动过程01 2017-01-18
文来自本人的旧博客 http://blog.163.com/awaken_ing/blog/static/12061319720157611510386
1. 方法
qemu-system-arm -M versatilepb -m 128M -kernel /opt/qemu_arm/linux-2.6.35.7/arch/arm/boot/compressed/vmlinux -S -s
需要留意, 这里-kernel的参数不是/opt/qemu_arm/linux-2.6.35.7/vmlinux
arm-none-linux-gnueabi-gdb -tui -q /opt/qemu_arm/linux-2.6.35.7/arch/arm/boot/compressed/vmlinux
Reading symbols from /opt/qemu_arm/linux-2.6.35.7/arch/arm/boot/compressed/vmlinux...done.
(gdb) target extended-remote localhost:1234
Remote debugging using localhost:1234
warning: Source file is more recent than executable.
start () at arch/arm/boot/compressed/head.S:115
(gdb) b __setup_mmu
Breakpoint 1 at 0x200: file arch/arm/boot/compressed/head.S, line 409.
(gdb) c
Continuing.
Breakpoint 1, __setup_mmu () at arch/arm/boot/compressed/head.S:409
(gdb) i r r3 r4
r3 0x4000 16384
r4 0x8000 32768
qemu观察arm linux启动过程02 2017-01-18
文来自本人的旧博客 http://blog.163.com/awaken_ing/blog/static/12061319720157119242210
1. _createpage_tables
pgtbl r4 @ page table address
其中pgtbl为宏
.macro pgtbl, rd
ldr \rd, =(KERNEL_RAM_PADDR - 0x4000)
.endm
这里KERNELRAMPADDR和zreladdr的值相等.
1.1 identity mapping
/*
* Create identity mapping for first MB of kernel to
* cater for the MMU enable. This identity mapping
* will be removed by paging_init(). We use our current program
* counter to determine corresponding section base address.
*/
mov r6, pc
mov r6, r6, lsr #20 @ start of kernel section
orr r3, r7, r6, lsl #20 @ flags + kernel base
str r3, [r4, r6, lsl #2] @ identity mapping
@ 和arch\arm\boot\compressed\head.S类似
@ r3内容:
@ 31 20 19 0
@ PC高12bit __cpu_mm_mmu_flags
@存放的地址:
@ 31 14 13 2 1 0
@ 页表基址(0x4000) 页表index(pc高12bit) 00
arm linux多核同时获取读写锁, 会死循环吗, 还是都得到写锁 2017-01-18
文来自本人的旧博客: http://blog.163.com/awaken_ing/blog/static/120613197201631133058159
本篇只提问, 不解答, 祝开心.
如果读写锁是unlocked, 然后cpu 0和cpu 1都想获取写锁, 如表格所示, CPU 0在t2时刻执行的是wfene, 这时, CPU 1执行的是ldrex, 然后是否会有cpu能够获取到锁? 源码来自 linux-3.10.86/arch/arm/include/asm/spinlock.h archwritelock()
时间 | CPU0 | 时间 | CPU1 |
---|---|---|---|
t0/t6 | 1: ldrex %0, [%1] | ||
t1/t7 | teq %0, #0 | ||
t2 | WFE("ne") | t2 | 1: ldrex %0, [%1] |
t3 | strexeq %0, %2, [%1] | t3 | teq %0, #0 |
t4 | teq %0, #0 | t4 | WFE("ne") |
t5 | bne 1b | t5 | strexeq %0, %2, [%1] |
t6 | t6 | teq %0, #0 | |
t7 | t7 | bne 1b |
中断, 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
SLUB 02:frozen 2017-01-14
本文假定没有打开CONFIGSLUBDEBUG, 没有配置CONFIG_NUMA.
1. 什么是frozen
linux-3.10.86/mm/slub.c
* If a slab is frozen then it is exempt(免除) from list management. It is not
* on any list. It is not on any list. The processor that froze the slab is the one who can
* perform list operations on the page. Other processors may put objects
* onto the freelist but the processor that froze the slab is the only
* one that can retrieve the objects from the page's freelist.
cpu01的c->page是frozen, 那么cpu01可以从该page中取出或放回obj, cpu02不能从该page中取obj, 只能把obj还给该page.
2. cpu partial上的page都是frozen状态
linux-3.10.86/include/linux/slub_def.h
struct kmem_cache_cpu {
...
struct page *partial; /* Partially allocated frozen slabs */
...
};