Interrupts mostly working, frame seems to be offset by one tho

This commit is contained in:
c0repwn3r 2022-05-14 12:42:37 -04:00
parent 5ba67be4c0
commit c2f8ccdf2e
Signed by: core
GPG Key ID: FDBF740DADDCEECF
21 changed files with 452 additions and 25 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,9 @@
#ifndef GDT_H
#define GDT_H
#define KERNEL_CODE 0x08
#define KERNEL_DATA 0x10
#define USERLAND_CODE 0x18
#define USERLAND_DATA 0x20
#endif

View File

@ -0,0 +1,38 @@
#ifndef IDT_H
#define IDT_H
#include <stdint.h>
#include <stdbool.h>
#include <shade/platform/gdt.h>
#define IDT_DESCRIPTORS 256
extern void* isr_stub_table[];
typedef struct idt_entry_struct {
uint16_t isr_low; // Low 16 bits of handler address
uint16_t kernel_cs; // The selector in the GDT that the CPU will load into CS before calling the handler
uint8_t ist; // The IST in the TSS that the CPU will load into RSP; set to zero for now
uint8_t attributes; // Type and attributes
uint16_t isr_mid; // Middle 16 bits of handler address
uint32_t isr_high; // Upper 32 bits of handler address
uint32_t reserved; // Reserved, set to 0
} __attribute__((packed)) idt_descriptor_t;
typedef struct idt_ptr_struct {
uint16_t limit;
uint64_t base;
} __attribute__((packed)) idt_ptr_t;
__attribute__((aligned(0x10)))
static idt_descriptor_t idt[IDT_DESCRIPTORS];
static idt_ptr_t idt_ptr;
static bool vectors[IDT_DESCRIPTORS];
void idt_set_gate(uint8_t index, void* isr, uint8_t flags);
void idt_assemble();
void idt_enable_interrupts();
void idt_disable_interrupts();
#endif

View File

@ -0,0 +1,45 @@
#ifndef ISR_H
#define ISR_H
#include <stdint.h>
#define ERR_MAX 5
static int err_count = 0;
typedef struct {
struct {
uint64_t cr4;
uint64_t cr3;
uint64_t cr2;
uint64_t cr0;
} control_registers;
struct {
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t rbx;
uint64_t rax;
} general_registers;
struct {
uint64_t rbp;
uint64_t vector;
uint64_t error_code;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t dss;
} base_frame;
} isr_xframe_t;
__attribute__((noreturn))
void exception_handler(isr_xframe_t frame);
__attribute__((noreturn))
void interrupt_handler(isr_xframe_t frame);
#endif

View File

@ -0,0 +1,40 @@
#ifndef PIC_H
#define PIC_H
#include <stdint.h>
#define PIC1 0x20 /* IO base address for master PIC */
#define PIC2 0xA0 /* IO base address for slave PIC */
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define PIC_EOI 0x20 /* End-of-interrupt command code */
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
void pic_send_eoi(uint8_t irq);
void pic_remap(int offset1, int offset2);
void pic_mask_irq(uint8_t irq);
void pic_unmask_irq(uint8_t irq);
static uint16_t __pic_get_irq_reg(int ocw3);
uint16_t pic_get_irr();
uint16_t pic_get_isr();
#endif

View File

@ -1,4 +1,11 @@
unsigned char port_byte_in(unsigned short port);
void port_byte_out(unsigned short port, unsigned char data);
unsigned short port_word_in(unsigned short port);
void port_word_out(unsigned short port, unsigned short data);
#ifndef PORTS_H
#define PORTS_H
unsigned char inb(unsigned short port);
void outb(unsigned short port, unsigned char data);
unsigned short inw(unsigned short port);
void outw(unsigned short port, unsigned short data);
void io_wait();
#endif

View File

@ -3,6 +3,5 @@
void memcpy(char *source, char *dest, int nbytes);
void memset(char *dest, char val, int len);
void int_to_ascii(int n, char str[]);
#endif

View File

@ -1,10 +1,17 @@
#ifndef STRINGS_H
#define STRINGS_H
#include <stdint.h>
void itoa(int n, char str[]);
void strrev(char s[]);
int strlen(char s[]);
char* strcpy(char* strDest, const char* strSrc);
char* strcnc(char* str1, char* str2);
char* u8_hex(const uint8_t x);
char* u16_hex(const uint16_t x);
char* u32_hex(const uint32_t x);
char* u64_hex(const uint64_t x);
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,7 @@
#include <shade/platform/ports.h>
#include <shade/print.h>
#include <shade/platform/interrupts/idt.h>
#include <shade/platform/interrupts/pic.h>
void kernel_welcome() {
print_str("Welcome to ");
@ -43,4 +45,10 @@ void kmain() {
print_str("This program is provided \"as-is\" and no express or implied warranty is provided.\n");
print_str("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n");
pic_remap(0x20, 0x28);
idt_assemble();
kernel_msg_ok("Enabled interrupts");
__asm__ __volatile__("int $2");
for (;;) {}
}

View File

@ -0,0 +1,33 @@
#include <shade/platform/interrupts/idt.h>
void idt_set_gate(uint8_t index, void* isr, uint8_t flags) {
idt_descriptor_t* descriptor = &idt[index];
descriptor->isr_low = (uint64_t)isr & 0xFFFF;
descriptor->kernel_cs = KERNEL_CODE;
descriptor->ist = 0;
descriptor->attributes = flags;
descriptor->isr_mid = ((uint64_t)isr >> 16) & 0xFFFF;
descriptor->isr_high = ((uint64_t)isr >> 32) & 0xFFFFFFFF;
descriptor->reserved = 0;
}
void idt_assemble() {
idt_ptr.base = (uintptr_t)&idt[0];
idt_ptr.limit = (uint16_t)sizeof(idt_descriptor_t) * IDT_DESCRIPTORS - 1;
for (uint8_t vector = 0; vector < 47; vector++) {
idt_set_gate(vector, isr_stub_table[vector], 0x8E);
vectors[vector] = true;
}
__asm__ __volatile__ ("lidt %0" : : "m"(idt_ptr));
idt_enable_interrupts();
}
void idt_enable_interrupts() {
__asm__ __volatile__("sti");
}
void idt_disable_interrupts() {
__asm__ __volatile__("cli");
}

View File

@ -0,0 +1,145 @@
extern exception_handler
%macro isr_err_stub 1
isr_stub_%+%1:
push %1
jmp isr_xframe_assembler
%endmacro
%macro isr_no_err_stub 1
isr_stub_%+%1:
push 0
push %1
jmp isr_xframe_assembler
%endmacro
%macro interrupt_stub 1
isr_stub_%+%1:
push 0
push %1
jmp isr_xframe_assembler
%endmacro
%macro pushagrd 0
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
%endmacro
%macro popagrd 0
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
%endmacro
%macro pushacrd 0
mov rax, cr0
push rax
mov rax, cr2
push rax
mov rax, cr3
push rax
mov rax, cr4
push rax
%endmacro
%macro popacrd 0
pop rax
mov cr4, rax
pop rax
mov cr3, rax
pop rax
mov cr2, rax
pop rax
mov cr0, rax
%endmacro
isr_xframe_assembler:
push rbp
mov rbp, rsp
pushagrd
pushacrd
mov ax, ds
push rax
push qword 0
mov ax, 0x10
mov ds, ax
mov es, ax
mov ss, ax
lea rdi, [rsp + 0x10]
call exception_handler
pop rax
pop rax
mov ds, ax
mov es, ax
popacrd
popagrd
pop rbp
add rsp, 0x10
iretq
isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2
isr_no_err_stub 3
isr_no_err_stub 4
isr_no_err_stub 5
isr_no_err_stub 6
isr_no_err_stub 7
isr_err_stub 8
isr_no_err_stub 9
isr_err_stub 10
isr_err_stub 11
isr_err_stub 12
isr_err_stub 13
isr_err_stub 14
isr_no_err_stub 15
isr_no_err_stub 16
isr_err_stub 17
isr_no_err_stub 18
isr_no_err_stub 19
isr_no_err_stub 20
isr_no_err_stub 21
isr_no_err_stub 22
isr_no_err_stub 23
isr_no_err_stub 24
isr_no_err_stub 25
isr_no_err_stub 26
isr_no_err_stub 27
isr_no_err_stub 28
isr_no_err_stub 29
isr_err_stub 30
isr_no_err_stub 31
interrupt_stub 32
interrupt_stub 33
interrupt_stub 34
interrupt_stub 35
interrupt_stub 36
interrupt_stub 37
interrupt_stub 38
interrupt_stub 39
interrupt_stub 40
interrupt_stub 41
interrupt_stub 42
interrupt_stub 43
interrupt_stub 44
interrupt_stub 45
interrupt_stub 46
interrupt_stub 47
global isr_stub_table
isr_stub_table:
%assign i 0
%rep 47
dq isr_stub_%+i
%assign i i+1
%endrep

View File

@ -0,0 +1,24 @@
#include <shade/print.h>
#include <shade/platform/interrupts/isr.h>
void exception_handler(isr_xframe_t frame) {
err_count++;
char s[256];
itoa(err_count, s);
print_str(" ");
print_str(s);
print_str(": cpu: check_exception ");
itoa(frame.base_frame.vector, s);
print_str(s);
print_str(" @ ");
itoa(frame.base_frame.rip, s);
print_str(s);
print_str(" err_code => ");
itoa(frame.base_frame.error_code, s);
print_str(s);
print_str("\n");
if (err_count > ERR_MAX) {
print_str("cpu: ierr hit err_max, halt");
__asm__ __volatile__("cli; hlt");
}
}

View File

@ -0,0 +1,79 @@
#include <shade/platform/interrupts/pic.h>
#include <shade/platform/ports.h>
void pic_send_eoi(uint8_t irq) {
if (irq >= 8) {
outb(PIC2_COMMAND, PIC_EOI);
}
outb(PIC1_COMMAND, PIC_EOI);
}
void pic_remap(int offset1, int offset2) {
uint8_t a1, a2;
a1 = inb(PIC1_DATA); // Save the current masks for later use
a2 = inb(PIC2_DATA); // Save the current masks for later use
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // starts the initialization sequence (in cascade mode)
io_wait();
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset
io_wait();
outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset
io_wait();
outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
io_wait();
outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010)
io_wait();
outb(PIC1_DATA, ICW4_8086);
io_wait();
outb(PIC2_DATA, ICW4_8086);
io_wait();
outb(PIC1_DATA, a1); // restore saved masks.
outb(PIC2_DATA, a2);
}
void pic_mask_irq(uint8_t irq) {
uint16_t port;
uint8_t value;
if (irq < 8) {
port = PIC1_DATA;
} else {
port = PIC2_DATA;
irq -= 8;
}
value = inb(port) | (1 << irq);
outb(port, value);
}
void pic_unmask_irq(uint8_t irq) {
uint16_t port;
uint8_t value;
if (irq < 8) {
port = PIC1_DATA;
} else {
port = PIC2_DATA;
irq -= 8;
}
value = inb(port) & ~(1 << irq);
outb(port, value);
}
static uint16_t __pic_get_irq_reg(int ocw3) {
outb(PIC1_COMMAND, ocw3);
outb(PIC2_COMMAND, ocw3);
return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
}
uint16_t pic_get_irr() {
return __pic_get_irq_reg(PIC_READ_IRR);
}
uint16_t pic_get_isr() {
return __pic_get_irq_reg(PIC_READ_ISR);
}

View File

@ -1,7 +1,7 @@
/*
* Read 1 byte from specified port
*/
unsigned char port_byte_in(unsigned short port) {
unsigned char inb(unsigned short port) {
unsigned char result;
// source and dest are backwards.
// "=a (result)" set the C variable to the value of register e'a'x
@ -9,18 +9,22 @@ unsigned char port_byte_in(unsigned short port) {
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
}
void port_byte_out(unsigned short port, unsigned char data) {
void outb(unsigned short port, unsigned char data) {
// both regs are C vars, nothing is returned, so no '=' in asm syntax
// comma because two vars in input area and none in return area
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
}
unsigned short port_word_in(unsigned short port) {
unsigned short inw(unsigned short port) {
unsigned short result;
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
return result;
}
void port_word_out(unsigned short port, unsigned short data) {
void outw(unsigned short port, unsigned short data) {
__asm__("out %%ax, %%dx" : : "a" (data), "d" (port));
}
void io_wait() {
outb(0x80, 0);
}

View File

@ -87,10 +87,10 @@ void print_set_color(char foreground, char background) {
void set_cursor_pos(int col, int row) {
int offset = col + NUM_COLS * row;
port_byte_out(REG_SCREEN_CTRL, 14);
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
port_byte_out(REG_SCREEN_CTRL, 15);
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset & 0xff));
outb(REG_SCREEN_CTRL, 14);
outb(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
outb(REG_SCREEN_CTRL, 15);
outb(REG_SCREEN_DATA, (unsigned char)(offset & 0xff));
}
void kernel_msg_ok(char* msg) {

View File

@ -10,16 +10,4 @@ void memcpy(char *source, char *dest, int nbytes) {
void memset(char *dest, char val, int len) {
char *temp = (char *)dest;
for(; len !=0; len--) *temp++ = val;
}
void int_to_ascii(int n, char str[]) {
int i, sign;
if ((sign = n) < 0) n = -n;
i = 0;
do {
str[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
if (sign < 0) str[i++] = '-';
str[i] = '\0';
}

View File

@ -1,5 +1,6 @@
#include <strings.h>
#include <stddef.h>
#include <stdint.h>
void itoa(int n, char str[]) {
int i, sign;