This is just a place where I scribble my exciting experience of Linux kernel with naughty hardwares
Thursday, November 21, 2013
Wednesday, November 20, 2013
GNU assembler - Linker Scripts
GNU assembler - Linker Scripts,
http://www.bravegnu.org/gnu-eprog/index.html
Arm gcc inline cook book,
http://www.ethernut.de/en/documents/arm-inline-asm.html
http://www.bravegnu.org/gnu-eprog/index.html
Arm gcc inline cook book,
http://www.ethernut.de/en/documents/arm-inline-asm.html
Tuesday, November 19, 2013
Work queue: What will happen if same work is queued twice?
> Hi,
>
> I have a single work queue, on which I have scheduled a worker function [using queue_work(wq, fn)] in interrupt context.
>
> I get the interrupt twice before the work queue gets a chance to run, and hence the same function will get queued twice (with different private context - arguments etc) which is fine and expected.
You got it wrong here.>
> I have a single work queue, on which I have scheduled a worker function [using queue_work(wq, fn)] in interrupt context.
>
> I get the interrupt twice before the work queue gets a chance to run, and hence the same function will get queued twice (with different private context - arguments etc) which is fine and expected.
bool queue_work_on(int cpu, struct workqueue_struct *wq,
struct work_struct *work)
{
bool ret = false;
unsigned long flags;
local_irq_save(flags);
if (!test_and_set_bit(WORK_
__queue_work(cpu, wq, work);
ret = true;
}
local_irq_restore(flags);
return ret;
}
EXPORT_SYMBOL(queue_work_on);
If you look at function queue_work_on, the function returns
immediately if WORK_STRUCT_PENDING_BIT was already set.
So in effect your second call to queue_work will just return.
HTH
Thanks,
Arun
Friday, November 15, 2013
Ram Dump - Linux System
Ram Dump
=========
Used for forensic analysis of a crashed or freeze kernel/system.
As the name points, its the dumping of complete ram contents for further investigation.
Divided into three sections
===================
The whole design is divided into three sections based on how ramdump is entered, transferred and stored.
1) Support in kernel to enter into ramdump mode when kernel crashes or freezes.
2) Support in boot-loader to detect ramdump, wait for a host tool to initiate ramdump and send the data to host.
3) A host tool which can receive data from device and save it on host PC file system.
Boot-loader Support
===============
During booting, boot-loader has to decide whether it has to enter in to ramdump mode or to boot linux normally. This is done by monitoring a magic value in any predefined location(typically SRAM register or any other, value should persists across reboot or reset). There are two magic numbers for example 0x12345678(for crash scenario) and 0x87654321(for freeze scenario). If the SRAM register is having any of the two magic number, the booloader will enter into ramdump mode and wait for the host side application to initiate upload. And if SRAM is not having any of these magic numbers, the bootloader will proceed with normal booting.
Kernel Support
===============
Kernel has to handle panic or freeze scenario and manage the magic numbers to be written in SRAM register.
Ramdump driver init
-----------------------
Write magic number for freeze scenario(MAGIC_FREEZE) in SRAM register.
Register for reboot and panic kernel notifiers.
During a freeze
-----------------
Kernel cannot do much here as the kernel is freezed. User has to press Power ON key for 10 sec, on which device will reset by PMU. While booting back, boot-loader sees MAGIC_FREEZE in SRAM register(which was written during init) and enters to ramdump mode.
During a crash
------------------
Panic notifier registered from the ramdump driver will be called by kernel. Ramdump driver has to do few things.
a) Invoke cache sycn api to make sure all the content the ram is coherent.(flush_cache_all(), outer_flush_all())
b) save core registers to ram
c) save MMU registers
d) write MAGIC_CRASH to SRAM regiter.
Then do a reboot. Now boot-loader finds the MAGIC_CRASH in SRAM register and goes to ramdump mode.
During a normal reboot
-------------------------
Device should not enter in to ramdump mode now.
Reboot notifier registered from the ramdump driver will be called by kernel. Ramdump driver clears MAGIC_FREEZE( written during the init ) and returns.
Saving pt_reg is done in two places,
File: arch/arm/mm/fault.c call the ramdump driver with pt_reg as argument to save for crashed cpu.
File: arch/arm/kernel/smp.c call ramdump driver with pt_reg from IPI_CPU_STOP to save the context of other cpus.
HOST side tool
============
Host side tool receive the data and saves to file system. We exploited fastboot to upload the data.
Design considerations
================
After a crash, device reboots and bootloader will be loaded again to RAM, which corrupts some part of the ram. This is something which cannot be avoided, unless ram upload is implemented in kernel itself. Another approach is to load the bootloader to a location which is of not much importance. For example, load bootloader to framebuffer location or some memory used by video subsystem or some carveout memory in the system.
U-boot relocates itself to the end of the ram. This behavior causes harm to the contents of the memory. So this should be taken care off.
Analyzing ramdump
==============
Ramdump can be analysed using T32 simulator or use amazing crash utility.
You need the corresponding vmlinux.
=========
Used for forensic analysis of a crashed or freeze kernel/system.
As the name points, its the dumping of complete ram contents for further investigation.
Divided into three sections
===================
The whole design is divided into three sections based on how ramdump is entered, transferred and stored.
1) Support in kernel to enter into ramdump mode when kernel crashes or freezes.
2) Support in boot-loader to detect ramdump, wait for a host tool to initiate ramdump and send the data to host.
3) A host tool which can receive data from device and save it on host PC file system.
Boot-loader Support
===============
During booting, boot-loader has to decide whether it has to enter in to ramdump mode or to boot linux normally. This is done by monitoring a magic value in any predefined location(typically SRAM register or any other, value should persists across reboot or reset). There are two magic numbers for example 0x12345678(for crash scenario) and 0x87654321(for freeze scenario). If the SRAM register is having any of the two magic number, the booloader will enter into ramdump mode and wait for the host side application to initiate upload. And if SRAM is not having any of these magic numbers, the bootloader will proceed with normal booting.
Kernel Support
===============
Kernel has to handle panic or freeze scenario and manage the magic numbers to be written in SRAM register.
Ramdump driver init
-----------------------
Write magic number for freeze scenario(MAGIC_FREEZE) in SRAM register.
Register for reboot and panic kernel notifiers.
During a freeze
-----------------
Kernel cannot do much here as the kernel is freezed. User has to press Power ON key for 10 sec, on which device will reset by PMU. While booting back, boot-loader sees MAGIC_FREEZE in SRAM register(which was written during init) and enters to ramdump mode.
During a crash
------------------
Panic notifier registered from the ramdump driver will be called by kernel. Ramdump driver has to do few things.
a) Invoke cache sycn api to make sure all the content the ram is coherent.(flush_cache_all(), outer_flush_all())
b) save core registers to ram
c) save MMU registers
d) write MAGIC_CRASH to SRAM regiter.
Then do a reboot. Now boot-loader finds the MAGIC_CRASH in SRAM register and goes to ramdump mode.
During a normal reboot
-------------------------
Device should not enter in to ramdump mode now.
Reboot notifier registered from the ramdump driver will be called by kernel. Ramdump driver clears MAGIC_FREEZE( written during the init ) and returns.
Saving pt_reg is done in two places,
File: arch/arm/mm/fault.c call the ramdump driver with pt_reg as argument to save for crashed cpu.
File: arch/arm/kernel/smp.c call ramdump driver with pt_reg from IPI_CPU_STOP to save the context of other cpus.
HOST side tool
============
Host side tool receive the data and saves to file system. We exploited fastboot to upload the data.
Design considerations
================
After a crash, device reboots and bootloader will be loaded again to RAM, which corrupts some part of the ram. This is something which cannot be avoided, unless ram upload is implemented in kernel itself. Another approach is to load the bootloader to a location which is of not much importance. For example, load bootloader to framebuffer location or some memory used by video subsystem or some carveout memory in the system.
U-boot relocates itself to the end of the ram. This behavior causes harm to the contents of the memory. So this should be taken care off.
Analyzing ramdump
==============
Ramdump can be analysed using T32 simulator or use amazing crash utility.
You need the corresponding vmlinux.
Monday, October 28, 2013
Notes about Virtual memory and Highmem
On a 1:3 VM split, kernel has 1GB of virtual space. This 1GB kenel VM is split accross I/O mapped registers, Interrupt vector table, VMALLOC area and your system memory(ie RAM).
For example let's say,
I/O mapped register + VMALLOC area + vector table = 200MB.
So virtual space left for System memory(DDR) = 1024MB - 200MB = 824MB.
Now consider you have 1GB of System memory(RAM). How will you use it?
Two ways
1) You can change VM split(user space:kernel space) to 2:2, or
2) Use High Mem.
If using 2:2 VM split, then your kernel space is 2GB and you have plenty of space to map system memory.
If using High mem, you will have a temporary mapping for High mem area. Virtual address for this temporary mapping depends on usage. Most of the allocation are for user space. Then virtual address will be user space virtual address. Kernel uses kmap function to map high mem area. In that case virtual address will be used from vmalloc area.
High mem, in our case will be 200MB( 1024MB - 824 MB)
where as:
1024 MB is total ram size
824 MB is already mapped to kernel virtual space as low mem.
Permanent mapping also is available from high mem. But this VM space will be limited in size(eg 2MB). This is know as pkmappings.
In general,
Low mem is the ram area which have permanent kernel address mapping.
High mem is mapped depending on the requirement, dynamically.
For more information have a look at page 253 of Linux kernel developement 3rd edition- Robert Love.
All this complexity will go into vents when 64 bit architeure comes because,
2^64 = 16ExtraByte(EB)
You have 16EB of virtual space compared to 4GB of virtual space for 32 bit architecure.
When Virtual memory is enabled, every memory your cpu generates is a virtual address. Which has to be converted to physical memory by MMU. MMU uses page tables(setup by kernel) to accomplish this task.
So when ever a kernel thread runs, it uses the mm pointer of the previous task which was preempted.
All the process has its own page tables, in which the page table entries pointing to the last 1GB address space(which is for kernel space) is same for all process. So kernel thread uses previous process mm to access information relating to kernel space memory.
Wednesday, October 9, 2013
git merge
Here is the procedure while porting kernel from 3.4.5 to 3.10
kernel.
$cd
/projects/mobcom_andrwks_ext8/users/arunks/kernel-porting/aosp/
Clone the AOSP kernel,
Now move into 3.4.5 kernel,
$git
remote add porting-3.10
/projects/mobcom_andrwks_ext8/users/arunks/kernel-porting/aosp/common
$git
fetch porting-3.10
/*Set the renamelimit to make merge complete. Otherwise git merge will
stop rename resolution when default value of renamelimit is reached.*/
$git config merge.renameLimit 999999
/*Set the renamelimit to make merge complete. Otherwise git merge will
stop rename resolution when default value of renamelimit is reached.*/
$git config merge.renameLimit 999999
Create a local branch with name android-3.10 tracking
remotes/origin/experimental/android-3.10
$git
merge -s recursive android-3.10
Now resolve all merge conflicts and git add or rm according.
Then do a git commit.
Subscribe to:
Posts (Atom)