跟踪内核启动过程CONFIG_DEBUG_LL【转自】

转自:http://bbs.chinaunix.net/thread-3642079-1-1.html

最近在调试Linux内核,跟踪启动过程。发现在没有turn on mmu之前,可以使用物理地址,通过向串口Fifo丢数据的方式输出调试信息。但是代码一旦运行到开启mmu,在汇编阶段,mmu只做了物理内存的映射,并没有映射io,所以就无法访问串口了。

 

此时应该通过串口输出的数据都保存在串口缓冲池里,直到在c语言阶段,建立io映射并初始化控制台后才进行输出。

 

但是,如果我想实时跟踪内核启动过程,应该如何才好?

这是就要提到Linux的Lowlevel Debug功能了。

 

这个选项位于:

Kernel hacking  ---> 

 [*] Kernel debugging 

 [*] Kernel low-level debugging functions 

 

打开这个选项会在.config中增加CONFIG_DEBUG_LL宏定义

初步估计,影响的地方有以下几点:

(1)arch/arm/kernel/head.s的__create_page_tables部分

(2)arch/arc/mach-处理器/处理器.c中的宏定义部分

(3)kernel/prink.c

为了提供DEBUG_LL功能,还必须完善arch/arc/mach-处理器/include/mach/debug-macro.S

 

首先说说好处,为什幺打开Kernel low-level debugging functions 功能。

打开这个宏定义后,会在head.s函数的__create_page_tables建立一部分io映射,具体代码如下:

 

#ifdef CONFIG_DEBUG_LL

ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags

/*

 * Map in IO space for serial debugging.

 * This allows debug messages to be output

 * via a serial console before paging_init.

 */

ldr r3, [r8, #MACHINFO_PGOFFIO]

add r0, r4, r3

rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long)

cmp r3, #0x0800 @ limit to 512MB

movhi r3, #0x0800

add r6, r0, r3

ldr r3, [r8, #MACHINFO_PHYSIO]

orr r3, r3, r7

1: str r3, [r0], #4

add r3, r3, #1 << 20

teq r0, r6

bne 1b

 

代码中也提到,映射io的作用是为了串口调试使用。

这段代码中使用的物理地址和虚拟地址从何而来?arch/arc/mach-处理器/处理器.c中的宏定义部分

比如以下处理器:

MACHINE_START(EASIC0718, "SEP0718 board")

 

.phys_io = 0x10005000,

.io_pg_offst = ((0xe005000) >> 18) & 0xfffc,

.boot_params = 0x30000100,

.fixup = fixup_gfd0718,

.map_io = sep0718_map_io,

.init_irq =  sep0718_init_irq,

.init_machine = sep0718_init,

.timer = &sep0718_timer,

 

MACHINE_END

 

中间

.phys_io = 0x10005000,

.io_pg_offst = ((0xe005000) >> 18) & 0xfffc,

就是供__create_page_tables的 CONFIG_DEBUG_LL中做io映射使用

 

最后就是对printk.c的改动了,主要是多定义了void printascii(char *)可以直接输出。

完善了debug-macro.S后可以用printascii了。建立了内存映射后,哪里都可以用,无论汇编还是C,无论开mmu前还是开mmu后。代码会判断有没有开mmu的。

同时prink会在缓冲池保留一份数据,也同时调用printkasii直接输出,因此内核启动后会看到信息输出了两次。

 

最后贴上debug-macro.S,writed by leeming,注意其中的io地址和处理器架构相关,不能直接使用。

/* linux/include/asm-arm/arch-sep0718/debug-macro.S

 *

 * Debugging macro include header

 *

 * This program is free software; you can redistribute it and/or modify

 * it under the terms of the GNU General Public License version 2 as

 * published by the Free Software Foundation.

 *

*/

#include <asm/hardware.h>

 

.macro addruart,rx

mrc p15, 0, \rx, c1, c0

tst \rx, #1 @ MMU enabled?

moveq \rx, #0x10000000

movne \rx, #0xe0000000

add  \rx, \rx, #0x5000

.endm

 

.macro senduart,rd,rx

str \rd, [\rx] @ UARTDR

.endm

            

.macro waituart,rd,rx

1001: ldr \rd, [\rx, #0x14] @ SYSFLGx

tst \rd, #1 << 6 @ UBUSYx

beq 1001b

.endm

 

.macro busyuart,rd,rx

1001: ldr \rd, [\rx, #0x14] @ SYSFLGx

tst \rd, #1 << 6 @ UBUSYx

beq 1001b

.endm

时间: 2024-11-01 05:33:01

跟踪内核启动过程CONFIG_DEBUG_LL【转自】的相关文章

Linux内核源码分析--内核启动之(1)zImage自解压过程(Linux-3.0 ARMv7) 【转】

转自:http://blog.chinaunix.net/uid-25909619-id-4938388.html   研究内核源码和内核运行原理的时候,很总要的一点是要了解内核的初始情况,也就是要了解内核启动过程.我在研究内核的内存管理的时候,想知道内核启动后的页表的放置,页表的初始化等信息,这促使我这次仔细地研究内核的启动代码.       CPU在bootloader的帮助下将内核载入到了内存中,并开始执行.当然,bootloader必须为zImage做好必要的准备:  1. CPU 寄存

U-Boot启动过程

开发板上电后,执行U-Boot的第一条指令,然后顺序执行U-Boot启动函数.看一下board/smdk2410/u-boot.lds这个链接脚本,可以知道目标程序的各部分链接顺序.第一个要链接的是cpu/arm920t/start.o,那么U-Boot的入口指令一定位于这个程序中.下面分两阶段介绍启动流程:                    第一阶段 1.cpu/arm920t/start.S 这个汇编程序是U-Boot的入口程序,开头就是复位向量的代码. _start: b       

ARM linux内核启动时几个关键地址【转】

转自:http://www.cnblogs.com/armlinux/archive/2011/11/06/2396787.html 1.       内核启动地址1.1.   名词解释ZTEXTADDR 解压代码运行的开始地址.没有物理地址和虚拟地址之分,因为此时MMU处于关闭状态.这个地址不一定时RAM的地址,可以是支持读写寻址的flash等存储中介. Start address of decompressor. here's no point in talking about virtua

走进Linux之systemd启动过程

走进Linux之systemd启动过程 Linux系统的启动方式有点复杂,而且总是有需要优化的地方.传统的Linux系统启动过程主要由著名的init进程(也被称为SysV init启动系统)处理,而基于init的启动系统被认为有效率不足的问题,systemd是Linux系统机器的另一种启动方式,宣称弥补了以传统Linux SysV init为基础的系统的缺点.在这里我们将着重讨论systemd的特性和争议,但是为了更好地理解它,也会看一下通过传统的以SysV init为基础的系统的Linux启动

《Android的设计与实现:卷I》——第3章 3.2Kernel启动过程

3.2 Kernel启动过程 Android Kernel启动过程与标准Linux Kernel的启动过程基本一致,都是对start_kernel函数的调用和执行.本节将分析Android正常启动流程的第二步:Kernel启动过程. 本节涉及的源码文件如下: kernel/arch/arm/kernel/head.Skernel /arch/arm/kernel/head-common.Skernel/init/main.cKernel启动过程分为两个阶段: 1)内核引导阶段.通常使用汇编语言编

Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 【转】

原文地址:Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 作者:tekkamanninja  转自:http://blog.chinaunix.net/uid-25909619-id-4938390.html   在构架相关的汇编代码运行完之后,程序跳入了构架无关的内核C语言代码:init/main.c中的start_kernel函数,在这个函数中Linux内核开始真正进入初始化阶段,      下面我就顺这代码逐个函数的解释,但是这

【内核】linux内核启动流程详细分析【转】

转自:http://www.cnblogs.com/lcw/p/3337937.html Linux内核启动流程  arch/arm/kernel/head-armv.S  该文件是内核最先执行的一个文件,包括内核入口ENTRY(stext)到start_kernel间的初始化代码, 主要作用是检查CPU ID, Architecture Type,初始化BSS等操作,并跳到start_kernel函数.在执行前,处理器应满足以下状态:  r0 - should be 0 r1 - unique

Linux内核源码分析--内核启动之(2)Image内核启动(汇编部分)(Linux-3.0 ARMv7) 【转】

转自:http://blog.chinaunix.net/uid-25909619-id-4938389.html  在完成了zImage自解压之后,就跳转到了解压后的内核(也就是vmlinux的bin版本Image),具体的入口可以在arch/arm/kernel/vmlinux.lds.S(最终的链接脚本是通过这个文件产生的)中获得:   ...... SECTIONS { #ifdef CONFIG_XIP_KERNEL . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_

S3C2410下WinCE6.0的启动过程详解

通过前两篇文章的介绍,我们已经知道NBOOT用来引导EBOOT,继而EBOOT加载并引导WinCE操作系统(NK).那么,WinCE6.0的启动过程又是怎样的呢?本文基于S3C2410的平台做一个详细的分析.需要说明的是,WinCE6.0的整个启动过程对于同一类型的MCU来说大同小异,如S3C2410和PXA270同属ARM平台的MCU,所以他们的启动过程是类似的,可以说唯一的不同就在OAL处,而WinCE操作系统的启动正是从OAL开始的.      OAL(OEM Adaptation Lay