Wednesday, April 27, 2022

Learn CPP

 This post captures few good materials on cpp

1) This blog has been the best introduction to C++ for me.  I still go back and reference it all the time.  The author keeps the contents updated with recent versions of C++ which is great:

https://www.learncpp.com/

2) cppCon 2017 Bjarne Stroustrup "Learning and teaching modern c++"


3) CppCon started doing a lot of “Back to Basics” talks and I think it’s nice to check them from time to time even if you are an experienced programmer.

4) A Tour of C++ by Bjarne Stroustrup comes to mind. A fairly straightforward C++ intro. I liked it was short (256 pages) and written by the language main designer.

5) cppCon 2015 "Stop teaching c"



Sunday, May 9, 2021

Skeleton of a platform driver with fops

 
struct dummy_drvdata {
struct cdev dummy_cdev;
struct device *dev;
};

static size_t dummy_read(struct file *file, char _user *data, size_t len, lofft *ppos)
{
struct dummy_drvdata = file->private_data;
        .......
}

static int dummy_open(struct inode *inode, struct file *file)
{
struct dummy_drvdata *drvdata = container_of(inode->i_cdev, 
                                                                struct dummy_drvdata, dummy_cdev);
file->private_data = drvdata;
return 0;
}

struct file_operations dummy_fops = {
.open = dummy_open,
.read = dummy_read,
};

static int dummy_devices_register(struct dummy_drvdata *drvdata)
{
dev_id dev;

alloc_chrdev_region(&dev, 0, 1, "dummy-devices");
cdev_init(&drv_data->dummy_cdev, dummy_fops);
cdev_add(&drvdata->dummy_cdev, dev, 1);
}

static int dummy_probe(struct platform_device *pdev)
{
struct dummy_drvdata *drvdata = kmalloc();
drvdata->dev = &pdev->dev;

platform_set_drvdata(pdev, drvdata); //needed in dummy_remove function
dummy_devices_register(drvdata);
}

const struct of_device_id dummy_device_id = {
{.compactible = "qcom,dummy-driver"},
{}
}

static struct platform_driver dummy_platform_driver = {
.probe = dummy_probe,
.remove = dummy_remove,
.device_driver = {
.name = "dummy-driver",
.of_match_table = dummy_match_table,
},
};
static int my_module_init(void)
{
platform_driver_register(
}
module_init(dummy_module_init);
module_exit(dummy_module_exit);

Wednesday, April 14, 2021

DS & Algos


Cheat Sheet for cpp and more: https://hackingcpp.com/cpp/cheat_sheets.html

https://github.com/orrsella/soft-eng-interview-prep

DP:

https://leetcode.com/discuss/general-discussion/475924/my-experience-and-notes-for-learning-dp

Quick Recap:

https://leetcode.com/discuss/career/217868/My-notes-for-the-night-before-interview.

Comprehensive Guide:

Comprehensive-data-structure-and-algorithm-study-guide

  Grouping similar questions - but algorithm or data structure used by the solution might vary.


Group 1

https://www.techiedelight.com/find-elements-array-greater-than-elements-right/

https://www.techiedelight.com/replace-every-element-array-least-greater-element-right/

https://www.geeksforgeeks.org/count-of-larger-elements-on-right-side-of-each-element-in-an-array/

https://www.geeksforgeeks.org/count-smaller-elements-on-right-side/

https://www.techiedelight.com/previous-smaller-element/

https://www.techiedelight.com/next-greater-element-circular-array/

https://www.techiedelight.com/inversion-count-array/


Sorting Logic application

https://www.techiedelight.com/problems-solved-using-partitioning-logic-quicksort/

https://www.techiedelight.com/segregate-positive-negative-integers-using-mergesort/


Dynamic Programing

https://www.techiedelight.com/4-sum-problem/


Trees

https://leetcode.com/problems/binary-tree-maximum-path-sum

https://leetcode.com/problems/path-sum-iv/solution/

Kth Frequent elements.

Kth frequent elements in a stream.

LRU cache Implementation

All of the above can be done in O(1) time


String

https://www.techiedelight.com/check-given-string-rotated-palindrome-not/

https://www.techiedelight.com/longest-palindromic-substring-non-dp-space-optimized-solution/


Custom Sort:

https://www.programmersought.com/article/82237172611/


Thursday, January 10, 2019

Using QEMU to run Linux kernel

We can use qemu to run linux kernel. I ll describe two cases one for arm and other for x86

If you want to use the latest qemu, clone and compile as follows,

To clone and compile qemu for arm64:

$ git clone git://git.qemu.org/qemu.git
$ cd qemu
$ sudo apt-get install libpixman-1-dev
$ ./configure --target-list=aarch64-softmmu
$ make -j4


Second step is to get a initrd. You can create one using the below steps,

## Build Busybox

To make Linux useful, it needs a shell. These following instructions will
construct a file system for the Linux RAM disk with the BusyBox shell as the
init process.


Install prerequisites:

$ sudo apt install make binutils-aarch64-linux-gnu


$ git clone git://busybox.net/busybox.git
$ cd busybox
$ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make defconfig
$ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make menuconfig

At this point you should ensure that the option `Settings > Build static binary
(no shared libs)` is selected. Then you can proceed with the following commands:

ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j24
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make install
cd _install
mkdir proc
mkdir sys
mkdir -p etc/init.d
cat < etc/init.d/rcS
#!bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
EOF
chmod u+x etc/init.d/rcS
grep -v tty ../examples/inittab > ./etc/inittab


## Create a RAM disk for Linux

find . | cpio -o -H newc | gzip > ../initrd.img

To run qemu for arm64:

qemu/aarch64-softmmu/qemu-system-aarch64 -M virt -m 1G -cpu cortex-a57 -nographic -kernel arch/arm64/boot/Image -initrd initrd.img -append "rdinit=/sbin/init

To run qemu for x86_64:
qemu-system-x86_64 -m 1G -nographic -kernel arch/x86/boot/bzImage -initrd initrd.img -append "console=ttyS0 rdinit=/sbin/init"


Friday, May 12, 2017

Lets try recovering a file from rm *

By mistake I deleted a source code which I spend around a day to develop. With the help of extundelete utility it is possible to recover file if same space is not reallocated by file system.

Here is what I did to recover my deleted file info_bootimg.c

sudo src/extundelete --restore-file  workspace/utils/helper_utills/bootinfo/info_bootimg.c  /dev/mapper/vg00-lv_local_mnt

"workspace/utils/helper_utills/bootinfo/" is the path relative to the root of partition

This is where the partition is mounted,

/dev/mapper/vg00-lv_local_mnt on /local/mnt type ext4 (rw)

File's absolute path is "/local/mnt/workspace/utils/helper_utills/bootinfo/info_bootimg.c"

But you have to strip "/local/mnt" to get it working.

Download extundelete from,
http://extundelete.sourceforge.net/

./configure and make

Tuesday, January 3, 2017

Debugging using T32 on a Multi cores/cpus

Contemporary processors are multi core/cpus. This has made life of a developer bit tougher. For eg, for the break point to hit, you need to set it on all the cpus, because you never know where the code is going to run. Another instance is to stop all the core at the same time.

Below is a set of scritps which helps you to make your job easier.

For eg we will consider working on a 4 core processor.

You need to create few cmm files. Contents and file names as shown below,

1) main.cmm
=========
GLOBAL &ScriptPath &vmlinuxPath

&ScriptPath="Z:\deleteme\T32"
&vmlinuxPath="Z:\kdevs\3.18\kdev\kobj"

globalon cmd i do &ScriptPath\initcore_all.cmm
globalon cmd pos do &ScriptPath\pos.cmm
globalon cmd load do &ScriptPath\load_all.cmm
globalon cmd ball do &ScriptPath\break_all.cmm


==========

2) initcore_all.cmm
============
intercom.execute localhost:15370 do &ScriptPath\initcore.cmm
intercom.execute localhost:15371 do &ScriptPath\initcore.cmm
intercom.execute localhost:15372 do &ScriptPath\initcore.cmm
intercom.execute localhost:15373 do &ScriptPath\initcore.cmm
============

3) initcore.cmm
==========
sys.m.a
snoop.pc ON
b.d
b.s die  /Onchip
b.s panic  /Onchip
===========

4) loadall.cmm
=========
intercom.execute localhost:15370 do &ScriptPath\load.cmm &vmlinuxPath
intercom.execute localhost:15371 do &ScriptPath\load.cmm &vmlinuxPath
intercom.execute localhost:15372 do &ScriptPath\load.cmm &vmlinuxPath
intercom.execute localhost:15373 do &ScriptPath\load.cmm &vmlinuxPath
==========

5) load.cmm
========
ENTRY &vmlinuxPath
d.load.elf &vmlinuxPath\vmlinux /NOCODE
========

6) pos.cmm
=======
intercom.execute localhost:15370 framepos 0 0 65 13
intercom.execute localhost:15371 framepos 75 0 65 13
intercom.execute localhost:15372 framepos 0 25 65 13
intercom.execute localhost:15373 framepos 75 25 65 13
========

7) break_all.cmm
===========
intercom.execute localhost:15370 break
intercom.execute localhost:15371 break
intercom.execute localhost:15372 break
intercom.execute localhost:15373 break
===========

Open four instances of T32. run main.cmm on T32 associated with core 0.

then type the i in the command line to run intercore_all.cmm




Using GDB to find structure info

As usual  load elf file

$gdb vmlinux

We are going to inspect the address layout of structure platform_device,

struct platform_device {
        const char      *name;
        int             id;
        bool            id_auto;
        struct device   dev;
        u32             num_resources;
        struct resource *resource;

        const struct platform_device_id *id_entry;
        char *driver_override; /* Driver name to force a match */

        /* MFD cell pointer */
        struct mfd_cell *mfd_cell;

        /* arch specific additions */
        struct pdev_archdata    archdata;
};


(gdb) p &((struct platform_device *)0)->name
$2 = (const char **) 0x0
(gdb) p &((struct platform_device *)0)->id
$3 = (int *) 0x8
(gdb) p &((struct platform_device *)0)->id_auto
$4 = (bool *) 0xc
(gdb) p &((struct platform_device *)0)->dev
$5 = (struct device *) 0x10

Above output shows the offset of different variables in the structure.


Tuesday, July 26, 2016

Enabling core dump on Ubuntu

type command,

ulimit -c unlimited

Still not present, monitor the logs here,
/var/log/apport.log

Thursday, December 3, 2015

crosscompiling and gdb

As an example I m trying to see how division is implemented on arm and arm64.

created a test.c

int main(void)
{
        int a = 10;
        int b = 20;
        return (a/b);
}

Make sure to comple with -o option always because a.out doesn't has symbols

To compile for arm64
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-gccc -o test64 test.c --sysroot=/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/ndk/9/platforms/android-17/arch-arm64/usr/

(gdb) disassemble main
Dump of assembler code for function main:
   0x00000000004005a8 <+0>:     sub     sp, sp, #0x10
   0x00000000004005ac <+4>:     mov     w0, #0xa                        // #10
   0x00000000004005b0 <+8>:     str     w0, [sp,#12]
   0x00000000004005b4 <+12>:    mov     w0, #0x14                       // #20
   0x00000000004005b8 <+16>:    str     w0, [sp,#8]
   0x00000000004005bc <+20>:    ldr     w1, [sp,#12]
   0x00000000004005c0 <+24>:    ldr     w0, [sp,#8]
   0x00000000004005c4 <+28>:    sdiv    w0, w1, w0
   0x00000000004005c8 <+32>:    add     sp, sp, #0x10
   0x00000000004005cc <+36>:    ret
End of assembler dump.


start gdb
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc -o test test.c --sysroot=/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/ndk/9/platforms/android-17/arch-arm/usr/

To compile for arm
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb test

start gdb
/usr2/arunks/workspace/LA.BR.1.3.1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb test

Dump of assembler code for function main:
   0x00008460 <+0>:     push    {r11, lr}
   0x00008464 <+4>:     add     r11, sp, #4
   0x00008468 <+8>:     sub     sp, sp, #8
   0x0000846c <+12>:    mov     r3, #10
   0x00008470 <+16>:    str     r3, [r11, #-8]
   0x00008474 <+20>:    mov     r3, #20
   0x00008478 <+24>:    str     r3, [r11, #-12]
   0x0000847c <+28>:    ldr     r0, [r11, #-8]
   0x00008480 <+32>:    ldr     r1, [r11, #-12]
   0x00008484 <+36>:    bl      0x8498 <__divsi3>
   0x00008488 <+40>:    mov     r3, r0
   0x0000848c <+44>:    mov     r0, r3
   0x00008490 <+48>:    sub     sp, r11, #4
   0x00008494 <+52>:    pop     {r11, pc}
End of assembler dump.

So arm32 implements division in software whereas arm64 has a dedicated instruction to do this.

Tuesday, April 29, 2014

Interpreting values in stack using crash utility

This post shows how to figure out the values in stack using crash utility.

Let me explain a scenario:
Speculation: Process named Binder_5 is in the runqueue holding cgroup_mutex and looping there infinitely.

Below is the do while code which I m suspecting,
File: kerne/cgroups.c
Function: cgroup_attach_task
kernel version:3.10.17

                                                                    Figure 1:

Backtrace of Binder_5 task is as follows,

                                                                      Figure 2:

So from the do while, task_cgroup_from_root is called and this process(binder_5) was preempted out. It was because of some other high priority task might have come.

To confirm that we are in this loop for ever, we need to check the if condition(marked in red box in figure 1). Lets take the objdump of vmlinux and see how to figure out the value of ent.cgrp and cgrp. Both will be stored in stack.

Figure 3 show the partial objdump of function cgroup_attach_task(corresponding c function is shown in figure 1). It is taken using the following command.
$ arm-none-linux-gnueabi-objdump -D vmlinux > vmlinux_objdump.txt

                                                                      Figure 3:

Now we need to find the value of r5 and r0. And if they are same, then my speculation of infinite loop is correct. Tough job ahead :-). Lets have fun.

Finding the value of r5:
If we are lucky the value of r5 will be pushed in to stack during entry of function task_cgroup_from_root.
Here is the objdump:

                                                                     Figure 4:

Yes it is pushed to the stack.
Now figure 5 explains below how to find out the value of r5.
The left part of the figure 5 is created by printing the frame of task binder_5 using crash tool.
The command used,
crash> bt -f 2077
whree 2077 is the pid of process binder_5

                                                                                     Figure :5

push    {r4, r5, fp, ip, lr, pc}

In above instruction, pc will be stored at highest address in stack, followed by lr. And so on.
This is because arm linux stack type is full descending.

So value of r5 = 0xed306c00.

Finding the value of r0:
Now from figure 3, r0 is also stored at fp - 84 th location(marked in red box). so if we look at that location we could get what was the value of r0 when task_cgroup_from_root returned last time.

So for this, we need to find the value of fp first. This will be stored in the frame of task_cgroup_from_root. Same way as our r5 was stored.

Below figure shows how we found the value of fp.
The left side of figure 6 show the backtrace with frames same as figure 5. This time I used the notepad++.


                                                                                     Figure :6

So value of r0 and r5 are same and the speculation of of infinite loop is proved.
This was a bug in the kernel 3.10 and is fixed later. commit

Thanks,
Arun

Friday, March 28, 2014

RB Tree parsing in crash utility

Requirement: see all the virual address allocated to a process.

This is just for the demo purpose of tree command. If you want to do this you can do using command
crash>vm -p

from the ps output,

we pick the process ".android.chrome" whose task_struct address is 0xe22f6200

crash> struct task_struct 0xe22f6200
----strip-------
 mm = 0xedab1500,
----strip-------

we got the value of mm.

 crash> struct mm_struct 0xe22f6200
 struct mm_struct {          
  mmap = 0x1,                
  mm_rb = {                  
    rb_node = 0xc2b00000    
  },                        
  mmap_cache = 0x2,          

Now to list all vm_area(vm_start and vm_end)
crash> tree -t rbtree -r mm_struct.mm_rb 0xedab1500 -o 16 -s vm_area_struct.vm_start,vm_end

the value passed to -o is calulate as follows,
 crash> struct vm_area_struct.vm_rb  
struct vm_area_struct {              
  [16] struct rb_node vm_rb;        
}  

Monday, March 17, 2014

Crash Utility: How to view user space back trace


Step 1) Download gcore extension from,

Step 2) To build the module from the top-level crash- directory, enter:
  $ tar xzf crash-gcore-command-1.2.2.tar.gz
  $ mv crash-gcore-command-1.2.2/* extensions
  $ make extensions

Step 3) Extend gcore command as follows from crash command prompt,
crash> extend /projects/mobcom_andrwks_ext8/users/arunks/crashutility/src/crash_utility/extensions/gcore.so

Step 4) Use gcore command to dump the user core dump file
            $gcore 1291
            Where 1291 is the pid of the process. This creates a file core.1291.init

Step 5) Use gdb to view the back trace. Pass elf and the core dump file to gdb as follows
            $ arm-none-linux-gnueabi-gdb /projects/mobcom_andrwks_ext8/users/arunks/bringup_eos2b/android/out/target/product/amethyst/obj/EXECUTABLES/init_intermediates/LINKED/init core.1291.init

Step 6) view back trace by bt command.
(gdb) bt
#0  umount2 () at bionic/libc/arch-arm/syscalls/umount2.S:10
#1  0x0000e0a0 in check_fs (blk_device=0x648b0 "/dev/block/platform/e6bd0000.mmcif/by-name/MODEMLOG", fs_type=0x64900 "ext4", target=0x648e8 "/mnt/modemlog") at system/core/fs_mgr/fs_mgr.c:512
#2  0x0000e7ea in fs_mgr_mount_all (fstab=0x645c0) at system/core/fs_mgr/fs_mgr.c:512
#3  0x0000873a in do_mount_all (nargs=Unhandled dwarf expression opcode 0xf3
) at bionic/libc/include/string.h:217
#4  0x0000992a in execute_one_command () at system/core/init/init.c:939
#5  0x00009e56 in main (argc=Unhandled dwarf expression opcode 0xf3
) at system/core/init/init.c:939

(gdb)

Friday, March 14, 2014

Setting up Tmux


For anyone else who wants to install tmux to their home folder (as non root) here is what you need to do.

1) Download libevent and ncurses.
2) Compile them to $HOME/local (ie ./configure --prefix=$HOME/local, then make install)
3) Install tmux by the following:

cd tmux
./configure
CPPFLAGS="-I$HOME/local/include" LDFLAGS="-static -L$HOME/local/include -L$HOME/local/include/ncurses -L$HOME/local/lib" make
make install

4)./tmux

My .tmux.conf file can be found here,
https://github.com/getarunks/linux_config/blob/master/.tmux.conf


Wednesday, March 12, 2014

Bug in Undefined Instruction Handler ARM

Problem Statement:

Multimedia team reported random user space crash.
The issue was tough to reproduce. If you run monkey test on, say 7 devices for around 5-10 hours.
They also indicated about a pattern, that SP is shifted by 8bytes in tombstone.

Most of the time crash was reproduced while returning from a bionic libc function strtoimax().
When objdump of strotimax was investigated, found few instruction which may cause corruption.
Out of them the most important one was vpush {d8} and vpop {d8}. This is basically a floating point instruction.

To confirm that vpush and vpop is causing the issue, added a new function called strtoimax_debug in bionic libc. This was a dummy function which does noting, but check for any stack corruption. We added those suspected instruction here,
Like stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}, vpush and vpos
and check for the expected SP, if not generate an intentional data abort doing an ldr r0 [0]

From the result of this experiment, confirmed that the issue is with vpop instruction.

Now did bit study on how vfp instruction are executed. By default vfp engine is turned off druing a context switch. When a process executes floating point instruction, a undefined exception will be generated.
exception handler enables the vfp engine and jump back to the same instruction which caused the exception.
code looks okey in that perspective.

Tracing __und_usr(arch/arm/kernel/entry-armv.S) revealed that control came out of exception handler without performing do_vfp which is necessary to handle any vfp instruction when the engine is off.
This gave an indication that there can be only one possibility(for deviating the path) and that is an exception has triggered while executing the path.

Looking at the code further, saw that und_user is reading the instruction which cause the undefined exception. And comment says that this can cause a fault. Now the question is why it can falut?. Onepossible option is the code page might have reclaimed by other core. A fixup handler is register in the exception table. This is not the normal exception table. Here what I m talking is about kernel's fixup exception table.
But the fixup handler was not proper. It was calling ret_from_execption which retrun back to the next instruction. The problem is present in latest kernel aswell, but this problem is very rarely hit.

Now the fix is to return to the same instruction which cause fault instead of next instruction.

Some Notes:

The NEON/VFP register file is managed using lazy preserve (on UP systems) and
lazy restore (on both SMP and UP systems). This means that the register file is
kept 'live', and is only preserved and restored when multiple tasks are
contending for the NEON/VFP unit (or, in the SMP case, when a task migrates to
another core). Lazy restore is implemented by disabling the NEON/VFP unit after
every context switch, resulting in a trap when subsequently a NEON/VFP
instruction is issued, allowing the kernel to step in and perform the restore if
necessary.

Difference btw Neon and VFP
Neon donot support double precision
no complex operations like square root and divide.

Managed to push this fix upstream, [Link to kenrel.org]

Friday, February 21, 2014

Editing a Ramdisk


cp ramdisk.img ramdisk.cpio.gz
gzip -d ramdisk.cpio.gz
mkdir ramdisk
cd ramdisk
cp -Rfp ../ramdisk.cpio .
cpio -i -F ramdisk.cpio
rm ramdisk.cpio
ls should show all the files in ramdisk. From here on add files as you like in ramdisk
find . | cpio -o -H newc | gzip > ../ramdisk.img

If you want uncompressed ramdisk, remove gzip from last step,ie 
find . | cpio -o -H newc > ../ramdisk.img

Wednesday, February 19, 2014

Stack in ARM

Different types of Stack:

Descending and Ascending: The stack grows downwards, starting with higher address and progressing to lower one(a descending stack). or upwards, starting with lower address and progressing to higher one(a ascending stack).

Empty or Full Stack:
The stack pointer can either point to the last item in the stack(a full stack), or the next free space on the stack(an empty stack).



To make it easier for the programmer, stack-oriented suffixes can be used instead of the
increment or decrement, and before or after suffixes


For example:
STMFD sp!, {r0-r5} ; Push onto a Full Descending Stack
LDMFD sp!, {r0-r5} ; Pop from a Full Descending Stack

! signifies, final address is written back to sp.

The Procedure Call Standard for the ARM Architecture (AAPCS), and ARM and Thumb C and C++ compilers always use a full descending stack. The PUSH and POP instructions assume a full descending stack.


Friday, February 7, 2014

ARM Linux do not use TTBR1

Russell King - ARM Linux linux@arm.linux.org.uk via vger.kernel.org 

6/26/13
to WillYalinlinux-archlinux-kernellinux-arm-kern.
As I don't have the original mail (because it wasn't copied to the right
list) I can't reply to the original author, so I'll do it like this
instead.

On Wed, Jun 26, 2013 at 06:16:49PM +0100, Will Deacon wrote:
> [adding the ARM list -- please try and remember to do that in future]
>
> On Wed, Jun 26, 2013 at 03:41:40AM +0100, Wang, Yalin wrote:
> > Hi  Will,
>
> Hello,
>
> > I have a question about  arm pagetable setting in Linux .
> >
> > From armV6,  there is TTBR0 and TTBR1  translation base address registers  in mmu .
> > But I  found linux only use TTBR0 for translation base address ,
> > Could we use TTBR0 and TTBR1 to split user task and kernel pagetables (swapper_pg_dir)?
We don't use TTBR1 because the configurable page table splits between
TTBR0 and TTBR1 are not appropriate for Linux kernels.  The common
configuration is to have 3GB of userspace and 1GB of kernel space.

However, the TTBR splits supported are 2GB, 1GB, 512MB etc.  As I had
prior knowledge of ARMv6 before it was released, I raised this point
with ARM Ltd because I knew that it would not be appropriate for Linux.
Unfortunately, the response was basically that they didn't want to know.
So, as the hardware provided support mismatches what we want, we don't
use the feature.

It's as simple as that; had we been listened to and the architecture
altered to do what we required, then we'd be using it...

> > 1. Because we don’t need copy kernel first –level pagetables into every
> > User task’s pagetables and flush tlb (for example fork() a new process).
>
> Well, you still need the TLB maintenance for setting up CoW, so this win is
> probably not very big.
>
> > 2. And don’t need handle kernel page fault because that user task’s kernel
> > Pagetable when it is not set up , need copy again( for example vmalloc()  ioremap()  kmap()  will change
> > Kernel pagetables and need update to every task pagetables ) .
>
> Is that really a fastpath?
No it isn't, because for all of the above cases we're talking about copying
L1 page table entries, not the individual L2 page table entries between
threads.

Every page table above TASK_SIZE gets shared between processes, and once
it's been shared to a process, any new process forked from that gets its
own pointer to that 2nd level page table immediately.

So, during the initial boot there will be a number of the L1 copies, but
the system will stabilize and there will be no further L1 faulted copies
needed.

Wednesday, January 8, 2014

Link List - C implementation

#include
#include

struct node {
  int value;
struct node *next;
};

void add_to_tail(struct node **head, int value)
{
  struct node *temp, *i;

  temp = malloc(sizeof(struct node));
  temp->value = value;
  temp->next = NULL;

    /* list empty */
  if (*head == NULL) {
*head = temp;
return;
}

/* find the tail node */
for( i = *head ; i->next != NULL ; i = i->next);

i->next = temp;
}

void print_list(struct node *head)
{
  struct node *i = head;

  while (i != NULL) {
printf("%d\n", i->value);
i = i->next;
}
}

void reverse_list(struct node **head)
{
struct node *prev, *curr, *next;

prev = NULL;
curr = *head;

while (curr != NULL) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}

*head = prev;
}

int main(void)
{
struct node *head = NULL;

add_to_tail(&head, 1);
add_to_tail(&head, 2);
add_to_tail(&head, 3);
add_to_tail(&head, 4);

print_list(head);

reverse_list(&head);

print_list(head);
}

Wednesday, December 11, 2013

using printascii and printhex8 for debugging during very early init

Situation:
Porting one of brcm board to kernel 3.13-rc3

Problem:
kernel was hanging at one do_one_initcall
To figure out which init call, put prints in do_one_initcal function

diff --git a/init/main.c b/init/main.c
index febc511..dd9f5c1 100644
--- a/init/main.c
+++ b/init/main.c
@@ -88,6 +88,8 @@
 #include
 #endif

+extern void printascii(const char *);
+extern void printhex8(unsigned int);
 static int kernel_init(void *);
@@ -693,6 +701,9 @@ int __init_or_module do_one_initcall(initcall_t fn)
        int ret;
        char msgbuf[64];

+       printascii("func:");
+       printhex8(fn);
+       printascii("\n");
        if (initcall_debug)

Output:
func:c0415524

System.map shows
c0415524 t customize_machine

arch/arm/kernel/setup.c:782:arch_initcall(customize_machine);
Function was calling machine_init.

Fixed in machine_init. It was an smc call to init L2 cache controller.