⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idt.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
字号:
/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * 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, * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <kerninc/kernel.hxx>#include <kerninc/IRQ.hxx>#include <kerninc/Thread.hxx>#include <kerninc/util.h>#include <kerninc/Debug.hxx>#include <kerninc/SysTimer.hxx>#include <kerninc/Task.hxx>#include <kerninc/Process.hxx>#include <eros/i486/io.h>#include "lostart.hxx"#include "IDT.hxx"#include "GDT.hxx"/* #define TIMING_DEBUG *//* #define INTRDEBUG */extern "C" {  extern uint32_t InterruptStackTop;  extern uint32_t InterruptStackBottom;  extern uint32_t InterruptStackLimit;  extern int _start;  extern int etext;}/* EROS IDT has null, code, data/stack, TSS */#define IDT_SIZE (IDT_ENTRIES * 8)#define IDT_CODE_ENTRY 0x8#define IDT_DATA_ENTRY 0x10#define IDT_STACK_ENTRY 0x10/* The gate interrupt number should not be zero, because * distinguishing it from divide-by-zero is too hard. There are just * too many things that show up with an exception code of zero. It * probably should be greater than 0x2f, so as to guarantee that it * will not collide with any hardware-generated interrupts.  While it * is possible to detect that an interrupt <= 0x2f was generated by an * INT instruction, it is hard enough that we want to avoid it on the * key invocation path. *  */class IDT IDT;extern "C" {  extern void istub0x00(void);  extern void istub0x01(void);  extern void istub0x02(void);  extern void istub0x03(void);  extern void istub0x04(void);  extern void istub0x05(void);  extern void istub0x06(void);  extern void istub0x07(void);  extern void istub0x08(void);  extern void istub0x09(void);  extern void istub0x0a(void);  extern void istub0x0b(void);  extern void istub0x0c(void);  extern void istub0x0d(void);  extern void istub0x0e(void);  extern void istub0x0f(void);  extern void istub0x10(void);  extern void istub0x11(void);  extern void istub0x12(void);  extern void istub0x13(void);  extern void istub0x14(void);  extern void istub0x15(void);  extern void istub0x16(void);  extern void istub0x17(void);  extern void istub0x18(void);  extern void istub0x19(void);  extern void istub0x1a(void);  extern void istub0x1b(void);  extern void istub0x1c(void);  extern void istub0x1d(void);  extern void istub0x1e(void);  extern void istub0x1f(void);  extern void intr_clock(void);  extern void istub0x21(void);  extern void istub0x22(void);  extern void istub0x23(void);  extern void istub0x24(void);  extern void istub0x25(void);  extern void istub0x26(void);  extern void istub0x27(void);  extern void istub0x28(void);  extern void istub0x29(void);  extern void istub0x2a(void);  extern void istub0x2b(void);  extern void istub0x2c(void);  extern void istub0x2d(void);  extern void istub0x2e(void);  extern void istub0x2f(void);  extern void istub0x30(void);	/* first purely software interrupt */  extern void intr_InvokeKey(void);	/* key invocation interrupt */  extern void intr_CapInstr(void);	/* kernel-emulated instructions */}/* Stashing the bindings in a table is slightly more space efficient * than initializing them explicitly: */struct {  void (*stub)(void);  bool allowUser;} IntStub[IDT_ENTRIES] = {  { istub0x00, false },  { istub0x01, false },  { istub0x02, false },  { istub0x03, true },  { istub0x04, true },  { istub0x05, true },  { istub0x06, false },  { istub0x07, false },  { istub0x08, false },  { istub0x09, false },  { istub0x0a, false },  { istub0x0b, false },  { istub0x0c, false },  { istub0x0d, false },  { istub0x0e, false },  { istub0x0f, false },  { istub0x10, false },  { istub0x11, false },  { istub0x12, false },  { istub0x13, false },  { istub0x14, false },  { istub0x15, false },  { istub0x16, false },  { istub0x17, false },  { istub0x18, false },  { istub0x19, false },  { istub0x1a, false },  { istub0x1b, false },  { istub0x1c, false },  { istub0x1d, false },  { istub0x1e, false },  { istub0x1f, false },  { intr_clock, false },  { istub0x21, false },  { istub0x22, false },  { istub0x23, false },  { istub0x24, false },  { istub0x25, false },  { istub0x26, false },  { istub0x27, false },  { istub0x28, false },  { istub0x29, false },  { istub0x2a, false },  { istub0x2b, false },  { istub0x2c, false },  { istub0x2d, false },  { istub0x2e, false },  { istub0x2f, false },  { istub0x30, false },		/* voluntary yield */  { intr_InvokeKey, true  },	/* key invocation interrupt */  { intr_CapInstr, true  }	/* kernel-emulated instructions */};GateDescriptor IdtTable[IDT_ENTRIES];/* *** INLINE FUNCTIONS FIRST */voidIDT::SetEntry(int entry, void (*procPtr)(void), bool allowUser){  uint32_t wProcPtr = (uint32_t) procPtr;  IdtTable[entry].loOffset = (uint16_t) wProcPtr;  IdtTable[entry].selector = Selector::KernelCode;  IdtTable[entry].zero = 0;  IdtTable[entry].type = 0xeu;  IdtTable[entry].system = 0;  /* Use RPL==1 for non-user so kernel threads can call them. */  IdtTable[entry].dpl = allowUser ? 3 : 1;  IdtTable[entry].present = 1;  IdtTable[entry].hiOffset = (uint16_t) (wProcPtr >> 16);}/* Moving this to IPC-vars has no appreciable impact. */IDT::VecFn IDT::IntVecEntry[IDT_ENTRIES];uint32_t IDT::IDTdescriptor[2];/* Note that the IDT gets set up immediately following the GDT, modulo * possibly being rounded up to an 8 byte boundary.  This causes them * both to live on the same page, which allows us to move them around * to get out of the way of the running domain as necessary. */voidIDT::Init(){  uint32_t widt;  uint32_t vec;  /* Wire up IDT entries and set up to handle unbound vectors: */  for (vec = 0; vec < IDT_ENTRIES; vec++) {    IdtTable[vec].present = 0;    WireVector(vec, UnboundVector);    SetEntry(vec, IntStub[vec].stub, IntStub[vec].allowUser);  }    /* Now set up to handle interrupts: */  for (vec = IntVec::IRQ0; vec <= IntVec::IRQ15; vec++)    WireVector(vec, IRQ::UnboundInterrupt);    /* Hand-wire a couple of common cases: */  WireVector(IntVec::Yield, YieldVector);  extern void BadOpcode(fixregs_t *sa);  extern void DivZeroFault(fixregs_t *sa);  extern void GPFault(fixregs_t *sa);  extern void SSFault(fixregs_t *sa);  extern void SegNotPresFault(fixregs_t *sa);  extern void BptTrap(fixregs_t *sa);  extern void PageFault(fixregs_t *sa);  extern void DebugException(fixregs_t *sa);  extern void ReservedException(fixregs_t *sa);  extern void DeviceNotAvailException(fixregs_t *sa);  extern void PseudoInstrException(fixregs_t *sa);  /* Hand-wire the processor-generated exceptions: */  WireVector(IntVec::BadOpcode, BadOpcode);  WireVector(IntVec::DivZero, DivZeroFault);  WireVector(IntVec::GeneralProtection, GPFault);  WireVector(IntVec::StackSeg, SSFault);  WireVector(IntVec::SegNotPresent, SegNotPresFault);  WireVector(IntVec::BreakPoint, BptTrap);  WireVector(IntVec::PageFault, PageFault);  WireVector(IntVec::Debug, DebugException);  WireVector(IntVec::DeviceNotAvail, DeviceNotAvailException);  WireVector(IntVec::EmulPseudoInstr, PseudoInstrException);  WireVector((IntVec::Type) 0xf, ReservedException);  for (int i = 0x11; i <= 0x1f; i++)    WireVector((IntVec::Type) i, ReservedException);#if 0  /* This path no longer comes through here... */  WireVector(IntVec::InvokeKey, Invoke);#endif    SetupInterruptControllers();    widt = KVTOL(IdtTable);	  IDTdescriptor[0] = IDT_SIZE | ((widt & 0xffff) << 16);  IDTdescriptor[1] = widt >> 16;  lidt();}voidIDT::SetupInterruptControllers(){  /* Set up the interrupt controller chip: */  old_outb(0x20, 0x11);		/* ctrlr1 init - edge triggered */  old_outb(0x21, 0x20);		/* interrupts from 0x20 to 0x27 */  old_outb(0x21, 0x4);		/* cascade on IRQ2 */  old_outb(0x21, 0x1);		/* 8086 mode */  old_outb(0x21, 0xff);		/* disable interrupts on pic1 */  old_outb(0xa0, 0x11);		/* ctrlr2 init - edge triggered */  old_outb(0xa1, 0x28);		/* interrupts from 0x28 to 0x2f */  old_outb(0xa1, 0x2);		/* cascade on IRQ2 */  old_outb(0xa1, 0x1);		/* 8086 mode */  old_outb(0xa1, 0xff);		/* disable interrupts on pic1 */  old_outb(0x20,0x20);		/* reset pic1 */  old_outb(0xa0,0x20);		/* reset pic2 */}#if 0extern void CheckConsistency(const char *);extern bool CheckUserContexts(const char *);#endifvoidIDT::UnboundVector(fixregs_t *saveArea){#if 0  fatal(		"** Unbound vector 0x%x  EIP =  0x%x  FVA=0x%08x  Code=0x%x\n"		"   Trap Depth = %d pic1 = 0x%02x pic2 = 0x%02x\n",		saveArea->ExceptionNo, saveArea->EIP,		saveArea->ExceptionAddr, saveArea->Error,		TrapDepth, pic1_cache, pic2_cache);#else  fatal(		"** Unbound vector 0x%x  EIP =  0x%x  FVA=0x%08x  Code=0x%x\n",		saveArea->ExceptNo, saveArea->EIP,		saveArea->ExceptAddr, saveArea->Error);#endif}voidIDT::YieldVector(fixregs_t * /* sa */){  /* Simply set the global that indicates we must reschedule.  This   * could be inlined, but since it only happens in kernel-mode   * interrupts (and then infrequently) it's better not to stick more   * tests on the common interrupt path.   */    Thread::ForceResched();}/* register an interrupt handler */voidIDT::WireVector(uint32_t vector, void (*pf)(fixregs_t* sa)){  IRQ::DISABLE();  IntVecEntry[vector] = pf;  IRQ::ENABLE();}voidIRQ::SetHandler(uint32_t irq, void (*pf)(fixregs_t *sa)){  printf("Setting irq %d\n", irq);  IDT::WireVector(IntVec::IRQ0 + irq, pf);}InterruptHandlerIRQ::GetHandler(uint32_t irq){  return IDT::GetVector(IntVec::IRQ0 + irq);}voidIRQ::UnsetHandler(uint32_t irq){  assert (irq >= 0 && irq <= 15);  printf("Unsetting irq %d\n", irq);  IDT::WireVector(IntVec::IRQ0 + irq, IRQ::UnboundInterrupt);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -