Wednesday, April 13, 2016

Linux kernel stacks. Page fault processing.

A call to filemap_fault to process a page fault in user space. The function is registered as

const struct vm_operations_struct generic_file_vm_ops = {
.fault = filemap_fault,
.page_mkwrite = filemap_page_mkwrite,
.remap_pages = generic_file_remap_pages,
};

The related kernel source is Quark X1000 Linux kernel 



#0  filemap_fault (vma=0xcc4dfb40, vmf=0xc006fe88) at mm/filemap.c:1591
#1  __do_fault (mm=mm@entry=0xcc4a0820, vma=vma@entry=0xcc4dfb40, address=address@entry=134768518, pmd=pmd@entry=0xcc4c6200, pgoff=63, flags=flags@entry=40, orig_pte=...) at mm/memory.c:3250
#2  do_linear_fault (page_table=0xcc4d2430, orig_pte=..., flags=40, pmd=0xcc4c6200, address=134768518, vma=0xcc4dfb40, mm=0xcc4a0820) at mm/memory.c:3404
#3  handle_pte_fault (mm=mm@entry=0xcc4a0820, vma=vma@entry=0xcc4dfb40, address=address@entry=134768518, pte=0xcc4d2430, pmd=pmd@entry=0xcc4c6200, flags=flags@entry=40) at mm/memory.c:3628
#4  handle_mm_fault (mm=mm@entry=0xcc4a0820, vma=vma@entry=0xcc4dfb40, address=address@entry=134768518, flags=flags@entry=40) at mm/memory.c:3768
#5  __do_page_fault (regs=0xc006ffb4, error_code=4294901780) at arch/x86/mm/fault.c:1192
#6  do_page_fault (regs=<optimised out>, error_code=<optimised out>) at arch/x86/mm/fault.c:1232
#7  <signal handler called>

Linux kernel stacks. Executable file mapping.

A call to generic_file_mmap registered as mmap file operation for ext3, i.e. the mmap member of file_operations structure and called by file->f_op->mmap . The related kernel source is Quark X1000 Linux kernel .



#0  generic_file_mmap (file=0xcea60300, vma=0xcc4df0c0) at mm/filemap.c:1746
#1  mmap_region (file=file@entry=0xcea60300, addr=1339731968, len=len@entry=8192, flags=flags@entry=2066, vm_flags=1050739, vm_flags@entry=2163, pgoff=pgoff@entry=32) at mm/mmap.c:1483
#2  do_mmap_pgoff (file=file@entry=0xcea60300, addr=<optimised out>, addr@entry=1339731968, len=len@entry=8192, prot=prot@entry=3, flags=flags@entry=2066, pgoff=pgoff@entry=32) at mm/mmap.c:1282
#3  vm_mmap_pgoff (file=file@entry=0xcea60300, addr=addr@entry=1339731968, len=len@entry=8192, prot=prot@entry=3, flag=flag@entry=2066, pgoff=pgoff@entry=32) at mm/util.c:362
#4  vm_mmap (file=file@entry=0xcea60300, addr=addr@entry=1339731968, len=len@entry=8192, prot=3, flag=2066, offset=offset@entry=131072) at mm/util.c:377
#5  elf_map (total_size=0, type=<optimised out>, prot=<optimised out>, eppnt=0xcebba1a0, addr=1339731968, filep=0xcea60300) at fs/binfmt_elf.c:353
#6  load_elf_interp (no_base=0, interp_map_addr=<synthetic pointer>, interpreter=0xcea60300, interp_elf_ex=0xcea604b4) at fs/binfmt_elf.c:457
#7  load_elf_binary (bprm=bprm@entry=0xce165500) at fs/binfmt_elf.c:894
#8  search_binary_handler (bprm=bprm@entry=0xce165500) at fs/exec.c:1401
#9  do_execve_common (filename=<optimised out>, argv=..., argv@entry=..., envp=..., envp@entry=...) at fs/exec.c:1539
#10 do_execve (__envp=0x9d7c608, __argv=0x9d81668, filename=<optimised out>) at fs/exec.c:1585
#11 sys_execve (filename=0x9d816c8 "\320\061\025\001", argv=0x9d81668, envp=0x9d7c608) at fs/exec.c:1681
#12 <signal handler called>

Linux kernel stacks. Lookup operation.

Some stacks for ext3 lookup operation. The related kernel source is Quark X1000 Linux kernel

Stack 1:


#0  ext3_lookup (dir=0xcd5df248, dentry=0xcb81df80, flags=1) at fs/ext3/namei.c:1019
#1  lookup_real (dir=dir@entry=0xcd5df248, dentry=0xcb81df80, flags=flags@entry=1) at fs/namei.c:1317
#2  __lookup_hash (name=name@entry=0xcc4e3ebc, base=base@entry=0xcd5dd400, flags=1) at fs/namei.c:1335
#3  lookup_slow (nd=nd@entry=0xcc4e3eb4, name=name@entry=0xcc4e3ebc, path=path@entry=0xcc4e3e74) at fs/namei.c:1447
#4  walk_component (follow=1, type=0, name=0xcc4e3ebc, path=0xcc4e3e74, nd=0xcc4e3eb4) at fs/namei.c:1536
#5  lookup_last (path=0xcc4e3e74, nd=0xcc4e3eb4) at fs/namei.c:1933
#6  path_lookupat (dfd=dfd@entry=-100, name=<optimised out>, flags=flags@entry=65, nd=nd@entry=0xcc4e3eb4) at fs/namei.c:1968
#7  filename_lookup (dfd=dfd@entry=-100, flags=flags@entry=1, nd=nd@entry=0xcc4e3eb4, name=0xcc4c6000) at fs/namei.c:2007
#8  user_path_at_empty (dfd=dfd@entry=-100, name=name@entry=0x9751188 "/work", flags=flags@entry=1, path=path@entry=0xcc4e3f40, empty=empty@entry=0x0) at fs/namei.c:2155
#9  user_path_at (dfd=dfd@entry=-100, name=name@entry=0x9751188 "/work", flags=flags@entry=1, path=path@entry=0xcc4e3f40) at fs/namei.c:2166
#10 vfs_fstatat (dfd=dfd@entry=-100, filename=filename@entry=0x9751188 "/work", stat=stat@entry=0xcc4e3f60, flag=flag@entry=0) at fs/stat.c:88
#11 vfs_stat (stat=0xcc4e3f60, name=0x9751188 "/work") at fs/stat.c:384
#12 sys_stat64 (filename=0x9751188 "/work", statbuf=0xbf9b40f0) at fs/stat.c:386
#13 <signal handler called>

Stack 2:



#0  ext3_lookup (dir=0xcd61ee50, dentry=0xcb83d380, flags=257) at fs/ext3/namei.c:1019
#1  lookup_real (dir=dir@entry=0xcd61ee50, dentry=dentry@entry=0xcb83d380, flags=<optimised out>) at fs/namei.c:1317
#2  lookup_open (opened=0xcc4c9eac, got_write=false, op=0xc135aa6c <open_exec_flags>, file=0xce26f500, path=0xcc4c9eb0, nd=0xcc4c9edc) at fs/namei.c:2641
#3  do_last (nd=nd@entry=0xcc4c9edc, path=path@entry=0xcc4c9eb0, file=file@entry=0xce26f500, op=op@entry=0xc135aa6c <open_exec_flags>, 
    opened=opened@entry=0xcc4c9eac, name=0xcc4c9f50) at fs/namei.c:2771
#4  path_openat (dfd=dfd@entry=-100, nd=nd@entry=0xcc4c9edc, op=0xc135aa6c <open_exec_flags>, flags=flags@entry=65, pathname=0xcc4c9f50) at fs/namei.c:2956
#5  do_filp_open (dfd=dfd@entry=-100, pathname=pathname@entry=0xcc4c9f50, op=op@entry=0xc135aa6c <open_exec_flags>, flags=flags@entry=1) at fs/namei.c:3004
#6  open_exec (name=name@entry=0xcc4b7010 "/bin/login") at fs/exec.c:762
#7  do_execve_common (filename=<optimised out>, argv=..., argv@entry=..., envp=..., envp@entry=...) at fs/exec.c:1499
#8  do_execve (__envp=0xbfb7cba0, __argv=0xbfb7a758, filename=<optimised out>) at fs/exec.c:1585
#9  sys_execve (filename=0x804d172 "/bin/login", argv=0xbfb7a758, envp=0xbfb7cba0) at fs/exec.c:1681
#10 <signal handler called>

Stack 3:


#0  ext3_lookup (dir=0xcb83fae0, dentry=0xcb844480, flags=257) at fs/ext3/namei.c:1019
#1  lookup_real (dir=dir@entry=0xcb83fae0, dentry=dentry@entry=0xcb844480, flags=<optimised out>) at fs/namei.c:1317
#2  0xc10e4e31 in lookup_open (opened=0xce0f5ec8, got_write=false, op=0xce0f5f78, file=0xce87a980, path=0xce0f5ecc, nd=0xce0f5ef8) at fs/namei.c:2641
#3  do_last (nd=nd@entry=0xce0f5ef8, path=path@entry=0xce0f5ecc, file=file@entry=0xce87a980, op=op@entry=0xce0f5f78, opened=opened@entry=0xce0f5ec8, name=0xcc4b7000) at fs/namei.c:2771
#4  path_openat (dfd=dfd@entry=-100, nd=nd@entry=0xce0f5ef8, op=0xce0f5f78, flags=flags@entry=65, pathname=0xcc4b7000) at fs/namei.c:2956
#5  do_filp_open (dfd=dfd@entry=-100, pathname=pathname@entry=0xcc4b7000, op=op@entry=0xce0f5f78, flags=flags@entry=1) at fs/namei.c:3004
#6  do_sys_open (dfd=dfd@entry=-100, filename=filename@entry=0xbf877ef0 "/work/1", flags=flags@entry=32768, mode=mode@entry=0) at fs/open.c:956
#7  0xc10d900b in sys_open (filename=0xbf877ef0 "/work/1", flags=32768, mode=0) at fs/open.c:977
#8  <signal handler called>


Monday, April 11, 2016

Linux kernel stacks. Creating an inode.

A call stack when ext3 file system driver creates an inode. The related kernel source is Quark X1000 Linux kernel




#0  ext3_new_inode (handle=handle@entry=0xcd5ea000, dir=dir@entry=0xcb83f928, qstr=qstr@entry=0xcb81df94, mode=mode@entry=33206) at fs/ext3/ialloc.c:348
#1  ext3_create (dir=0xcb83f928, dentry=0xcb81df80, mode=33206, excl=false) at fs/ext3/namei.c:1715
#2  vfs_create (dir=0xcb83f928, dentry=0xcb81df80, mode=<optimised out>, want_excl=false) at fs/namei.c:2338
#3  lookup_open (opened=0xce265ec8, got_write=true, op=0xce265f78, file=0xce182400, path=0xce265ecc, nd=0xce265ef8) at fs/namei.c:2666
#4  do_last (nd=nd@entry=0xce265ef8, path=path@entry=0xce265ecc, file=file@entry=0xce182400, op=op@entry=0xce265f78, opened=opened@entry=0xce265ec8, name=0xcc4b2000) at fs/namei.c:2771
#5  path_openat (dfd=dfd@entry=-100, nd=nd@entry=0xce265ef8, op=0xce265f78, flags=flags@entry=65, pathname=0xcc4b2000) at fs/namei.c:2956
#6  do_filp_open (dfd=dfd@entry=-100, pathname=pathname@entry=0xcc4b2000, op=op@entry=0xce265f78, flags=flags@entry=1) at fs/namei.c:3004
#7  do_sys_open (dfd=dfd@entry=-100, filename=filename@entry=0x83b3568 "/work/1", flags=flags@entry=33345, mode=mode@entry=438) at fs/open.c:956
#8  sys_open (filename=0x83b3568 "/work/1", flags=33345, mode=438) at fs/open.c:977
#9  <signal handler called>

Linux kernel stacks. x86 registers .

A contents of the IA-32 registers when running Linux on Intel Quark X1000. Note CR3 with a physical address for PD.

