Core functionality common to interrupt and exception handling (the IDT for example) has been moved into cpu.c
Signed-off-by: Graeme Russ <[EMAIL PROTECTED]> --- Future rework on the i386 branch will include support for the SC520 interrupt controller which can handle up to 22 interrupt lines - Seperating out exception handling now will make life a lot easier later on --- cpu/i386/Makefile | 2 +- cpu/i386/cpu.c | 44 +++++++++ cpu/i386/exceptions.c | 205 +++++++++++++++++++++++++++++++++++++++ cpu/i386/interrupts.c | 209 ---------------------------------------- include/asm-i386/u-boot-i386.h | 3 + lib_i386/board.c | 3 +- 6 files changed, 255 insertions(+), 211 deletions(-) create mode 100644 cpu/i386/exceptions.c diff --git a/cpu/i386/Makefile b/cpu/i386/Makefile index 761c4f6..f72cd6e 100644 --- a/cpu/i386/Makefile +++ b/cpu/i386/Makefile @@ -29,7 +29,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a START = start.o start16.o resetvec.o -COBJS = serial.o interrupts.o cpu.o timer.o +COBJS = serial.o interrupts.o exceptions.o cpu.o timer.o SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c index b9af5f8..70e575c 100644 --- a/cpu/i386/cpu.c +++ b/cpu/i386/cpu.c @@ -37,8 +37,30 @@ #include <command.h> #include <asm/interrupt.h> +struct idt_entry { + u16 base_low; + u16 selector; + u8 res; + u8 access; + u16 base_high; +} __attribute__ ((packed)); + +#define IDT_SIZE 256 + +static struct idt_entry idt[IDT_SIZE]; + +void __attribute__ ((regparm(0))) default_isr(void); +asm ("default_isr: iret\n"); + +asm ("idt_ptr:\n" + ".word 0x800\n" /* size of the table 8*256 bytes */ + ".long idt\n" /* offset */ + ".word 0x18\n"); /* data segment */ + int cpu_init(void) { + int i; + /* initialize FPU, reset EM, set MP and NE */ asm ("fninit\n" \ "movl %cr0, %eax\n" \ @@ -46,9 +68,31 @@ int cpu_init(void) "orl $0x22, %eax\n" \ "movl %eax, %cr0\n" ); + /* Just in case... */ + disable_interrupts(); + + /* Setup the IDT */ + for (i = 0; i < IDT_SIZE; i++) { + idt[i].access = 0x8e; + idt[i].res = 0; + idt[i].selector = 0x10; + set_vector(i, default_isr); + } + + asm ("cs lidt idt_ptr\n"); + + /* It is now safe to enable interrupts */ + enable_interrupts(); + return 0; } +void set_vector(int intnum, void *routine) +{ + idt[intnum].base_high = (u16)((u32)(routine)>>16); + idt[intnum].base_low = (u16)((u32)(routine)&0xffff); +} + int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { printf ("resetting ...\n"); diff --git a/cpu/i386/exceptions.c b/cpu/i386/exceptions.c new file mode 100644 index 0000000..55169b2 --- /dev/null +++ b/cpu/i386/exceptions.c @@ -0,0 +1,205 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, [EMAIL PROTECTED] + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/interrupt.h> + +asm ("exp_return:\n" + " addl $12, %esp\n" + " pop %esp\n" + " popa\n" + " iret\n"); + +char exception_stack[4096]; + +#define DECLARE_EXCEPTION(x, f) \ + asm(".globl exp_"#x"\n" \ + "exp_"#x":\n" \ + "pusha \n" \ + "movl %esp, %ebx\n" \ + "movl $exception_stack, %eax\n" \ + "movl %eax, %esp \n" \ + "pushl %ebx\n" \ + "movl 32(%esp), %ebx\n" \ + "xorl %edx, %edx\n" \ + "movw 36(%esp), %dx\n" \ + "pushl %edx\n" \ + "pushl %ebx\n" \ + "pushl $"#x"\n" \ + "pushl $exp_return\n" \ + "jmp "#f"\n"); \ + void __attribute__ ((regparm(0))) exp_##x(void) + +DECLARE_EXCEPTION(0, divide_exception_entry); /* Divide exception */ +DECLARE_EXCEPTION(1, debug_exception_entry); /* Debug exception */ +DECLARE_EXCEPTION(2, nmi_entry); /* NMI */ +DECLARE_EXCEPTION(3, unknown_exception_entry); /* Breakpoint/Coprocessor Error */ +DECLARE_EXCEPTION(4, unknown_exception_entry); /* Overflow */ +DECLARE_EXCEPTION(5, unknown_exception_entry); /* Bounds */ +DECLARE_EXCEPTION(6, invalid_instruction_entry); /* Invalid instruction */ +DECLARE_EXCEPTION(7, unknown_exception_entry); /* Device not present */ +DECLARE_EXCEPTION(8, double_fault_entry); /* Double fault */ +DECLARE_EXCEPTION(9, unknown_exception_entry); /* Co-processor segment overrun */ +DECLARE_EXCEPTION(10, invalid_tss_exception_entry);/* Invalid TSS */ +DECLARE_EXCEPTION(11, seg_fault_entry); /* Segment not present */ +DECLARE_EXCEPTION(12, stack_fault_entry); /* Stack overflow */ +DECLARE_EXCEPTION(13, gpf_entry); /* GPF */ +DECLARE_EXCEPTION(14, page_fault_entry); /* PF */ +DECLARE_EXCEPTION(15, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(16, fp_exception_entry); /* Floating point */ +DECLARE_EXCEPTION(17, alignment_check_entry); /* alignment check */ +DECLARE_EXCEPTION(18, machine_check_entry); /* machine check */ +DECLARE_EXCEPTION(19, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(20, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(21, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(22, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(23, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(24, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(25, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(26, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(27, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(28, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(29, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(30, unknown_exception_entry); /* Reserved */ +DECLARE_EXCEPTION(31, unknown_exception_entry); /* Reserved */ + +void __attribute__ ((regparm(0))) unknown_exception_entry(int cause, int ip, int seg) +{ + printf("Unknown Exception %d at %04x:%08x\n", cause, seg, ip); +} + +void __attribute__ ((regparm(0))) divide_exception_entry(int cause, int ip, int seg) +{ + printf("Divide Error (Division by zero) at %04x:%08x\n", seg, ip); + while(1); +} + +void __attribute__ ((regparm(0))) debug_exception_entry(int cause, int ip, int seg) +{ + printf("Debug Interrupt (Single step) at %04x:%08x\n", seg, ip); +} + +void __attribute__ ((regparm(0))) nmi_entry(int cause, int ip, int seg) +{ + printf("NMI Interrupt at %04x:%08x\n", seg, ip); +} + +void __attribute__ ((regparm(0))) invalid_instruction_entry(int cause, int ip, int seg) +{ + printf("Invalid Instruction at %04x:%08x\n", seg, ip); + while(1); +} + +void __attribute__ ((regparm(0))) double_fault_entry(int cause, int ip, int seg) +{ + printf("Double fault at %04x:%08x\n", seg, ip); + while(1); +} + +void __attribute__ ((regparm(0))) invalid_tss_exception_entry(int cause, int ip, int seg) +{ + printf("Invalid TSS at %04x:%08x\n", seg, ip); +} + +void __attribute__ ((regparm(0))) seg_fault_entry(int cause, int ip, int seg) +{ + printf("Segmentation fault at %04x:%08x\n", seg, ip); + while(1); +} + +void __attribute__ ((regparm(0))) stack_fault_entry(int cause, int ip, int seg) +{ + printf("Stack fault at %04x:%08x\n", seg, ip); + while(1); +} + +void __attribute__ ((regparm(0))) gpf_entry(int cause, int ip, int seg) +{ + printf("General protection fault at %04x:%08x\n", seg, ip); +} + +void __attribute__ ((regparm(0))) page_fault_entry(int cause, int ip, int seg) +{ + printf("Page fault at %04x:%08x\n", seg, ip); + while(1); +} + +void __attribute__ ((regparm(0))) fp_exception_entry(int cause, int ip, int seg) +{ + printf("Floating point exception at %04x:%08x\n", seg, ip); +} + +void __attribute__ ((regparm(0))) alignment_check_entry(int cause, int ip, int seg) +{ + printf("Alignment check at %04x:%08x\n", seg, ip); +} + +void __attribute__ ((regparm(0))) machine_check_entry(int cause, int ip, int seg) +{ + printf("Machine check exception at %04x:%08x\n", seg, ip); +} + +int exception_init(void) +{ + /* Just in case... */ + disable_interrupts(); + + /* Setup exceptions */ + set_vector(0x00, exp_0); + set_vector(0x01, exp_1); + set_vector(0x02, exp_2); + set_vector(0x03, exp_3); + set_vector(0x04, exp_4); + set_vector(0x05, exp_5); + set_vector(0x06, exp_6); + set_vector(0x07, exp_7); + set_vector(0x08, exp_8); + set_vector(0x09, exp_9); + set_vector(0x0a, exp_10); + set_vector(0x0b, exp_11); + set_vector(0x0c, exp_12); + set_vector(0x0d, exp_13); + set_vector(0x0e, exp_14); + set_vector(0x0f, exp_15); + set_vector(0x10, exp_16); + set_vector(0x11, exp_17); + set_vector(0x12, exp_18); + set_vector(0x13, exp_19); + set_vector(0x14, exp_20); + set_vector(0x15, exp_21); + set_vector(0x16, exp_22); + set_vector(0x17, exp_23); + set_vector(0x18, exp_24); + set_vector(0x19, exp_25); + set_vector(0x1a, exp_26); + set_vector(0x1b, exp_27); + set_vector(0x1c, exp_28); + set_vector(0x1d, exp_29); + set_vector(0x1e, exp_30); + set_vector(0x1f, exp_31); + + /* It is now safe to enable interrupts */ + enable_interrupts(); + + return 0; +} diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c index badb30b..1934fb1 100644 --- a/cpu/i386/interrupts.c +++ b/cpu/i386/interrupts.c @@ -28,19 +28,6 @@ #include <asm/ibmpc.h> #include <asm/interrupt.h> - -struct idt_entry { - u16 base_low; - u16 selector; - u8 res; - u8 access; - u16 base_high; -} __attribute__ ((packed)); - - -struct idt_entry idt[256]; - - #define MAX_IRQ 16 typedef struct irq_handler { @@ -63,14 +50,6 @@ asm ("irq_return:\n" " popa\n" " iret\n"); -asm ("exp_return:\n" - " addl $12, %esp\n" - " pop %esp\n" - " popa\n" - " iret\n"); - -char exception_stack[4096]; - #define DECLARE_INTERRUPT(x) \ asm(".globl irq_"#x"\n" \ "irq_"#x":\n" \ @@ -80,57 +59,6 @@ char exception_stack[4096]; "jmp do_irq\n"); \ void __attribute__ ((regparm(0))) irq_##x(void) -#define DECLARE_EXCEPTION(x, f) \ - asm(".globl exp_"#x"\n" \ - "exp_"#x":\n" \ - "pusha \n" \ - "movl %esp, %ebx\n" \ - "movl $exception_stack, %eax\n" \ - "movl %eax, %esp \n" \ - "pushl %ebx\n" \ - "movl 32(%esp), %ebx\n" \ - "xorl %edx, %edx\n" \ - "movw 36(%esp), %dx\n" \ - "pushl %edx\n" \ - "pushl %ebx\n" \ - "pushl $"#x"\n" \ - "pushl $exp_return\n" \ - "jmp "#f"\n"); \ - void __attribute__ ((regparm(0))) exp_##x(void) - -DECLARE_EXCEPTION(0, divide_exception_entry); /* Divide exception */ -DECLARE_EXCEPTION(1, debug_exception_entry); /* Debug exception */ -DECLARE_EXCEPTION(2, nmi_entry); /* NMI */ -DECLARE_EXCEPTION(3, unknown_exception_entry); /* Breakpoint/Coprocessor Error */ -DECLARE_EXCEPTION(4, unknown_exception_entry); /* Overflow */ -DECLARE_EXCEPTION(5, unknown_exception_entry); /* Bounds */ -DECLARE_EXCEPTION(6, invalid_instruction_entry); /* Invalid instruction */ -DECLARE_EXCEPTION(7, unknown_exception_entry); /* Device not present */ -DECLARE_EXCEPTION(8, double_fault_entry); /* Double fault */ -DECLARE_EXCEPTION(9, unknown_exception_entry); /* Co-processor segment overrun */ -DECLARE_EXCEPTION(10, invalid_tss_exception_entry);/* Invalid TSS */ -DECLARE_EXCEPTION(11, seg_fault_entry); /* Segment not present */ -DECLARE_EXCEPTION(12, stack_fault_entry); /* Stack overflow */ -DECLARE_EXCEPTION(13, gpf_entry); /* GPF */ -DECLARE_EXCEPTION(14, page_fault_entry); /* PF */ -DECLARE_EXCEPTION(15, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(16, fp_exception_entry); /* Floating point */ -DECLARE_EXCEPTION(17, alignment_check_entry); /* alignment check */ -DECLARE_EXCEPTION(18, machine_check_entry); /* machine check */ -DECLARE_EXCEPTION(19, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(20, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(21, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(22, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(23, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(24, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(25, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(26, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(27, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(28, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(29, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(30, unknown_exception_entry); /* Reserved */ -DECLARE_EXCEPTION(31, unknown_exception_entry); /* Reserved */ - DECLARE_INTERRUPT(0); DECLARE_INTERRUPT(1); DECLARE_INTERRUPT(3); @@ -147,9 +75,6 @@ DECLARE_INTERRUPT(13); DECLARE_INTERRUPT(14); DECLARE_INTERRUPT(15); -void __attribute__ ((regparm(0))) default_isr(void); -asm ("default_isr: iret\n"); - void disable_irq(int irq) { if (irq >= MAX_IRQ) { @@ -242,84 +167,6 @@ void __attribute__ ((regparm(0))) do_irq(int irq) specific_eoi(irq); } - -void __attribute__ ((regparm(0))) unknown_exception_entry(int cause, int ip, int seg) -{ - printf("Unknown Exception %d at %04x:%08x\n", cause, seg, ip); -} - -void __attribute__ ((regparm(0))) divide_exception_entry(int cause, int ip, int seg) -{ - printf("Divide Error (Division by zero) at %04x:%08x\n", seg, ip); - while(1); -} - -void __attribute__ ((regparm(0))) debug_exception_entry(int cause, int ip, int seg) -{ - printf("Debug Interrupt (Single step) at %04x:%08x\n", seg, ip); -} - -void __attribute__ ((regparm(0))) nmi_entry(int cause, int ip, int seg) -{ - printf("NMI Interrupt at %04x:%08x\n", seg, ip); -} - -void __attribute__ ((regparm(0))) invalid_instruction_entry(int cause, int ip, int seg) -{ - printf("Invalid Instruction at %04x:%08x\n", seg, ip); - while(1); -} - -void __attribute__ ((regparm(0))) double_fault_entry(int cause, int ip, int seg) -{ - printf("Double fault at %04x:%08x\n", seg, ip); - while(1); -} - -void __attribute__ ((regparm(0))) invalid_tss_exception_entry(int cause, int ip, int seg) -{ - printf("Invalid TSS at %04x:%08x\n", seg, ip); -} - -void __attribute__ ((regparm(0))) seg_fault_entry(int cause, int ip, int seg) -{ - printf("Segmentation fault at %04x:%08x\n", seg, ip); - while(1); -} - -void __attribute__ ((regparm(0))) stack_fault_entry(int cause, int ip, int seg) -{ - printf("Stack fault at %04x:%08x\n", seg, ip); - while(1); -} - -void __attribute__ ((regparm(0))) gpf_entry(int cause, int ip, int seg) -{ - printf("General protection fault at %04x:%08x\n", seg, ip); -} - -void __attribute__ ((regparm(0))) page_fault_entry(int cause, int ip, int seg) -{ - printf("Page fault at %04x:%08x\n", seg, ip); - while(1); -} - -void __attribute__ ((regparm(0))) fp_exception_entry(int cause, int ip, int seg) -{ - printf("Floating point exception at %04x:%08x\n", seg, ip); -} - -void __attribute__ ((regparm(0))) alignment_check_entry(int cause, int ip, int seg) -{ - printf("Alignment check at %04x:%08x\n", seg, ip); -} - -void __attribute__ ((regparm(0))) machine_check_entry(int cause, int ip, int seg) -{ - printf("Machine check exception at %04x:%08x\n", seg, ip); -} - - void irq_install_handler(int ino, interrupt_handler_t *func, void *pdata) { int status; @@ -371,19 +218,6 @@ void irq_free_handler(int ino) return; } - -asm ("idt_ptr:\n" - ".word 0x800\n" /* size of the table 8*256 bytes */ - ".long idt\n" /* offset */ - ".word 0x18\n");/* data segment */ - -void set_vector(int intnum, void *routine) -{ - idt[intnum].base_high = (u16)((u32)(routine)>>16); - idt[intnum].base_low = (u16)((u32)(routine)&0xffff); -} - - int interrupt_init(void) { int i; @@ -396,49 +230,6 @@ int interrupt_init(void) memset(irq_table, 0, sizeof(irq_table)); - /* Setup the IDT */ - for (i=0;i<256;i++) { - idt[i].access = 0x8e; - idt[i].res = 0; - idt[i].selector = 0x10; - set_vector(i, default_isr); - } - - asm ("cs lidt idt_ptr\n"); - - /* Setup exceptions */ - set_vector(0x00, exp_0); - set_vector(0x01, exp_1); - set_vector(0x02, exp_2); - set_vector(0x03, exp_3); - set_vector(0x04, exp_4); - set_vector(0x05, exp_5); - set_vector(0x06, exp_6); - set_vector(0x07, exp_7); - set_vector(0x08, exp_8); - set_vector(0x09, exp_9); - set_vector(0x0a, exp_10); - set_vector(0x0b, exp_11); - set_vector(0x0c, exp_12); - set_vector(0x0d, exp_13); - set_vector(0x0e, exp_14); - set_vector(0x0f, exp_15); - set_vector(0x10, exp_16); - set_vector(0x11, exp_17); - set_vector(0x12, exp_18); - set_vector(0x13, exp_19); - set_vector(0x14, exp_20); - set_vector(0x15, exp_21); - set_vector(0x16, exp_22); - set_vector(0x17, exp_23); - set_vector(0x18, exp_24); - set_vector(0x19, exp_25); - set_vector(0x1a, exp_26); - set_vector(0x1b, exp_27); - set_vector(0x1c, exp_28); - set_vector(0x1d, exp_29); - set_vector(0x1e, exp_30); - set_vector(0x1f, exp_31); /* Setup interrupts */ diff --git a/include/asm-i386/u-boot-i386.h b/include/asm-i386/u-boot-i386.h index 12d10a7..8d079ae 100644 --- a/include/asm-i386/u-boot-i386.h +++ b/include/asm-i386/u-boot-i386.h @@ -45,6 +45,9 @@ extern ulong i386boot_bios_size; /* size of BIOS emulation code */ int cpu_init(void); int timer_init(void); +/* cpu/.../exceptions.c */ +int exception_init(void); + /* board/.../... */ int board_init(void); int dram_init(void); diff --git a/lib_i386/board.c b/lib_i386/board.c index 659f9a2..ee7d794 100644 --- a/lib_i386/board.c +++ b/lib_i386/board.c @@ -201,7 +201,8 @@ init_fnc_t *init_sequence[] = { board_init, /* basic board dependent setup */ dram_init, /* configure available RAM banks */ mem_malloc_init, /* dependant on dram_init */ - interrupt_init, /* set up exceptions */ + interrupt_init, /* set up interrupts */ + exception_init, /* set up exceptions */ timer_init, serial_init, env_init, /* initialize environment */ -- 1.5.4.3
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot