Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

24137
1186
128669


ARM64(Aarch64) - Special Register 설정(Trace32) [Linux] ARM 프로세서 이야기

AArch64 64비트 아키텍쳐에서 설정해야 할 Special Register에 대해서 잠깐 살펴볼께요.
우선 커널이 구동될 때의 Exception Level이 1이니까 EL1 모드만 점검하죠.


TTBR1_EL1
약자는 Translation Table Base Register인데, 가상주소와 물리주소를 변환할 때 쓰이죠.

Trace32로 이 레지스터를 설정하고 싶으면 아래 커맨드를 써야 하지오.
Data.Set SPR:0x30201 %Quad 0x82ba1000  // TTBR1_EL1

TCR_EL1
Translation Control Register의 약자인데 Stage 1 가상 주소 Translation 시 필요한 Translation 베이스 레지스터 정보를
포함하고 있어요.
Trace32로 이 레지스터를 설정하고 싶으면 아래 커맨드를 쓰면 되죠.
Data.Set SPR:0x30202 %Quad 0x00000032B5193519 // TCR_EL1

MAIR_EL1
Memory Attribute Indirection Register이거든요. Trace32로 아래 명령어로 설정 가능해요.
Data.Set SPR:0x30A20 %Quad 0x000000FF440C0400 // MAIR_EL1

SCTLR_EL1
가장 중요한 레지스터인데요.

ARM53 문서께서 System Control Register라고 하시네요.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488d/CIHDIEBD.html

Trace32 설정 커맨드는 아래와 같아요.
Data.Set SPR:0x30100 %Quad 0x0000000004C5D93D // SCTLR_EL1

그럼 커널 패닉이 일어났을 때 이 레지스터 정보를 찍고 싶으면 어떻게 해야 할까요?
아래 패치를 적용하면 커널 로그로 확인이 가능하죠. panic reboot notifier call을 하나 설정하고 콜백함수에 해당 루틴을 추가하면 되죠.
diff --git a/drivers/soc/pompeii/crash_handle_panic.c b/drivers/soc/pompeii/crash_handle_panic.c
index 27b9b60..431fd85 100644
--- a/drivers/soc/pompeii/crash_handle_panic.c
+++ b/drivers/soc/pompeii/crash_handle_panic.c
@@ -70,6 +70,41 @@ static int gen_key_panic = 0;
 static int key_crash_cnt = 0;
 static unsigned long key_crash_last_time = 0;
 
+static DEFINE_SPINLOCK(panic_lock);
+
+static u64 ttbr1_el1_reg = 0;
+static u64 tcr_el1_reg = 0;
+static u64 mair_el1_reg = 0;
+static u64 amair_el1_reg = 0;
+static u64 sctlr_el1_reg = 0;
+
+void get_mmu_sys_ctrl_register(void)
+{
+       ttbr1_el1_reg = read_sysreg(ttbr1_el1);
+       tcr_el1_reg = read_sysreg(tcr_el1);
+       mair_el1_reg = read_sysreg(mair_el1);
+       amair_el1_reg = read_sysreg(amair_el1);
+       sctlr_el1_reg = read_sysreg(sctlr_el1);
+
+       printk("ttbr1: %llx  tcr: %llx sctlr: %llx mair: %llx amair: %llx \n",
+                                       ttbr1_el1_reg, sctlr_el1_reg, sctlr_el1_reg, mair_el1_reg, amair_el1_reg);
+}
+
+static int crash_handler_panic(struct notifier_block *this,
+                 unsigned long event,
+                 void *ptr)
+{
+    unsigned long flags;
+    spin_lock_irqsave(&panic_lock, flags);
+
+    printk(KERN_CRIT "%s called\n", __func__);
+    get_mmu_sys_ctrl_register();
+
+    spin_unlock_irqrestore(&panic_lock, flags);
+    return NOTIFY_DONE;
+}
+
+
+static struct notifier_block panic_blk = {
+    .notifier_call  = crash_handler_panic,
+    .priority    = 1004,
+};
+
 static int __init crash_panic_handler_early_init(void)
 {
        struct device_node *np;
@@ -477,6 +517,8 @@ static int __init lge_panic_handler_early_init(void)
                return -ENODEV;
        }
 
+       atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
+
        of_property_read_u32(np, "mem-addr", (u32*)&panic_handler->fb_addr);
        of_property_read_u32(np, "mem-size", (u32*)&panic_handler->fb_size);

번외로 한 가지 주의할 점은 u64로 설정한 변수는 %llx, %lld 로 printk 아규먼트를 줘야 해요.
 

Reference(프로세스 관리)
4.9 프로세스 컨택스트 정보는 어떻게 저장할까?
 4.9.1 컨택스트 소개
 4.9.2 인터럽트 컨택스트 정보 확인하기
 4.9.3 Soft IRQ 컨택스트 정보 확인하기
 4.9.4 선점 스케줄링 여부 정보 저장
4.10 프로세스 디스크립터 접근 매크로 함수
 4.10.1 current_thread_info()
 4.10.2 current 매크로란
4.11 프로세스 디버깅
 4.11.1 glibc fork 함수 gdb 디버깅
 4.11.2 유저 프로그램 실행 추적 

핑백

덧글

댓글 입력 영역