
git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@123 315a16e6-25f9-4109-90ae-ca3045a26c18
180 lines
7.6 KiB
C
180 lines
7.6 KiB
C
/*
|
|
* Copyright 2010 Stefan Lankes, Chair for Operating Systems,
|
|
* RWTH Aachen University
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* This file is part of MetalSVM.
|
|
*/
|
|
|
|
#include <metalsvm/stdio.h>
|
|
#include <metalsvm/string.h>
|
|
#include <metalsvm/tasks.h>
|
|
#include <asm/irqflags.h>
|
|
#include <asm/isrs.h>
|
|
#include <asm/idt.h>
|
|
|
|
/*
|
|
* These are function prototypes for all of the exception
|
|
* handlers: The first 32 entries in the IDT are reserved
|
|
* by Intel, and are designed to service exceptions!
|
|
*/
|
|
extern void isr0(void);
|
|
extern void isr1(void);
|
|
extern void isr2(void);
|
|
extern void isr3(void);
|
|
extern void isr4(void);
|
|
extern void isr5(void);
|
|
extern void isr6(void);
|
|
extern void isr7(void);
|
|
extern void isr8(void);
|
|
extern void isr9(void);
|
|
extern void isr10(void);
|
|
extern void isr11(void);
|
|
extern void isr12(void);
|
|
extern void isr13(void);
|
|
extern void isr14(void);
|
|
extern void isr15(void);
|
|
extern void isr16(void);
|
|
extern void isr17(void);
|
|
extern void isr18(void);
|
|
extern void isr19(void);
|
|
extern void isr20(void);
|
|
extern void isr21(void);
|
|
extern void isr22(void);
|
|
extern void isr23(void);
|
|
extern void isr24(void);
|
|
extern void isr25(void);
|
|
extern void isr26(void);
|
|
extern void isr27(void);
|
|
extern void isr28(void);
|
|
extern void isr29(void);
|
|
extern void isr30(void);
|
|
extern void isr31(void);
|
|
|
|
/*
|
|
* This is a very repetitive function... it's not hard, it's
|
|
* just annoying. As you can see, we set the first 32 entries
|
|
* in the IDT to the first 32 ISRs. We can't use a for loop
|
|
* for this, because there is no way to get the function names
|
|
* that correspond to that given entry. We set the access
|
|
* flags to 0x8E. This means that the entry is present, is
|
|
* running in ring 0 (kernel level), and has the lower 5 bits
|
|
* set to the required '14', which is represented by 'E' in
|
|
* hex.
|
|
*/
|
|
void isrs_install(void)
|
|
{
|
|
idt_set_gate(0, (unsigned)isr0, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(1, (unsigned)isr1, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(2, (unsigned)isr2, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(3, (unsigned)isr3, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(4, (unsigned)isr4, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(5, (unsigned)isr5, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(6, (unsigned)isr6, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(7, (unsigned)isr7, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(8, (unsigned)isr8, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(9, (unsigned)isr9, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(10, (unsigned)isr10, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(11, (unsigned)isr11, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(12, (unsigned)isr12, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(13, (unsigned)isr13, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(14, (unsigned)isr14, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(15, (unsigned)isr15, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(16, (unsigned)isr16, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(17, (unsigned)isr17, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(18, (unsigned)isr18, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(19, (unsigned)isr19, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(20, (unsigned)isr20, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(21, (unsigned)isr21, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(22, (unsigned)isr22, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(23, (unsigned)isr23, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(24, (unsigned)isr24, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(25, (unsigned)isr25, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(26, (unsigned)isr26, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(27, (unsigned)isr27, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(28, (unsigned)isr28, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(29, (unsigned)isr29, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(30, (unsigned)isr30, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
idt_set_gate(31, (unsigned)isr31, KERNEL_CODE_SELECTOR,
|
|
IDT_FLAG_PRESENT|IDT_FLAG_RING0|IDT_FLAG_32BIT|IDT_FLAG_INTTRAP);
|
|
}
|
|
|
|
/*
|
|
* This is a simple string array. It contains the message that
|
|
* corresponds to each and every exception. We get the correct
|
|
* message by accessing like:
|
|
* exception_message[interrupt_number]
|
|
*/
|
|
static const char *exception_messages[] = {
|
|
"Division By Zero", "Debug", "Non Maskable Interrupt",
|
|
"Breakpoint", "Into Detected Overflow", "Out of Bounds", "Invalid Opcode",
|
|
"No Coprocessor", "Double Fault", "Coprocessor Segment Overrun", "Bad TSS",
|
|
"Segment Not Present", "Stack Fault", "General Protection Fault", "Page Fault",
|
|
"Unknown Interrupt", "Coprocessor Fault", "Alignment Check", "Machine Check",
|
|
"Reserved", "Reserved", "Reserved", "Reserved", "Reserved",
|
|
"Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved",
|
|
"Reserved", "Reserved" };
|
|
|
|
/*
|
|
* All of our Exception handling Interrupt Service Routines will
|
|
* point to this function. This will tell us what exception has
|
|
* happened! Right now, we simply abort the current task.
|
|
* All ISRs disable interrupts while they are being
|
|
* serviced as a 'locking' mechanism to prevent an IRQ from
|
|
* happening and messing up kernel data structures
|
|
*/
|
|
void fault_handler(struct state *s)
|
|
{
|
|
if (s->int_no < 32) {
|
|
kputs(exception_messages[s->int_no]);
|
|
kputs(" Exception.\n");
|
|
|
|
/* Now, we signalize that we have handled the interrupt */
|
|
outportb(0x20, 0x20);
|
|
irq_enable();
|
|
|
|
abort();
|
|
}
|
|
}
|