feature (kernel): implemented PIC functionalities and PIT functionalities

This commit is contained in:
antifallobst 2023-02-17 12:51:11 +01:00
parent 12cc5ca0e1
commit 68d2ef7de4
7 changed files with 274 additions and 11 deletions

View File

@ -0,0 +1,26 @@
/* Copyright (C) Antifallobst <antifallobst@systemausfall.org>
*
* NoxOS 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 3 of the License,
* or (at your option) any later version.
*
* NoxOS 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, see <https://www.gnu.org/licenses/>.
*/
#ifndef NOX_PIT_H
#define NOX_PIT_H
#include "utils/stdtypes.h"
#define PIT_CHANNEL_0_PORT 0x40
#define PIT_DIVISOR 32768 // This gives an interrupt every ~27.46ms
void pit_set_divisor(uint16_t divisor);
#endif //NOX_PIT_H

View File

@ -22,6 +22,43 @@
#define IDT_ENTRY_CALL_GATE 0b10001100 #define IDT_ENTRY_CALL_GATE 0b10001100
#define IDT_ENTRY_TRAP_GATE 0b10001111 #define IDT_ENTRY_TRAP_GATE 0b10001111
#define PIC_MASTER_PORT 0x20
#define PIC_MASTER_COMMAND 0x20
#define PIC_MASTER_DATA 0x21
#define PIC_SLAVE_PORT 0xA0
#define PIC_SLAVE_COMMAND 0xA0
#define PIC_SLAVE_DATA 0xA1
#define PIC_END_OF_INTERRUPT 0x20
#define ICW1_ICW4 0x01
#define ICW1_INIT 0x10
#define ICW4_8086 0x01
#define IRQ_MASTER_OFFSET 0x20
#define IRQ_SLAVE_OFFSET 0x28
typedef enum {
// Master PIC
IRQ_PIT,
IRQ_KEYBOARD,
IRQ_CASCADE,
IRQ_COM2,
IRQ_COM1,
IRQ_LPT2,
IRQ_FLOPPY,
IRQ_SPURIOUS,
// Slave PIC
IRQ_CMOS_RTC,
IRQ_FREE_0,
IRQ_FREE_1,
IRQ_FREE_2,
IRQ_PS2_MOUSE,
IRQ_FPU,
IRQ_ATA_PRIMARY,
IRQ_ATA_SECONDARY
} pic_irq_E;
typedef struct { typedef struct {
uint16_t limit; uint16_t limit;
uint64_t offset; uint64_t offset;
@ -39,6 +76,11 @@ typedef struct {
extern idt_register_T g_idt_register; extern idt_register_T g_idt_register;
void idt_init(); void idt_init ();
void pic_init ();
void pic_remap ();
void pic_send_end_of_interrupt (pic_irq_E irq);
void pic_mask_irq (pic_irq_E irq);
void pic_unmask_irq (pic_irq_E irq);
#endif //NOX_INTERRUPTS_H #endif //NOX_INTERRUPTS_H

View File

@ -18,8 +18,11 @@
#include "utils/logger.h" #include "utils/logger.h"
#define CORE_HALT_WHILE(a) while(a) { asm("hlt"); } #define CORE_HALT_WHILE(a) while(a) { asm("hlt"); }
#define CORE_HALT_FOREVER log(LOG_WARNING, "!=====[ HALTING SYSTEM ]=====!");\ #define CORE_HALT_FOREVER log(LOG_WARNING, "!=====[ HALTING SYSTEM ]=====!");\
while(1) { asm("hlt"); } while(1) { asm("hlt"); }
#define CORE_INTERRUPTS_ENABLE asm("sti");
#define CORE_INTERRUPTS_DISABLE asm("cli");
#endif //NOX_CORE_H #endif //NOX_CORE_H

View File

@ -0,0 +1,31 @@
/* Copyright (C) Antifallobst <antifallobst@systemausfall.org>
*
* NoxOS 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 3 of the License,
* or (at your option) any later version.
*
* NoxOS 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, see <https://www.gnu.org/licenses/>.
*/
#include "drivers/time/pit.h"
#include "utils/io.h"
#include "utils/logger.h"
uint16_t g_divisor;
void pit_set_divisor(uint16_t divisor) {
if (divisor < 100) { divisor = 100; }
g_divisor = divisor;
io_out_byte(PIT_CHANNEL_0_PORT, divisor & 0x00FF); io_wait();
io_out_byte(PIT_CHANNEL_0_PORT, (divisor & 0xFF00) >> 8);
log(LOG_INFO, "pit -> divisor set to %d", divisor);
}

View File

@ -17,21 +17,27 @@
#include "utils/core.h" #include "utils/core.h"
#include "utils/memory.h" #include "utils/memory.h"
#include "boot/boot_info.h" #include "boot/boot_info.h"
#include "platform/gdt.h"
#include "platform/interrupts.h" #include "platform/interrupts.h"
#include "mm/page_frame.h" #include "mm/page_frame.h"
#include "mm/page_map.h" #include "mm/page_map.h"
#include "drivers/time/pit.h"
void limine_terminal_print(boot_info_T* boot_info, string_t string) { void limine_terminal_print(boot_info_T* boot_info, string_t string) {
boot_info->terminal->write(boot_info->terminal->terminals[0], string, string_length(string)); boot_info->terminal->write(boot_info->terminal->terminals[0], string, string_length(string));
} }
void kernel_init(boot_info_T* boot_info) { void kernel_init(boot_info_T* boot_info) {
gdt_init();
pframe_manager_init(boot_info); pframe_manager_init(boot_info);
CORE_INTERRUPTS_DISABLE
idt_init(); idt_init();
pic_init();
pit_set_divisor(PIT_DIVISOR);
CORE_INTERRUPTS_ENABLE
paging_init(); paging_init();
memory_allocator_init((void*)0x100000000000); memory_allocator_init((void*)0x100000000000);
// scheduler_init();
} }
void kmain(boot_info_T boot_info) { void kmain(boot_info_T boot_info) {
@ -41,7 +47,11 @@ void kmain(boot_info_T boot_info) {
kernel_init(&boot_info); kernel_init(&boot_info);
void* debug = memory_allocate(1312); log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
asm("int $0x80");
// void* debug = memory_allocate(1312);
CORE_HALT_FOREVER CORE_HALT_FOREVER
} }

View File

@ -19,10 +19,13 @@
#include "platform/exceptions.h" #include "platform/exceptions.h"
#include "mm/page_frame.h" #include "mm/page_frame.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "utils/io.h"
idt_register_T g_idt_register; idt_register_T g_idt_register;
extern void idt_load(idt_register_T* idt_register); extern void idt_load(idt_register_T* idt_register);
// Exceptions
extern void interrupt_stub_0x00(); extern void interrupt_stub_0x00();
extern void interrupt_stub_0x01(); extern void interrupt_stub_0x01();
extern void interrupt_stub_0x02(); extern void interrupt_stub_0x02();
@ -56,6 +59,29 @@ extern void interrupt_stub_0x1D();
extern void interrupt_stub_0x1E(); extern void interrupt_stub_0x1E();
extern void interrupt_stub_0x1F(); extern void interrupt_stub_0x1F();
// IRQs on Master PIC
extern void interrupt_stub_0x20();
extern void interrupt_stub_0x21();
extern void interrupt_stub_0x22();
extern void interrupt_stub_0x23();
extern void interrupt_stub_0x24();
extern void interrupt_stub_0x25();
extern void interrupt_stub_0x26();
extern void interrupt_stub_0x27();
// IRQs on Slave PIC
extern void interrupt_stub_0x28();
extern void interrupt_stub_0x29();
extern void interrupt_stub_0x2A();
extern void interrupt_stub_0x2B();
extern void interrupt_stub_0x2C();
extern void interrupt_stub_0x2D();
extern void interrupt_stub_0x2E();
extern void interrupt_stub_0x2F();
// Custom
extern void interrupt_stub_0x80();
void idt_set_descriptor_entry_offset(idt_descriptor_entry_T* entry, uint64_t offset) { void idt_set_descriptor_entry_offset(idt_descriptor_entry_T* entry, uint64_t offset) {
entry->offset0 = (uint16_t) (offset & 0x000000000000ffff); entry->offset0 = (uint16_t) (offset & 0x000000000000ffff);
entry->offset1 = (uint16_t) ((offset & 0x00000000ffff0000) >> 16); entry->offset1 = (uint16_t) ((offset & 0x00000000ffff0000) >> 16);
@ -81,7 +107,7 @@ void idt_init() {
g_idt_register.limit = 0x0FFF; g_idt_register.limit = 0x0FFF;
g_idt_register.offset = (uint64_t)pframe_request(); g_idt_register.offset = (uint64_t)pframe_request();
// Exceptions
idt_set_gate((void*)interrupt_stub_0x00, 0x00, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE); idt_set_gate((void*)interrupt_stub_0x00, 0x00, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x01, 0x01, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE); idt_set_gate((void*)interrupt_stub_0x01, 0x01, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x02, 0x02, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE); idt_set_gate((void*)interrupt_stub_0x02, 0x02, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
@ -115,16 +141,119 @@ void idt_init() {
idt_set_gate((void*)interrupt_stub_0x1E, 0x1E, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE); idt_set_gate((void*)interrupt_stub_0x1E, 0x1E, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x1F, 0x1F, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE); idt_set_gate((void*)interrupt_stub_0x1F, 0x1F, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
// IRQs on Master PIC
idt_set_gate((void*)interrupt_stub_0x20, 0x20, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x21, 0x21, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x22, 0x22, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x23, 0x23, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x24, 0x24, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x25, 0x25, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x26, 0x26, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x27, 0x27, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
// IRQs on Slave PIC
idt_set_gate((void*)interrupt_stub_0x28, 0x28, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x29, 0x29, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x2A, 0x2A, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x2B, 0x2B, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x2C, 0x2C, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x2D, 0x2D, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x2E, 0x2E, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_set_gate((void*)interrupt_stub_0x2F, 0x2F, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
// Custom
idt_set_gate((void*)interrupt_stub_0x80, 0x80, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
idt_load(&g_idt_register); idt_load(&g_idt_register);
log(LOG_INFO, "Interrupts initialized"); log(LOG_INFO, "Interrupts initialized");
} }
void pic_init() {
pic_remap();
pic_unmask_irq(IRQ_PIT);
}
void pic_remap() {
uint8_t master_masks = io_in_byte(PIC_MASTER_DATA); io_wait();
uint8_t slave_masks = io_in_byte(PIC_SLAVE_DATA); io_wait();
io_out_byte(PIC_MASTER_COMMAND, ICW1_INIT | ICW1_ICW4); io_wait();
io_out_byte(PIC_SLAVE_COMMAND, ICW1_INIT | ICW1_ICW4); io_wait();
// set the IRQ offsets
io_out_byte(PIC_MASTER_DATA, 0x20); io_wait();
io_out_byte(PIC_SLAVE_DATA, 0x28); io_wait();
io_out_byte(PIC_MASTER_DATA, 4); io_wait();
io_out_byte(PIC_SLAVE_DATA, 2); io_wait();
io_out_byte(PIC_MASTER_DATA, ICW4_8086); io_wait();
io_out_byte(PIC_SLAVE_DATA, ICW4_8086); io_wait();
io_out_byte(PIC_MASTER_DATA, master_masks);
io_out_byte(PIC_SLAVE_DATA, slave_masks);
}
void pic_send_end_of_interrupt(pic_irq_E irq) {
if (irq >= 8) {
io_out_byte(PIC_SLAVE_COMMAND, PIC_END_OF_INTERRUPT);
}
io_out_byte(PIC_MASTER_COMMAND, PIC_END_OF_INTERRUPT);
}
void pic_mask_irq(pic_irq_E irq) {
uint16_t port = PIC_MASTER_DATA;
if (irq >= 8) {
port = PIC_SLAVE_DATA;
irq -= 8;
}
uint8_t value = io_in_byte(port) | (1 << irq);
io_out_byte(port, value);
}
void pic_unmask_irq(pic_irq_E irq) {
uint16_t port = PIC_MASTER_DATA;
if (irq >= 8) {
port = PIC_SLAVE_DATA;
irq -= 8;
}
uint8_t value = io_in_byte(port) & ~(1 << irq);
io_out_byte(port, value);
}
cpu_state_T* irq_handle(cpu_state_T* state, pic_irq_E irq) {
cpu_state_T* return_state = state;
switch (irq) {
case IRQ_PIT: {
log(LOG_DEBUG, "PIT -> Tick");
break;
}
default: {
log(LOG_WARNING, "Unhandled IRQ");
break;
}
}
pic_send_end_of_interrupt(irq);
return return_state;
}
cpu_state_T* interrupts_handle(cpu_state_T* state) { cpu_state_T* interrupts_handle(cpu_state_T* state) {
if (state->interrupt_id < EXCEPTIONS_ENUM_END) { if (state->interrupt_id < EXCEPTIONS_ENUM_END) {
return exception_handle(state); return exception_handle(state);
} }
log(LOG_WARNING, "Non exception interrupt detected ID: 0x%xb", state->interrupt_id); if (state->interrupt_id < IRQ_MASTER_OFFSET + 0x10 && state->interrupt_id >= IRQ_MASTER_OFFSET) {
return irq_handle(state, state->interrupt_id - IRQ_MASTER_OFFSET);
}
log(LOG_WARNING, "Unhandled interrupt: 0x%xb", state->interrupt_id);
return state; return state;
} }

View File

@ -24,7 +24,7 @@ interrupt_common_handler:
call interrupts_handle call interrupts_handle
mov rsp, rax mov rsp, rax
; load cpu_state ; load page map
pop rax pop rax
mov cr3, rax mov cr3, rax
@ -90,4 +90,26 @@ interrupt_stub 0x1B
interrupt_stub 0x1C interrupt_stub 0x1C
interrupt_stub 0x1D interrupt_stub 0x1D
interrupt_stub 0x1E interrupt_stub 0x1E
interrupt_stub 0x1F interrupt_stub 0x1F
;IRQs
interrupt_stub 0x20 ; PIT
interrupt_stub 0x21 ; Keyboard
interrupt_stub 0x22 ; Cascade
interrupt_stub 0x23 ; COM2
interrupt_stub 0x24 ; COM1
interrupt_stub 0x25 ; LPT2
interrupt_stub 0x26 ; Floppy
interrupt_stub 0x27 ; Spurious
interrupt_stub 0x28 ; CMOS RTC
interrupt_stub 0x29 ; Free 0
interrupt_stub 0x2A ; Free 1
interrupt_stub 0x2B ; Free 2
interrupt_stub 0x2C ; PS/2 Mouse
interrupt_stub 0x2D ; FPU
interrupt_stub 0x2E ; Primary ATA
interrupt_stub 0x2F ; Secondary ATA
; Custom
interrupt_stub 0x80 ; Syscall