linux-0.11之Kernel-traps.c

在linux内核的硬件中断处理程序中,主要代码集中在asm.s和traps.c中。asm.s用于实现大部分硬件异常所引起的中断的汇编语言处理过程。而traps.c程序则实现了asm.s的中断处理过程中调用的C函数。

一般的硬件异常所引起的中断处理流程如下图:

  

traps.c中初始化函数trap_init()是在main.c中被调用的,用于初始化硬件异常处理中断向量(陷阱门),并设置允许中断信号的到来。

traps.c程序主要包括一些在处理异常故障(硬件中断)底层代码asm.s文件中调用的相应C函数。用于显示出错位置和出错调试信息。其中die()函数就是用于在中断处理中显示出错信息。目前主要用于调试目的,以后将扩展用来杀死遭损坏的进程。主要源代码如下注释:

*
 *  linux/kernel/traps.c
 *
 *  (C) 1991  Linus Torvalds
 */


/*
 * 'Traps.c' handles hardware traps and faults after we have saved some
 * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
 * to mainly kill the offending process (probably by giving it a signal,
 * but possibly by killing it outright if necessary).
 */
 /*在程序asm.s中保存了一些状态后,本程序用来处理硬件陷阱和故障。主要用于调试*/
 
#include <string.h> /*字符串头文件*/
#include <linux/head.h> /*定义了段描述符的简单结构,和选择符常量*/
#include <linux/sched.h> /*调度程序头文件*/
#include <linux/kernel.h> /*内核头文件*/
#include <asm/system.h> /*系统头文件*/
#include <asm/segment.h> /*段操作头文件*/
#include <asm/io.h> /*输入、输出头文件*/


#define get_seg_byte(seg,addr) ({ \ /*宏定义:取段seg中地址addr处的一个字节*/
register char __res; \ /*定义一个寄存器变量*/
__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
:"=a" (__res):"0" (seg),"m" (*(addr))); \ /*输入:_res;输出:seg 内存地址*/
__res;})


#define get_seg_long(seg,addr) ({ \ /*宏定义:取段seg中地址addr处的4个字节(long)*/
register unsigned long __res; \ /*定义一个寄存器变量*/
__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \
:"=a" (__res):"0" (seg),"m" (*(addr))); \ /*输入:_res;输出:seg 内存地址*/
__res;})


#define _fs() ({ \ /*宏定义:取fs段寄存器的值*/
register unsigned short __res; \ /*定义一个寄存器变量*/
__asm__("mov %%fs,%%ax":"=a" (__res):); \ /*输入:_res*/
__res;})


/*函数声明*/
int do_exit(long code); /*程序退出处理函数*/


void page_exception(void); /*页异常,实际是page_fault*/
/*中断处理程序声明*/
void divide_error(void); /*int0 中断处理*/
void debug(void); /*int1 中断处理*/
void nmi(void); /*int2 中断处理*/
void int3(void); /*int3 中断处理*/
void overflow(void); /*int4 中断处理*/
void bounds(void); /*int5 中断处理*/
void invalid_op(void); /*int6 中断处理*/
void device_not_available(void); /*int7 中断处理*/
void double_fault(void); /*int8 中断处理*/
void coprocessor_segment_overrun(void); /*int9 中断处理*/
void invalid_TSS(void); /*int10 中断处理*/
void segment_not_present(void); /*int11 中断处理*/
void stack_segment(void); /*int12 中断处理*/
void general_protection(void); /*int13 中断处理*/
void page_fault(void); /*int14 中断处理*/
void coprocessor_error(void); /*int16 中断处理*/
void reserved(void); /*int15 中断处理*/
void parallel_interrupt(void); /*int39 中断处理*/
void irq13(void); /*int45 中断协助处理*/
/*该子程序用来打印出错中断的名称、出错号...*/
static void die(char * str,long esp_ptr,long nr)
{
long * esp = (long *) esp_ptr;
int i;


printk("%s: %04x\n\r",str,nr&0xffff); /*打印中断和出错号*/
printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n",
esp[1],esp[0],esp[2],esp[4],esp[3]); /*打印段选择符、eip、eflegs、esp*/
printk("fs: %04x\n",_fs()); /*打印段寄存器的值*/
printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17));/*打印段寄存器的基址和长度*/
if (esp[4] == 0x17) { /*打印栈数据*/
printk("Stack: ");
for (i=0;i<4;i++)
printk("%p ",get_seg_long(0x17,i+(long *)esp[3]));
printk("\n");
}
str(i); /*获取当前任务号*/
printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i); /*打印进程pid*/
for(i=0;i<10;i++) /*打印10个指令码*/
printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0])));
printk("\n\r");
do_exit(11); /* play segment exception */
}
/*中断处理调用函数*/
void do_double_fault(long esp, long error_code)
{
die("double fault",esp,error_code);
}


