Start cleaning up kernel assembly mixins & start ISR/interrupts

master
Garrett Mills 3 years ago
parent 9e4aaa56ba
commit 9904ac83d8
Signed by: garrettmills
GPG Key ID: D2BF5FBA8298F246

@ -30,9 +30,9 @@ $(BUILD_DIR)/bootloader.bin: $(BOOTLOADER_DIR)/main16.asm
cd $(BOOTLOADER_DIR); nasm -f bin -o ../../build/bootloader.bin main16.asm
# Builds the kernel entry object file
$(BUILD_DIR)/kernel_entry.o: asm/boot.asm
$(BUILD_DIR)/kernel_entry.o: asm/kasm.asm
$(MKDIR_P) $(dir $@)
nasm asm/boot.asm -f elf -o $@
cd asm; nasm kasm.asm -f elf -o ../build/kernel_entry.o
# Build C++ sources
$(BUILD_DIR)/%.cpp.o: %.cpp

@ -5,4 +5,4 @@
[extern main] ; going to call main in kernel.c
call main
jmp $
jmp $

@ -0,0 +1,89 @@
[bits 32]
[extern isr_handler]
%macro ISR_NOERRORCODE 1 ; define a macro, taking one parameter
[GLOBAL isr%1] ; %1 accesses the first parameter.
isr%1:
cli
push byte 0
push byte %1
jmp isr_common_stub
%endmacro
%macro ISR_ERRORCODE 1
[GLOBAL isr%1]
isr%1:
cli
push byte %1
jmp isr_common_stub
%endmacro
ISR_NOERRORCODE 0
ISR_NOERRORCODE 1
ISR_NOERRORCODE 2
ISR_NOERRORCODE 3
ISR_NOERRORCODE 4
ISR_NOERRORCODE 5
ISR_NOERRORCODE 6
ISR_NOERRORCODE 7
ISR_ERRORCODE 8
ISR_NOERRORCODE 9
ISR_ERRORCODE 10
ISR_ERRORCODE 11
ISR_ERRORCODE 12
ISR_ERRORCODE 13
ISR_ERRORCODE 14
ISR_NOERRORCODE 15
ISR_NOERRORCODE 16
ISR_NOERRORCODE 17
ISR_NOERRORCODE 18
ISR_NOERRORCODE 19
ISR_NOERRORCODE 20
ISR_NOERRORCODE 21
ISR_NOERRORCODE 22
ISR_NOERRORCODE 23
ISR_NOERRORCODE 24
ISR_NOERRORCODE 25
ISR_NOERRORCODE 26
ISR_NOERRORCODE 27
ISR_NOERRORCODE 28
ISR_NOERRORCODE 29
ISR_NOERRORCODE 30
ISR_NOERRORCODE 31
; In isr.c
[EXTERN isr_handler]
; This is our common ISR stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
isr_common_stub:
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov ax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor
mov ax, 0x10 ; load the kernel data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call isr_handler
pop eax ; reload the original data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
popa ; Pops edi,esi,ebp...
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
[GLOBAL idt_flush]
idt_flush:
mov eax, [esp + 4]
lidt [eax]
ret

@ -0,0 +1,5 @@
; NOT part of the bootloader
; this is the kernel entry code that calls main() in kernel.cpp
%include "boot.asm"
%include "idt.asm"

@ -0,0 +1,61 @@
#include "idt.h"
#include "../kernel/mem.h"
#include "../drivers/vga.h"
void isr_handler(registers_t regs) {
VGA vga;
vga.print("Received interrupt!");
}
static void init_idt() {
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
idt_ptr.base = (uint32_t) &idt_entries;
mem_set((uint8_t*) &idt_entries, 0, sizeof(idt_entry_t) * 256);
idt_set_gate(0, (uint32_t) isr0, 0x08, 0x8e);
idt_set_gate(1, (uint32_t) isr1, 0x08, 0x8e);
idt_set_gate(2, (uint32_t) isr2, 0x08, 0x8e);
idt_set_gate(3, (uint32_t) isr3, 0x08, 0x8e);
idt_set_gate(4, (uint32_t) isr4, 0x08, 0x8e);
idt_set_gate(5, (uint32_t) isr5, 0x08, 0x8e);
idt_set_gate(6, (uint32_t) isr6, 0x08, 0x8e);
idt_set_gate(7, (uint32_t) isr7, 0x08, 0x8e);
idt_set_gate(8, (uint32_t) isr8, 0x08, 0x8e);
idt_set_gate(9, (uint32_t) isr9, 0x08, 0x8e);
idt_set_gate(10, (uint32_t) isr10, 0x08, 0x8e);
idt_set_gate(11, (uint32_t) isr11, 0x08, 0x8e);
idt_set_gate(12, (uint32_t) isr12, 0x08, 0x8e);
idt_set_gate(13, (uint32_t) isr13, 0x08, 0x8e);
idt_set_gate(14, (uint32_t) isr14, 0x08, 0x8e);
idt_set_gate(15, (uint32_t) isr15, 0x08, 0x8e);
idt_set_gate(16, (uint32_t) isr16, 0x08, 0x8e);
idt_set_gate(17, (uint32_t) isr17, 0x08, 0x8e);
idt_set_gate(18, (uint32_t) isr18, 0x08, 0x8e);
idt_set_gate(19, (uint32_t) isr19, 0x08, 0x8e);
idt_set_gate(20, (uint32_t) isr20, 0x08, 0x8e);
idt_set_gate(21, (uint32_t) isr21, 0x08, 0x8e);
idt_set_gate(22, (uint32_t) isr22, 0x08, 0x8e);
idt_set_gate(23, (uint32_t) isr23, 0x08, 0x8e);
idt_set_gate(24, (uint32_t) isr24, 0x08, 0x8e);
idt_set_gate(25, (uint32_t) isr25, 0x08, 0x8e);
idt_set_gate(26, (uint32_t) isr26, 0x08, 0x8e);
idt_set_gate(27, (uint32_t) isr27, 0x08, 0x8e);
idt_set_gate(28, (uint32_t) isr28, 0x08, 0x8e);
idt_set_gate(29, (uint32_t) isr29, 0x08, 0x8e);
idt_set_gate(30, (uint32_t) isr30, 0x08, 0x8e);
idt_set_gate(31, (uint32_t) isr31, 0x08, 0x8e);
idt_flush((uint32_t) &idt_ptr);
}
static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) {
idt_entries[num].base_lo = base & 0xFFFF;
idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
idt_entries[num].sel = sel;
idt_entries[num].always0 = 0;
// We must uncomment the OR below when we get to using user-mode.
// It sets the interrupt gate's privilege level to 3.
idt_entries[num].flags = flags /* | 0x60 */;
}

@ -0,0 +1,77 @@
#ifndef KERNEL_CPU_IDT_H
#define KERNEL_CPU_IDT_H
#include "types.h"
typedef struct registers
{
uint32_t ds; // Data segment selector
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha.
uint32_t int_no, err_code; // Interrupt number and error code (if applicable)
uint32_t eip, cs, eflags, useresp, ss; // Pushed by the processor automatically.
} registers_t;
void isr_handler(registers_t);
// A struct describing an interrupt gate.
struct idt_entry_struct
{
uint16_t base_lo; // The lower 16 bits of the address to jump to when this interrupt fires.
uint16_t sel; // Kernel segment selector.
uint8_t always0; // This must always be zero.
uint8_t flags; // More flags. See documentation.
uint16_t base_hi; // The upper 16 bits of the address to jump to.
} __attribute__((packed));
typedef struct idt_entry_struct idt_entry_t;
// A struct describing a pointer to an array of interrupt handlers.
// This is in a format suitable for giving to 'lidt'.
struct idt_ptr_struct {
uint16_t limit;
uint32_t base; // The address of the first element in our idt_entry_t array.
} __attribute__((packed));
typedef struct idt_ptr_struct idt_ptr_t;
extern void idt_flush(uint32_t);
static void init_idt();
static void idt_set_gate(uint8_t, uint32_t, uint16_t, uint8_t);
idt_entry_t idt_entries[256];
idt_ptr_t idt_ptr;
// References to ASM ISR handlers
extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
#endif //KERNEL_CPU_IDT_H

@ -2,12 +2,7 @@
#define KERNEL_CPU_TYPES_H
// Non-semantic types specific to 32-bit Intel x86
typedef unsigned int u32_t;
typedef int i32_t;
typedef unsigned short u16_t;
typedef short i16_t;
typedef unsigned char u8_t;
typedef char i8_t;
#include <stdint.h>
#define LOW16(address) (u16)((address) & 0xffff)
#define HIGH16(address) (u16)(((address) >> 16) & 0xffff)

@ -9,8 +9,8 @@
* @param port
* @return the read byte
*/
u8_t io_byte_in(u16_t port) {
u8_t result;
uint8_t io_byte_in(uint16_t port) {
uint8_t result;
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
return result;
}
@ -24,7 +24,7 @@ u8_t io_byte_in(u16_t port) {
* @param port
* @param data
*/
void io_byte_out(u16_t port, u8_t data) {
void io_byte_out(uint16_t port, uint8_t data) {
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
}
@ -37,8 +37,8 @@ void io_byte_out(u16_t port, u8_t data) {
* @param port
* @return the read word
*/
u16_t io_word_in(u16_t port) {
u16_t result;
uint16_t io_word_in(uint16_t port) {
uint16_t result;
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
return result;
}
@ -52,6 +52,6 @@ u16_t io_word_in(u16_t port) {
* @param port
* @param data
*/
void io_word_out(u16_t port, u16_t data) {
void io_word_out(uint16_t port, uint16_t data) {
__asm__("out %%ax, %%dx" : : "a" (data), "d" (port));
}

@ -1,6 +1,8 @@
#ifndef KERNEL_IO_H
#define KERNEL_IO_H
#include <stdint.h>
/**
* Wrapper function that reads a byte from the specified I/O port.
*
@ -10,7 +12,7 @@
* @param port
* @return the read byte
*/
u8_t io_byte_in(u16_t port);
uint8_t io_byte_in(uint16_t port);
/**
* Wrapper function that writes a byte to the specified I/O port.
@ -21,7 +23,7 @@ u8_t io_byte_in(u16_t port);
* @param port
* @param data
*/
void io_byte_out(u16_t port, u8_t data);
void io_byte_out(uint16_t port, uint8_t data);
/**
* Wrapper function that reads a word from the specified I/O port.
@ -32,7 +34,7 @@ void io_byte_out(u16_t port, u8_t data);
* @param port
* @return the read word
*/
u16_t io_word_in(u16_t port);
uint16_t io_word_in(uint16_t port);
/**
* Wrapper function that writes a word to the specified I/O port.
@ -43,6 +45,6 @@ u16_t io_word_in(u16_t port);
* @param port
* @param data
*/
void io_word_out(u16_t port, u16_t data);
void io_word_out(uint16_t port, uint16_t data);
#endif //KERNEL_IO_H

@ -1,3 +1,4 @@
#include "util.h"
/**
* Copy `num_bytes` many bytes from the `source` memory to the
@ -7,8 +8,16 @@
* @param destination
* @param num_bytes
*/
void mem_copy(char* source, char* destination, int num_bytes) {
void mem_copy(uint8_t* source, uint8_t* destination, int num_bytes) {
for ( int i = 0; i < num_bytes; i += 1 ) {
*(destination + i) = *(source + i);
}
}
void mem_set(uint8_t* destination, uint8_t value, uint32_t length) {
uint8_t* temp = (uint8_t*) destination;
while ( length != 0 ) {
*temp++ = value;
length -= 1;
}
}

@ -1,6 +1,8 @@
#ifndef KERNEL_MEM_H
#define KERNEL_MEM_H
void mem_copy(char* source, char* destination, int num_bytes);
void mem_copy(uint8_t* source, uint8_t* destination, int num_bytes);
void mem_set(uint8_t* destination, uint8_t value, uint32_t length);
#endif //KERNEL_MEM_H

Loading…
Cancel
Save