I will post certain pieces of code as time permits. (Very busy at the moment.)
I have IDTs set-up with the following code:
idt.c:
Code:
/*
* idt.c
* x86 interrupt descriptor table definition and initialization.
* For WolfNet OS
* By John Wolfe 2015
*/
/* LibC headers. */
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* LibK headers. */
#include <arch.h>
#include <kernelint.h>
#include <core/interrupts.h>
#include <drivers/virt_ic.h>
/*
* Name Bit Full Name Description
* Offset 48..63 Offset 16..31 Higher part of the offset.
* P 47 Present Set to 0 for unused interrupts.
* DPL 45,46 Descriptor Privilege Level Gate call protection. Specifies the lowest privilege Level the caller can have. So hardware and CPU interrupts can be protected from being called out of userspace.
* S 44 Storage Segment Set to 0 for interrupt gates (see below).
* Type 40..43 Gate Type 0..3
* IDT gate types:
* 0b0101 0x5 32 bit task gate
* 0b0110 0x6 16-bit interrupt gate
* 0b0111 0x7 16-bit trap gate
* 0b1110 0xE 32-bit interrupt gate
* 0b1111 0xF 32-bit trap gate
* 0 32..39 Unused 0..7 Have to be 0.
* Selector 16..31 Selector 0..15 Selector of the interrupt function (to make sense - the kernel's selector). The selector's descriptor's DPL field has to be 0.
* Offset 0..15 Offset 0..15 Lower part of the interrupt function's offset address (also known as pointer).
*/
static inline void idt_defineidtr(void*, kernel_uint16_t);
void idt_initialize(void)
{
printf("Initializing IDT...\n");
for (int i = 0; i < (IDT_ENTRIES - 1); ++i) {
memset(&idt[i], '0', sizeof(idt_table_t));
}
#ifdef __debug_kernel
printf("sizeof(idt): %u bytes.\n", (unsigned int) sizeof(idt));
printf("sizeof idt_table_t: %u bytes.\n", (unsigned int) sizeof(idt_table_t));
printf("idt_table_t.offset_1 offset: %u bytes.\n", (unsigned int) offsetof(idt_table_t, offset_1));
printf("idt_table_t.selector offset: %u bytes.\n", (unsigned int) offsetof(idt_table_t, selector));
printf("idt_table_t.zero offset: %u bytes.\n", (unsigned int) offsetof(idt_table_t, zero));
printf("idt_table_t.type_attr offset: %u bytes.\n", (unsigned int) offsetof(idt_table_t, type_attr));
printf("idt_table_t.offset_2 offset: %u bytes.\n", (unsigned int) offsetof(idt_table_t, offset_2));
#endif
idt_defineidtr(&idt, sizeof(idt));
printf("IDT initialization complete!\n");
}
void idt_encode_entry(void* idt_entry, kernel_uint16_t selector, void* offset, kernel_uint8_t gate_type, kernel_uint8_t priv_level, kernel_uint8_t used_bit)
{
idt_table_t* new_entry = (idt_table_t*) idt_entry;
kernel_uint32_t pointer = (kernel_uint32_t) offset;
new_entry->offset_1 = (kernel_uint16_t) pointer & 0xFFFF;
new_entry->offset_2 = (kernel_uint16_t) pointer >> 16;
new_entry->selector = selector; /* NOTE: Minimum privilege for calling process. */
new_entry->zero = 0; /* NOTE: THIS MUST NEVER BE CHANGED! */
new_entry->type_attr = gate_type & 0x0F;
new_entry->type_attr |= (priv_level & 0x03) << 5;
if (used_bit == 1) {
new_entry->type_attr |= 0x80;
}
else if (used_bit == 0) {
new_entry->type_attr &= ~(0x80);
}
if (gate_type == 0xE || gate_type == 0x6) {
new_entry->type_attr &= ~(0x10); /* NOTE: This is always set to zero for interrupt gates. */
}
}
/* IDT definition function. */
static inline void idt_defineidtr(void* base, kernel_uint16_t size)
{
typedef struct lidt_data {
kernel_uint16_t length;
kernel_uint32_t base;
} __attribute__((packed)) lidt_data_t;
lidt_data_t lidt_data;
lidt_data.length = size;
lidt_data.base = (kernel_uint32_t) base;
if (offsetof(lidt_data_t, base) != 2) {
printf("IDT Error: LIDT base offset = %u\n", (unsigned int) offsetof(lidt_data_t, base));
kernel_exit();
}
#ifdef __debug_kernel
printf("LIDT length offset = %u\n", (unsigned int) offsetof(lidt_data_t, length));
printf("LIDT length base = %u\n", (unsigned int) offsetof(lidt_data_t, base));
#endif
__asm__ __volatile__ ("lidt (%0)"::"r"(&lidt_data));
}
Because my most recent try was using the ISRs PIC and Multitasking method each entry is initialized in interrupts_initialize() by:
Code:
idt_encode_entry(idt+32, KERNEL_CODE_DESCRIPTOR, irq0handler, INTERRUPT_GATE, 0, 1);
arch.h:
This points to x86.h on the x86 and x86_64 (x86_64 is unimplemented.)
x86.h:
Code:
/* IDT. */
void idt_initialize(void);
void idt_encode_entry(void*, kernel_uint16_t, void *, kernel_uint8_t, kernel_uint8_t, kernel_uint8_t);
Interrupt handlers defined in 8259_pic.h, this file (during it's init routine) install the functions to function pointers in virt_ic.h
The handlers are defined in interrupts_init.c where the idt entries are encoded using the method described in ISRs PIC and Multitasking.
If any more information is required, feel free to PM me for a tarball or more snippets.