void do_general_protection(long esp, long error_code)
{
die("general protection",esp,error_code);
}


void do_divide_error(long esp, long error_code)
{
die("divide error",esp,error_code);
}


void do_int3(long * esp, long error_code,
long fs,long es,long ds,
long ebp,long esi,long edi,
long edx,long ecx,long ebx,long eax)
{
int tr;


__asm__("str %%ax":"=a" (tr):"0" (0));
printk("eax\t\tebx\t\tecx\t\tedx\n\r%8x\t%8x\t%8x\t%8x\n\r",
eax,ebx,ecx,edx);
printk("esi\t\tedi\t\tebp\t\tesp\n\r%8x\t%8x\t%8x\t%8x\n\r",
esi,edi,ebp,(long) esp);
printk("\n\rds\tes\tfs\ttr\n\r%4x\t%4x\t%4x\t%4x\n\r",
ds,es,fs,tr);
printk("EIP: %8x   CS: %4x  EFLAGS: %8x\n\r",esp[0],esp[1],esp[2]);
}


void do_nmi(long esp, long error_code)
{
die("nmi",esp,error_code);
}


void do_debug(long esp, long error_code)
{
die("debug",esp,error_code);
}


void do_overflow(long esp, long error_code)
{
die("overflow",esp,error_code);
}


void do_bounds(long esp, long error_code)
{
die("bounds",esp,error_code);
}


void do_invalid_op(long esp, long error_code)
{
die("invalid operand",esp,error_code);
}


void do_device_not_available(long esp, long error_code)
{
die("device not available",esp,error_code);
}


void do_coprocessor_segment_overrun(long esp, long error_code)
{
die("coprocessor segment overrun",esp,error_code);
}


void do_invalid_TSS(long esp,long error_code)
{
die("invalid TSS",esp,error_code);
}


void do_segment_not_present(long esp,long error_code)
{
die("segment not present",esp,error_code);
}


void do_stack_segment(long esp,long error_code)
{
die("stack segment",esp,error_code);
}


void do_coprocessor_error(long esp, long error_code)
{
if (last_task_used_math != current)
return;
die("coprocessor error",esp,error_code);
}


void do_reserved(long esp, long error_code)
{
die("reserved (15,17-47) error",esp,error_code);
}


/*中断程序初始化子程序,设置中断调用门,set_trap_gate()和set_system_gate()都使用了中断描述
*符表IDT中的陷阱门(Trap Gate),前者设置的特权级为0,后者为3。两者都是嵌入汇编宏程序。
*/
void trap_init(void)
{
int i;
/*设置各个中断向量值,除操作出错*/
set_trap_gate(0,&divide_error);
set_trap_gate(1,&debug);
set_trap_gate(2,&nmi);
/*中断3-5可以被所有程序执行*/
set_system_gate(3,&int3);
set_system_gate(4,&overflow);
set_system_gate(5,&bounds);
set_trap_gate(6,&invalid_op);
set_trap_gate(7,&device_not_available);
set_trap_gate(8,&double_fault);
set_trap_gate(9,&coprocessor_segment_overrun);
set_trap_gate(10,&invalid_TSS);
set_trap_gate(11,&segment_not_present);
set_trap_gate(12,&stack_segment);
set_trap_gate(13,&general_protection);
set_trap_gate(14,&page_fault);
set_trap_gate(15,&reserved);
set_trap_gate(16,&coprocessor_error);
/*把int17-47的中断先设置为reserverd,后面初始化时会重新设置自己的中断*/
for (i=17;i<48;i++)
set_trap_gate(i,&reserved);
/*设置协处理器中断45,允许产生中断请求,设置并行口中断描述符*/
set_trap_gate(45,&irq13);
outb_p(inb_p(0x21)&0xfb,0x21); /*允许8259A主芯片的IRQ2中断请求*/
outb(inb_p(0xA1)&0xdf,0xA1); /*允许8259A主芯片的IRQ3中断请求*/
set_trap_gate(39,&parallel_interrupt); /*设置并行口1的中断0x27陷阱门描述符*/
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值