아래 패치를 적용하면 해당 프로세스의 스택 메모리 덤프를 stack_dump 배열에 저장합니다.
인터럽트 처리가 마무리 된 후 프로세스 레벨에서 stack_dump 배열에 저장된 메모리 덤프를 커널 로그로 출력하면,
인터럽트 벡터 심볼 __irq_svc과 스택에 푸쉬한 레지스터 정보를 모두 볼 수 있습니다.
diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c
index 612293c..2623e0d 100644
--- a/drivers/video/fbdev/bcm2708_fb.c
+++ b/drivers/video/fbdev/bcm2708_fb.c
@@ -713,9 +713,28 @@ static void bcm2708_fb_imageblit(struct fb_info *info,
cfb_imageblit(info, image);
}
+#define _DEBUG_ARM_STACK_SIZE 0x2000
+static unsigned int stack_dump[_DEBUG_ARM_STACK_SIZE];
+
+#define _DEBUG_ADDRESS_OFFSET 4
+
static irqreturn_t bcm2708_fb_dma_irq(int irq, void *cxt)
{
struct bcm2708_fb *fb = cxt;
+
+ register unsigned long current_sp asm ("sp");
+ unsigned long temp_stack_addr = 0x0;
+ unsigned int stack_bottom_addr = 0x0;
+ int proc_times = 0;
+
+ stack_bottom_addr = (unsigned int)current->stack + _DEBUG_ARM_STACK_SIZE; //<<--[1]
+
+ temp_stack_addr = current_sp; //<<--[2]
+ for (proc_times = 0; temp_stack_addr < stack_bottom_addr; proc_times++)
+ {
+ stack_dump[temp_stack_addr] = *((unsigned long*)(temp_stack_addr)); //<<--[3]
+ temp_stack_addr += _DEBUG_ADDRESS_OFFSET;
+ }
/* FIXME: should read status register to check if this is
* actually interrupting us or not, in case this interrupt
[1]: 현재 구동 중인 프로세스의 태스크 디스크립터는 current란 매크로로 가져옵니다.
struct task_struct->stack 멤버로 스택 Bottom 주소를 가져와서 프로세스 스택 사이즈를 더해 스택 Top 주소를 구합니다
[2]: "register unsigned long current_sp asm ("sp");" 명령어로 현재 실행 중인 코드의 스택 주소를 current_sp 변수에 저장했습니다.
이 값을 temp_stack_addr 로컬 변수에 저장합니다.
[3]: temp_stack_addr 현재 스택 주소에서 4바이트 씩 계속 더하면서 스택 Top 주소까지 스택 메모리 덤프를 stack_dump 배열에 저장합니다.
스택 덤프를 어떤 방식으로 표현할 지 고민 중입니다.



최근 덧글