void install_apicIRQs(void) { /* install all additional IRQs */ #ifdef SMP iInfos[CALL_FUNCTION_IRQNR].used = 1; iInfos[CALL_FUNCTION_IRQNR].vector_number = CALL_FUNCTION_VECTOR; iInfos[CALL_FUNCTION_IRQNR].functions = &ipIRQ; /* install the IPI-Handlers*/ int_gate(CALL_FUNCTION_VECTOR, &call_function_ipi, 0x80 /*present bit */ | 14 /*irq gate */ ); #endif iInfos[LAPIC_TIMER_IRQNR].used = 1; iInfos[LAPIC_TIMER_IRQNR].vector_number = LAPIC_TIMER_VECTOR; iInfos[LAPIC_TIMER_IRQNR].functions = &local_timer_IRQ; #ifdef TIMESLICING_TIMER_IRQ /* the system timer IRQ0 is set to hwint00apic ->"=disabled" */ iInfos[0].used = 0; int_gate(iInfos[0].vector_number, hwint00apic, 0x80 /*present bit */ | 14 /*irq gate */ ); #endif /* install the local APIC timer-Handlers*/ int_gate(LAPIC_TIMER_VECTOR, local_timer_int, 0x80 /*present bit */ | 14 /*irq gate */ ); /* install the error and spurious Handlers*/ int_gate(SPURIOUS_APIC_VECTOR, spurious_apic, 0x80 /*present bit */ | 14 /*irq gate */ ); int_gate(ERROR_APIC_VECTOR, error_apic, 0x80 /*present bit */ | 14 /*irq gate */ ); }
/** * \brief Set up tables for protected mode * All GDT slots are allocated at compile time */ void prot_init() { struct gate_table_s *gtp; struct desctableptr_s *dtp; unsigned ldt_index; struct proc *rp; static struct gate_table_s { void (*gate)(void); unsigned char vec_nr; unsigned char privilege; } gate_table[] = { { divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE }, { single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE }, { nmi, NMI_VECTOR, INTR_PRIVILEGE }, { breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE }, { overflow, OVERFLOW_VECTOR, USER_PRIVILEGE }, { bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE }, { inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE }, { copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE }, { double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE }, { copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE }, { inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE }, { segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE }, { stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE }, { general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE }, { page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE }, { copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE }, { hwint00, IRQ0_VECTOR + CLOCK_IRQ, INTR_PRIVILEGE }, { hwint01, IRQ0_VECTOR + KEYBOARD_IRQ, INTR_PRIVILEGE }, { hwint02, IRQ0_VECTOR + CASCADE_IRQ, INTR_PRIVILEGE }, { hwint03, IRQ0_VECTOR + ETHER_IRQ, INTR_PRIVILEGE }, { hwint04, IRQ0_VECTOR + RS232_IRQ, INTR_PRIVILEGE }, { hwint05, IRQ0_VECTOR + 5, INTR_PRIVILEGE }, { hwint06, IRQ0_VECTOR + 6, INTR_PRIVILEGE }, { hwint07, IRQ0_VECTOR + 7, INTR_PRIVILEGE }, { hwint08, IRQ0_VECTOR + 8, INTR_PRIVILEGE }, { hwint09, IRQ0_VECTOR + 9, INTR_PRIVILEGE }, { hwint10, IRQ0_VECTOR + 10, INTR_PRIVILEGE }, { hwint11, IRQ0_VECTOR + 11, INTR_PRIVILEGE }, { hwint12, IRQ0_VECTOR + 12, INTR_PRIVILEGE }, { hwint13, IRQ0_VECTOR + 13, INTR_PRIVILEGE }, { hwint14, IRQ0_VECTOR + IDE_IRQ, INTR_PRIVILEGE }, { hwint15, IRQ0_VECTOR + 15, INTR_PRIVILEGE }, { s_call, SYS_VECTOR, USER_PRIVILEGE }, // system call { level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE }, }; /* since it is now in protected mode and it enters protected mode * in boot loader where global segment descriptor is set up to * map all physical memory, that is base is 0, and limit is MAX * physical memory - 1 * * so here when apply vir2phys ( kinfo.data_base + vir ), still * get vir */ // Build gdt and idt pointers in GDT where the BIOS expects them dtp = (struct desctableptr_s *) &gdt[GDT_INDEX]; *((u16_t *) dtp->limit) = (sizeof gdt) - 1; *((u32_t *) dtp->base) = vir2phys(gdt); dtp = (struct desctableptr_s *) &gdt[IDT_INDEX]; *((u16_t *) dtp->limit) = (sizeof idt) - 1; *((u32_t *) dtp->base) = vir2phys(idt); // Build segment descriptors for tasks and interrupt handlers init_codeseg(&gdt[CS_INDEX], kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE); init_dataseg(&gdt[DS_INDEX], kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE); init_dataseg(&gdt[ES_INDEX], 0L, 0, TASK_PRIVILEGE); // Build scratch descriptors for functions in klib88 init_dataseg(&gdt[DS_286_INDEX], 0L, 0, TASK_PRIVILEGE); init_dataseg(&gdt[ES_286_INDEX], 0L, 0, TASK_PRIVILEGE); /* Build local descriptors in GDT for LDT's in process table. * The LDT's are allocated at compile time in the process table, and * initialized whenever a process' map is initialized or changed. */ for (rp = BEG_PROC_ADDR, ldt_index = FIRST_LDT_INDEX; rp < END_PROC_ADDR; ++rp, ldt_index++) { init_dataseg(&gdt[ldt_index], vir2phys(rp->p_ldt), sizeof(rp->p_ldt), INTR_PRIVILEGE); gdt[ldt_index].access = PRESENT | LDT; rp->p_ldt_sel = ldt_index * DESC_SIZE; } /* Build main TSS. * This is used only to record the stack pointer to be used after an interrupt. * Actually it points to stackframe of proc * * The pointer is set up so that an interrupt automatically saves the * current process's registers eip:cs:eflags:esp:ss in the correct slots in the * process table. */ tss.ss0 = DS_SELECTOR; init_dataseg(&gdt[TSS_INDEX], vir2phys(&tss), sizeof(tss), INTR_PRIVILEGE); gdt[TSS_INDEX].access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE; // Build descriptors for interrupt gates in IDT for (gtp = &gate_table[0]; gtp < &gate_table[sizeof gate_table / sizeof gate_table[0]]; ++gtp) { int_gate(gtp->vec_nr, (vir_bytes) gtp->gate, PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT)); } // Complete building of main TSS tss.iobase = sizeof tss; // empty i/o permissions map }