(0) eax (/32): 0x00000000
(1) ecx (/32): 0x00000000
(2) edx (/32): 0xC14B4000
(3) ebx (/32): 0xC14B4000
(4) esp (/32): 0xC14B5F94
(5) ebp (/32): 0xC14B5FA0
(6) esi (/32): 0x00096800
(7) edi (/32): 0xC14B7800
(8) eip (/32): 0xC10093C5
(9) eflags (/32): 0x00000246
(10) cs (/32): 0x00000060
(11) ss (/32): 0x00000068
(12) ds (/32): 0x0000007B
(13) es (/32): 0x0000007B
(14) fs (/32): 0x00000000
(15) gs (/32): 0x00000000
(16) st0 (/32)
(17) st1 (/32)
(18) st2 (/32)
(19) st3 (/32)
(20) st4 (/32)
(21) st5 (/32)
(22) st6 (/32)
(23) st7 (/32)
(24) fctrl (/32)
(25) fstat (/32)
(26) ftag (/32)
(27) fiseg (/32)
(28) fioff (/32)
(29) foseg (/32)
(30) fooff (/32)
(31) fop (/32)
(32) cr0 (/32): 0x8005003B
(33) cr2 (/32): 0xB75E1000
(34) cr3 (/32): 0x0C4F9000
(35) cr4 (/32): 0x00100030
(36) dr0 (/32): 0x00000000
(37) dr1 (/32): 0x00000000
(38) dr2 (/32): 0x00000000
(39) dr3 (/32): 0x00000000
(40) dr6 (/32): 0xFFFF0FF0
(41) dr7 (/32): 0x00000000
(42) idtbase (/32): 0xFFFBA000
(43) idtlimit (/32): 0x000007FF
(44) idtar (/32): 0xFFFFFFFF
(45) gdtbase (/32): 0xC14B8000
(46) gdtlimit (/32): 0x000000FF
(47) gdtar (/32): 0xFFFFFFFF
(48) tr (/32): 0x00000080
(49) ldtr (/32): 0x00000000
(50) ldbase (/32): 0x00000000
(51) ldlimit (/32): 0x0000FFFF
(52) ldtar (/32): 0xFFFF7FFF
(53) csbase (/32): 0x00000000
(54) cslimit (/32): 0xFFFFFFFF
(55) csar (/32): 0xFFFF9BFF
(56) dsbase (/32): 0x00000000
(57) dslimit (/32): 0xFFFFFFFF
(58) dsar (/32): 0xFFFFF3FF
(59) esbase (/32): 0x00000000
(60) eslimit (/32): 0xFFFFFFFF
(61) esar (/32): 0xFFFFF3FF
(62) fsbase (/32): 0x00000000
(63) fslimit (/32): 0xFFFFFFFF
(64) fsar (/32): 0xFF3F11FF
(65) gsbase (/32): 0xB7741700
(66) gslimit (/32): 0xFFFFFFFF
(67) gsar (/32): 0xFF3F11FF
(68) ssbase (/32): 0x00000000
(69) sslimit (/32): 0xFFFFFFFF
(70) ssar (/32): 0xFFFF93FF
(71) tssbase (/32): 0xC14C17C0
(72) tsslimit (/32): 0x0000206B
(73) tssar (/32): 0xFFFFFFFF
(74) pmcr (/32): 0x00000000

Sunday, April 10, 2016

Debugging Linux kernel on Intel Quark X100 .

For source level debugging I use OLIMEX JTAG . This is a fast guide how to configure it on Linux machine.  A more detailed description can be found in Intel documentation Source Level Debug using OpenOCD/GDB/Eclipse on Intel ® QuarkTM SoC X1000

Compile and install OpenOCD with Quark support.

$ git clone git://git.code.sf.net/p/openocd/code openocd-code
$ cd openocd-code
$ git branch quark v0.8.0
$ git checkout quark
$ ./bootstrap
$ ./configure --enable-ftdi
$ make
$ sudo make install

By default OpenOCD is installed in the following folders

/usr/local/bin/openocd
/usr/local/share/openocd/scripts

Connect an OLIMEX JTAG to a board and your machine

Intel Galileo with OLIMEX JTAG
Intel Galileo with OLIMEX JTAG

Power on a board and start an OpenOCD session for Quark X1000. This will start a GDB server on 3333 port.

$ openocd -f ./interface/ftdi/olimex-arm-usb-ocd-h.cfg -f target/quark_x10xx.cfg

If OpenOCD managed to locate a JTAG and connect to a board the output will be


Start GDB and attach to a GDB server started by OpenOCD. Provide GDB with a path to a kernel compiled with debug symbols.

$ gdb
(gdb) target remote localhost:3333
(gdb) monitor halt
(gdb) symbol-file <PATH TO LINUX SOURCE>/vmlinux
(gdb) c

Ctrl-C will break kernel execution into the debugger.

Linux kernel stacks. CFS scheduler deques a task .


A set of call stacks when a scheduler switches task. The related kernel source is Quark X1000 Linux kernel

Stack 1:

#0  __dequeue_entity (se=0xce2edfac, cfs_rq=0xc14d4700 <runqueues+64>) at kernel/sched/fair.c:531
#1  set_next_entity (cfs_rq=cfs_rq@entry=0xc14d4700 <runqueues+64>, se=se@entry=0xce2edfac) at kernel/sched/fair.c:1868
#2  pick_next_task_fair (rq=0xc14d46c0 <runqueues>) at kernel/sched/fair.c:3608
#3  pick_next_task (rq=0xc14d46c0 <runqueues>) at kernel/sched/core.c:2832
#4  __schedule () at kernel/sched/core.c:2934
#5  schedule () at kernel/sched/core.c:2979
#6  cpu_idle () at arch/x86/kernel/process.c:367
#7  rest_init () at init/main.c:385
#8  start_kernel () at init/main.c:643
#9  i386_start_kernel () at arch/x86/kernel/head32.c:66


Stack 2:

#0  __dequeue_entity (se=0xc00623fc, cfs_rq=0xc14d4700 <runqueues+64>) at kernel/sched/fair.c:531
#1  set_next_entity (cfs_rq=cfs_rq@entry=0xc14d4700 <runqueues+64>, se=se@entry=0xc00623fc) at kernel/sched/fair.c:1868
#2  pick_next_task_fair (rq=0xc14d46c0 <runqueues>) at kernel/sched/fair.c:3608
#3  pick_next_task (rq=0xc14d46c0 <runqueues>) at kernel/sched/core.c:2832
#4  __schedule () at kernel/sched/core.c:2934
#5  schedule () at kernel/sched/core.c:2979
#6  schedule_hrtimeout_range_clock (expires=expires@entry=0xce30ff7c, delta=delta@entry=999997, 
    mode=mode@entry=HRTIMER_MODE_ABS, clock=clock@entry=1) at kernel/hrtimer.c:1809
#7  schedule_hrtimeout_range (expires=expires@entry=0xce30ff7c, delta=delta@entry=999997, mode=mode@entry=HRTIMER_MODE_ABS)
    at kernel/hrtimer.c:1850
#8  ep_poll (timeout=1000, maxevents=<optimised out>, events=0x97062b8, ep=<optimised out>) at fs/eventpoll.c:1546
#9  sys_epoll_wait (epfd=6, events=0x97062b8, maxevents=1025, timeout=1000) at fs/eventpoll.c:1892
#10 <signal handler called>

Stack 3:

#0  __dequeue_entity (se=0xce288c1c, cfs_rq=0xc14d4700 <runqueues+64>) at kernel/sched/fair.c:531
#1  set_next_entity (cfs_rq=cfs_rq@entry=0xc14d4700 <runqueues+64>, se=se@entry=0xce288c1c) at kernel/sched/fair.c:1868
#2  pick_next_task_fair (rq=0xc14d46c0 <runqueues>) at kernel/sched/fair.c:3608
#3  pick_next_task (rq=0xc14d46c0 <runqueues>) at kernel/sched/core.c:2832
#4  __schedule () at kernel/sched/core.c:2934
#5  schedule () at kernel/sched/core.c:2979
#6  worker_thread (__worker=0xcc4f9c40) at kernel/workqueue.c:2407
#7  kthread (_create=0xcea53ec4) at kernel/kthread.c:168
#8  ret_from_kernel_thread () at arch/x86/kernel/entry_32.S:311
#9  ?? () at kernel/kthread.c:420

Stack 4:

#0  __dequeue_entity (se=0xce9f3bdc, cfs_rq=0xc14d4700 <runqueues+64>) at kernel/sched/fair.c:531
#1  set_next_entity (cfs_rq=cfs_rq@entry=0xc14d4700 <runqueues+64>, se=se@entry=0xce9f3bdc) at kernel/sched/fair.c:1868
#2  pick_next_task_fair (rq=0xc14d46c0 <runqueues>) at kernel/sched/fair.c:3608
#3  pick_next_task (rq=0xc14d46c0 <runqueues>) at kernel/sched/core.c:2832
#4  __schedule () at kernel/sched/core.c:2934
#5  schedule () at kernel/sched/core.c:2979
#6  futex_wait_queue_me (hb=<optimised out>, q=q@entry=0xce183e6c, timeout=timeout@entry=0xce183ea4) at kernel/futex.c:1808
#7  futex_wait (uaddr=uaddr@entry=0x807f524, flags=flags@entry=2, val=val@entry=4733, abs_time=abs_time@entry=0xce183f98, 
    bitset=4294967295) at kernel/futex.c:1923
#8  do_futex (uaddr=uaddr@entry=0x807f524, op=op@entry=393, val=val@entry=4733, timeout=0xce183f98, 
    uaddr2=uaddr2@entry=0x807f550, val2=0, val3=<optimised out>, val3@entry=4294967295) at kernel/futex.c:2669
#9  sys_futex (uaddr=0x807f524, op=393, val=4733, utime=0x8081d5c, uaddr2=0x807f550, val3=4294967295) at kernel/futex.c:2727
#10 <signal handler called>