major refactorings
Signed-off-by: kaguya3311 <kaguya3311@national.shitposting.agency>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#include "asm.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
void halt(void) {
|
||||
asm("hlt");
|
||||
}
|
||||
|
||||
void cli(void) {
|
||||
asm("cli");
|
||||
}
|
||||
|
||||
void sti(void) {
|
||||
asm("sti");
|
||||
}
|
||||
|
||||
void pause(void) {
|
||||
asm("pause");
|
||||
}
|
||||
|
||||
void nop(void) {
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
void dbgbrk(void) {
|
||||
asm("int 3");
|
||||
}
|
||||
|
||||
bool int_state(void) {
|
||||
uint64_t flags;
|
||||
asm volatile("pushfq; pop %0" : "=rm"(flags)::"memory");
|
||||
return flags & (1 << 9);
|
||||
}
|
||||
|
||||
|
||||
bool int_toggle(bool state) {
|
||||
bool ret = int_state();
|
||||
if (state) {
|
||||
sti();
|
||||
} else {
|
||||
cli();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define FLAT_PTR(PTR) (*((uintptr_t(*)[])(PTR)))
|
||||
|
||||
#define BYTE_PTR(PTR) (*((uint8_t *)(PTR)))
|
||||
#define WORD_PTR(PTR) (*((uint16_t *)(PTR)))
|
||||
#define DWORD_PTR(PTR) (*((uint32_t *)(PTR)))
|
||||
#define QWORD_PTR(PTR) (*((uint64_t *)(PTR)))
|
||||
|
||||
|
||||
void halt(void);
|
||||
void cli(void);
|
||||
void sti(void);
|
||||
void pause(void);
|
||||
void nop(void);
|
||||
void dbgbrk(void);
|
||||
bool int_state(void);
|
||||
bool int_toggle(bool state);
|
||||
@@ -0,0 +1,66 @@
|
||||
; Taken from Limine
|
||||
; Added memset32
|
||||
section .text
|
||||
|
||||
global memcpy
|
||||
memcpy:
|
||||
mov rcx, rdx
|
||||
mov rax, rdi
|
||||
rep movsb
|
||||
ret
|
||||
|
||||
global memset
|
||||
memset:
|
||||
push rdi
|
||||
mov rax, rsi
|
||||
mov rcx, rdx
|
||||
rep stosb
|
||||
pop rax
|
||||
ret
|
||||
|
||||
global memset32
|
||||
memset32:
|
||||
push rdi
|
||||
mov rax, rsi
|
||||
mov rcx, rdx
|
||||
rep stosd
|
||||
pop rax
|
||||
ret
|
||||
|
||||
global memmove
|
||||
memmove:
|
||||
mov rcx, rdx
|
||||
mov rax, rdi
|
||||
|
||||
cmp rdi, rsi
|
||||
ja .copy_backwards
|
||||
|
||||
rep movsb
|
||||
jmp .done
|
||||
|
||||
.copy_backwards:
|
||||
lea rdi, [rdi+rcx-1]
|
||||
lea rsi, [rsi+rcx-1]
|
||||
std
|
||||
rep movsb
|
||||
cld
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
global memcmp
|
||||
memcmp:
|
||||
mov rcx, rdx
|
||||
repe cmpsb
|
||||
je .equal
|
||||
|
||||
mov al, byte [rdi-1]
|
||||
sub al, byte [rsi-1]
|
||||
movsx rax, al
|
||||
jmp .done
|
||||
|
||||
.equal:
|
||||
xor eax, eax
|
||||
|
||||
.done:
|
||||
ret
|
||||
+15
-29
@@ -2,8 +2,7 @@
|
||||
#include "mm/memory.h"
|
||||
#include "mp/spinlock.h"
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#include "libk/debug.h"
|
||||
|
||||
struct gdt_desc {
|
||||
uint16_t limit;
|
||||
@@ -37,40 +36,28 @@ struct gdtr {
|
||||
|
||||
struct gdtr gdt = {0};
|
||||
struct gdt_ptr gdt_pointer = {0};
|
||||
struct tss kernel_tss = {0};
|
||||
spinlock_t s_gdt_lock = SPINLOCK_INIT;
|
||||
spinlock_t gdt_lock;
|
||||
|
||||
|
||||
extern void gdt_reload(void);
|
||||
extern void tss_reload(void);
|
||||
|
||||
|
||||
void x86_64_GDT_Initialize(void) {
|
||||
uint64_t flags;
|
||||
spinlock_acquire_irqsave(&s_gdt_lock, &flags);
|
||||
|
||||
// null desc
|
||||
memset(&gdt.entries[0], 0, sizeof(struct gdt_desc));
|
||||
void gdt_init(void) {
|
||||
spinlock_acquire_or_wait(&gdt_lock);
|
||||
// Kernel code
|
||||
gdt.entries[1].limit = 0xFFFF;
|
||||
gdt.entries[1].access = 0x9A;
|
||||
gdt.entries[1].granularity = 0x20;
|
||||
gdt.entries[1].access = 0b10011010;
|
||||
gdt.entries[1].granularity = 0b00100000;
|
||||
|
||||
// Kernel data
|
||||
gdt.entries[2].limit = 0xFFFF;
|
||||
gdt.entries[2].access = 0x92;
|
||||
gdt.entries[2].granularity = 0x00;
|
||||
gdt.entries[2].access = 0b10010010;
|
||||
|
||||
// User data
|
||||
gdt.entries[3].limit = 0xFFFF;
|
||||
gdt.entries[3].access = 0xF2;
|
||||
gdt.entries[3].granularity = 0x00;
|
||||
gdt.entries[3].access = 0b11110010;
|
||||
|
||||
// User code
|
||||
gdt.entries[4].limit = 0xFFFF;
|
||||
gdt.entries[4].access = 0xFA;
|
||||
gdt.entries[4].granularity = 0x20;
|
||||
gdt.entries[4].access = 0b11111010;
|
||||
gdt.entries[4].granularity = 0b00100000;
|
||||
|
||||
// TSS 0x28
|
||||
// TSS
|
||||
gdt.tss.length = sizeof(struct tss);
|
||||
gdt.tss.flags1 = 0b10001001;
|
||||
|
||||
@@ -80,12 +67,11 @@ void x86_64_GDT_Initialize(void) {
|
||||
|
||||
gdt_reload();
|
||||
tss_reload();
|
||||
spinlock_release_irqrestore(&s_gdt_lock, flags);
|
||||
spinlock_drop(&gdt_lock);
|
||||
}
|
||||
|
||||
void gdt_load_tss(size_t addr) {
|
||||
uint64_t flags;
|
||||
spinlock_acquire_irqsave(&s_gdt_lock, &flags);
|
||||
spinlock_acquire_or_wait(&gdt_lock);
|
||||
gdt.tss.base_low = (uint16_t)addr;
|
||||
gdt.tss.base_mid = (uint8_t)(addr >> 16);
|
||||
gdt.tss.flags1 = 0b10001001;
|
||||
@@ -93,5 +79,5 @@ void gdt_load_tss(size_t addr) {
|
||||
gdt.tss.base_upper32 = (uint32_t)(addr >> 32);
|
||||
|
||||
tss_reload();
|
||||
spinlock_release_irqrestore(&s_gdt_lock, flags);
|
||||
spinlock_drop(&gdt_lock);
|
||||
}
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
|
||||
#define GDT_KERNEL_BASE 0x0
|
||||
#define GDT_KERNEL_CODE64 0x8
|
||||
#define GDT_KERNEL_DATA64 0x10
|
||||
#define GDT_USER_BASE 0x18
|
||||
#define GDT_USER_DATA64 0x18
|
||||
#define GDT_USER_CODE64 0x20
|
||||
#define GDT_TSS 0x28
|
||||
#define GDT_USER_DATA64 0x20
|
||||
#define GDT_USER_CODE64 0x28
|
||||
#define GDT_TSS 0x30
|
||||
|
||||
struct tss {
|
||||
uint32_t reserved;
|
||||
@@ -30,7 +29,7 @@ struct tss {
|
||||
uint16_t iomap_base;
|
||||
} __attribute__((packed));
|
||||
|
||||
extern struct tss kernel_tss;
|
||||
extern void gdt_reload(void);
|
||||
|
||||
void x86_64_GDT_Initialize(void);
|
||||
void gdt_init(void);
|
||||
void gdt_load_tss(size_t addr);
|
||||
@@ -1,27 +0,0 @@
|
||||
.intel_syntax noprefix
|
||||
.global x86_64_GDT_Load
|
||||
.extern gdt_pointer
|
||||
|
||||
.global gdt_reload
|
||||
gdt_reload:
|
||||
lgdt [rip + gdt_pointer]
|
||||
|
||||
push 0x08
|
||||
lea rax, [rip + .flush]
|
||||
push rax
|
||||
lretq
|
||||
|
||||
.flush:
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
ret
|
||||
|
||||
.global tss_reload
|
||||
tss_reload:
|
||||
mov ax, 0x2B
|
||||
ltr ax
|
||||
ret
|
||||
@@ -0,0 +1,23 @@
|
||||
extern gdt_pointer
|
||||
global gdt_reload
|
||||
|
||||
gdt_reload:
|
||||
lgdt [rel gdt_pointer]
|
||||
push 8
|
||||
lea rax, [rel .flush]
|
||||
push rax
|
||||
retfq
|
||||
.flush:
|
||||
mov eax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
ret
|
||||
|
||||
global tss_reload
|
||||
tss_reload:
|
||||
mov ax, 0x2B
|
||||
ltr ax
|
||||
ret
|
||||
+30
-27
@@ -1,35 +1,38 @@
|
||||
#include "idt.h"
|
||||
#include "libk/binary.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct idt_entry {
|
||||
uint16_t offset_lo;
|
||||
uint16_t selector;
|
||||
uint8_t ist;
|
||||
uint8_t flags;
|
||||
uint16_t offset_mid;
|
||||
uint32_t offset_hi;
|
||||
uint32_t zero;
|
||||
} __attribute__((packed));
|
||||
|
||||
IDTEntry g_IDT[256];
|
||||
IDTDescriptor g_IDTDescriptor = { sizeof(g_IDT) - 1, g_IDT };
|
||||
struct idt_register {
|
||||
uint16_t size;
|
||||
uint64_t address;
|
||||
} __attribute__((packed));
|
||||
|
||||
extern void x86_64_IDT_Load(IDTDescriptor* descriptor);
|
||||
struct idt_entry idt[256] = {0};
|
||||
|
||||
void x86_64_IDT_SetGate(int interrupt, void* base, uint16_t segmentDescriptor, uint8_t flags)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)base;
|
||||
g_IDT[interrupt].BaseLow = addr & 0xFFFF;
|
||||
g_IDT[interrupt].SegmentSelector = segmentDescriptor;
|
||||
g_IDT[interrupt].IST = 0;
|
||||
g_IDT[interrupt].Flags = flags;
|
||||
g_IDT[interrupt].BaseMid = (addr >> 16) & 0xFFFF;
|
||||
g_IDT[interrupt].BaseHigh = (addr >> 32) & 0xFFFFFFFF;
|
||||
g_IDT[interrupt].Reserved = 0;
|
||||
}
|
||||
void x86_64_IDT_EnableGate(int interrupt)
|
||||
{
|
||||
FLAG_SET(g_IDT[interrupt].Flags, IDT_FLAG_PRESENT);
|
||||
void idt_set_gate(size_t vec, void *handler, uint8_t ist) {
|
||||
uint64_t p = (uint64_t)handler;
|
||||
|
||||
idt[vec].offset_lo = (uint16_t)p;
|
||||
idt[vec].selector = 8;
|
||||
idt[vec].ist = ist;
|
||||
idt[vec].flags = 0x8E;
|
||||
idt[vec].offset_mid = (uint16_t)(p >> 16);
|
||||
idt[vec].offset_hi = (uint32_t)(p >> 32);
|
||||
idt[vec].zero = 0;
|
||||
}
|
||||
|
||||
void x86_64_IDT_DisableGate(int interrupt)
|
||||
{
|
||||
FLAG_UNSET(g_IDT[interrupt].Flags, IDT_FLAG_PRESENT);
|
||||
void idt_reload(void) {
|
||||
struct idt_register idt_ptr = {sizeof(idt) - 1, (uint64_t)idt};
|
||||
|
||||
asm volatile("lidtq %0" : : "m"(idt_ptr));
|
||||
}
|
||||
|
||||
|
||||
void x86_64_IDT_Initialize(void)
|
||||
{
|
||||
x86_64_IDT_Load(&g_IDTDescriptor);
|
||||
}
|
||||
@@ -1,44 +1,7 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IDT_FLAG_GATE_TASK = 0x5,
|
||||
IDT_FLAG_GATE_16BIT_INT = 0x6,
|
||||
IDT_FLAG_GATE_16BIT_TRAP = 0x7,
|
||||
IDT_FLAG_GATE_32BIT_INT = 0xE,
|
||||
IDT_FLAG_GATE_32BIT_TRAP = 0xF,
|
||||
|
||||
IDT_FLAG_RING0 = (0 << 5),
|
||||
IDT_FLAG_RING1 = (1 << 5),
|
||||
IDT_FLAG_RING2 = (2 << 5),
|
||||
IDT_FLAG_RING3 = (3 << 5),
|
||||
|
||||
IDT_FLAG_PRESENT = 0x80,
|
||||
|
||||
} IDT_FLAGS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t BaseLow;
|
||||
uint16_t SegmentSelector;
|
||||
uint8_t IST; // Interrupt Stack Table (0 = default)
|
||||
uint8_t Flags;
|
||||
uint16_t BaseMid;
|
||||
uint32_t BaseHigh;
|
||||
uint32_t Reserved;
|
||||
} __attribute__((packed)) IDTEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t Limit;
|
||||
IDTEntry* Ptr;
|
||||
} __attribute__((packed)) IDTDescriptor;
|
||||
|
||||
|
||||
void x86_64_IDT_Initialize(void);
|
||||
void x86_64_IDT_SetGate(int interrupt, void* base, uint16_t segmentDescriptor, uint8_t flags);
|
||||
void x86_64_IDT_EnableGate(int interrupt);
|
||||
void x86_64_IDT_DisableGate(int interrupt);
|
||||
void idt_set_gate(size_t vec, void *handler, uint8_t ist);
|
||||
void idt_reload(void);
|
||||
@@ -1,6 +0,0 @@
|
||||
.intel_syntax noprefix
|
||||
.global x86_64_IDT_Load
|
||||
|
||||
x86_64_IDT_Load:
|
||||
lidt [rdi] # descriptor in RDI
|
||||
ret
|
||||
+348
-110
@@ -1,124 +1,362 @@
|
||||
// ... includes ...
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include "libk/debug.h"
|
||||
#include "arch/x86_64/boot/isr.h"
|
||||
#include "idt.h"
|
||||
#define MODULE "ISR"
|
||||
#include "mm/vmm.h"
|
||||
#include "arch/x86_64/cpu/reg.h"
|
||||
#include "mp/mp.h"
|
||||
#include "mm/memory.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "arch/x86_64/sys/halt.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
static inline uint64_t x86_64_read_cr2(void)
|
||||
{
|
||||
uint64_t value;
|
||||
__asm__ volatile ("mov %%cr2, %0" : "=r"(value));
|
||||
return value;
|
||||
void isr_install(void) {
|
||||
idt_set_gate(0, isr0, 0);
|
||||
idt_set_gate(1, isr1, 0);
|
||||
idt_set_gate(2, isr2, 0);
|
||||
idt_set_gate(3, isr3, 0);
|
||||
idt_set_gate(4, isr4, 0);
|
||||
idt_set_gate(5, isr5, 0);
|
||||
idt_set_gate(6, isr6, 0);
|
||||
idt_set_gate(7, isr7, 0);
|
||||
idt_set_gate(8, isr8, 0);
|
||||
idt_set_gate(9, isr9, 0);
|
||||
idt_set_gate(10, isr10, 0);
|
||||
idt_set_gate(11, isr11, 0);
|
||||
idt_set_gate(12, isr12, 0);
|
||||
idt_set_gate(13, isr13, 0);
|
||||
idt_set_gate(14, isr14, 2);
|
||||
idt_set_gate(15, isr15, 0);
|
||||
idt_set_gate(16, isr16, 0);
|
||||
idt_set_gate(17, isr17, 0);
|
||||
idt_set_gate(18, isr18, 0);
|
||||
idt_set_gate(19, isr19, 0);
|
||||
idt_set_gate(20, isr20, 0);
|
||||
idt_set_gate(21, isr21, 0);
|
||||
idt_set_gate(22, isr22, 0);
|
||||
idt_set_gate(23, isr23, 0);
|
||||
idt_set_gate(24, isr24, 0);
|
||||
idt_set_gate(25, isr25, 0);
|
||||
idt_set_gate(26, isr26, 0);
|
||||
idt_set_gate(27, isr27, 0);
|
||||
idt_set_gate(28, isr28, 0);
|
||||
idt_set_gate(29, isr29, 0);
|
||||
idt_set_gate(30, isr30, 0);
|
||||
idt_set_gate(31, isr31, 0);
|
||||
idt_set_gate(32, isr32, 0);
|
||||
idt_set_gate(33, isr33, 0);
|
||||
idt_set_gate(34, isr34, 0);
|
||||
idt_set_gate(35, isr35, 0);
|
||||
idt_set_gate(36, isr36, 0);
|
||||
idt_set_gate(37, isr37, 0);
|
||||
idt_set_gate(38, isr38, 0);
|
||||
idt_set_gate(39, isr39, 0);
|
||||
idt_set_gate(40, isr40, 0);
|
||||
idt_set_gate(41, isr41, 0);
|
||||
idt_set_gate(42, isr42, 0);
|
||||
idt_set_gate(43, isr43, 0);
|
||||
idt_set_gate(44, isr44, 0);
|
||||
idt_set_gate(45, isr45, 0);
|
||||
idt_set_gate(46, isr46, 0);
|
||||
idt_set_gate(47, isr47, 0);
|
||||
idt_set_gate(48, isr48, 1);
|
||||
idt_set_gate(49, isr49, 0);
|
||||
idt_set_gate(50, isr50, 0);
|
||||
idt_set_gate(51, isr51, 0);
|
||||
idt_set_gate(52, isr52, 0);
|
||||
idt_set_gate(53, isr53, 0);
|
||||
idt_set_gate(54, isr54, 0);
|
||||
idt_set_gate(55, isr55, 0);
|
||||
idt_set_gate(56, isr56, 0);
|
||||
idt_set_gate(57, isr57, 0);
|
||||
idt_set_gate(58, isr58, 0);
|
||||
idt_set_gate(59, isr59, 0);
|
||||
idt_set_gate(60, isr60, 0);
|
||||
idt_set_gate(61, isr61, 0);
|
||||
idt_set_gate(62, isr62, 0);
|
||||
idt_set_gate(63, isr63, 0);
|
||||
idt_set_gate(64, isr64, 0);
|
||||
idt_set_gate(65, isr65, 0);
|
||||
idt_set_gate(66, isr66, 0);
|
||||
idt_set_gate(67, isr67, 0);
|
||||
idt_set_gate(68, isr68, 0);
|
||||
idt_set_gate(69, isr69, 0);
|
||||
idt_set_gate(70, isr70, 0);
|
||||
idt_set_gate(71, isr71, 0);
|
||||
idt_set_gate(72, isr72, 0);
|
||||
idt_set_gate(73, isr73, 0);
|
||||
idt_set_gate(74, isr74, 0);
|
||||
idt_set_gate(75, isr75, 0);
|
||||
idt_set_gate(76, isr76, 0);
|
||||
idt_set_gate(77, isr77, 0);
|
||||
idt_set_gate(78, isr78, 0);
|
||||
idt_set_gate(79, isr79, 0);
|
||||
idt_set_gate(80, isr80, 0);
|
||||
idt_set_gate(81, isr81, 0);
|
||||
idt_set_gate(82, isr82, 0);
|
||||
idt_set_gate(83, isr83, 0);
|
||||
idt_set_gate(84, isr84, 0);
|
||||
idt_set_gate(85, isr85, 0);
|
||||
idt_set_gate(86, isr86, 0);
|
||||
idt_set_gate(87, isr87, 0);
|
||||
idt_set_gate(88, isr88, 0);
|
||||
idt_set_gate(89, isr89, 0);
|
||||
idt_set_gate(90, isr90, 0);
|
||||
idt_set_gate(91, isr91, 0);
|
||||
idt_set_gate(92, isr92, 0);
|
||||
idt_set_gate(93, isr93, 0);
|
||||
idt_set_gate(94, isr94, 0);
|
||||
idt_set_gate(95, isr95, 0);
|
||||
idt_set_gate(96, isr96, 0);
|
||||
idt_set_gate(97, isr97, 0);
|
||||
idt_set_gate(98, isr98, 0);
|
||||
idt_set_gate(99, isr99, 0);
|
||||
idt_set_gate(100, isr100, 0);
|
||||
idt_set_gate(101, isr101, 0);
|
||||
idt_set_gate(102, isr102, 0);
|
||||
idt_set_gate(103, isr103, 0);
|
||||
idt_set_gate(104, isr104, 0);
|
||||
idt_set_gate(105, isr105, 0);
|
||||
idt_set_gate(106, isr106, 0);
|
||||
idt_set_gate(107, isr107, 0);
|
||||
idt_set_gate(108, isr108, 0);
|
||||
idt_set_gate(109, isr109, 0);
|
||||
idt_set_gate(110, isr110, 0);
|
||||
idt_set_gate(111, isr111, 0);
|
||||
idt_set_gate(112, isr112, 0);
|
||||
idt_set_gate(113, isr113, 0);
|
||||
idt_set_gate(114, isr114, 0);
|
||||
idt_set_gate(115, isr115, 0);
|
||||
idt_set_gate(116, isr116, 0);
|
||||
idt_set_gate(117, isr117, 0);
|
||||
idt_set_gate(118, isr118, 0);
|
||||
idt_set_gate(119, isr119, 0);
|
||||
idt_set_gate(120, isr120, 0);
|
||||
idt_set_gate(121, isr121, 0);
|
||||
idt_set_gate(122, isr122, 0);
|
||||
idt_set_gate(123, isr123, 0);
|
||||
idt_set_gate(124, isr124, 0);
|
||||
idt_set_gate(125, isr125, 0);
|
||||
idt_set_gate(126, isr126, 0);
|
||||
idt_set_gate(127, isr127, 0);
|
||||
idt_set_gate(128, isr128, 0);
|
||||
idt_set_gate(129, isr129, 0);
|
||||
idt_set_gate(130, isr130, 0);
|
||||
idt_set_gate(131, isr131, 0);
|
||||
idt_set_gate(132, isr132, 0);
|
||||
idt_set_gate(133, isr133, 0);
|
||||
idt_set_gate(134, isr134, 0);
|
||||
idt_set_gate(135, isr135, 0);
|
||||
idt_set_gate(136, isr136, 0);
|
||||
idt_set_gate(137, isr137, 0);
|
||||
idt_set_gate(138, isr138, 0);
|
||||
idt_set_gate(139, isr139, 0);
|
||||
idt_set_gate(140, isr140, 0);
|
||||
idt_set_gate(141, isr141, 0);
|
||||
idt_set_gate(142, isr142, 0);
|
||||
idt_set_gate(143, isr143, 0);
|
||||
idt_set_gate(144, isr144, 0);
|
||||
idt_set_gate(145, isr145, 0);
|
||||
idt_set_gate(146, isr146, 0);
|
||||
idt_set_gate(147, isr147, 0);
|
||||
idt_set_gate(148, isr148, 0);
|
||||
idt_set_gate(149, isr149, 0);
|
||||
idt_set_gate(150, isr150, 0);
|
||||
idt_set_gate(151, isr151, 0);
|
||||
idt_set_gate(152, isr152, 0);
|
||||
idt_set_gate(153, isr153, 0);
|
||||
idt_set_gate(154, isr154, 0);
|
||||
idt_set_gate(155, isr155, 0);
|
||||
idt_set_gate(156, isr156, 0);
|
||||
idt_set_gate(157, isr157, 0);
|
||||
idt_set_gate(158, isr158, 0);
|
||||
idt_set_gate(159, isr159, 0);
|
||||
idt_set_gate(160, isr160, 0);
|
||||
idt_set_gate(161, isr161, 0);
|
||||
idt_set_gate(162, isr162, 0);
|
||||
idt_set_gate(163, isr163, 0);
|
||||
idt_set_gate(164, isr164, 0);
|
||||
idt_set_gate(165, isr165, 0);
|
||||
idt_set_gate(166, isr166, 0);
|
||||
idt_set_gate(167, isr167, 0);
|
||||
idt_set_gate(168, isr168, 0);
|
||||
idt_set_gate(169, isr169, 0);
|
||||
idt_set_gate(170, isr170, 0);
|
||||
idt_set_gate(171, isr171, 0);
|
||||
idt_set_gate(172, isr172, 0);
|
||||
idt_set_gate(173, isr173, 0);
|
||||
idt_set_gate(174, isr174, 0);
|
||||
idt_set_gate(175, isr175, 0);
|
||||
idt_set_gate(176, isr176, 0);
|
||||
idt_set_gate(177, isr177, 0);
|
||||
idt_set_gate(178, isr178, 0);
|
||||
idt_set_gate(179, isr179, 0);
|
||||
idt_set_gate(180, isr180, 0);
|
||||
idt_set_gate(181, isr181, 0);
|
||||
idt_set_gate(182, isr182, 0);
|
||||
idt_set_gate(183, isr183, 0);
|
||||
idt_set_gate(184, isr184, 0);
|
||||
idt_set_gate(185, isr185, 0);
|
||||
idt_set_gate(186, isr186, 0);
|
||||
idt_set_gate(187, isr187, 0);
|
||||
idt_set_gate(188, isr188, 0);
|
||||
idt_set_gate(189, isr189, 0);
|
||||
idt_set_gate(190, isr190, 0);
|
||||
idt_set_gate(191, isr191, 0);
|
||||
idt_set_gate(192, isr192, 0);
|
||||
idt_set_gate(193, isr193, 0);
|
||||
idt_set_gate(194, isr194, 0);
|
||||
idt_set_gate(195, isr195, 0);
|
||||
idt_set_gate(196, isr196, 0);
|
||||
idt_set_gate(197, isr197, 0);
|
||||
idt_set_gate(198, isr198, 0);
|
||||
idt_set_gate(199, isr199, 0);
|
||||
idt_set_gate(200, isr200, 0);
|
||||
idt_set_gate(201, isr201, 0);
|
||||
idt_set_gate(202, isr202, 0);
|
||||
idt_set_gate(203, isr203, 0);
|
||||
idt_set_gate(204, isr204, 0);
|
||||
idt_set_gate(205, isr205, 0);
|
||||
idt_set_gate(206, isr206, 0);
|
||||
idt_set_gate(207, isr207, 0);
|
||||
idt_set_gate(208, isr208, 0);
|
||||
idt_set_gate(209, isr209, 0);
|
||||
idt_set_gate(210, isr210, 0);
|
||||
idt_set_gate(211, isr211, 0);
|
||||
idt_set_gate(212, isr212, 0);
|
||||
idt_set_gate(213, isr213, 0);
|
||||
idt_set_gate(214, isr214, 0);
|
||||
idt_set_gate(215, isr215, 0);
|
||||
idt_set_gate(216, isr216, 0);
|
||||
idt_set_gate(217, isr217, 0);
|
||||
idt_set_gate(218, isr218, 0);
|
||||
idt_set_gate(219, isr219, 0);
|
||||
idt_set_gate(220, isr220, 0);
|
||||
idt_set_gate(221, isr221, 0);
|
||||
idt_set_gate(222, isr222, 0);
|
||||
idt_set_gate(223, isr223, 0);
|
||||
idt_set_gate(224, isr224, 0);
|
||||
idt_set_gate(225, isr225, 0);
|
||||
idt_set_gate(226, isr226, 0);
|
||||
idt_set_gate(227, isr227, 0);
|
||||
idt_set_gate(228, isr228, 0);
|
||||
idt_set_gate(229, isr229, 0);
|
||||
idt_set_gate(230, isr230, 0);
|
||||
idt_set_gate(231, isr231, 0);
|
||||
idt_set_gate(232, isr232, 0);
|
||||
idt_set_gate(233, isr233, 0);
|
||||
idt_set_gate(234, isr234, 0);
|
||||
idt_set_gate(235, isr235, 0);
|
||||
idt_set_gate(236, isr236, 0);
|
||||
idt_set_gate(237, isr237, 0);
|
||||
idt_set_gate(238, isr238, 0);
|
||||
idt_set_gate(239, isr239, 0);
|
||||
idt_set_gate(240, isr240, 0);
|
||||
idt_set_gate(241, isr241, 0);
|
||||
idt_set_gate(242, isr242, 0);
|
||||
idt_set_gate(243, isr243, 0);
|
||||
idt_set_gate(244, isr244, 0);
|
||||
idt_set_gate(245, isr245, 0);
|
||||
idt_set_gate(246, isr246, 0);
|
||||
idt_set_gate(247, isr247, 0);
|
||||
idt_set_gate(248, isr248, 0);
|
||||
idt_set_gate(249, isr249, 0);
|
||||
idt_set_gate(250, isr250, 0);
|
||||
idt_set_gate(251, isr251, 0);
|
||||
idt_set_gate(252, isr252, 0);
|
||||
idt_set_gate(253, isr253, 0);
|
||||
idt_set_gate(254, isr254, 0);
|
||||
idt_set_gate(255, isr255, 0);
|
||||
idt_reload();
|
||||
}
|
||||
|
||||
ISRHandler g_ISRHandlers[256];
|
||||
static const char* const g_Exceptions[] = {
|
||||
"Divide by zero error",
|
||||
"Debug",
|
||||
"Non-maskable Interrupt",
|
||||
"Breakpoint",
|
||||
"Overflow",
|
||||
"Bound Range Exceeded",
|
||||
"Invalid Opcode",
|
||||
"Device Not Available",
|
||||
"Double Fault",
|
||||
"Coprocessor Segment Overrun",
|
||||
"Invalid TSS",
|
||||
"Segment Not Present",
|
||||
"Stack-Segment Fault",
|
||||
"General Protection Fault",
|
||||
"Page Fault",
|
||||
"",
|
||||
"x87 Floating-Point Exception",
|
||||
"Alignment Check",
|
||||
"Machine Check",
|
||||
"SIMD Floating-Point Exception",
|
||||
"Virtualization Exception",
|
||||
"Control Protection Exception ",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"Hypervisor Injection Exception",
|
||||
"VMM Communication Exception",
|
||||
"Security Exception",
|
||||
""
|
||||
};
|
||||
static const char *isr_exception_messages[] = {"Divide by zero",
|
||||
"Debug",
|
||||
"NMI",
|
||||
"Breakpoint",
|
||||
"Overflow",
|
||||
"Bound Range Exceeded",
|
||||
"Invalid Opcode",
|
||||
"Device Not Available",
|
||||
"Double fault",
|
||||
"Co-processor Segment Overrun",
|
||||
"Invalid TSS",
|
||||
"Segment not present",
|
||||
"Stack-Segment Fault",
|
||||
"GPF",
|
||||
"Page Fault",
|
||||
"Reserved",
|
||||
"x87 Floating Point Exception",
|
||||
"alignment check",
|
||||
"Machine check",
|
||||
"SIMD floating-point exception",
|
||||
"Virtualization Exception",
|
||||
"Deadlock",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Security Exception",
|
||||
"Reserved",
|
||||
"Triple Fault",
|
||||
"FPU error"};
|
||||
|
||||
extern void x86_64_ISR_InitializeGates(void); // defined in isrs_gen.c
|
||||
static event_handlers_t event_handlers[256] = {NULL};
|
||||
|
||||
void x86_64_ISR_Initialize(void)
|
||||
{
|
||||
x86_64_ISR_InitializeGates();
|
||||
for (int i = 0; i < 256; i++)
|
||||
x86_64_IDT_EnableGate(i);
|
||||
x86_64_IDT_DisableGate(0x80); // syscall gate
|
||||
void isr_register_handler(int n, void *handler) {
|
||||
event_handlers[n] = handler;
|
||||
}
|
||||
|
||||
void page_fault_handler(Registers* regs, uint64_t cr2)
|
||||
{
|
||||
void isr_handle(registers_t *r) {
|
||||
if (r->cs & 0x3) {
|
||||
swapgs();
|
||||
}
|
||||
|
||||
if (r->isrNumber < 256 && event_handlers[r->isrNumber] != NULL) {
|
||||
event_handlers[r->isrNumber](r);
|
||||
} else {
|
||||
if (r->isrNumber < 32) {
|
||||
if (r->cs & 0x3) {
|
||||
struct thread *thrd = sched_get_running_thread();
|
||||
kprintf(
|
||||
"Killing user thread tid %d under process %s for exception "
|
||||
"%s\n",
|
||||
thrd->tid, thrd->mother_proc->name,
|
||||
isr_exception_messages[r->isrNumber]);
|
||||
kprintf("User thread crashed at address: %p\n", r->rip);
|
||||
thread_kill(thrd, true);
|
||||
} else {
|
||||
halt_other_cpus();
|
||||
kprintffos(0, "AH! UNHANDLED EXCEPTION!\n");
|
||||
kprintffos(0, "RIP: %p RBP: %p RSP: %p\n", r->rip, r->rbp,
|
||||
r->rsp);
|
||||
kprintffos(0, "RAX: %p RBX: %p RCX: %p\n", r->rax, r->rbx,
|
||||
r->rcx);
|
||||
kprintffos(0, "RDX: %p RDI: %p RSI: %p\n", r->rdx, r->rdi,
|
||||
r->rsi);
|
||||
kprintffos(0, "R8 : %p R9 : %p R10: %p\n", r->r8, r->r9,
|
||||
r->r10);
|
||||
kprintffos(0, "R11: %p R12: %p R13: %p\n", r->r11, r->r12,
|
||||
r->r13);
|
||||
kprintffos(0, "R14: %p R15: %p ERR: 0b%b\n", r->r14, r->r15,
|
||||
r->errorCode);
|
||||
kprintffos(0, "CS : %p SS : %p RFLAGS: %p\n", r->cs, r->ss,
|
||||
r->rflags);
|
||||
kprintffos(0, "FS : %p UGS: %p KGS: %p\n", read_fs_base(),
|
||||
read_user_gs(), read_kernel_gs());
|
||||
panic_((void *)r->rip, (void *)r->rbp,
|
||||
"Unhandled Exception: %s\n",
|
||||
isr_exception_messages[r->isrNumber]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// bit 0: present
|
||||
// bit 1: write
|
||||
// bit 2: user-mode
|
||||
// bit 3: reserved overwrite
|
||||
// bit 4: instruction fetch
|
||||
|
||||
log_crit(MODULE, "KERNEL PANIC! Exception %d (%s)", regs->interrupt, g_Exceptions[regs->interrupt]);
|
||||
|
||||
log_crit(MODULE, " rax=%x rbx=%x rcx=%x rdx=%x rsi=%x rdi=%x",
|
||||
regs->rax, regs->rbx, regs->rcx, regs->rdx, regs->rsi, regs->rdi);
|
||||
|
||||
log_crit(MODULE, " rsp=%x rbp=%x rip=%x rflags=%x cs=%x ss=%x",
|
||||
regs->rsp, regs->rbp, regs->rip, regs->rflags, regs->cs, regs->ss);
|
||||
|
||||
log_crit(MODULE, " interrupt=%x errorcode=%x", regs->interrupt, regs->error);
|
||||
|
||||
log_crit("PAGEFAULT", "Fault at address %lx (rip=%lx, err=%x)",
|
||||
cr2, regs->rip, regs->error);
|
||||
|
||||
log_crit(MODULE, "KERNEL PANIC!");
|
||||
|
||||
x86_64_Panic(); // or attempt recovery
|
||||
if (r->cs & 0x3) {
|
||||
swapgs();
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((used)) x86_64_ISR_Handler(Registers* regs)
|
||||
{
|
||||
if (regs->interrupt == 14)
|
||||
{
|
||||
uint64_t cr2 = x86_64_read_cr2();
|
||||
page_fault_handler(regs, cr2);
|
||||
|
||||
}
|
||||
|
||||
if (g_ISRHandlers[regs->interrupt])
|
||||
g_ISRHandlers[regs->interrupt](regs);
|
||||
else if (regs->interrupt >= 32)
|
||||
log_err(MODULE, "Unhandled interrupt %d!", regs->interrupt);
|
||||
else {
|
||||
// panic log (use regs->rax etc. now)
|
||||
log_crit(MODULE, "KERNEL PANIC! Exception %d (%s)", regs->interrupt, g_Exceptions[regs->interrupt]);
|
||||
// ... print registers with rax/rbx etc. ...
|
||||
log_crit(MODULE, " rax=%x rbx=%x rcx=%x rdx=%x rsi=%x rdi=%x",
|
||||
regs->rax, regs->rbx, regs->rcx, regs->rdx, regs->rsi, regs->rdi);
|
||||
|
||||
log_crit(MODULE, " rsp=%x rbp=%x rip=%x rflags=%x cs=%x ss=%x",
|
||||
regs->rsp, regs->rbp, regs->rip, regs->rflags, regs->cs, regs->ss);
|
||||
|
||||
log_crit(MODULE, " interrupt=%x errorcode=%x", regs->interrupt, regs->error);
|
||||
|
||||
log_crit(MODULE, "KERNEL PANIC!");
|
||||
x86_64_Panic();
|
||||
}
|
||||
}
|
||||
|
||||
void x86_64_ISR_RegisterHandler(int interrupt, ISRHandler handler)
|
||||
{
|
||||
g_ISRHandlers[interrupt] = handler;
|
||||
x86_64_IDT_EnableGate(interrupt);
|
||||
}
|
||||
+41
-10
@@ -1,15 +1,46 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "arch/x86_64/cpu/reg.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
|
||||
uint64_t rdi, rsi, rbp, rdx, rcx, rbx, rax;
|
||||
uint64_t interrupt, error;
|
||||
uint64_t rip, cs, rflags, rsp, ss;
|
||||
} __attribute__((packed)) Registers;
|
||||
#define PASTER(x, y) x##y
|
||||
#define EVALUATOR(x, y) PASTER(x, y)
|
||||
// This first macro makes functions like "void isr0(void)"
|
||||
// But the number is summed up on each call
|
||||
#define ONE EVALUATOR(void isr, __COUNTER__)(void)
|
||||
// Different granularities
|
||||
#define TWO \
|
||||
ONE; \
|
||||
ONE
|
||||
#define TEN \
|
||||
TWO; \
|
||||
TWO; \
|
||||
TWO; \
|
||||
TWO; \
|
||||
TWO
|
||||
#define TWENTY \
|
||||
TEN; \
|
||||
TEN
|
||||
#define HUNDRED \
|
||||
TWENTY; \
|
||||
TWENTY; \
|
||||
TWENTY; \
|
||||
TWENTY; \
|
||||
TWENTY
|
||||
// Define 255 ISRs based on previous granularities
|
||||
#define DEFISR \
|
||||
HUNDRED; \
|
||||
HUNDRED; \
|
||||
TWENTY; \
|
||||
TWENTY; \
|
||||
TEN; \
|
||||
TWO; \
|
||||
TWO; \
|
||||
TWO
|
||||
|
||||
typedef void (*ISRHandler)(Registers* regs);
|
||||
DEFISR;
|
||||
|
||||
void x86_64_ISR_Initialize(void);
|
||||
void x86_64_ISR_RegisterHandler(int interrupt, ISRHandler handler);
|
||||
typedef void (*event_handlers_t)(registers_t *);
|
||||
|
||||
void isr_install(void);
|
||||
extern void isr_handle(registers_t *r);
|
||||
void isr_register_handler(int n, void *handler);
|
||||
@@ -1,58 +0,0 @@
|
||||
.intel_syntax noprefix
|
||||
.extern x86_64_ISR_Handler
|
||||
|
||||
.macro ISR_NOERRORCODE num
|
||||
.global x86_64_ISR\num
|
||||
x86_64_ISR\num:
|
||||
push 0
|
||||
push \num
|
||||
jmp isr_common
|
||||
.endm
|
||||
|
||||
.macro ISR_ERRORCODE num
|
||||
.global x86_64_ISR\num
|
||||
x86_64_ISR\num:
|
||||
push \num
|
||||
jmp isr_common
|
||||
.endm
|
||||
|
||||
.include "arch/x86_64/boot/isrs_gen.inc"
|
||||
|
||||
isr_common:
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rbp
|
||||
push rsi
|
||||
push rdi
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
mov rdi, rsp // Registers* in RDI
|
||||
call x86_64_ISR_Handler
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbp
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
|
||||
add rsp, 16 // pop interrupt + error code
|
||||
iretq
|
||||
@@ -0,0 +1,87 @@
|
||||
|
||||
%macro pushall 0
|
||||
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rbp
|
||||
push rdi
|
||||
push rsi
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
%endmacro
|
||||
|
||||
%macro popall 0
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbp
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
|
||||
%endmacro
|
||||
|
||||
extern isr_handle
|
||||
|
||||
; Common handler for the ISRs
|
||||
isr_common_format:
|
||||
pushall
|
||||
cld
|
||||
mov rdi, rsp
|
||||
xor rbp, rbp
|
||||
call isr_handle
|
||||
popall
|
||||
add rsp, 24
|
||||
iretq
|
||||
|
||||
%macro isr 1
|
||||
|
||||
global isr%1
|
||||
isr%1:
|
||||
push 0
|
||||
push %1
|
||||
push fs
|
||||
jmp isr_common_format
|
||||
|
||||
%endmacro
|
||||
|
||||
%macro error_isr 1
|
||||
|
||||
global isr%1
|
||||
isr%1:
|
||||
push %1
|
||||
push fs
|
||||
jmp isr_common_format
|
||||
|
||||
%endmacro
|
||||
|
||||
%define has_errcode(i) (i == 8 || (i >= 10 && i <= 14) || i == 17 || i == 21 || i == 29 || i == 30)
|
||||
|
||||
; Define ISRs
|
||||
%assign i 0
|
||||
%rep 256
|
||||
%if !has_errcode(i)
|
||||
isr i
|
||||
%else
|
||||
error_isr i
|
||||
%endif
|
||||
%assign i i + 1
|
||||
%endrep
|
||||
@@ -1,520 +0,0 @@
|
||||
// !!! THIS FILE IS AUTOGENERATED !!!
|
||||
#include "idt.h"
|
||||
#include "gdt.h"
|
||||
|
||||
void x86_64_ISR0();
|
||||
void x86_64_ISR1();
|
||||
void x86_64_ISR2();
|
||||
void x86_64_ISR3();
|
||||
void x86_64_ISR4();
|
||||
void x86_64_ISR5();
|
||||
void x86_64_ISR6();
|
||||
void x86_64_ISR7();
|
||||
void x86_64_ISR8();
|
||||
void x86_64_ISR9();
|
||||
void x86_64_ISR10();
|
||||
void x86_64_ISR11();
|
||||
void x86_64_ISR12();
|
||||
void x86_64_ISR13();
|
||||
void x86_64_ISR14();
|
||||
void x86_64_ISR15();
|
||||
void x86_64_ISR16();
|
||||
void x86_64_ISR17();
|
||||
void x86_64_ISR18();
|
||||
void x86_64_ISR19();
|
||||
void x86_64_ISR20();
|
||||
void x86_64_ISR21();
|
||||
void x86_64_ISR22();
|
||||
void x86_64_ISR23();
|
||||
void x86_64_ISR24();
|
||||
void x86_64_ISR25();
|
||||
void x86_64_ISR26();
|
||||
void x86_64_ISR27();
|
||||
void x86_64_ISR28();
|
||||
void x86_64_ISR29();
|
||||
void x86_64_ISR30();
|
||||
void x86_64_ISR31();
|
||||
void x86_64_ISR32();
|
||||
void x86_64_ISR33();
|
||||
void x86_64_ISR34();
|
||||
void x86_64_ISR35();
|
||||
void x86_64_ISR36();
|
||||
void x86_64_ISR37();
|
||||
void x86_64_ISR38();
|
||||
void x86_64_ISR39();
|
||||
void x86_64_ISR40();
|
||||
void x86_64_ISR41();
|
||||
void x86_64_ISR42();
|
||||
void x86_64_ISR43();
|
||||
void x86_64_ISR44();
|
||||
void x86_64_ISR45();
|
||||
void x86_64_ISR46();
|
||||
void x86_64_ISR47();
|
||||
void x86_64_ISR48();
|
||||
void x86_64_ISR49();
|
||||
void x86_64_ISR50();
|
||||
void x86_64_ISR51();
|
||||
void x86_64_ISR52();
|
||||
void x86_64_ISR53();
|
||||
void x86_64_ISR54();
|
||||
void x86_64_ISR55();
|
||||
void x86_64_ISR56();
|
||||
void x86_64_ISR57();
|
||||
void x86_64_ISR58();
|
||||
void x86_64_ISR59();
|
||||
void x86_64_ISR60();
|
||||
void x86_64_ISR61();
|
||||
void x86_64_ISR62();
|
||||
void x86_64_ISR63();
|
||||
void x86_64_ISR64();
|
||||
void x86_64_ISR65();
|
||||
void x86_64_ISR66();
|
||||
void x86_64_ISR67();
|
||||
void x86_64_ISR68();
|
||||
void x86_64_ISR69();
|
||||
void x86_64_ISR70();
|
||||
void x86_64_ISR71();
|
||||
void x86_64_ISR72();
|
||||
void x86_64_ISR73();
|
||||
void x86_64_ISR74();
|
||||
void x86_64_ISR75();
|
||||
void x86_64_ISR76();
|
||||
void x86_64_ISR77();
|
||||
void x86_64_ISR78();
|
||||
void x86_64_ISR79();
|
||||
void x86_64_ISR80();
|
||||
void x86_64_ISR81();
|
||||
void x86_64_ISR82();
|
||||
void x86_64_ISR83();
|
||||
void x86_64_ISR84();
|
||||
void x86_64_ISR85();
|
||||
void x86_64_ISR86();
|
||||
void x86_64_ISR87();
|
||||
void x86_64_ISR88();
|
||||
void x86_64_ISR89();
|
||||
void x86_64_ISR90();
|
||||
void x86_64_ISR91();
|
||||
void x86_64_ISR92();
|
||||
void x86_64_ISR93();
|
||||
void x86_64_ISR94();
|
||||
void x86_64_ISR95();
|
||||
void x86_64_ISR96();
|
||||
void x86_64_ISR97();
|
||||
void x86_64_ISR98();
|
||||
void x86_64_ISR99();
|
||||
void x86_64_ISR100();
|
||||
void x86_64_ISR101();
|
||||
void x86_64_ISR102();
|
||||
void x86_64_ISR103();
|
||||
void x86_64_ISR104();
|
||||
void x86_64_ISR105();
|
||||
void x86_64_ISR106();
|
||||
void x86_64_ISR107();
|
||||
void x86_64_ISR108();
|
||||
void x86_64_ISR109();
|
||||
void x86_64_ISR110();
|
||||
void x86_64_ISR111();
|
||||
void x86_64_ISR112();
|
||||
void x86_64_ISR113();
|
||||
void x86_64_ISR114();
|
||||
void x86_64_ISR115();
|
||||
void x86_64_ISR116();
|
||||
void x86_64_ISR117();
|
||||
void x86_64_ISR118();
|
||||
void x86_64_ISR119();
|
||||
void x86_64_ISR120();
|
||||
void x86_64_ISR121();
|
||||
void x86_64_ISR122();
|
||||
void x86_64_ISR123();
|
||||
void x86_64_ISR124();
|
||||
void x86_64_ISR125();
|
||||
void x86_64_ISR126();
|
||||
void x86_64_ISR127();
|
||||
void x86_64_ISR128();
|
||||
void x86_64_ISR129();
|
||||
void x86_64_ISR130();
|
||||
void x86_64_ISR131();
|
||||
void x86_64_ISR132();
|
||||
void x86_64_ISR133();
|
||||
void x86_64_ISR134();
|
||||
void x86_64_ISR135();
|
||||
void x86_64_ISR136();
|
||||
void x86_64_ISR137();
|
||||
void x86_64_ISR138();
|
||||
void x86_64_ISR139();
|
||||
void x86_64_ISR140();
|
||||
void x86_64_ISR141();
|
||||
void x86_64_ISR142();
|
||||
void x86_64_ISR143();
|
||||
void x86_64_ISR144();
|
||||
void x86_64_ISR145();
|
||||
void x86_64_ISR146();
|
||||
void x86_64_ISR147();
|
||||
void x86_64_ISR148();
|
||||
void x86_64_ISR149();
|
||||
void x86_64_ISR150();
|
||||
void x86_64_ISR151();
|
||||
void x86_64_ISR152();
|
||||
void x86_64_ISR153();
|
||||
void x86_64_ISR154();
|
||||
void x86_64_ISR155();
|
||||
void x86_64_ISR156();
|
||||
void x86_64_ISR157();
|
||||
void x86_64_ISR158();
|
||||
void x86_64_ISR159();
|
||||
void x86_64_ISR160();
|
||||
void x86_64_ISR161();
|
||||
void x86_64_ISR162();
|
||||
void x86_64_ISR163();
|
||||
void x86_64_ISR164();
|
||||
void x86_64_ISR165();
|
||||
void x86_64_ISR166();
|
||||
void x86_64_ISR167();
|
||||
void x86_64_ISR168();
|
||||
void x86_64_ISR169();
|
||||
void x86_64_ISR170();
|
||||
void x86_64_ISR171();
|
||||
void x86_64_ISR172();
|
||||
void x86_64_ISR173();
|
||||
void x86_64_ISR174();
|
||||
void x86_64_ISR175();
|
||||
void x86_64_ISR176();
|
||||
void x86_64_ISR177();
|
||||
void x86_64_ISR178();
|
||||
void x86_64_ISR179();
|
||||
void x86_64_ISR180();
|
||||
void x86_64_ISR181();
|
||||
void x86_64_ISR182();
|
||||
void x86_64_ISR183();
|
||||
void x86_64_ISR184();
|
||||
void x86_64_ISR185();
|
||||
void x86_64_ISR186();
|
||||
void x86_64_ISR187();
|
||||
void x86_64_ISR188();
|
||||
void x86_64_ISR189();
|
||||
void x86_64_ISR190();
|
||||
void x86_64_ISR191();
|
||||
void x86_64_ISR192();
|
||||
void x86_64_ISR193();
|
||||
void x86_64_ISR194();
|
||||
void x86_64_ISR195();
|
||||
void x86_64_ISR196();
|
||||
void x86_64_ISR197();
|
||||
void x86_64_ISR198();
|
||||
void x86_64_ISR199();
|
||||
void x86_64_ISR200();
|
||||
void x86_64_ISR201();
|
||||
void x86_64_ISR202();
|
||||
void x86_64_ISR203();
|
||||
void x86_64_ISR204();
|
||||
void x86_64_ISR205();
|
||||
void x86_64_ISR206();
|
||||
void x86_64_ISR207();
|
||||
void x86_64_ISR208();
|
||||
void x86_64_ISR209();
|
||||
void x86_64_ISR210();
|
||||
void x86_64_ISR211();
|
||||
void x86_64_ISR212();
|
||||
void x86_64_ISR213();
|
||||
void x86_64_ISR214();
|
||||
void x86_64_ISR215();
|
||||
void x86_64_ISR216();
|
||||
void x86_64_ISR217();
|
||||
void x86_64_ISR218();
|
||||
void x86_64_ISR219();
|
||||
void x86_64_ISR220();
|
||||
void x86_64_ISR221();
|
||||
void x86_64_ISR222();
|
||||
void x86_64_ISR223();
|
||||
void x86_64_ISR224();
|
||||
void x86_64_ISR225();
|
||||
void x86_64_ISR226();
|
||||
void x86_64_ISR227();
|
||||
void x86_64_ISR228();
|
||||
void x86_64_ISR229();
|
||||
void x86_64_ISR230();
|
||||
void x86_64_ISR231();
|
||||
void x86_64_ISR232();
|
||||
void x86_64_ISR233();
|
||||
void x86_64_ISR234();
|
||||
void x86_64_ISR235();
|
||||
void x86_64_ISR236();
|
||||
void x86_64_ISR237();
|
||||
void x86_64_ISR238();
|
||||
void x86_64_ISR239();
|
||||
void x86_64_ISR240();
|
||||
void x86_64_ISR241();
|
||||
void x86_64_ISR242();
|
||||
void x86_64_ISR243();
|
||||
void x86_64_ISR244();
|
||||
void x86_64_ISR245();
|
||||
void x86_64_ISR246();
|
||||
void x86_64_ISR247();
|
||||
void x86_64_ISR248();
|
||||
void x86_64_ISR249();
|
||||
void x86_64_ISR250();
|
||||
void x86_64_ISR251();
|
||||
void x86_64_ISR252();
|
||||
void x86_64_ISR253();
|
||||
void x86_64_ISR254();
|
||||
void x86_64_ISR255();
|
||||
|
||||
void x86_64_ISR_InitializeGates()
|
||||
{
|
||||
x86_64_IDT_SetGate(0, x86_64_ISR0, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(1, x86_64_ISR1, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(2, x86_64_ISR2, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(3, x86_64_ISR3, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(4, x86_64_ISR4, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(5, x86_64_ISR5, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(6, x86_64_ISR6, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(7, x86_64_ISR7, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(8, x86_64_ISR8, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(9, x86_64_ISR9, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(10, x86_64_ISR10, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(11, x86_64_ISR11, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(12, x86_64_ISR12, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(13, x86_64_ISR13, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(14, x86_64_ISR14, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(15, x86_64_ISR15, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(16, x86_64_ISR16, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(17, x86_64_ISR17, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(18, x86_64_ISR18, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(19, x86_64_ISR19, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(20, x86_64_ISR20, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(21, x86_64_ISR21, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(22, x86_64_ISR22, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(23, x86_64_ISR23, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(24, x86_64_ISR24, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(25, x86_64_ISR25, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(26, x86_64_ISR26, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(27, x86_64_ISR27, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(28, x86_64_ISR28, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(29, x86_64_ISR29, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(30, x86_64_ISR30, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(31, x86_64_ISR31, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(32, x86_64_ISR32, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(33, x86_64_ISR33, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(34, x86_64_ISR34, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(35, x86_64_ISR35, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(36, x86_64_ISR36, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(37, x86_64_ISR37, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(38, x86_64_ISR38, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(39, x86_64_ISR39, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(40, x86_64_ISR40, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(41, x86_64_ISR41, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(42, x86_64_ISR42, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(43, x86_64_ISR43, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(44, x86_64_ISR44, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(45, x86_64_ISR45, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(46, x86_64_ISR46, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(47, x86_64_ISR47, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(48, x86_64_ISR48, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(49, x86_64_ISR49, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(50, x86_64_ISR50, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(51, x86_64_ISR51, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(52, x86_64_ISR52, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(53, x86_64_ISR53, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(54, x86_64_ISR54, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(55, x86_64_ISR55, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(56, x86_64_ISR56, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(57, x86_64_ISR57, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(58, x86_64_ISR58, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(59, x86_64_ISR59, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(60, x86_64_ISR60, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(61, x86_64_ISR61, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(62, x86_64_ISR62, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(63, x86_64_ISR63, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(64, x86_64_ISR64, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(65, x86_64_ISR65, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(66, x86_64_ISR66, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(67, x86_64_ISR67, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(68, x86_64_ISR68, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(69, x86_64_ISR69, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(70, x86_64_ISR70, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(71, x86_64_ISR71, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(72, x86_64_ISR72, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(73, x86_64_ISR73, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(74, x86_64_ISR74, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(75, x86_64_ISR75, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(76, x86_64_ISR76, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(77, x86_64_ISR77, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(78, x86_64_ISR78, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(79, x86_64_ISR79, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(80, x86_64_ISR80, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(81, x86_64_ISR81, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(82, x86_64_ISR82, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(83, x86_64_ISR83, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(84, x86_64_ISR84, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(85, x86_64_ISR85, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(86, x86_64_ISR86, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(87, x86_64_ISR87, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(88, x86_64_ISR88, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(89, x86_64_ISR89, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(90, x86_64_ISR90, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(91, x86_64_ISR91, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(92, x86_64_ISR92, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(93, x86_64_ISR93, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(94, x86_64_ISR94, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(95, x86_64_ISR95, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(96, x86_64_ISR96, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(97, x86_64_ISR97, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(98, x86_64_ISR98, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(99, x86_64_ISR99, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(100, x86_64_ISR100, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(101, x86_64_ISR101, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(102, x86_64_ISR102, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(103, x86_64_ISR103, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(104, x86_64_ISR104, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(105, x86_64_ISR105, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(106, x86_64_ISR106, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(107, x86_64_ISR107, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(108, x86_64_ISR108, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(109, x86_64_ISR109, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(110, x86_64_ISR110, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(111, x86_64_ISR111, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(112, x86_64_ISR112, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(113, x86_64_ISR113, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(114, x86_64_ISR114, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(115, x86_64_ISR115, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(116, x86_64_ISR116, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(117, x86_64_ISR117, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(118, x86_64_ISR118, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(119, x86_64_ISR119, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(120, x86_64_ISR120, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(121, x86_64_ISR121, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(122, x86_64_ISR122, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(123, x86_64_ISR123, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(124, x86_64_ISR124, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(125, x86_64_ISR125, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(126, x86_64_ISR126, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(127, x86_64_ISR127, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(128, x86_64_ISR128, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(129, x86_64_ISR129, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(130, x86_64_ISR130, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(131, x86_64_ISR131, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(132, x86_64_ISR132, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(133, x86_64_ISR133, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(134, x86_64_ISR134, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(135, x86_64_ISR135, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(136, x86_64_ISR136, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(137, x86_64_ISR137, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(138, x86_64_ISR138, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(139, x86_64_ISR139, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(140, x86_64_ISR140, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(141, x86_64_ISR141, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(142, x86_64_ISR142, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(143, x86_64_ISR143, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(144, x86_64_ISR144, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(145, x86_64_ISR145, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(146, x86_64_ISR146, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(147, x86_64_ISR147, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(148, x86_64_ISR148, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(149, x86_64_ISR149, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(150, x86_64_ISR150, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(151, x86_64_ISR151, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(152, x86_64_ISR152, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(153, x86_64_ISR153, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(154, x86_64_ISR154, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(155, x86_64_ISR155, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(156, x86_64_ISR156, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(157, x86_64_ISR157, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(158, x86_64_ISR158, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(159, x86_64_ISR159, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(160, x86_64_ISR160, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(161, x86_64_ISR161, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(162, x86_64_ISR162, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(163, x86_64_ISR163, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(164, x86_64_ISR164, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(165, x86_64_ISR165, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(166, x86_64_ISR166, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(167, x86_64_ISR167, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(168, x86_64_ISR168, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(169, x86_64_ISR169, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(170, x86_64_ISR170, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(171, x86_64_ISR171, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(172, x86_64_ISR172, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(173, x86_64_ISR173, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(174, x86_64_ISR174, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(175, x86_64_ISR175, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(176, x86_64_ISR176, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(177, x86_64_ISR177, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(178, x86_64_ISR178, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(179, x86_64_ISR179, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(180, x86_64_ISR180, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(181, x86_64_ISR181, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(182, x86_64_ISR182, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(183, x86_64_ISR183, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(184, x86_64_ISR184, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(185, x86_64_ISR185, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(186, x86_64_ISR186, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(187, x86_64_ISR187, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(188, x86_64_ISR188, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(189, x86_64_ISR189, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(190, x86_64_ISR190, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(191, x86_64_ISR191, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(192, x86_64_ISR192, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(193, x86_64_ISR193, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(194, x86_64_ISR194, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(195, x86_64_ISR195, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(196, x86_64_ISR196, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(197, x86_64_ISR197, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(198, x86_64_ISR198, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(199, x86_64_ISR199, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(200, x86_64_ISR200, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(201, x86_64_ISR201, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(202, x86_64_ISR202, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(203, x86_64_ISR203, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(204, x86_64_ISR204, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(205, x86_64_ISR205, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(206, x86_64_ISR206, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(207, x86_64_ISR207, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(208, x86_64_ISR208, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(209, x86_64_ISR209, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(210, x86_64_ISR210, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(211, x86_64_ISR211, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(212, x86_64_ISR212, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(213, x86_64_ISR213, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(214, x86_64_ISR214, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(215, x86_64_ISR215, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(216, x86_64_ISR216, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(217, x86_64_ISR217, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(218, x86_64_ISR218, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(219, x86_64_ISR219, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(220, x86_64_ISR220, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(221, x86_64_ISR221, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(222, x86_64_ISR222, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(223, x86_64_ISR223, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(224, x86_64_ISR224, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(225, x86_64_ISR225, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(226, x86_64_ISR226, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(227, x86_64_ISR227, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(228, x86_64_ISR228, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(229, x86_64_ISR229, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(230, x86_64_ISR230, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(231, x86_64_ISR231, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(232, x86_64_ISR232, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(233, x86_64_ISR233, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(234, x86_64_ISR234, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(235, x86_64_ISR235, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(236, x86_64_ISR236, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(237, x86_64_ISR237, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(238, x86_64_ISR238, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(239, x86_64_ISR239, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(240, x86_64_ISR240, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(241, x86_64_ISR241, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(242, x86_64_ISR242, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(243, x86_64_ISR243, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(244, x86_64_ISR244, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(245, x86_64_ISR245, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(246, x86_64_ISR246, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(247, x86_64_ISR247, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(248, x86_64_ISR248, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(249, x86_64_ISR249, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(250, x86_64_ISR250, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(251, x86_64_ISR251, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(252, x86_64_ISR252, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(253, x86_64_ISR253, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(254, x86_64_ISR254, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
x86_64_IDT_SetGate(255, x86_64_ISR255, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
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_ERRORCODE 17
|
||||
ISR_NOERRORCODE 18
|
||||
ISR_NOERRORCODE 19
|
||||
ISR_NOERRORCODE 20
|
||||
ISR_ERRORCODE 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
|
||||
ISR_NOERRORCODE 32
|
||||
ISR_NOERRORCODE 33
|
||||
ISR_NOERRORCODE 34
|
||||
ISR_NOERRORCODE 35
|
||||
ISR_NOERRORCODE 36
|
||||
ISR_NOERRORCODE 37
|
||||
ISR_NOERRORCODE 38
|
||||
ISR_NOERRORCODE 39
|
||||
ISR_NOERRORCODE 40
|
||||
ISR_NOERRORCODE 41
|
||||
ISR_NOERRORCODE 42
|
||||
ISR_NOERRORCODE 43
|
||||
ISR_NOERRORCODE 44
|
||||
ISR_NOERRORCODE 45
|
||||
ISR_NOERRORCODE 46
|
||||
ISR_NOERRORCODE 47
|
||||
ISR_NOERRORCODE 48
|
||||
ISR_NOERRORCODE 49
|
||||
ISR_NOERRORCODE 50
|
||||
ISR_NOERRORCODE 51
|
||||
ISR_NOERRORCODE 52
|
||||
ISR_NOERRORCODE 53
|
||||
ISR_NOERRORCODE 54
|
||||
ISR_NOERRORCODE 55
|
||||
ISR_NOERRORCODE 56
|
||||
ISR_NOERRORCODE 57
|
||||
ISR_NOERRORCODE 58
|
||||
ISR_NOERRORCODE 59
|
||||
ISR_NOERRORCODE 60
|
||||
ISR_NOERRORCODE 61
|
||||
ISR_NOERRORCODE 62
|
||||
ISR_NOERRORCODE 63
|
||||
ISR_NOERRORCODE 64
|
||||
ISR_NOERRORCODE 65
|
||||
ISR_NOERRORCODE 66
|
||||
ISR_NOERRORCODE 67
|
||||
ISR_NOERRORCODE 68
|
||||
ISR_NOERRORCODE 69
|
||||
ISR_NOERRORCODE 70
|
||||
ISR_NOERRORCODE 71
|
||||
ISR_NOERRORCODE 72
|
||||
ISR_NOERRORCODE 73
|
||||
ISR_NOERRORCODE 74
|
||||
ISR_NOERRORCODE 75
|
||||
ISR_NOERRORCODE 76
|
||||
ISR_NOERRORCODE 77
|
||||
ISR_NOERRORCODE 78
|
||||
ISR_NOERRORCODE 79
|
||||
ISR_NOERRORCODE 80
|
||||
ISR_NOERRORCODE 81
|
||||
ISR_NOERRORCODE 82
|
||||
ISR_NOERRORCODE 83
|
||||
ISR_NOERRORCODE 84
|
||||
ISR_NOERRORCODE 85
|
||||
ISR_NOERRORCODE 86
|
||||
ISR_NOERRORCODE 87
|
||||
ISR_NOERRORCODE 88
|
||||
ISR_NOERRORCODE 89
|
||||
ISR_NOERRORCODE 90
|
||||
ISR_NOERRORCODE 91
|
||||
ISR_NOERRORCODE 92
|
||||
ISR_NOERRORCODE 93
|
||||
ISR_NOERRORCODE 94
|
||||
ISR_NOERRORCODE 95
|
||||
ISR_NOERRORCODE 96
|
||||
ISR_NOERRORCODE 97
|
||||
ISR_NOERRORCODE 98
|
||||
ISR_NOERRORCODE 99
|
||||
ISR_NOERRORCODE 100
|
||||
ISR_NOERRORCODE 101
|
||||
ISR_NOERRORCODE 102
|
||||
ISR_NOERRORCODE 103
|
||||
ISR_NOERRORCODE 104
|
||||
ISR_NOERRORCODE 105
|
||||
ISR_NOERRORCODE 106
|
||||
ISR_NOERRORCODE 107
|
||||
ISR_NOERRORCODE 108
|
||||
ISR_NOERRORCODE 109
|
||||
ISR_NOERRORCODE 110
|
||||
ISR_NOERRORCODE 111
|
||||
ISR_NOERRORCODE 112
|
||||
ISR_NOERRORCODE 113
|
||||
ISR_NOERRORCODE 114
|
||||
ISR_NOERRORCODE 115
|
||||
ISR_NOERRORCODE 116
|
||||
ISR_NOERRORCODE 117
|
||||
ISR_NOERRORCODE 118
|
||||
ISR_NOERRORCODE 119
|
||||
ISR_NOERRORCODE 120
|
||||
ISR_NOERRORCODE 121
|
||||
ISR_NOERRORCODE 122
|
||||
ISR_NOERRORCODE 123
|
||||
ISR_NOERRORCODE 124
|
||||
ISR_NOERRORCODE 125
|
||||
ISR_NOERRORCODE 126
|
||||
ISR_NOERRORCODE 127
|
||||
ISR_NOERRORCODE 128
|
||||
ISR_NOERRORCODE 129
|
||||
ISR_NOERRORCODE 130
|
||||
ISR_NOERRORCODE 131
|
||||
ISR_NOERRORCODE 132
|
||||
ISR_NOERRORCODE 133
|
||||
ISR_NOERRORCODE 134
|
||||
ISR_NOERRORCODE 135
|
||||
ISR_NOERRORCODE 136
|
||||
ISR_NOERRORCODE 137
|
||||
ISR_NOERRORCODE 138
|
||||
ISR_NOERRORCODE 139
|
||||
ISR_NOERRORCODE 140
|
||||
ISR_NOERRORCODE 141
|
||||
ISR_NOERRORCODE 142
|
||||
ISR_NOERRORCODE 143
|
||||
ISR_NOERRORCODE 144
|
||||
ISR_NOERRORCODE 145
|
||||
ISR_NOERRORCODE 146
|
||||
ISR_NOERRORCODE 147
|
||||
ISR_NOERRORCODE 148
|
||||
ISR_NOERRORCODE 149
|
||||
ISR_NOERRORCODE 150
|
||||
ISR_NOERRORCODE 151
|
||||
ISR_NOERRORCODE 152
|
||||
ISR_NOERRORCODE 153
|
||||
ISR_NOERRORCODE 154
|
||||
ISR_NOERRORCODE 155
|
||||
ISR_NOERRORCODE 156
|
||||
ISR_NOERRORCODE 157
|
||||
ISR_NOERRORCODE 158
|
||||
ISR_NOERRORCODE 159
|
||||
ISR_NOERRORCODE 160
|
||||
ISR_NOERRORCODE 161
|
||||
ISR_NOERRORCODE 162
|
||||
ISR_NOERRORCODE 163
|
||||
ISR_NOERRORCODE 164
|
||||
ISR_NOERRORCODE 165
|
||||
ISR_NOERRORCODE 166
|
||||
ISR_NOERRORCODE 167
|
||||
ISR_NOERRORCODE 168
|
||||
ISR_NOERRORCODE 169
|
||||
ISR_NOERRORCODE 170
|
||||
ISR_NOERRORCODE 171
|
||||
ISR_NOERRORCODE 172
|
||||
ISR_NOERRORCODE 173
|
||||
ISR_NOERRORCODE 174
|
||||
ISR_NOERRORCODE 175
|
||||
ISR_NOERRORCODE 176
|
||||
ISR_NOERRORCODE 177
|
||||
ISR_NOERRORCODE 178
|
||||
ISR_NOERRORCODE 179
|
||||
ISR_NOERRORCODE 180
|
||||
ISR_NOERRORCODE 181
|
||||
ISR_NOERRORCODE 182
|
||||
ISR_NOERRORCODE 183
|
||||
ISR_NOERRORCODE 184
|
||||
ISR_NOERRORCODE 185
|
||||
ISR_NOERRORCODE 186
|
||||
ISR_NOERRORCODE 187
|
||||
ISR_NOERRORCODE 188
|
||||
ISR_NOERRORCODE 189
|
||||
ISR_NOERRORCODE 190
|
||||
ISR_NOERRORCODE 191
|
||||
ISR_NOERRORCODE 192
|
||||
ISR_NOERRORCODE 193
|
||||
ISR_NOERRORCODE 194
|
||||
ISR_NOERRORCODE 195
|
||||
ISR_NOERRORCODE 196
|
||||
ISR_NOERRORCODE 197
|
||||
ISR_NOERRORCODE 198
|
||||
ISR_NOERRORCODE 199
|
||||
ISR_NOERRORCODE 200
|
||||
ISR_NOERRORCODE 201
|
||||
ISR_NOERRORCODE 202
|
||||
ISR_NOERRORCODE 203
|
||||
ISR_NOERRORCODE 204
|
||||
ISR_NOERRORCODE 205
|
||||
ISR_NOERRORCODE 206
|
||||
ISR_NOERRORCODE 207
|
||||
ISR_NOERRORCODE 208
|
||||
ISR_NOERRORCODE 209
|
||||
ISR_NOERRORCODE 210
|
||||
ISR_NOERRORCODE 211
|
||||
ISR_NOERRORCODE 212
|
||||
ISR_NOERRORCODE 213
|
||||
ISR_NOERRORCODE 214
|
||||
ISR_NOERRORCODE 215
|
||||
ISR_NOERRORCODE 216
|
||||
ISR_NOERRORCODE 217
|
||||
ISR_NOERRORCODE 218
|
||||
ISR_NOERRORCODE 219
|
||||
ISR_NOERRORCODE 220
|
||||
ISR_NOERRORCODE 221
|
||||
ISR_NOERRORCODE 222
|
||||
ISR_NOERRORCODE 223
|
||||
ISR_NOERRORCODE 224
|
||||
ISR_NOERRORCODE 225
|
||||
ISR_NOERRORCODE 226
|
||||
ISR_NOERRORCODE 227
|
||||
ISR_NOERRORCODE 228
|
||||
ISR_NOERRORCODE 229
|
||||
ISR_NOERRORCODE 230
|
||||
ISR_NOERRORCODE 231
|
||||
ISR_NOERRORCODE 232
|
||||
ISR_NOERRORCODE 233
|
||||
ISR_NOERRORCODE 234
|
||||
ISR_NOERRORCODE 235
|
||||
ISR_NOERRORCODE 236
|
||||
ISR_NOERRORCODE 237
|
||||
ISR_NOERRORCODE 238
|
||||
ISR_NOERRORCODE 239
|
||||
ISR_NOERRORCODE 240
|
||||
ISR_NOERRORCODE 241
|
||||
ISR_NOERRORCODE 242
|
||||
ISR_NOERRORCODE 243
|
||||
ISR_NOERRORCODE 244
|
||||
ISR_NOERRORCODE 245
|
||||
ISR_NOERRORCODE 246
|
||||
ISR_NOERRORCODE 247
|
||||
ISR_NOERRORCODE 248
|
||||
ISR_NOERRORCODE 249
|
||||
ISR_NOERRORCODE 250
|
||||
ISR_NOERRORCODE 251
|
||||
ISR_NOERRORCODE 252
|
||||
ISR_NOERRORCODE 253
|
||||
ISR_NOERRORCODE 254
|
||||
ISR_NOERRORCODE 255
|
||||
+11
-11
@@ -1,7 +1,7 @@
|
||||
#include "ata.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include "libk/stdio.h"
|
||||
#include <stdbool.h>
|
||||
#include "libk/debug.h"
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ void ata_init(void)
|
||||
ata_wait_ready();
|
||||
x86_64_outb(ATA_PRIMARY_DRIVE, 0xA0); // select master
|
||||
ata_wait_ready();
|
||||
printf("ATA: Primary master (hda) initialized\n");
|
||||
kprintf("ATA: Primary master (hda) initialized\n");
|
||||
}
|
||||
|
||||
void ata_identify(void)
|
||||
@@ -71,30 +71,30 @@ void ata_identify(void)
|
||||
x86_64_outb(ATA_PRIMARY_COMMAND, ATA_CMD_IDENTIFY);
|
||||
|
||||
if (x86_64_inb(ATA_PRIMARY_STATUS) == 0) {
|
||||
printf("ATA: No primary master drive detected\n");
|
||||
kprintf("ATA: No primary master drive detected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ata_poll()) {
|
||||
printf("ATA poll failed at ATA_IDENTIFY\n");
|
||||
kprintf("ATA poll failed at ATA_IDENTIFY\n");
|
||||
}
|
||||
|
||||
if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) {
|
||||
printf("ATA: Identify error\n");
|
||||
kprintf("ATA: Identify error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
x86_64_insw(ATA_PRIMARY_DATA, buffer, 256);
|
||||
|
||||
printf("ATA: Disk model: ");
|
||||
kprintf("ATA: Disk model: ");
|
||||
for (int i = 27; i <= 46; i++) {
|
||||
uint16_t w = buffer[i];
|
||||
char high = w >> 8;
|
||||
char low = w & 0xFF;
|
||||
printf("%c%c", high, low); // swap bytes
|
||||
kprintf("%c%c", high, low); // swap bytes
|
||||
}
|
||||
printf("\n");
|
||||
printf("ATA: Total sectors: %lu\n", (uint64_t)buffer[60] | ((uint64_t)buffer[61] << 16));
|
||||
kprintf("\n");
|
||||
kprintf("ATA: Total sectors: %lu\n", (uint64_t)buffer[60] | ((uint64_t)buffer[61] << 16));
|
||||
}
|
||||
|
||||
bool ata_read_sectors(uint64_t lba, uint8_t sector_count, void* buffer)
|
||||
@@ -114,11 +114,11 @@ bool ata_read_sectors(uint64_t lba, uint8_t sector_count, void* buffer)
|
||||
uint16_t* buf = buffer;
|
||||
for (uint8_t i = 0; i < sector_count; i++) {
|
||||
if (!ata_poll()) {
|
||||
printf("ATA poll failed at ATA_read_sectors\n");
|
||||
kprintf("ATA poll failed at ATA_read_sectors\n");
|
||||
}
|
||||
|
||||
if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) {
|
||||
printf("ATA read error at LBA %lu\n", lba + i);
|
||||
kprintf("ATA read error at LBA %lu\n", lba + i);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "arch/x86_64/asm/asm.h"
|
||||
|
||||
static inline void mmoutb(void *addr, uint8_t value) {
|
||||
asm volatile("mov %0, %1\n\t"
|
||||
: "=m"(BYTE_PTR(addr))
|
||||
: "r"(value)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void mmoutw(void *addr, uint16_t value) {
|
||||
asm volatile("mov %0, %1\n\t"
|
||||
: "=m"(WORD_PTR(addr))
|
||||
: "r"(value)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void mmoutd(void *addr, uint32_t value) {
|
||||
asm volatile("mov %0, %1\n\t"
|
||||
: "=m"(DWORD_PTR(addr))
|
||||
: "r"(value)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void mmoutq(void *addr, uint64_t value) {
|
||||
asm volatile("mov %0, %1\n\t"
|
||||
: "=m"(QWORD_PTR(addr))
|
||||
: "r"(value)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline uint8_t mminb(void *addr) {
|
||||
uint8_t ret;
|
||||
asm volatile("mov %0, %1\n\t" : "=r"(ret) : "m"(BYTE_PTR(addr)) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint16_t mminw(void *addr) {
|
||||
uint16_t ret;
|
||||
asm volatile("mov %0, %1\n\t" : "=r"(ret) : "m"(WORD_PTR(addr)) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t mmind(void *addr) {
|
||||
uint32_t ret;
|
||||
asm volatile("mov %0, %1\n\t"
|
||||
: "=r"(ret)
|
||||
: "m"(DWORD_PTR(addr))
|
||||
: "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint64_t mminq(void *addr) {
|
||||
uint64_t ret;
|
||||
asm volatile("mov %0, %1\n\t"
|
||||
: "=r"(ret)
|
||||
: "m"(QWORD_PTR(addr))
|
||||
: "memory");
|
||||
return ret;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "pci.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include "libk/stdio.h"
|
||||
#include "libk/debug.h"
|
||||
|
||||
#define PCI_CFG_ADDR 0x0CF8
|
||||
#define PCI_CFG_DATA 0x0CFC
|
||||
@@ -69,7 +69,7 @@ static void pci_read_bars(pci_device_t* dev)
|
||||
|
||||
void pci_init(void)
|
||||
{
|
||||
printf("[PCI] Scanning bus 0...\n");
|
||||
kprintf("[PCI] Scanning bus 0...\n");
|
||||
pci_print_all();
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ void pci_print_all(void)
|
||||
};
|
||||
pci_read_bars(&d);
|
||||
|
||||
printf("[PCI] %02x:%02x.%x %04x:%04x class %04x rev %02x\n",
|
||||
kprintf("[PCI] %02x:%02x.%x %04x:%04x class %04x rev %02x\n",
|
||||
bus, dev, func, vendor, device_id, class_sub, revision);
|
||||
|
||||
if (func == 0 && (pci_read8(addr, 0x0E) & 0x80) == 0)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
section .text
|
||||
|
||||
extern syscall_handler
|
||||
global amd_syscall_entry
|
||||
amd_syscall_entry:
|
||||
swapgs
|
||||
|
||||
mov qword [gs:0016], rsp
|
||||
mov rsp, qword [gs:0008]
|
||||
|
||||
push 0x1b ; ss
|
||||
push qword [gs:0016] ; rsp
|
||||
push r11 ; rflags
|
||||
push 0x23 ; cs
|
||||
push rcx ; rip
|
||||
|
||||
sub rsp, 24
|
||||
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rbp
|
||||
push rdi
|
||||
push rsi
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
mov rdi, rsp
|
||||
sti
|
||||
call syscall_handler
|
||||
|
||||
cli
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbp
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
|
||||
add rsp, 24
|
||||
|
||||
mov rsp, qword [gs:0016]
|
||||
|
||||
swapgs
|
||||
|
||||
o64 sysret
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#define write_cr(reg, val) \
|
||||
asm volatile("mov cr" reg ", %0" ::"r"(val) : "memory");
|
||||
|
||||
#define read_cr(reg) \
|
||||
({ \
|
||||
size_t cr; \
|
||||
asm volatile("mov %0, cr" reg : "=r"(cr)::"memory"); \
|
||||
cr; \
|
||||
})
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#define CPUID_INVARIANT_TSC (1 << 8)
|
||||
#define CPUID_TSC_DEADLINE (1 << 24)
|
||||
#define CPUID_SMEP (1 << 7)
|
||||
#define CPUID_SMAP (1 << 20)
|
||||
#define CPUID_UMIP (1 << 2)
|
||||
#define CPUID_X2APIC (1 << 21)
|
||||
#define CPUID_GBPAGE (1 << 26)
|
||||
@@ -13,4 +13,4 @@ void x86_64_iowait(void);
|
||||
void x86_64_Panic(void) __attribute__((noreturn));
|
||||
void x86_64_EnableInterrupts(void);
|
||||
void x86_64_DisableInterrupts(void);
|
||||
void x86_64_crashme(void);
|
||||
void x86_64_crashme(void);
|
||||
|
||||
@@ -1,96 +1,102 @@
|
||||
.intel_syntax noprefix
|
||||
section .text
|
||||
|
||||
.global x86_64_outb
|
||||
global x86_64_outb
|
||||
x86_64_outb:
|
||||
mov dx, di
|
||||
mov al, sil
|
||||
out dx, al
|
||||
ret
|
||||
|
||||
.global x86_64_inb
|
||||
global x86_64_inb
|
||||
x86_64_inb:
|
||||
mov dx, di
|
||||
xor eax, eax
|
||||
in al, dx
|
||||
ret
|
||||
|
||||
.global x86_64_inw
|
||||
global x86_64_inw
|
||||
x86_64_inw:
|
||||
mov dx, di
|
||||
xor eax, eax
|
||||
in ax, dx
|
||||
ret
|
||||
|
||||
.global x86_64_outw
|
||||
global x86_64_outw
|
||||
x86_64_outw:
|
||||
mov dx, di
|
||||
mov ax, si
|
||||
out dx, ax
|
||||
ret
|
||||
|
||||
.global x86_64_outl
|
||||
global x86_64_outl
|
||||
x86_64_outl:
|
||||
mov dx, di
|
||||
mov eax, esi
|
||||
out dx, eax
|
||||
ret
|
||||
|
||||
.global x86_64_inl
|
||||
global x86_64_inl
|
||||
x86_64_inl:
|
||||
mov dx, di
|
||||
xor eax, eax
|
||||
in eax, dx
|
||||
ret
|
||||
|
||||
.global x86_64_insw
|
||||
global x86_64_insw
|
||||
x86_64_insw:
|
||||
test rdx, rdx
|
||||
jz .inswdone
|
||||
jz .done
|
||||
|
||||
mov rcx, rdx
|
||||
mov dx, di
|
||||
mov rdi, rsi
|
||||
cld
|
||||
rep insw
|
||||
.inswdone:
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
.global x86_64_outsw
|
||||
global x86_64_outsw
|
||||
x86_64_outsw:
|
||||
test rdx, rdx
|
||||
jz .outswdone
|
||||
jz .done
|
||||
|
||||
mov rcx, rdx
|
||||
mov dx, di
|
||||
mov rsi, rsi
|
||||
; RSI already contains source pointer
|
||||
cld
|
||||
rep outsw
|
||||
.outswdone:
|
||||
|
||||
.done:
|
||||
ret
|
||||
|
||||
.global x86_64_Panic
|
||||
global x86_64_Panic
|
||||
x86_64_Panic:
|
||||
cli
|
||||
hlt
|
||||
1: jmp 1b
|
||||
|
||||
.global x86_64_EnableInterrupts
|
||||
.hang:
|
||||
jmp .hang
|
||||
|
||||
global x86_64_EnableInterrupts
|
||||
x86_64_EnableInterrupts:
|
||||
sti
|
||||
ret
|
||||
|
||||
.global x86_64_DisableInterrupts
|
||||
global x86_64_DisableInterrupts
|
||||
x86_64_DisableInterrupts:
|
||||
cli
|
||||
ret
|
||||
|
||||
.global x86_64_iowait
|
||||
global x86_64_iowait
|
||||
x86_64_iowait:
|
||||
out 0x80, al // classic I/O wait
|
||||
out 0x80, al ; classic I/O wait
|
||||
ret
|
||||
|
||||
.global x86_64_crashme
|
||||
global x86_64_crashme
|
||||
x86_64_crashme:
|
||||
xor rdx, rdx
|
||||
mov rax, 1
|
||||
mov rbx, 0
|
||||
xor rbx, rbx
|
||||
div rbx
|
||||
ret
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint64_t rdmsr(uint32_t msr) {
|
||||
uint32_t edx, eax;
|
||||
asm volatile("rdmsr" : "=a"(eax), "=d"(edx) : "c"(msr) : "memory");
|
||||
return ((uint64_t)edx << 32) | eax;
|
||||
}
|
||||
|
||||
static inline void wrmsr(uint32_t msr, uint64_t value) {
|
||||
uint32_t edx = value >> 32;
|
||||
uint32_t eax = (uint32_t)value;
|
||||
asm volatile("wrmsr" ::"a"(eax), "c"(msr), "d"(edx) : "memory");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint64_t r15;
|
||||
uint64_t r14;
|
||||
uint64_t r13;
|
||||
uint64_t r12;
|
||||
uint64_t r11;
|
||||
uint64_t r10;
|
||||
uint64_t r9;
|
||||
uint64_t r8;
|
||||
uint64_t rsi;
|
||||
uint64_t rdi;
|
||||
uint64_t rbp;
|
||||
uint64_t rdx;
|
||||
uint64_t rcx;
|
||||
uint64_t rbx;
|
||||
uint64_t rax;
|
||||
uint64_t core;
|
||||
uint64_t isrNumber;
|
||||
uint64_t errorCode;
|
||||
uint64_t rip;
|
||||
uint64_t cs;
|
||||
uint64_t rflags;
|
||||
uint64_t rsp;
|
||||
uint64_t ss;
|
||||
} __attribute__((packed)) registers_t;
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "mp/mp.h"
|
||||
#include "libk/debug.h"
|
||||
#include "libk/errno.h"
|
||||
#include "mm/vmm.h"
|
||||
#include "sched/sched.h"
|
||||
#include "sched/syscall.h"
|
||||
#include "arch/x86_64/boot/isr.h"
|
||||
#include "arch/x86_64/sys/prcb.h"
|
||||
|
||||
void syscall_handler(registers_t *reg) {
|
||||
cli();
|
||||
prcb_return_current_cpu()->running_thread->reg = *reg;
|
||||
prcb_return_current_cpu()->running_thread->stack =
|
||||
prcb_return_current_cpu()->user_stack;
|
||||
prcb_return_current_cpu()->fpu_save(
|
||||
prcb_return_current_cpu()->running_thread->fpu_storage);
|
||||
sti();
|
||||
|
||||
struct syscall_arguments args = {.syscall_nr = reg->rax,
|
||||
.args0 = reg->rdi,
|
||||
.args1 = reg->rsi,
|
||||
.args2 = reg->rdx,
|
||||
.args3 = reg->r10,
|
||||
.args4 = reg->r8,
|
||||
.args5 = reg->r9,
|
||||
.ret = reg->rax};
|
||||
|
||||
syscall_handle(&args);
|
||||
|
||||
int64_t ret = (int64_t)args.ret;
|
||||
if (ret < 0) {
|
||||
ret = -((int)errno);
|
||||
reg->rax = ret;
|
||||
} else
|
||||
reg->rax = args.ret;
|
||||
}
|
||||
|
||||
void syscall_install_handler(void) {
|
||||
isr_register_handler(0x80, syscall_handler);
|
||||
}
|
||||
|
||||
uint64_t syscall_helper_user_to_kernel_address(uintptr_t user_addr) {
|
||||
struct process *proc = sched_get_running_thread()->mother_proc;
|
||||
struct pagemap *target_pagemap = proc->process_pagemap;
|
||||
|
||||
uint64_t kernel_addr = vmm_virt_to_kernel(target_pagemap, user_addr);
|
||||
return kernel_addr;
|
||||
}
|
||||
|
||||
bool syscall_helper_copy_to_user(uintptr_t user_addr, void *buffer,
|
||||
size_t count) {
|
||||
vmm_switch_pagemap(kernel_pagemap);
|
||||
|
||||
struct process *proc = sched_get_running_thread()->mother_proc;
|
||||
struct pagemap *target_pagemap = proc->process_pagemap;
|
||||
|
||||
uint64_t kernel_addr = vmm_virt_to_kernel(target_pagemap, user_addr);
|
||||
|
||||
if (!kernel_addr) {
|
||||
errno = EFAULT;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy((void *)kernel_addr, buffer, count);
|
||||
vmm_switch_pagemap(target_pagemap);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool syscall_helper_copy_from_user(uintptr_t user_addr, void *buffer,
|
||||
size_t count) {
|
||||
vmm_switch_pagemap(kernel_pagemap);
|
||||
|
||||
struct process *proc = sched_get_running_thread()->mother_proc;
|
||||
struct pagemap *target_pagemap = proc->process_pagemap;
|
||||
|
||||
uint64_t kernel_addr = vmm_virt_to_kernel(target_pagemap, user_addr);
|
||||
|
||||
if (!kernel_addr) {
|
||||
errno = EFAULT;
|
||||
return false;
|
||||
}
|
||||
memcpy(buffer, (void *)kernel_addr, count);
|
||||
vmm_switch_pagemap(target_pagemap);
|
||||
return true;
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include "libk/string.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "mm/vmm.h"
|
||||
#include "mm/memory.h"
|
||||
#include "libk/stdio.h"
|
||||
#include "fs/elf.h"
|
||||
#include "sched/scheduler.h"
|
||||
|
||||
extern uintptr_t g_hhdm_offset;
|
||||
|
||||
#define USER_STACK_TOP 0x00007FFFFFFFE000ULL
|
||||
#define USER_STACK_PAGES 8
|
||||
#define USER_STACK_SIZE (USER_STACK_PAGES * PAGE_SIZE)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static uint64_t user_stack_phys_base = 0;
|
||||
|
||||
//extern struct pagemap *kernel_pagemap;
|
||||
|
||||
struct pagemap *create_user_pagemap(void)
|
||||
{
|
||||
struct pagemap *pm = kmalloc(sizeof(struct pagemap));
|
||||
if (!pm) {
|
||||
printf("Failed to allocate user pagemap struct!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spinlock_init(&pm->lock);
|
||||
|
||||
/* Allocate a fresh PML4 (physical page) */
|
||||
pm->top_level = (uint64_t *)((uintptr_t)pmm_allocz(1) + MEM_PHYS_OFFSET);
|
||||
if (!pm->top_level) {
|
||||
printf("Failed to allocate user PML4!\n");
|
||||
kfree(pm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy kernel higher-half mappings (kernel + HHDM) */
|
||||
for (size_t i = 0; i < 512; i++) {
|
||||
pm->top_level[i] = kernel_pagemap->top_level[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 256; i++) {
|
||||
pm->top_level[i] = 0;
|
||||
}
|
||||
|
||||
/* Lower half remains zero (user address space) */
|
||||
printf("[usermode] user pagemap created (PML4 phys = 0x%lx)\n",
|
||||
(uint64_t)pm->top_level - MEM_PHYS_OFFSET);
|
||||
|
||||
return pm;
|
||||
}
|
||||
|
||||
uintptr_t setup_user_stack(struct pagemap *pagemap)
|
||||
{
|
||||
user_stack_phys_base = (uint64_t)pmm_allocz(USER_STACK_PAGES);
|
||||
|
||||
if (!user_stack_phys_base) {
|
||||
printf("Failed to allocate user stack pages!\n");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
uintptr_t stack_bottom = USER_STACK_TOP - USER_STACK_SIZE;
|
||||
|
||||
for (int i = 0; i < USER_STACK_PAGES; i++) {
|
||||
uintptr_t virt = stack_bottom + i * PAGE_SIZE;
|
||||
uintptr_t phys = user_stack_phys_base + i * PAGE_SIZE;
|
||||
|
||||
if (!vmm_map_page(pagemap,
|
||||
virt,
|
||||
phys,
|
||||
PAGE_READ | PAGE_WRITE | PAGE_USER,
|
||||
Size4KiB))
|
||||
{
|
||||
printf("Failed mapping user stack page\n");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uintptr_t rsp = USER_STACK_TOP;
|
||||
rsp &= ~0xFULL;
|
||||
return rsp;
|
||||
}
|
||||
|
||||
|
||||
void start_userspace(void)
|
||||
{
|
||||
struct pagemap *user_pagemap = create_user_pagemap();
|
||||
if (!user_pagemap) {
|
||||
printf("Failed to create user pagemap\n");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void *elf_entry = NULL;
|
||||
uint64_t tls_fs_base = 0;
|
||||
uint64_t phdr_va = 0;
|
||||
uint16_t phent = 0;
|
||||
uint16_t phnum = 0;
|
||||
|
||||
if (!ELF_Read("helloworld.elf",
|
||||
&elf_entry,
|
||||
user_pagemap,
|
||||
&tls_fs_base,
|
||||
&phdr_va,
|
||||
&phent,
|
||||
&phnum)) {
|
||||
printf("Failed to load helloworld.elf\n");
|
||||
for(;;);
|
||||
}
|
||||
|
||||
printf("ELF: entry=0x%lx TLS_FS=0x%lx PHDR=0x%lx PHENT=0x%x PHNUM=%u\n",
|
||||
(uint64_t)elf_entry, tls_fs_base, phdr_va, phent, phnum);
|
||||
|
||||
uintptr_t user_rsp = setup_user_stack(user_pagemap);
|
||||
|
||||
printf("Entering usermode RIP=%p RSP=%p\n", elf_entry, (void*)user_rsp);
|
||||
|
||||
sched_create_user_task("init",
|
||||
(uint64_t)elf_entry,
|
||||
user_rsp,
|
||||
user_pagemap,
|
||||
tls_fs_base,
|
||||
phdr_va,
|
||||
phent,
|
||||
phnum);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
void start_userspace(void);
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "libk/debug.h"
|
||||
#include <stddef.h>
|
||||
#include "mm/vmm.h"
|
||||
|
||||
void backtrace(uintptr_t *bp) {
|
||||
kprintf("Stack trace:\n");
|
||||
uintptr_t *rbp = (uintptr_t *)bp;
|
||||
|
||||
if (rbp == NULL)
|
||||
asm volatile("mov %%rbp, %0" : "=g"(rbp)::"memory");
|
||||
|
||||
if (rbp == NULL || (uintptr_t)(rbp) < MEM_PHYS_OFFSET)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
uintptr_t *old_rbp = (uintptr_t *)rbp[0];
|
||||
uintptr_t *rip = (uintptr_t *)rbp[1];
|
||||
|
||||
if (rip == NULL || old_rbp == NULL ||
|
||||
((uintptr_t)rip) < MEM_PHYS_OFFSET)
|
||||
break;
|
||||
|
||||
kprintf("%p\n", rip);
|
||||
|
||||
rbp = old_rbp;
|
||||
}
|
||||
|
||||
|
||||
kprintf("Kernel base: %p Mem phys base: %p\n", KERNEL_BASE,
|
||||
MEM_PHYS_OFFSET);
|
||||
}
|
||||
|
||||
void backtrace_unsafe(uintptr_t *bp) {
|
||||
kprintf("Stack trace:\n");
|
||||
uintptr_t *rbp = (uintptr_t *)bp;
|
||||
|
||||
if (rbp == NULL)
|
||||
asm volatile("mov %%rbp, %0" : "=g"(rbp)::"memory");
|
||||
|
||||
if (rbp == NULL)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
uintptr_t *old_rbp = (uintptr_t *)rbp[0];
|
||||
uintptr_t *rip = (uintptr_t *)rbp[1];
|
||||
|
||||
if (rip == NULL || old_rbp == NULL)
|
||||
break;
|
||||
|
||||
kprintf("%p\n", rip);
|
||||
|
||||
rbp = old_rbp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "arch/x86_64/boot/isr.h"
|
||||
#include "libk/debug.h"
|
||||
#include "arch/x86_64/sys/halt.h"
|
||||
#include "mp/mp.h"
|
||||
#include "sched/sched.h"
|
||||
#include "arch/x86_64/serial/serial.h"
|
||||
|
||||
static void backtrace_dump(registers_t *reg) {
|
||||
kprintffos(0, "============ Backtrace ==========\n");
|
||||
|
||||
kprintffos(0, "-> %p\n", reg->rip);
|
||||
|
||||
uintptr_t *rbp = (uintptr_t *)reg->rbp;
|
||||
|
||||
if (rbp == NULL)
|
||||
asm volatile("mov %%rbp, %0" : "=g"(rbp)::"memory");
|
||||
|
||||
if (rbp == NULL)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
uintptr_t *old_rbp = (uintptr_t *)rbp[0];
|
||||
uintptr_t *rip = (uintptr_t *)rbp[1];
|
||||
|
||||
if (rip == NULL || old_rbp == NULL)
|
||||
break;
|
||||
|
||||
kprintffos(0, "%p\n", rip);
|
||||
|
||||
rbp = old_rbp;
|
||||
}
|
||||
|
||||
kprintffos(0, "============ End of dumps ==========\n");
|
||||
}
|
||||
|
||||
static void register_dump(registers_t *reg) {
|
||||
kprintffos(0, "========= Register dumps =========\n");
|
||||
kprintffos(0, "RIP: %p RBP: %p RSP: %p\n", reg->rip, reg->rbp, reg->rsp);
|
||||
kprintffos(0, "RAX: %p RBX: %p RCX: %p\n", reg->rax, reg->rbx, reg->rcx);
|
||||
kprintffos(0, "RDX: %p RDI: %p RSI: %p\n", reg->rdx, reg->rdi, reg->rsi);
|
||||
kprintffos(0, "R8 : %p R9 : %p R10: %p\n", reg->r8, reg->r9, reg->r10);
|
||||
kprintffos(0, "R11: %p R12: %p R13: %p\n", reg->r11, reg->r12, reg->r13);
|
||||
kprintffos(0, "R14: %p R15: %p\n", reg->r14, reg->r15);
|
||||
kprintffos(0, "CS : %p SS : %p RFLAGS: %p\n", reg->cs, reg->ss,
|
||||
reg->rflags);
|
||||
kprintffos(0, "FS: %p UGS: %p KGS: %p\n", read_fs_base(), read_user_gs(),
|
||||
read_kernel_gs());
|
||||
|
||||
kprintffos(0, "============ End of dumps ==========\n");
|
||||
}
|
||||
|
||||
static void tss_dump(void) {
|
||||
kprintffos(0, "============ TSS Dumps ==========\n");
|
||||
|
||||
kprintffos(0, "tss.rsp0: %p\n", prcb_return_current_cpu()->cpu_tss.rsp0);
|
||||
kprintffos(0, "tss.rsp1: %p\n", prcb_return_current_cpu()->cpu_tss.rsp1);
|
||||
kprintffos(0, "tss.rsp2: %p\n", prcb_return_current_cpu()->cpu_tss.rsp2);
|
||||
|
||||
kprintffos(0, "tss.ist1: %p\n", prcb_return_current_cpu()->cpu_tss.ist1);
|
||||
kprintffos(0, "tss.ist2: %p\n", prcb_return_current_cpu()->cpu_tss.ist2);
|
||||
kprintffos(0, "tss.ist3: %p\n", prcb_return_current_cpu()->cpu_tss.ist3);
|
||||
kprintffos(0, "tss.ist4: %p\n", prcb_return_current_cpu()->cpu_tss.ist4);
|
||||
kprintffos(0, "tss.ist5: %p\n", prcb_return_current_cpu()->cpu_tss.ist5);
|
||||
kprintffos(0, "tss.ist6: %p\n", prcb_return_current_cpu()->cpu_tss.ist6);
|
||||
kprintffos(0, "tss.ist7: %p\n", prcb_return_current_cpu()->cpu_tss.ist7);
|
||||
|
||||
kprintffos(0, "tss.iomap_base: %p\n",
|
||||
prcb_return_current_cpu()->cpu_tss.iomap_base);
|
||||
|
||||
kprintffos(0, "============ End of dumps ==========\n");
|
||||
}
|
||||
|
||||
static void prcb_dump(void) {
|
||||
kprintffos(0, "============ PRCB Dumps ==========\n");
|
||||
|
||||
kprintffos(0, "prcb->cpu_number: %u\n",
|
||||
prcb_return_current_cpu()->cpu_number);
|
||||
kprintffos(0, "prcb->kernel_stack: %p\n",
|
||||
prcb_return_current_cpu()->kernel_stack);
|
||||
kprintffos(0, "prcb->user_stack: %p\n",
|
||||
prcb_return_current_cpu()->user_stack);
|
||||
kprintffos(0, "prcb->running_thread: %p\n",
|
||||
prcb_return_current_cpu()->running_thread);
|
||||
kprintffos(0, "prcb->sched_ticks: %p\n",
|
||||
prcb_return_current_cpu()->user_stack);
|
||||
|
||||
kprintffos(0, "prcb->lapic_id: %u\n", prcb_return_current_cpu()->lapic_id);
|
||||
kprintffos(0, "prcb->fpu_storage_size: %p\n",
|
||||
prcb_return_current_cpu()->fpu_storage_size);
|
||||
kprintffos(0, "prcb->fpu_save: %p\n", prcb_return_current_cpu()->fpu_save);
|
||||
kprintffos(0, "prcb->fpu_restore: %p\n",
|
||||
prcb_return_current_cpu()->fpu_restore);
|
||||
|
||||
kprintffos(0, "============ End of dumps ==========\n");
|
||||
}
|
||||
|
||||
void breakpoint_handler(registers_t *reg) {
|
||||
if (reg->cs & 0x3) {
|
||||
kprintffos(0, "Breakpoint hit in user!\n");
|
||||
thread_kill(prcb_return_current_cpu()->running_thread, true);
|
||||
return;
|
||||
} else {
|
||||
kprintffos(0, "Breakpoint hit in kernel!\n");
|
||||
}
|
||||
|
||||
pause_other_cpus();
|
||||
|
||||
kprintffos(0, "=========== Start of dumps =========\n");
|
||||
kprintffos(0, "Breakpoint hit on CPU%u\n",
|
||||
prcb_return_current_cpu()->cpu_number);
|
||||
|
||||
kprintffos(0, "========= Register dumps =========\n");
|
||||
kprintffos(0, "RIP: %p RBP: %p RSP: %p\n", reg->rip, reg->rbp, reg->rsp);
|
||||
kprintffos(0, "RAX: %p RBX: %p RCX: %p\n", reg->rax, reg->rbx, reg->rcx);
|
||||
kprintffos(0, "RDX: %p RDI: %p RSI: %p\n", reg->rdx, reg->rdi, reg->rsi);
|
||||
kprintffos(0, "R8 : %p R9 : %p R10: %p\n", reg->r8, reg->r9, reg->r10);
|
||||
kprintffos(0, "R11: %p R12: %p R13: %p\n", reg->r11, reg->r12, reg->r13);
|
||||
kprintffos(0, "R14: %p R15: %p\n", reg->r14, reg->r15);
|
||||
kprintffos(0, "CS : %p SS : %p RFLAGS: %p\n", reg->cs, reg->ss,
|
||||
reg->rflags);
|
||||
kprintffos(0, "FS: %p UGS: %p KGS: %p\n", read_fs_base(), read_user_gs(),
|
||||
read_kernel_gs());
|
||||
|
||||
kprintffos(0, "============ End of dumps ==========\n");
|
||||
|
||||
char option = 0;
|
||||
|
||||
while (option != 'C') {
|
||||
kprintffos(0, "(C)ontinue, Dump (P)RCB, Dump (R)egisters, Dump (T)SS, "
|
||||
"(B)acktrace?\n");
|
||||
option = serial_getchar();
|
||||
serial_putchar('\n');
|
||||
switch (option) {
|
||||
case 'P':
|
||||
prcb_dump();
|
||||
break;
|
||||
case 'R':
|
||||
register_dump(reg);
|
||||
break;
|
||||
case 'T':
|
||||
tss_dump();
|
||||
break;
|
||||
case 'B':
|
||||
backtrace_dump(reg);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unpause_other_cpus();
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
#include "libk/debug.h"
|
||||
#include "libk/kargs.h"
|
||||
#include <stdint.h>
|
||||
|
||||
struct tu_source_location {
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
};
|
||||
|
||||
struct tu_type_descriptor {
|
||||
uint16_t kind;
|
||||
uint16_t info;
|
||||
char name[];
|
||||
};
|
||||
|
||||
struct tu_overflow_data {
|
||||
struct tu_source_location location;
|
||||
struct tu_type_descriptor *type;
|
||||
};
|
||||
|
||||
struct tu_shift_out_of_bounds_data {
|
||||
struct tu_source_location location;
|
||||
struct tu_type_descriptor *left_type;
|
||||
struct tu_type_descriptor *right_type;
|
||||
};
|
||||
|
||||
struct tu_invalid_value_data {
|
||||
struct tu_source_location location;
|
||||
struct tu_type_descriptor *type;
|
||||
};
|
||||
|
||||
struct tu_array_out_of_bounds_data {
|
||||
struct tu_source_location location;
|
||||
struct tu_type_descriptor *array_type;
|
||||
struct tu_type_descriptor *index_type;
|
||||
};
|
||||
|
||||
struct tu_type_mismatch_v1_data {
|
||||
struct tu_source_location location;
|
||||
struct tu_type_descriptor *type;
|
||||
unsigned char log_alignment;
|
||||
unsigned char type_check_kind;
|
||||
};
|
||||
|
||||
struct tu_negative_vla_data {
|
||||
struct tu_source_location location;
|
||||
struct tu_type_descriptor *type;
|
||||
};
|
||||
|
||||
struct tu_nonnull_return_data {
|
||||
struct tu_source_location location;
|
||||
};
|
||||
|
||||
struct tu_nonnull_arg_data {
|
||||
struct tu_source_location location;
|
||||
};
|
||||
|
||||
struct tu_unreachable_data {
|
||||
struct tu_source_location location;
|
||||
};
|
||||
|
||||
struct tu_invalid_builtin_data {
|
||||
struct tu_source_location location;
|
||||
unsigned char kind;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern bool print_now;
|
||||
extern bool put_to_fb;
|
||||
|
||||
static void tu_print_location(const char *message,
|
||||
struct tu_source_location loc) {
|
||||
if (print_now &&
|
||||
!(kernel_arguments.kernel_args & KERNEL_ARGS_SUPPRESS_UBSAN)) {
|
||||
kprintffos(0, "tinyubsan: %s at file %s, line %d, column %d\n", message,
|
||||
loc.file, loc.line, loc.column);
|
||||
put_to_fb = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_add_overflow(struct tu_overflow_data *data) {
|
||||
tu_print_location("addition overflow", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_sub_overflow(struct tu_overflow_data *data) {
|
||||
tu_print_location("subtraction overflow", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_mul_overflow(struct tu_overflow_data *data) {
|
||||
tu_print_location("multiplication overflow", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_divrem_overflow(struct tu_overflow_data *data) {
|
||||
tu_print_location("division overflow", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_negate_overflow(struct tu_overflow_data *data) {
|
||||
tu_print_location("negation overflow", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_pointer_overflow(struct tu_overflow_data *data) {
|
||||
tu_print_location("pointer overflow", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds(
|
||||
struct tu_shift_out_of_bounds_data *data) {
|
||||
tu_print_location("shift out of bounds", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_load_invalid_value(struct tu_invalid_value_data *data) {
|
||||
tu_print_location("invalid load value", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds(struct tu_array_out_of_bounds_data *data) {
|
||||
tu_print_location("array out of bounds", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1(struct tu_type_mismatch_v1_data *data,
|
||||
uintptr_t ptr) {
|
||||
if (!ptr) {
|
||||
tu_print_location("use of NULL pointer", data->location);
|
||||
}
|
||||
|
||||
else if (ptr & ((1 << data->log_alignment) - 1)) {
|
||||
// tu_print_location("use of misaligned pointer", data->location);
|
||||
} else {
|
||||
tu_print_location("no space for object", data->location);
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_vla_bound_not_positive(struct tu_negative_vla_data *data) {
|
||||
tu_print_location("variable-length argument is negative", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return(struct tu_nonnull_return_data *data) {
|
||||
tu_print_location("non-null return is null", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_arg(struct tu_nonnull_arg_data *data) {
|
||||
tu_print_location("non-null argument is null", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_builtin_unreachable(struct tu_unreachable_data *data) {
|
||||
|
||||
tu_print_location("unreachable code reached", data->location);
|
||||
}
|
||||
|
||||
void __ubsan_handle_invalid_builtin(struct tu_invalid_builtin_data *data) {
|
||||
|
||||
tu_print_location("invalid builtin", data->location);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "arch/x86_64/sys/tsc.h"
|
||||
#include <uacpi/uacpi.h>
|
||||
#include <uacpi/event.h>
|
||||
#include <uacpi/sleep.h>
|
||||
#include <uacpi/tables.h>
|
||||
#include "arch/x86_64/sys/timer.h"
|
||||
#include "madt.h"
|
||||
#include "libk/debug.h"
|
||||
|
||||
void acpi_init() {
|
||||
|
||||
calibrate_tsc();
|
||||
/*
|
||||
* Start with this as the first step of the initialization. This loads all
|
||||
* tables, brings the event subsystem online, and enters ACPI mode. We pass
|
||||
* in 0 as the flags as we don't want to override any default behavior for now.
|
||||
*/
|
||||
uacpi_status ret = uacpi_initialize(0);
|
||||
if (uacpi_unlikely_error(ret)) {
|
||||
kprintf("uacpi_initialize error: %s", uacpi_status_to_string(ret));
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the AML namespace. This feeds DSDT and all SSDTs to the interpreter
|
||||
* for execution.
|
||||
*/
|
||||
ret = uacpi_namespace_load();
|
||||
if (uacpi_unlikely_error(ret)) {
|
||||
kprintf("uacpi_namespace_load error: %s", uacpi_status_to_string(ret));
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the namespace. This calls all necessary _STA/_INI AML methods,
|
||||
* as well as _REG for registered operation region handlers.
|
||||
*/
|
||||
ret = uacpi_namespace_initialize();
|
||||
if (uacpi_unlikely_error(ret)) {
|
||||
kprintf("uacpi_namespace_initialize error: %s", uacpi_status_to_string(ret));
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell uACPI that we have marked all GPEs we wanted for wake (even though we haven't
|
||||
* actually marked any, as we have no power management support right now). This is
|
||||
* needed to let uACPI enable all unmarked GPEs that have a corresponding AML handler.
|
||||
* These handlers are used by the firmware to dynamically execute AML code at runtime
|
||||
* to e.g. react to thermal events or device hotplug.
|
||||
*/
|
||||
ret = uacpi_finalize_gpe_initialization();
|
||||
if (uacpi_unlikely_error(ret)) {
|
||||
kprintf("uACPI GPE initialization error: %s", uacpi_status_to_string(ret));
|
||||
}
|
||||
|
||||
|
||||
timer_init();
|
||||
madt_init();
|
||||
}
|
||||
|
||||
void *acpi_find_sdt(const char *signature) {
|
||||
struct uacpi_table sdt;
|
||||
uacpi_status st = uacpi_table_find_by_signature(signature, &sdt);
|
||||
if (uacpi_unlikely_error(st)) {
|
||||
panic("Could not find %s: %s\n", signature, uacpi_status_to_string(st));
|
||||
}
|
||||
return (void *)sdt.ptr;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct acpi_header_t {
|
||||
char signature[4];
|
||||
uint32_t length;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
char oem[6];
|
||||
char oem_table[8];
|
||||
uint32_t oem_revision;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_revision;
|
||||
} __attribute__((packed)) acpi_header_t;
|
||||
|
||||
typedef struct acpi_gas_t {
|
||||
uint8_t address_space;
|
||||
uint8_t bit_width;
|
||||
uint8_t bit_offset;
|
||||
uint8_t access_size;
|
||||
uint64_t base;
|
||||
} __attribute__((packed)) acpi_gas_t;
|
||||
|
||||
void acpi_init();
|
||||
void *acpi_find_sdt(const char *signature);
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <uacpi/tables.h>
|
||||
#include "madt.h"
|
||||
#include <stddef.h>
|
||||
#include "libk/debug.h"
|
||||
#include "arch/x86_64/asm/asm.h"
|
||||
|
||||
|
||||
struct madt *madt;
|
||||
|
||||
lapic_vec_t madt_local_apics;
|
||||
ioapic_vec_t madt_io_apics;
|
||||
iso_vec_t madt_isos;
|
||||
nmi_vec_t madt_nmis;
|
||||
|
||||
uintptr_t lapic_addr = 0;
|
||||
|
||||
uintptr_t acpi_get_lapic(void) {
|
||||
return lapic_addr;
|
||||
}
|
||||
|
||||
void madt_init(void) {
|
||||
vec_init(&madt_local_apics);
|
||||
vec_init(&madt_io_apics);
|
||||
vec_init(&madt_isos);
|
||||
vec_init(&madt_nmis);
|
||||
|
||||
struct uacpi_table madt_table;
|
||||
uacpi_status st = uacpi_table_find_by_signature("APIC", &madt_table);
|
||||
if (uacpi_unlikely_error(st)) {
|
||||
panic("Could not find MADT: %s\n", uacpi_status_to_string(st));
|
||||
}
|
||||
|
||||
madt = (struct madt *)madt_table.ptr;
|
||||
|
||||
lapic_addr = madt->local_controller_addr;
|
||||
kprintf("MADT: MADT at %p\n", madt);
|
||||
for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
|
||||
(uintptr_t)madt_ptr < (uintptr_t)madt + madt->sdt.length;
|
||||
madt_ptr += *(madt_ptr + 1)) {
|
||||
switch (*(madt_ptr)) {
|
||||
case 0:
|
||||
// Processor local APIC
|
||||
kprintf("MADT: Got local APIC 0x%x\n", madt_local_apics.length);
|
||||
vec_push(&madt_local_apics, (void *)madt_ptr);
|
||||
break;
|
||||
case 1:
|
||||
// I/O APIC
|
||||
kprintf("MADT: Got IO APIC 0x%x\n", madt_io_apics.length);
|
||||
vec_push(&madt_io_apics, (void *)madt_ptr);
|
||||
break;
|
||||
case 2:
|
||||
// Interrupt source override
|
||||
kprintf("MADT: Got ISO 0x%x\n", madt_isos.length);
|
||||
vec_push(&madt_isos, (void *)madt_ptr);
|
||||
break;
|
||||
case 4:
|
||||
// NMI
|
||||
kprintf("MADT: Got NMI 0x%x\n", madt_nmis.length);
|
||||
vec_push(&madt_nmis, (void *)madt_ptr);
|
||||
break;
|
||||
case 5:
|
||||
// Local APIC address override
|
||||
lapic_addr = QWORD_PTR(madt_ptr + 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "libk/vec.h"
|
||||
#include <uacpi/acpi.h>
|
||||
#include "acpi.h"
|
||||
|
||||
|
||||
|
||||
|
||||
struct madt {
|
||||
acpi_header_t sdt;
|
||||
uint32_t local_controller_addr;
|
||||
uint32_t flags;
|
||||
char madt_entries_begin[];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct madt_header {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct madt_lapic {
|
||||
struct madt_header madt_header;
|
||||
uint8_t processor_id;
|
||||
uint8_t apic_id;
|
||||
uint32_t flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct madt_ioapic {
|
||||
struct madt_header madt_header;
|
||||
uint8_t apic_id;
|
||||
uint8_t reserved;
|
||||
uint32_t addr;
|
||||
uint32_t gsib;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct madt_iso {
|
||||
struct madt_header madt_header;
|
||||
uint8_t bus_source;
|
||||
uint8_t irq_source;
|
||||
uint32_t gsi;
|
||||
uint16_t flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct madt_nmi {
|
||||
struct madt_header madt_header;
|
||||
uint8_t processor;
|
||||
uint16_t flags;
|
||||
uint8_t lint;
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef vec_t(struct madt_lapic *) lapic_vec_t;
|
||||
typedef vec_t(struct madt_ioapic *) ioapic_vec_t;
|
||||
typedef vec_t(struct madt_iso *) iso_vec_t;
|
||||
typedef vec_t(struct madt_nmi *) nmi_vec_t;
|
||||
|
||||
extern struct madt *madt;
|
||||
extern lapic_vec_t madt_local_apics;
|
||||
extern ioapic_vec_t madt_io_apics;
|
||||
extern iso_vec_t madt_isos;
|
||||
extern nmi_vec_t madt_nmis;
|
||||
|
||||
uintptr_t acpi_get_lapic(void);
|
||||
void madt_init(void);
|
||||
@@ -0,0 +1,297 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "mm/vmm.h"
|
||||
#include "mm/memory.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "mm/slab.h"
|
||||
#include "mp/mp.h"
|
||||
#include "mp/spinlock.h"
|
||||
#include "fs/elf.h"
|
||||
#include "sched/sched_types.h"
|
||||
#include "sched/sched.h"
|
||||
#include "arch/x86_64/cpu/reg.h"
|
||||
#include "mm/mmap.h"
|
||||
#include "libk/string.h"
|
||||
#include "libk/misc.h"
|
||||
|
||||
|
||||
void thread_setup_context(struct thread *thrd, uintptr_t pc_address,
|
||||
uint64_t arguments, bool user) {
|
||||
|
||||
bool old_state = int_toggle(false);
|
||||
thrd->reg.rip = pc_address;
|
||||
thrd->reg.rdi = arguments;
|
||||
thrd->kernel_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
|
||||
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
|
||||
thrd->fpu_storage =
|
||||
(void *)((uintptr_t)pmm_allocz(DIV_ROUNDUP(
|
||||
prcb_return_current_cpu()->fpu_storage_size, PAGE_SIZE)) +
|
||||
MEM_PHYS_OFFSET);
|
||||
thrd->pf_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
|
||||
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
|
||||
|
||||
struct process *proc = thrd->mother_proc;
|
||||
|
||||
if (user) {
|
||||
thrd->reg.cs = 0x23;
|
||||
thrd->reg.ss = 0x1b;
|
||||
thrd->reg.rsp = (uint64_t)pmm_allocz(STACK_SIZE / PAGE_SIZE);
|
||||
thrd->stack = thrd->reg.rsp;
|
||||
|
||||
mmap_range(proc->process_pagemap, proc->stack_top - STACK_SIZE,
|
||||
(uintptr_t)thrd->reg.rsp, STACK_SIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS);
|
||||
|
||||
thrd->reg.rsp = proc->stack_top;
|
||||
proc->stack_top -= STACK_SIZE;
|
||||
|
||||
prcb_return_current_cpu()->fpu_restore(thrd->fpu_storage);
|
||||
uint16_t default_fcw = 0b1100111111;
|
||||
asm volatile("fldcw %0" ::"m"(default_fcw) : "memory");
|
||||
uint32_t default_mxcsr = 0b1111110000000;
|
||||
asm volatile("ldmxcsr %0" ::"m"(default_mxcsr) : "memory");
|
||||
prcb_return_current_cpu()->fpu_save(thrd->fpu_storage);
|
||||
|
||||
thrd->fs_base = 0;
|
||||
thrd->gs_base = 0;
|
||||
} else {
|
||||
thrd->reg.cs = 0x08;
|
||||
thrd->reg.ss = 0x10;
|
||||
|
||||
thrd->stack = thrd->kernel_stack;
|
||||
thrd->reg.rsp = thrd->stack;
|
||||
|
||||
thrd->fs_base = read_fs_base();
|
||||
thrd->gs_base = read_kernel_gs();
|
||||
}
|
||||
|
||||
thrd->reg.rflags = 0x202;
|
||||
int_toggle(old_state);
|
||||
}
|
||||
|
||||
void thread_setup_context_from_user(struct thread *thrd, uintptr_t pc_address,
|
||||
uintptr_t sp) {
|
||||
bool old_state = int_toggle(false);
|
||||
thrd->reg.rip = pc_address;
|
||||
thrd->kernel_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
|
||||
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
|
||||
thrd->fpu_storage =
|
||||
(void *)((uintptr_t)pmm_allocz(DIV_ROUNDUP(
|
||||
prcb_return_current_cpu()->fpu_storage_size, PAGE_SIZE)) +
|
||||
MEM_PHYS_OFFSET);
|
||||
|
||||
struct process *proc = thrd->mother_proc;
|
||||
thrd->reg.cs = 0x23;
|
||||
thrd->reg.ss = 0x1b;
|
||||
thrd->reg.rsp = sp;
|
||||
thrd->stack = thrd->reg.rsp;
|
||||
|
||||
thrd->pf_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
|
||||
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
|
||||
|
||||
prcb_return_current_cpu()->fpu_restore(thrd->fpu_storage);
|
||||
uint16_t default_fcw = 0b1100111111;
|
||||
asm volatile("fldcw %0" ::"m"(default_fcw) : "memory");
|
||||
uint32_t default_mxcsr = 0b1111110000000;
|
||||
asm volatile("ldmxcsr %0" ::"m"(default_mxcsr) : "memory");
|
||||
prcb_return_current_cpu()->fpu_save(thrd->fpu_storage);
|
||||
|
||||
thrd->fs_base = 0;
|
||||
thrd->gs_base = 0;
|
||||
|
||||
thrd->reg.rflags = 0x202;
|
||||
int_toggle(old_state);
|
||||
}
|
||||
|
||||
// I am still surprised that I still know how this works.
|
||||
// I will properly document it sometime soon.
|
||||
void thread_setup_context_for_execve(struct thread *thrd, uintptr_t pc_address,
|
||||
char **argv, char **envp) {
|
||||
bool old_state = int_toggle(false);
|
||||
struct process *proc = thrd->mother_proc;
|
||||
|
||||
thrd->reg.rip = pc_address;
|
||||
thrd->reg.rsp = (uint64_t)pmm_allocz(STACK_SIZE / PAGE_SIZE);
|
||||
thrd->stack = thrd->reg.rsp;
|
||||
thrd->reg.cs = 0x23;
|
||||
thrd->reg.ss = 0x1b;
|
||||
|
||||
mmap_range(proc->process_pagemap, proc->stack_top - STACK_SIZE,
|
||||
(uintptr_t)thrd->reg.rsp, STACK_SIZE + 1, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS);
|
||||
|
||||
thrd->reg.rsp = proc->stack_top;
|
||||
|
||||
thrd->reg.rflags = 0x202;
|
||||
|
||||
prcb_return_current_cpu()->fpu_restore(thrd->fpu_storage);
|
||||
uint16_t default_fcw = 0b1100111111;
|
||||
asm volatile("fldcw %0" ::"m"(default_fcw) : "memory");
|
||||
uint32_t default_mxcsr = 0b1111110000000;
|
||||
asm volatile("ldmxcsr %0" ::"m"(default_mxcsr) : "memory");
|
||||
prcb_return_current_cpu()->fpu_save(thrd->fpu_storage);
|
||||
|
||||
thrd->fs_base = 0;
|
||||
thrd->gs_base = 0;
|
||||
|
||||
struct auxval auxv = proc->auxv;
|
||||
|
||||
// the stack structure.
|
||||
// the address values are not accurate.
|
||||
/*
|
||||
* 0x70000000000 - "USER=root\0" // envp[0][9]
|
||||
* 0x6fffffffff6 - proc->name // argv[0][255]
|
||||
* 0x6fffffffef6 - 0x0, 0x0 // zeros
|
||||
* 0x6fffffffee6 - AT_ENTRY
|
||||
* 0x6fffffffede - 0x400789 // example values
|
||||
* 0x6fffffffed6 - AT_PHDR
|
||||
* 0x6fffffffece - 2
|
||||
* 0x6fffffffec6 - AT_PHENT
|
||||
* 0x6fffffffebe - 7
|
||||
* 0x6fffffffeb6 - AT_PHNUM
|
||||
* 0x6fffffffeae - 5
|
||||
* 0x6fffffffea6 - 0x0 // START OF ENVP
|
||||
* 0x6fffffffe9e - 0x6fffffffff6 // pointer to envp[0]
|
||||
* 0x6fffffffe96 - 0x0 // START OF ARGV
|
||||
* 0x6fffffffe8e - 0x6fffffffef6 // pointer to argv[0]
|
||||
* 0x6fffffffe86 - 1 // argc
|
||||
*/
|
||||
|
||||
uint64_t *stack = (uint64_t *)(thrd->stack + STACK_SIZE + MEM_PHYS_OFFSET);
|
||||
|
||||
int envp_len = 0;
|
||||
uint64_t address_difference = 0;
|
||||
|
||||
uint8_t *stack_but_in_bytes = (uint8_t *)stack;
|
||||
|
||||
for (envp_len = 0; envp[envp_len] != NULL; envp_len++) {
|
||||
stack_but_in_bytes -= (strlen(envp[envp_len]) + 1);
|
||||
memcpy((void *)stack_but_in_bytes, envp[envp_len],
|
||||
strlen(envp[envp_len]) + 1);
|
||||
}
|
||||
|
||||
stack = (uint64_t *)stack_but_in_bytes;
|
||||
address_difference =
|
||||
(thrd->stack + STACK_SIZE) - ((uint64_t)stack - MEM_PHYS_OFFSET);
|
||||
uint64_t addr_to_env = (uint64_t)proc->stack_top - address_difference;
|
||||
|
||||
int argv_len;
|
||||
for (argv_len = 0; argv[argv_len] != NULL; argv_len++) {
|
||||
stack_but_in_bytes -= (strlen(argv[argv_len]) + 1);
|
||||
memcpy((void *)stack_but_in_bytes, argv[argv_len],
|
||||
strlen(argv[argv_len]) + 1);
|
||||
}
|
||||
|
||||
stack = (uint64_t *)stack_but_in_bytes;
|
||||
address_difference =
|
||||
(thrd->stack + STACK_SIZE) - ((uint64_t)stack - MEM_PHYS_OFFSET);
|
||||
uint64_t addr_to_arg = (uint64_t)proc->stack_top - address_difference;
|
||||
|
||||
// alignments
|
||||
|
||||
stack = (uintptr_t *)ALIGN_DOWN((uintptr_t)stack, 16);
|
||||
if (((argv_len + envp_len + 1) & 1) != 0)
|
||||
stack--;
|
||||
|
||||
*(--stack) = 0;
|
||||
*(--stack) = 0;
|
||||
stack -= 2;
|
||||
stack[0] = 23; // AT_SECURE
|
||||
stack[1] = 0;
|
||||
stack -= 2;
|
||||
stack[0] = 9;
|
||||
stack[1] = auxv.at_entry;
|
||||
stack -= 2;
|
||||
stack[0] = 3;
|
||||
stack[1] = auxv.at_phdr;
|
||||
stack -= 2;
|
||||
stack[0] = 4;
|
||||
stack[1] = auxv.at_phent;
|
||||
stack -= 2;
|
||||
stack[0] = 5;
|
||||
stack[1] = auxv.at_phnum;
|
||||
|
||||
*(--stack) = 0;
|
||||
|
||||
stack -= envp_len;
|
||||
|
||||
uint64_t offset = 0;
|
||||
for (int i = envp_len - 1; i >= 0; i--) {
|
||||
if (i != envp_len - 1) {
|
||||
offset += strlen(envp[i + 1]) + 1;
|
||||
}
|
||||
stack[i] = addr_to_env + offset;
|
||||
}
|
||||
|
||||
*(--stack) = 0;
|
||||
|
||||
stack -= argv_len;
|
||||
|
||||
offset = 0;
|
||||
for (int i = argv_len - 1; i >= 0; i--) {
|
||||
if (i != argv_len - 1) {
|
||||
offset += strlen(argv[i + 1]) + 1;
|
||||
}
|
||||
stack[i] = addr_to_arg + offset;
|
||||
}
|
||||
|
||||
*(--stack) = argv_len;
|
||||
|
||||
address_difference =
|
||||
(thrd->stack + STACK_SIZE) - ((uint64_t)stack - MEM_PHYS_OFFSET);
|
||||
|
||||
thrd->reg.rsp -= address_difference;
|
||||
proc->stack_top -= STACK_SIZE;
|
||||
int_toggle(old_state);
|
||||
}
|
||||
|
||||
void thread_fork_context(struct thread *thrd, struct thread *fthrd) {
|
||||
bool old_state = int_toggle(false);
|
||||
fthrd->kernel_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
|
||||
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
|
||||
fthrd->pf_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
|
||||
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
|
||||
fthrd->reg = thrd->reg;
|
||||
fthrd->reg.rax = 0;
|
||||
fthrd->reg.rbx = 0;
|
||||
fthrd->fs_base = thrd->fs_base;
|
||||
fthrd->gs_base = thrd->gs_base;
|
||||
fthrd->fpu_storage =
|
||||
(void *)((uintptr_t)pmm_allocz(DIV_ROUNDUP(
|
||||
prcb_return_current_cpu()->fpu_storage_size, PAGE_SIZE)) +
|
||||
MEM_PHYS_OFFSET);
|
||||
|
||||
memcpy(fthrd->fpu_storage, thrd->fpu_storage,
|
||||
prcb_return_current_cpu()->fpu_storage_size);
|
||||
int_toggle(old_state);
|
||||
}
|
||||
|
||||
void thread_destroy_context(struct thread *thrd) {
|
||||
bool old_state = int_toggle(false);
|
||||
pmm_free((void *)(thrd->kernel_stack - MEM_PHYS_OFFSET - CPU_STACK_SIZE),
|
||||
CPU_STACK_SIZE / PAGE_SIZE);
|
||||
pmm_free((void *)(thrd->pf_stack - MEM_PHYS_OFFSET - CPU_STACK_SIZE),
|
||||
CPU_STACK_SIZE / PAGE_SIZE);
|
||||
pmm_free(
|
||||
(void *)((uint64_t)thrd->fpu_storage - MEM_PHYS_OFFSET),
|
||||
DIV_ROUNDUP(prcb_return_current_cpu()->fpu_storage_size, PAGE_SIZE));
|
||||
int_toggle(old_state);
|
||||
}
|
||||
|
||||
void process_setup_context(struct process *proc, bool user) {
|
||||
if (user) {
|
||||
proc->process_pagemap = vmm_new_pagemap();
|
||||
} else {
|
||||
proc->process_pagemap = kernel_pagemap;
|
||||
}
|
||||
}
|
||||
|
||||
void process_fork_context(struct process *proc, struct process *fproc) {
|
||||
fproc->process_pagemap = vmm_fork_pagemap(proc->process_pagemap);
|
||||
}
|
||||
|
||||
void process_destroy_context(struct process *proc) {
|
||||
(void)proc;
|
||||
vmm_destroy_pagemap(proc->process_pagemap);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "mm/vmm.h"
|
||||
#include "mm/memory.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "mm/slab.h"
|
||||
#include "mp/mp.h"
|
||||
#include "mp/spinlock.h"
|
||||
#include "sched/syscall.h"
|
||||
#include "sched/sched.h"
|
||||
#include "libk/errno.h"
|
||||
|
||||
#define ARCH_SET_GS 0x1001
|
||||
#define ARCH_SET_FS 0x1002
|
||||
#define ARCH_GET_FS 0x1003
|
||||
#define ARCH_GET_GS 0x1004
|
||||
|
||||
void syscall_prctl(struct syscall_arguments *args) {
|
||||
int option = (int)args->args0;
|
||||
uint64_t value = args->args1;
|
||||
switch (option) {
|
||||
case ARCH_SET_GS: {
|
||||
sched_get_running_thread()->gs_base = value;
|
||||
// set_user_gs(prcb_return_current_cpu()->running_thread->gs_base);
|
||||
break;
|
||||
}
|
||||
case ARCH_GET_GS:
|
||||
args->ret = read_user_gs();
|
||||
break;
|
||||
case ARCH_SET_FS: {
|
||||
sched_get_running_thread()->fs_base = value;
|
||||
set_fs_base(sched_get_running_thread()->fs_base);
|
||||
break;
|
||||
}
|
||||
case ARCH_GET_FS:
|
||||
args->ret = read_fs_base();
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "mm/vmm.h"
|
||||
#include "mm/memory.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "mm/slab.h"
|
||||
#include "mp/mp.h"
|
||||
#include "mp/spinlock.h"
|
||||
#include "arch/x86_64/cpu/reg.h"
|
||||
#include "arch/x86_64/sys/timer.h"
|
||||
#include "sched/sched.h"
|
||||
#include "arch/x86_64/sys/apic.h"
|
||||
#include "libk/time.h"
|
||||
#include "arch/x86_64/sys/prcb.h"
|
||||
|
||||
|
||||
extern uint32_t smp_bsp_lapic_id;
|
||||
|
||||
extern void resched_context_switch(registers_t *reg);
|
||||
|
||||
void sched_yield(bool save) {
|
||||
cli();
|
||||
timer_stop_sched();
|
||||
|
||||
struct thread *thrd = sched_get_running_thread();
|
||||
|
||||
if (save) {
|
||||
spinlock_acquire_or_wait(&thrd->yield_lock);
|
||||
} else {
|
||||
spinlock_drop(&thrd->lock);
|
||||
prcb_return_current_cpu()->running_thread = NULL;
|
||||
}
|
||||
|
||||
apic_send_ipi(prcb_return_current_cpu()->lapic_id, 48);
|
||||
sti();
|
||||
|
||||
if (save) {
|
||||
spinlock_acquire_or_wait(
|
||||
&thrd->yield_lock); // the lock is released when the thread is
|
||||
// rescheduled
|
||||
spinlock_drop(&thrd->yield_lock);
|
||||
} else {
|
||||
for (;;) {
|
||||
halt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sched_trigger_yield(uint64_t cpu_number) {
|
||||
struct prcb *target = NULL;
|
||||
for (size_t i = 0; i < prcb_return_installed_cpus(); i++) {
|
||||
if (prcbs[i].cpu_number == cpu_number) {
|
||||
target = &prcbs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (target) {
|
||||
apic_send_ipi(target->lapic_id, 48);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t last = 0;
|
||||
|
||||
void resched(registers_t *reg) {
|
||||
vmm_switch_pagemap(kernel_pagemap);
|
||||
prcb_return_current_cpu()->sched_ticks++;
|
||||
timer_stop_sched();
|
||||
|
||||
struct thread *running_thrd = prcb_return_current_cpu()->running_thread;
|
||||
|
||||
if (prcb_return_current_cpu()->lapic_id == smp_bsp_lapic_id) {
|
||||
uint64_t current = timer_count();
|
||||
if (timer_handler((current - last) * 1000000)) {
|
||||
last = current;
|
||||
}
|
||||
}
|
||||
|
||||
if (running_thrd) {
|
||||
spinlock_drop(&running_thrd->yield_lock);
|
||||
running_thrd->reg = *reg;
|
||||
running_thrd->fs_base = read_fs_base();
|
||||
running_thrd->gs_base = read_user_gs();
|
||||
prcb_return_current_cpu()->fpu_save(running_thrd->fpu_storage);
|
||||
running_thrd->last_scheduled = timer_count();
|
||||
running_thrd->running_on_cpu = -1;
|
||||
running_thrd->stack = prcb_return_current_cpu()->user_stack;
|
||||
if (running_thrd->state == THREAD_NORMAL) {
|
||||
running_thrd->state = THREAD_READY_TO_RUN;
|
||||
}
|
||||
spinlock_drop(&running_thrd->lock);
|
||||
}
|
||||
|
||||
running_thrd = sched_get_next_thread(running_thrd);
|
||||
|
||||
if (running_thrd == NULL) {
|
||||
apic_eoi();
|
||||
prcb_return_current_cpu()->running_thread = NULL;
|
||||
timer_sched_oneshot(48, 20000);
|
||||
for (;;) {
|
||||
sti();
|
||||
halt();
|
||||
}
|
||||
}
|
||||
|
||||
prcb_return_current_cpu()->running_thread = running_thrd;
|
||||
prcb_return_current_cpu()->cpu_tss.ist2 = running_thrd->pf_stack;
|
||||
|
||||
prcb_return_current_cpu()->kernel_stack = running_thrd->kernel_stack;
|
||||
prcb_return_current_cpu()->user_stack = running_thrd->stack;
|
||||
prcb_return_current_cpu()->running_thread->state = THREAD_NORMAL;
|
||||
prcb_return_current_cpu()->fpu_restore(running_thrd->fpu_storage);
|
||||
|
||||
running_thrd->running_on_cpu = prcb_return_current_cpu()->cpu_number;
|
||||
|
||||
set_fs_base(running_thrd->fs_base);
|
||||
// set_user_gs(running_thrd->gs_base);
|
||||
|
||||
vmm_switch_pagemap(running_thrd->mother_proc->process_pagemap);
|
||||
|
||||
apic_eoi();
|
||||
|
||||
timer_sched_oneshot(48, running_thrd->runtime);
|
||||
resched_context_switch(&running_thrd->reg);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
global resched_context_switch
|
||||
|
||||
resched_context_switch:
|
||||
mov rsp, rdi
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbp
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
add rsp, 24
|
||||
iretq
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "serial.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
|
||||
void serial_init(void) {
|
||||
x86_64_outb(COM1 + 1, 0x1);
|
||||
x86_64_outb(COM1 + 3, 0x80);
|
||||
x86_64_outb(COM1, 0x1);
|
||||
x86_64_outb(COM1 + 1, 0x0);
|
||||
x86_64_outb(COM1 + 3, 0x3);
|
||||
x86_64_outb(COM1 + 2, 0xC7);
|
||||
x86_64_outb(COM1 + 4, 0xB);
|
||||
}
|
||||
|
||||
static inline bool is_transmit_empty(void) {
|
||||
return (x86_64_inb(COM1 + 5) & 0b1000000) != 0;
|
||||
}
|
||||
|
||||
static inline void transmit_data(uint8_t value) {
|
||||
while (!is_transmit_empty()) {
|
||||
asm volatile("pause");
|
||||
}
|
||||
x86_64_outb(COM1, value);
|
||||
}
|
||||
|
||||
void serial_putchar(char ch) {
|
||||
transmit_data(ch);
|
||||
}
|
||||
|
||||
void serial_puts(char *str) {
|
||||
while (*str) {
|
||||
if (*str == '\n')
|
||||
transmit_data('\r');
|
||||
transmit_data(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
int serial_received(void) {
|
||||
return x86_64_inb(COM1 + 5) & 1;
|
||||
}
|
||||
|
||||
char serial_get_byte(void) {
|
||||
while (serial_received() == 0)
|
||||
;
|
||||
|
||||
return x86_64_inb(COM1);
|
||||
}
|
||||
|
||||
char serial_getchar(void) {
|
||||
char c = '\0';
|
||||
char last_c = c;
|
||||
while (1) {
|
||||
if (c != '\0')
|
||||
serial_putchar('\b');
|
||||
serial_putchar(c);
|
||||
c = serial_get_byte();
|
||||
if (c == '\r')
|
||||
break;
|
||||
|
||||
last_c = c;
|
||||
}
|
||||
return last_c;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define COM1 0x3F8
|
||||
|
||||
void serial_init(void);
|
||||
void serial_putchar(char ch);
|
||||
void serial_puts(char *str);
|
||||
char serial_get_byte(void);
|
||||
char serial_getchar(void);
|
||||
+219
-116
@@ -2,146 +2,249 @@
|
||||
#include "mm/vmm.h"
|
||||
#include "mm/memory.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include "libk/stdio.h"
|
||||
/* ── Internal state ───────────────────────────────────────────────────────── */
|
||||
static volatile uint32_t *g_lapic = NULL; /* Virtual address of LAPIC MMIO */
|
||||
#include "arch/x86_64/cpu/features.h"
|
||||
#include "libk/debug.h"
|
||||
#include "mp/mp.h"
|
||||
#include "arch/x86_64/sys/prcb.h"
|
||||
#include "arch/x86_64/fw/madt.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include <cpuid.h>
|
||||
#include "arch/x86_64/bus/mmio.h"
|
||||
|
||||
/* ── Low-level helpers ────────────────────────────────────────────────────── */
|
||||
static uintptr_t lapic_addr = 0;
|
||||
static bool x2apic = false;
|
||||
|
||||
static inline uint32_t lapic_read(uint32_t reg) {
|
||||
return g_lapic[reg >> 2];
|
||||
// Converts xAPIC MMIO offset into x2APIC MSR
|
||||
static inline uint32_t reg_to_x2apic(uint32_t reg) {
|
||||
uint32_t x2apic_reg = 0;
|
||||
// MSR 831H is reserved; read/write operations cause general-protection
|
||||
// exceptions. The contents of the APIC register at MMIO offset 310H are
|
||||
// accessible in x2APIC mode through the MSR at address 830H
|
||||
// -- Intel SDM Volume 3A 10.12.1.2 Note 4
|
||||
if (reg == 0x310) {
|
||||
x2apic_reg = 0x30;
|
||||
} else {
|
||||
x2apic_reg = reg >> 4;
|
||||
}
|
||||
return x2apic_reg + 0x800;
|
||||
}
|
||||
|
||||
static inline void lapic_write(uint32_t reg, uint32_t val) {
|
||||
g_lapic[reg >> 2] = val;
|
||||
/* Serialise: read back a read-only register to ensure the write landed
|
||||
* before we continue (required by the APIC spec). */
|
||||
(void)g_lapic[LAPIC_ID >> 2];
|
||||
uint32_t lapic_read(uint32_t reg) {
|
||||
if (x2apic) {
|
||||
return rdmsr(reg_to_x2apic(reg));
|
||||
}
|
||||
return mmind((void *)lapic_addr + MEM_PHYS_OFFSET + reg);
|
||||
}
|
||||
|
||||
static inline void rdmsr(uint32_t msr, uint32_t *lo, uint32_t *hi) {
|
||||
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
|
||||
void lapic_write(uint32_t reg, uint32_t value) {
|
||||
if (x2apic) {
|
||||
wrmsr(reg_to_x2apic(reg), value);
|
||||
} else {
|
||||
mmoutd((void *)lapic_addr + MEM_PHYS_OFFSET + reg, value);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wrmsr(uint32_t msr, uint32_t lo, uint32_t hi) {
|
||||
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
|
||||
static void lapic_set_nmi(uint8_t vec, uint8_t current_processor_id,
|
||||
uint8_t processor_id, uint16_t flags, uint8_t lint) {
|
||||
// A value of 0xFF means all the processors
|
||||
if (processor_id != 0xFF) {
|
||||
if (current_processor_id != processor_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Set to raise in vector number "vec" and set NMI flag
|
||||
uint32_t nmi = 0x400 | vec;
|
||||
|
||||
// Set to active low if needed
|
||||
if (flags & 2) {
|
||||
nmi |= 1 << 13;
|
||||
}
|
||||
|
||||
// Set to level triggered if needed
|
||||
if (flags & 8) {
|
||||
nmi |= 1 << 15;
|
||||
}
|
||||
|
||||
// Use the proper LINT register
|
||||
if (lint == 0) {
|
||||
lapic_write(0x350, nmi);
|
||||
} else if (lint == 1) {
|
||||
lapic_write(0x360, nmi);
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Public API ───────────────────────────────────────────────────────────── */
|
||||
|
||||
uint64_t lapic_get_phys_base(void) {
|
||||
uint32_t lo, hi;
|
||||
rdmsr(IA32_APIC_BASE_MSR, &lo, &hi);
|
||||
/* Physical base is in bits [35:12] of the 64-bit MSR */
|
||||
return ((uint64_t)(hi & 0xFu) << 32) | (lo & 0xFFFFF000u);
|
||||
uint8_t lapic_get_id(void) {
|
||||
return (uint8_t)(lapic_read(0x20) >> 24);
|
||||
}
|
||||
|
||||
void lapic_eoi(void) {
|
||||
lapic_write(LAPIC_EOI, 0);
|
||||
void lapic_init(uint8_t processor_id) {
|
||||
kprintf("LAPIC: Setting up LAPIC on Processor %u\n", processor_id);
|
||||
uint64_t apic_msr = rdmsr(0x1B);
|
||||
// Set APIC enable flag
|
||||
apic_msr |= 1 << 11;
|
||||
uint32_t a = 0, b = 0, c = 0, d = 0;
|
||||
if (__get_cpuid(1, &a, &b, &c, &d)) {
|
||||
if (c & CPUID_X2APIC) {
|
||||
x2apic = true;
|
||||
// Set x2APIC flag if support is detected
|
||||
apic_msr |= 1 << 10;
|
||||
}
|
||||
}
|
||||
wrmsr(0x1B, apic_msr);
|
||||
|
||||
// Initialize local APIC
|
||||
lapic_write(0x80, 0);
|
||||
lapic_write(0xF0, lapic_read(0xF0) | 0x100);
|
||||
if (!x2apic) {
|
||||
lapic_write(0xE0, 0xF0000000);
|
||||
lapic_write(0xD0, lapic_read(0x20));
|
||||
}
|
||||
|
||||
// Set NMIs according to the MADT
|
||||
for (int i = 0; i < madt_nmis.length; i++) {
|
||||
struct madt_nmi *nmi = madt_nmis.data[i];
|
||||
lapic_set_nmi(2, processor_id, nmi->processor, nmi->flags, nmi->lint);
|
||||
}
|
||||
|
||||
// Set up APIC timer
|
||||
|
||||
// Tell APIC timer to divide by 16
|
||||
lapic_write(0x3E0, 3);
|
||||
// Set timer init counter to -1
|
||||
lapic_write(0x380, 0xFFFFFFFF);
|
||||
|
||||
timer_sleep(10);
|
||||
|
||||
// Stop the APIC timer
|
||||
lapic_write(0x320, 0x10000);
|
||||
|
||||
// How much the APIC timer ticked in 10ms
|
||||
prcb_return_current_cpu()->tick_in_10ms = 0xFFFFFFFF - lapic_read(0x390);
|
||||
|
||||
// With divider 16
|
||||
lapic_write(0x3E0, 3);
|
||||
lapic_write(0x380, prcb_return_current_cpu()->tick_in_10ms / 10);
|
||||
}
|
||||
|
||||
uint32_t lapic_id(void) {
|
||||
/* On xAPIC the LAPIC ID sits in bits [31:24] of the ID register */
|
||||
return lapic_read(LAPIC_ID) >> 24;
|
||||
static uint32_t ioapic_read(uintptr_t ioapic_address, size_t reg) {
|
||||
mmoutd((void *)ioapic_address + MEM_PHYS_OFFSET, reg & 0xFF);
|
||||
return mmind((void *)ioapic_address + MEM_PHYS_OFFSET + 16);
|
||||
}
|
||||
|
||||
void lapic_init(void) {
|
||||
/*
|
||||
* ── Step 1: Re-enable the APIC global enable bit ─────────────────────
|
||||
*
|
||||
* Earlier in kmain (before pmm_init) we cleared bit 11 of IA32_APIC_BASE
|
||||
* so that the i8259 PIC would raise interrupts properly under Limine.
|
||||
* Now that the LAPIC is being brought online we must restore that bit;
|
||||
* without it the LAPIC is completely off and nothing below will work.
|
||||
*/
|
||||
uint32_t lo, hi;
|
||||
rdmsr(IA32_APIC_BASE_MSR, &lo, &hi);
|
||||
lo |= IA32_APIC_BASE_ENABLE;
|
||||
wrmsr(IA32_APIC_BASE_MSR, lo, hi);
|
||||
static void ioapic_write(uintptr_t ioapic_address, size_t reg, uint32_t data) {
|
||||
mmoutd((void *)ioapic_address + MEM_PHYS_OFFSET, reg & 0xFF);
|
||||
mmoutd((void *)ioapic_address + MEM_PHYS_OFFSET + 16, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* ── Step 2: Locate the LAPIC MMIO window ─────────────────────────────
|
||||
*
|
||||
* The physical address is almost always 0xFEE00000 but we read it from
|
||||
* the MSR to be correct. vmm_init() already identity-maps all physical
|
||||
* memory through the HHDM (up to 256 GiB), so the MMIO page is reachable
|
||||
* at phys + MEM_PHYS_OFFSET with no extra mapping needed.
|
||||
*
|
||||
* TODO: For strict correctness the LAPIC page should be mapped as
|
||||
* uncacheable (PAT / PCD). In practice, QEMU / BOCHS work fine
|
||||
* because MTRRs mark the 0xFEE00000 range as UC by default.
|
||||
*/
|
||||
uint64_t phys_base = ((uint64_t)(hi & 0xFu) << 32) | (lo & 0xFFFFF000u);
|
||||
printf("[LAPIC] Physical base: 0x%08x%08x\n",
|
||||
(uint32_t)(phys_base >> 32), (uint32_t)phys_base);
|
||||
static uint32_t get_gsi_count(uintptr_t ioapic_address) {
|
||||
return (ioapic_read(ioapic_address, 1) & 0xFF0000) >> 16;
|
||||
}
|
||||
|
||||
g_lapic = (volatile uint32_t *)(phys_base + MEM_PHYS_OFFSET);
|
||||
static struct madt_ioapic *get_ioapic_by_gsi(uint32_t gsi) {
|
||||
// Search through every I/O APIC to find its GSI
|
||||
for (int i = 0; i < madt_io_apics.length; i++) {
|
||||
struct madt_ioapic *ioapic = madt_io_apics.data[i];
|
||||
if (ioapic->gsib <= gsi &&
|
||||
ioapic->gsib + get_gsi_count(ioapic->addr) > gsi) {
|
||||
return ioapic;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ── Step 3: Software-enable the LAPIC via the SVR ────────────────────
|
||||
*
|
||||
* Bit 8 = Software Enable. The lower 8 bits are the "spurious interrupt
|
||||
* vector" delivered if the CPU acknowledges an interrupt that was
|
||||
* retracted by the LAPIC; 0xFF is the conventional choice.
|
||||
*/
|
||||
lapic_write(LAPIC_SVR, LAPIC_SVR_ENABLE | 0xFF);
|
||||
// Return NULL if none was found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ── Step 4: Configure LINT0 as ExtINT (i8259 pass-through) ──────────
|
||||
*
|
||||
* On a standard PC the i8259 INTR pin is wired to the BSP's LINT0.
|
||||
* Setting LINT0 to ExtINT delivery mode makes the LAPIC act as a
|
||||
* transparent relay: the i8259 interrupt acknowledge cycle goes through
|
||||
* normally, the full 8-bit vector comes from the i8259, and the CPU's
|
||||
* existing IDT entries + irq.c EOI code all keep working unchanged.
|
||||
*
|
||||
* This is the "Virtual Wire" mode described in the Intel MP Spec.
|
||||
*/
|
||||
lapic_write(LAPIC_LVT_LINT0, LAPIC_LVT_DM_EXTINT);
|
||||
void ioapic_redirect_gsi(uint32_t gsi, uint8_t vec, uint16_t flags) {
|
||||
// Get I/O APIC address of the GSI
|
||||
size_t io_apic = get_ioapic_by_gsi(gsi)->addr;
|
||||
|
||||
/*
|
||||
* ── Step 5: Configure LINT1 as NMI ───────────────────────────────────
|
||||
*
|
||||
* LINT1 is the NMI pin on standard PCs. Delivery mode = 4 (NMI),
|
||||
* unmasked, edge-triggered (the default when LAPIC_LVT_LEVEL is clear).
|
||||
*/
|
||||
lapic_write(LAPIC_LVT_LINT1, LAPIC_LVT_DM_NMI);
|
||||
uint32_t low_index = 0x10 + (gsi - get_ioapic_by_gsi(gsi)->gsib) * 2;
|
||||
uint32_t high_index = low_index + 1;
|
||||
|
||||
/*
|
||||
* ── Step 6: Mask LVT entries we are not yet using ────────────────────
|
||||
*
|
||||
* Timer, error, and (if present) thermal / perf entries all start masked.
|
||||
* Assign distinct vectors in the 0xF0-0xFE range so that if one fires
|
||||
* spuriously the IDT handler can identify it and send EOI.
|
||||
*/
|
||||
lapic_write(LAPIC_LVT_TIMER, LAPIC_LVT_MASKED | 0xFD);
|
||||
lapic_write(LAPIC_LVT_ERROR, LAPIC_LVT_MASKED | 0xFE);
|
||||
uint32_t high = ioapic_read(io_apic, high_index);
|
||||
|
||||
/* Version register: bits [23:16] = max LVT entry index */
|
||||
uint32_t ver = lapic_read(LAPIC_VER);
|
||||
uint32_t max_lvt = (ver >> 16) & 0xFF;
|
||||
if (max_lvt >= 4) lapic_write(LAPIC_LVT_THERMAL, LAPIC_LVT_MASKED | 0xFC);
|
||||
if (max_lvt >= 5) lapic_write(LAPIC_LVT_PERF, LAPIC_LVT_MASKED | 0xFB);
|
||||
// Set APIC ID
|
||||
high &= ~0xFF000000;
|
||||
high |= ioapic_read(io_apic, 0) << 24;
|
||||
ioapic_write(io_apic, high_index, high);
|
||||
|
||||
/*
|
||||
* ── Step 7: Clear the Error Status Register ───────────────────────────
|
||||
*
|
||||
* The APIC spec requires writing ESR twice to clear stale error bits.
|
||||
*/
|
||||
lapic_write(LAPIC_ESR, 0);
|
||||
lapic_write(LAPIC_ESR, 0);
|
||||
uint32_t low = ioapic_read(io_apic, low_index);
|
||||
|
||||
/* Dismiss any stale in-service interrupt */
|
||||
lapic_write(LAPIC_EOI, 0);
|
||||
// Unmask the IRQ
|
||||
low &= ~(1 << 16);
|
||||
|
||||
/*
|
||||
* ── Step 8: Set Task Priority to 0 ───────────────────────────────────
|
||||
*
|
||||
* TPR = 0 means the CPU will accept all interrupt priorities.
|
||||
* Raise this later if need to block lower-priority interrupts.
|
||||
*/
|
||||
lapic_write(LAPIC_TPR, 0);
|
||||
// Set to physical delivery mode
|
||||
low &= ~(1 << 11);
|
||||
|
||||
// Set to fixed delivery mode
|
||||
low &= ~0x700;
|
||||
|
||||
// Set delivery vector
|
||||
low &= ~0xFF;
|
||||
low |= vec;
|
||||
|
||||
// Active high(0) or low(1)
|
||||
if (flags & 2) {
|
||||
low |= 1 << 13;
|
||||
}
|
||||
|
||||
// Edge(0) or level(1) triggered
|
||||
if (flags & 8) {
|
||||
low |= 1 << 15;
|
||||
}
|
||||
|
||||
ioapic_write(io_apic, low_index, low);
|
||||
}
|
||||
|
||||
void ioapic_redirect_irq(uint32_t irq, uint8_t vect) {
|
||||
// Use ISO table to find flags and interrupt overrides
|
||||
for (int i = 0; i < madt_isos.length; i++) {
|
||||
if (madt_isos.data[i]->irq_source == irq) {
|
||||
ioapic_redirect_gsi(madt_isos.data[i]->gsi, vect,
|
||||
madt_isos.data[i]->flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ioapic_redirect_gsi(irq, vect, 0);
|
||||
}
|
||||
|
||||
void apic_send_ipi(uint32_t lapic_id, uint32_t flags) {
|
||||
if (x2apic) {
|
||||
// Write MSR directly, because lapic_write receives a 32-bit argument
|
||||
// Whilst in x2APIC, 0x830 is a 64-bit register
|
||||
wrmsr(0x830, ((uint64_t)lapic_id << 32) | flags);
|
||||
} else {
|
||||
lapic_write(0x310, (lapic_id << 24));
|
||||
lapic_write(0x300, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void apic_eoi(void) {
|
||||
// Writing any other value different than 0 may cause a #GP exception
|
||||
lapic_write(0xB0, 0);
|
||||
}
|
||||
|
||||
void timer_stop_sched(void) {
|
||||
lapic_write(0x380, 0);
|
||||
lapic_write(0x320, (1 << 16));
|
||||
}
|
||||
|
||||
void timer_sched_oneshot(uint8_t isr, uint32_t us) {
|
||||
timer_stop_sched();
|
||||
lapic_write(0x320, isr | 0x20000);
|
||||
lapic_write(0x3E0, 3);
|
||||
lapic_write(0x380,
|
||||
((prcb_return_current_cpu()->tick_in_10ms * (us / 1000))) / 10);
|
||||
}
|
||||
|
||||
void apic_init(void) {
|
||||
pic_init();
|
||||
|
||||
lapic_addr = acpi_get_lapic();
|
||||
|
||||
ioapic_redirect_irq(0, 48);
|
||||
}
|
||||
|
||||
printf("[LAPIC] Online. ID=%u version=0x%02x max_lvt=%u\n",
|
||||
lapic_id(), ver & 0xFF, max_lvt);
|
||||
}
|
||||
@@ -2,73 +2,13 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* Local APIC (xAPIC mode, MMIO access)
|
||||
* Register offsets are byte offsets; we shift right by 2 for uint32_t indexing.
|
||||
*/
|
||||
|
||||
/* ── Register offsets ─────────────────────────────────────────────────────── */
|
||||
#define LAPIC_ID 0x020 /* LAPIC ID (bits [27:24] on P4, [31:24] on modern) */
|
||||
#define LAPIC_VER 0x030 /* Version register */
|
||||
#define LAPIC_TPR 0x080 /* Task Priority Register */
|
||||
#define LAPIC_APR 0x090 /* Arbitration Priority (RO) */
|
||||
#define LAPIC_PPR 0x0A0 /* Processor Priority (RO) */
|
||||
#define LAPIC_EOI 0x0B0 /* End-Of-Interrupt (write 0 to ack) */
|
||||
#define LAPIC_RRD 0x0C0 /* Remote Read (RO) */
|
||||
#define LAPIC_LDR 0x0D0 /* Logical Destination */
|
||||
#define LAPIC_DFR 0x0E0 /* Destination Format */
|
||||
#define LAPIC_SVR 0x0F0 /* Spurious Interrupt Vector */
|
||||
#define LAPIC_ESR 0x280 /* Error Status Register */
|
||||
#define LAPIC_ICR_LO 0x300 /* Interrupt Command (low 32 bits) */
|
||||
#define LAPIC_ICR_HI 0x310 /* Interrupt Command (high 32 bits) */
|
||||
#define LAPIC_LVT_TIMER 0x320 /* LVT: APIC timer */
|
||||
#define LAPIC_LVT_THERMAL 0x330 /* LVT: Thermal sensor */
|
||||
#define LAPIC_LVT_PERF 0x340 /* LVT: Performance monitoring */
|
||||
#define LAPIC_LVT_LINT0 0x350 /* LVT: Local interrupt pin 0 */
|
||||
#define LAPIC_LVT_LINT1 0x360 /* LVT: Local interrupt pin 1 */
|
||||
#define LAPIC_LVT_ERROR 0x370 /* LVT: Error */
|
||||
#define LAPIC_TIMER_ICR 0x380 /* Timer Initial Count */
|
||||
#define LAPIC_TIMER_CCR 0x390 /* Timer Current Count (RO) */
|
||||
#define LAPIC_TIMER_DCR 0x3E0 /* Timer Divide Configuration */
|
||||
|
||||
/* ── SVR flags ────────────────────────────────────────────────────────────── */
|
||||
#define LAPIC_SVR_ENABLE (1u << 8) /* Software-enable the LAPIC */
|
||||
|
||||
/* ── LVT delivery modes (bits [10:8]) ────────────────────────────────────── */
|
||||
#define LAPIC_LVT_DM_FIXED (0u << 8) /* Fixed delivery */
|
||||
#define LAPIC_LVT_DM_SMI (2u << 8)
|
||||
#define LAPIC_LVT_DM_NMI (4u << 8) /* NMI */
|
||||
#define LAPIC_LVT_DM_EXTINT (7u << 8) /* ExtINT: pass-through from i8259 */
|
||||
|
||||
/* ── LVT misc flags ───────────────────────────────────────────────────────── */
|
||||
#define LAPIC_LVT_MASKED (1u << 16) /* Mask this LVT entry */
|
||||
#define LAPIC_LVT_LEVEL (1u << 15) /* Level-triggered (vs edge) */
|
||||
#define LAPIC_LVT_ACTIVE_LOW (1u << 13) /* Active-low polarity */
|
||||
|
||||
/* ── IA32_APIC_BASE MSR ───────────────────────────────────────────────────── */
|
||||
#define IA32_APIC_BASE_MSR 0x1B
|
||||
#define IA32_APIC_BASE_ENABLE (1u << 11) /* APIC global enable bit */
|
||||
#define IA32_APIC_BASE_BSP (1u << 8) /* Bootstrap processor flag */
|
||||
|
||||
/* ── Public API ───────────────────────────────────────────────────────────── */
|
||||
|
||||
/**
|
||||
* lapic_init - Map the LAPIC MMIO, re-enable the APIC global bit in the MSR
|
||||
* (which was cleared earlier to let the i8259 work), then bring
|
||||
* the LAPIC online with LINT0=ExtINT so the i8259/PIT path is
|
||||
* completely preserved.
|
||||
*
|
||||
* Call AFTER uacpi_initialize() so that paging and the heap are live.
|
||||
*/
|
||||
void lapic_init(void);
|
||||
|
||||
/**
|
||||
* lapic_eoi - Signal end-of-interrupt to the LAPIC.
|
||||
*/
|
||||
void lapic_eoi(void);
|
||||
|
||||
/** lapic_id - Return the LAPIC ID of the current CPU. */
|
||||
uint32_t lapic_id(void);
|
||||
|
||||
/** lapic_get_phys_base - Return the physical base address from the MSR. */
|
||||
uint64_t lapic_get_phys_base(void);
|
||||
void apic_eoi(void);
|
||||
void apic_init(void);
|
||||
void apic_send_ipi(uint32_t lapic_id, uint32_t flags);
|
||||
void ioapic_redirect_irq(uint32_t irq, uint8_t vect);
|
||||
uint32_t lapic_read(uint32_t reg);
|
||||
void lapic_write(uint32_t reg, uint32_t value);
|
||||
uint8_t lapic_get_id(void);
|
||||
void lapic_init(uint8_t processor_id);
|
||||
void timer_sched_oneshot(uint8_t isr, uint32_t us);
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "arch/x86_64/asm/asm.h"
|
||||
#include "halt.h"
|
||||
#include "arch/x86_64/sys/apic.h"
|
||||
|
||||
|
||||
extern bool is_smp;
|
||||
bool is_halting = false;
|
||||
uint8_t is_pausing = false;
|
||||
|
||||
void halt_current_cpu(void) {
|
||||
for (;;) {
|
||||
cli();
|
||||
halt();
|
||||
}
|
||||
}
|
||||
|
||||
void halt_other_cpus(void) {
|
||||
if (!is_smp)
|
||||
return;
|
||||
|
||||
is_halting = true;
|
||||
|
||||
uint64_t icr = 0;
|
||||
icr |= (0b100) << 8; // set delivery mode to nmi
|
||||
icr |= (0b11) << 18; // set destination shorthand to all excluding self
|
||||
lapic_write(0x300, icr);
|
||||
lapic_write(0x310, icr >> 32);
|
||||
}
|
||||
|
||||
void pause_other_cpus(void) {
|
||||
if (!is_smp)
|
||||
return;
|
||||
|
||||
is_pausing = 0;
|
||||
is_pausing |= PAUSING;
|
||||
|
||||
uint64_t icr = 0;
|
||||
icr |= (0b100) << 8;
|
||||
icr |= (0b11) << 18;
|
||||
lapic_write(0x300, icr);
|
||||
lapic_write(0x310, icr >> 32);
|
||||
}
|
||||
|
||||
void unpause_other_cpus(void) {
|
||||
if (!is_smp)
|
||||
return;
|
||||
|
||||
is_pausing = 0;
|
||||
is_pausing |= UNPAUSING;
|
||||
|
||||
uint64_t icr = 0;
|
||||
icr |= (0b100) << 8;
|
||||
icr |= (0b11) << 18;
|
||||
lapic_write(0x300, icr);
|
||||
lapic_write(0x310, icr >> 32);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define PAUSING (1 << 0)
|
||||
#define UNPAUSING (1 << 1)
|
||||
|
||||
void halt_current_cpu(void);
|
||||
void halt_other_cpus(void);
|
||||
void pause_other_cpus(void);
|
||||
void unpause_other_cpus(void);
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <uacpi/uacpi.h>
|
||||
#include <stdint.h>
|
||||
#include "arch/x86_64/fw/acpi.h"
|
||||
|
||||
struct hpet_table {
|
||||
acpi_header_t header;
|
||||
uint8_t hardware_rev_id;
|
||||
uint8_t comparator_count : 5;
|
||||
uint8_t counter_size : 1;
|
||||
uint8_t reserved : 1;
|
||||
uint8_t legacy_replacement : 1;
|
||||
uint16_t pci_vendor_id;
|
||||
acpi_gas_t address;
|
||||
uint8_t hpet_number;
|
||||
uint16_t minimum_tick;
|
||||
uint8_t page_protection;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct hpet {
|
||||
uint64_t general_capabilities;
|
||||
uint64_t reserved;
|
||||
uint64_t general_configuration;
|
||||
uint64_t reserved2;
|
||||
uint64_t general_int_status;
|
||||
uint64_t reserved3;
|
||||
uint64_t reserved4[24];
|
||||
uint64_t main_counter_value;
|
||||
uint64_t reserved5;
|
||||
};
|
||||
|
||||
uint64_t hpet_counter_value(void);
|
||||
void hpet_sleep(uint64_t us);
|
||||
@@ -1,166 +0,0 @@
|
||||
#include "pic.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define PIC1_COMMAND_PORT 0x20
|
||||
#define PIC1_DATA_PORT 0x21
|
||||
#define PIC2_COMMAND_PORT 0xA0
|
||||
#define PIC2_DATA_PORT 0xA1
|
||||
|
||||
// Initialization Control Word 1
|
||||
// -----------------------------
|
||||
// 0 IC4 if set, the PIC expects to receive ICW4 during initialization
|
||||
// 1 SGNL if set, only 1 PIC in the system; if unset, the PIC is cascaded with slave PICs
|
||||
// and ICW3 must be sent to controller
|
||||
// 2 ADI call address interval, set: 4, not set: 8; ignored on x86, set to 0
|
||||
// 3 LTIM if set, operate in level triggered mode; if unset, operate in edge triggered mode
|
||||
// 4 INIT set to 1 to initialize PIC
|
||||
// 5-7 ignored on x86, set to 0
|
||||
|
||||
enum {
|
||||
PIC_ICW1_ICW4 = 0x01,
|
||||
PIC_ICW1_SINGLE = 0x02,
|
||||
PIC_ICW1_INTERVAL4 = 0x04,
|
||||
PIC_ICW1_LEVEL = 0x08,
|
||||
PIC_ICW1_INITIALIZE = 0x10
|
||||
} PIC_ICW1;
|
||||
|
||||
|
||||
// Initialization Control Word 4
|
||||
// -----------------------------
|
||||
// 0 uPM if set, PIC is in 80x86 mode; if cleared, in MCS-80/85 mode
|
||||
// 1 AEOI if set, on last interrupt acknowledge pulse, controller automatically performs
|
||||
// end of interrupt operation
|
||||
// 2 M/S only use if BUF is set; if set, selects buffer master; otherwise, selects buffer slave
|
||||
// 3 BUF if set, controller operates in buffered mode
|
||||
// 4 SFNM specially fully nested mode; used in systems with large number of cascaded controllers
|
||||
// 5-7 reserved, set to 0
|
||||
enum {
|
||||
PIC_ICW4_8086 = 0x1,
|
||||
PIC_ICW4_AUTO_EOI = 0x2,
|
||||
PIC_ICW4_BUFFER_MASTER = 0x4,
|
||||
PIC_ICW4_BUFFER_SLAVE = 0x0,
|
||||
PIC_ICW4_BUFFERRED = 0x8,
|
||||
PIC_ICW4_SFNM = 0x10,
|
||||
} PIC_ICW4;
|
||||
|
||||
|
||||
enum {
|
||||
PIC_CMD_END_OF_INTERRUPT = 0x20,
|
||||
PIC_CMD_READ_IRR = 0x0A,
|
||||
PIC_CMD_READ_ISR = 0x0B,
|
||||
} PIC_CMD;
|
||||
|
||||
|
||||
static uint16_t g_PicMask = 0xffff;
|
||||
static bool g_AutoEoi = false;
|
||||
|
||||
void i8259_SetMask(uint16_t newMask)
|
||||
{
|
||||
g_PicMask = newMask;
|
||||
x86_64_outb(PIC1_DATA_PORT, g_PicMask & 0xFF);
|
||||
x86_64_iowait();
|
||||
x86_64_outb(PIC2_DATA_PORT, g_PicMask >> 8);
|
||||
x86_64_iowait();
|
||||
}
|
||||
|
||||
uint16_t i8259_GetMask()
|
||||
{
|
||||
return x86_64_inb(PIC1_DATA_PORT) | (x86_64_inb(PIC2_DATA_PORT) << 8);
|
||||
}
|
||||
|
||||
void i8259_Configure(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi)
|
||||
{
|
||||
// Mask everything
|
||||
i8259_SetMask(0xFFFF);
|
||||
|
||||
// initialization control word 1
|
||||
x86_64_outb(PIC1_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE);
|
||||
x86_64_iowait();
|
||||
x86_64_outb(PIC2_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE);
|
||||
x86_64_iowait();
|
||||
|
||||
// initialization control word 2 - the offsets
|
||||
x86_64_outb(PIC1_DATA_PORT, offsetPic1);
|
||||
x86_64_iowait();
|
||||
x86_64_outb(PIC2_DATA_PORT, offsetPic2);
|
||||
x86_64_iowait();
|
||||
|
||||
// initialization control word 3
|
||||
x86_64_outb(PIC1_DATA_PORT, 0x4); // tell PIC1 that it has a slave at IRQ2 (0000 0100)
|
||||
x86_64_iowait();
|
||||
x86_64_outb(PIC2_DATA_PORT, 0x2); // tell PIC2 its cascade identity (0000 0010)
|
||||
x86_64_iowait();
|
||||
|
||||
// initialization control word 4
|
||||
uint8_t icw4 = PIC_ICW4_8086;
|
||||
if (autoEoi) {
|
||||
icw4 |= PIC_ICW4_AUTO_EOI;
|
||||
}
|
||||
|
||||
x86_64_outb(PIC1_DATA_PORT, icw4);
|
||||
x86_64_iowait();
|
||||
x86_64_outb(PIC2_DATA_PORT, icw4);
|
||||
x86_64_iowait();
|
||||
|
||||
// mask all interrupts until they are enabled by the device driver
|
||||
i8259_SetMask(0xFFFF);
|
||||
}
|
||||
|
||||
void i8259_SendEndOfInterrupt(int irq)
|
||||
{
|
||||
if (irq >= 8)
|
||||
x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT);
|
||||
x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT);
|
||||
}
|
||||
|
||||
void i8259_Disable()
|
||||
{
|
||||
i8259_SetMask(0xFFFF);
|
||||
}
|
||||
|
||||
void i8259_Mask(int irq)
|
||||
{
|
||||
i8259_SetMask(g_PicMask | (1 << irq));
|
||||
}
|
||||
|
||||
void i8259_Unmask(int irq)
|
||||
{
|
||||
i8259_SetMask(g_PicMask & ~(1 << irq));
|
||||
}
|
||||
|
||||
uint16_t i8259_ReadIrqRequestRegister()
|
||||
{
|
||||
x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_IRR);
|
||||
x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_IRR);
|
||||
return ((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) | (((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) << 8);
|
||||
}
|
||||
|
||||
uint16_t i8259_ReadInServiceRegister()
|
||||
{
|
||||
x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_ISR);
|
||||
x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_ISR);
|
||||
return ((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) | (((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) << 8);
|
||||
}
|
||||
|
||||
bool i8259_Probe()
|
||||
{
|
||||
i8259_Disable();
|
||||
i8259_SetMask(0x1337);
|
||||
return i8259_GetMask() == 0x1337;
|
||||
}
|
||||
|
||||
static const PICDriver g_PicDriver = {
|
||||
.Name = "8259 PIC",
|
||||
.Probe = &i8259_Probe,
|
||||
.Initialize = &i8259_Configure,
|
||||
.Disable = &i8259_Disable,
|
||||
.SendEndOfInterrupt = &i8259_SendEndOfInterrupt,
|
||||
.Mask = &i8259_Mask,
|
||||
.Unmask = &i8259_Unmask,
|
||||
};
|
||||
|
||||
const PICDriver* i8259_GetDriver()
|
||||
{
|
||||
return &g_PicDriver;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "pic.h"
|
||||
|
||||
const PICDriver* i8259_GetDriver();
|
||||
uint16_t i8259_GetMask();
|
||||
void i8259_SetMask(uint16_t newMask);
|
||||
|
||||
void i8259_Configure(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi);
|
||||
void i8259_Disable();
|
||||
@@ -1,359 +0,0 @@
|
||||
#include "ioapic.h"
|
||||
#include "apic.h"
|
||||
#include "mm/vmm.h"
|
||||
#include "mm/memory.h"
|
||||
#include "libk/stdio.h"
|
||||
#include <uacpi/tables.h> /* uacpi_table_find_by_signature / uacpi_table_unref */
|
||||
#include "pic.h"
|
||||
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
* ACPI MADT structures
|
||||
* (Defined locally so we don't depend on uACPI's internal acpi.h layout.)
|
||||
* ══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
extern const PICDriver* g_Driver; // old pic driver
|
||||
|
||||
bool g_IOAPIC = false; // IOAPIC enabled
|
||||
|
||||
typedef struct {
|
||||
uint8_t signature[4]; /* "APIC" */
|
||||
uint32_t length;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
uint8_t oem_id[6];
|
||||
uint8_t oem_table_id[8];
|
||||
uint32_t oem_revision;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_revision;
|
||||
/* --- MADT-specific -------------------------------------------------- */
|
||||
uint32_t local_apic_addr; /* Default LAPIC physical address (32-bit) */
|
||||
uint32_t flags; /* bit 0 = dual 8259 PICs present */
|
||||
/* followed by variable-length Interrupt Controller Structure entries */
|
||||
} __attribute__((packed)) madt_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
} __attribute__((packed)) madt_entry_hdr_t;
|
||||
|
||||
/* Type 0: Processor Local APIC */
|
||||
typedef struct {
|
||||
madt_entry_hdr_t hdr;
|
||||
uint8_t uid;
|
||||
uint8_t apic_id;
|
||||
uint32_t flags; /* bit 0 = enabled */
|
||||
} __attribute__((packed)) madt_lapic_t;
|
||||
|
||||
/* Type 1: I/O APIC */
|
||||
typedef struct {
|
||||
madt_entry_hdr_t hdr;
|
||||
uint8_t id;
|
||||
uint8_t reserved;
|
||||
uint32_t address; /* Physical MMIO base */
|
||||
uint32_t gsi_base; /* First GSI handled by this IOAPIC */
|
||||
} __attribute__((packed)) madt_ioapic_t;
|
||||
|
||||
/* Type 2: Interrupt Source Override */
|
||||
typedef struct {
|
||||
madt_entry_hdr_t hdr;
|
||||
uint8_t bus; /* 0 = ISA */
|
||||
uint8_t source; /* ISA IRQ number */
|
||||
uint32_t gsi; /* Remapped GSI */
|
||||
uint16_t flags; /* bits [1:0] = polarity, bits [3:2] = trigger mode */
|
||||
} __attribute__((packed)) madt_iso_t;
|
||||
|
||||
/* Type 4: Local APIC NMI */
|
||||
typedef struct {
|
||||
madt_entry_hdr_t hdr;
|
||||
uint8_t uid; /* 0xFF = all processors */
|
||||
uint16_t flags;
|
||||
uint8_t lint; /* 0 or 1 */
|
||||
} __attribute__((packed)) madt_nmi_t;
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
* Internal state
|
||||
* ══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t *base; /* Virtual address of IOAPIC MMIO */
|
||||
uint32_t gsi_base;
|
||||
uint32_t gsi_count; /* Number of redirection entries */
|
||||
} ioapic_t;
|
||||
|
||||
static ioapic_t g_ioapics[IOAPIC_MAX];
|
||||
static int g_ioapic_count = 0;
|
||||
|
||||
/* ISA interrupt source overrides (max 16 ISA IRQs) */
|
||||
typedef struct {
|
||||
bool present;
|
||||
uint32_t gsi;
|
||||
bool active_low;
|
||||
bool level;
|
||||
} iso_t;
|
||||
static iso_t g_iso[16]; /* indexed by ISA IRQ (source) */
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
* Low-level IOAPIC MMIO access
|
||||
*
|
||||
* The IOAPIC has two MMIO registers:
|
||||
* base+0x00 IOREGSEL – index register (write which register to access)
|
||||
* base+0x10 IOWIN – data window (read/write the selected register)
|
||||
* ══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
static uint32_t ioapic_read(const ioapic_t *io, uint8_t reg) {
|
||||
*((volatile uint32_t *)(io->base + (0x00 >> 2))) = reg;
|
||||
return *((volatile uint32_t *)(io->base + (0x10 >> 2)));
|
||||
}
|
||||
|
||||
static void ioapic_write(const ioapic_t *io, uint8_t reg, uint32_t val) {
|
||||
*((volatile uint32_t *)(io->base + (0x00 >> 2))) = reg;
|
||||
*((volatile uint32_t *)(io->base + (0x10 >> 2))) = val;
|
||||
}
|
||||
|
||||
/* ── Find which IOAPIC owns a given GSI ─────────────────────────────────── */
|
||||
|
||||
static ioapic_t *ioapic_for_gsi(uint32_t gsi) {
|
||||
for (int i = 0; i < g_ioapic_count; i++) {
|
||||
ioapic_t *io = &g_ioapics[i];
|
||||
if (gsi >= io->gsi_base && gsi < io->gsi_base + io->gsi_count)
|
||||
return io;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
* Public API
|
||||
* ══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
uint32_t ioapic_gsi_for_isa_irq(uint8_t isa_irq) {
|
||||
if (isa_irq < 16 && g_iso[isa_irq].present)
|
||||
return g_iso[isa_irq].gsi;
|
||||
return isa_irq;
|
||||
}
|
||||
|
||||
void ioapic_redirect(uint32_t gsi, uint8_t vector, uint8_t dest_lapic,
|
||||
bool active_low, bool level, bool masked) {
|
||||
ioapic_t *io = ioapic_for_gsi(gsi);
|
||||
if (!io) {
|
||||
printf("[IOAPIC] No IOAPIC for GSI %u\n", gsi);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t idx = (uint8_t)(gsi - io->gsi_base);
|
||||
uint32_t lo = (uint32_t)vector
|
||||
| IOAPIC_RTE_DM_FIXED
|
||||
| (active_low ? IOAPIC_RTE_ACTIVE_LOW : 0)
|
||||
| (level ? IOAPIC_RTE_LEVEL : 0)
|
||||
| (masked ? IOAPIC_RTE_MASKED : 0);
|
||||
uint32_t hi = (uint32_t)dest_lapic << 24;
|
||||
|
||||
/* Write high word first, then low (avoids momentary spurious delivery) */
|
||||
ioapic_write(io, IOAPIC_REDTBL_HI(idx), hi);
|
||||
ioapic_write(io, IOAPIC_REDTBL_LO(idx), lo);
|
||||
}
|
||||
|
||||
void ioapic_mask_gsi(uint32_t gsi) {
|
||||
ioapic_t *io = ioapic_for_gsi(gsi);
|
||||
if (!io) return;
|
||||
uint8_t idx = (uint8_t)(gsi - io->gsi_base);
|
||||
uint32_t lo = ioapic_read(io, IOAPIC_REDTBL_LO(idx));
|
||||
ioapic_write(io, IOAPIC_REDTBL_LO(idx), lo | IOAPIC_RTE_MASKED);
|
||||
}
|
||||
|
||||
void ioapic_unmask_gsi(uint32_t gsi) {
|
||||
ioapic_t *io = ioapic_for_gsi(gsi);
|
||||
if (!io) return;
|
||||
uint8_t idx = (uint8_t)(gsi - io->gsi_base);
|
||||
uint32_t lo = ioapic_read(io, IOAPIC_REDTBL_LO(idx));
|
||||
ioapic_write(io, IOAPIC_REDTBL_LO(idx), lo & ~IOAPIC_RTE_MASKED);
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
* Initialisation
|
||||
* ══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
void ioapic_init(void) {
|
||||
/*
|
||||
* ── Step 1: Find the MADT via uACPI ──────────────────────────────────
|
||||
*
|
||||
* The MADT signature in ACPI is "APIC" (not "MADT").
|
||||
* uacpi_table_find_by_signature returns a handle whose .ptr field points
|
||||
* to the raw table data in (HHDM-mapped) physical memory.
|
||||
*/
|
||||
struct uacpi_table madt_table;
|
||||
uacpi_status st = uacpi_table_find_by_signature("APIC", &madt_table);
|
||||
if (uacpi_unlikely_error(st)) {
|
||||
printf("[IOAPIC] Could not find MADT: %s\n", uacpi_status_to_string(st));
|
||||
return;
|
||||
}
|
||||
|
||||
madt_t *madt = (madt_t *)madt_table.ptr;
|
||||
printf("[IOAPIC] MADT @ virt 0x%lx len=%u lapic_addr=0x%08x\n",
|
||||
(uint64_t)madt, madt->length, madt->local_apic_addr);
|
||||
|
||||
/*
|
||||
* ── Step 2: Walk the MADT entry list ─────────────────────────────────
|
||||
*
|
||||
* Entries start immediately after the fixed 44-byte MADT header and run
|
||||
* until madt->length bytes from the table base.
|
||||
*/
|
||||
const uint8_t *entry_ptr = (const uint8_t *)madt + sizeof(madt_t);
|
||||
const uint8_t *madt_end = (const uint8_t *)madt + madt->length;
|
||||
|
||||
while (entry_ptr < madt_end) {
|
||||
const madt_entry_hdr_t *hdr = (const madt_entry_hdr_t *)entry_ptr;
|
||||
|
||||
if (hdr->length < 2) {
|
||||
printf("[IOAPIC] MADT entry with length < 2, stopping parse\n");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (hdr->type) {
|
||||
|
||||
/* ── Type 0: Processor Local APIC ──────────────────────────────── */
|
||||
case 0: {
|
||||
const madt_lapic_t *e = (const madt_lapic_t *)entry_ptr;
|
||||
printf("[IOAPIC] MADT[0] Processor UID=%u LAPIC ID=%u flags=0x%x%s\n",
|
||||
e->uid, e->apic_id, e->flags,
|
||||
(e->flags & 1) ? "" : " (disabled)");
|
||||
break;
|
||||
}
|
||||
|
||||
/* ── Type 1: I/O APIC ───────────────────────────────────────────── */
|
||||
case 1: {
|
||||
const madt_ioapic_t *e = (const madt_ioapic_t *)entry_ptr;
|
||||
if (g_ioapic_count >= IOAPIC_MAX) {
|
||||
printf("[IOAPIC] Too many IOAPICs, skipping ID=%u\n", e->id);
|
||||
break;
|
||||
}
|
||||
|
||||
ioapic_t *io = &g_ioapics[g_ioapic_count];
|
||||
io->gsi_base = e->gsi_base;
|
||||
|
||||
/*
|
||||
* Map the IOAPIC MMIO page. Like the LAPIC, the HHDM covers the
|
||||
* IOAPIC's physical address (typically 0xFEC00000) so we just add
|
||||
* MEM_PHYS_OFFSET. Two MMIO registers are accessed (offsets 0 and
|
||||
* 0x10) so one 4 KiB page is sufficient.
|
||||
*
|
||||
* TODO: Mark the page UC (cache-disable) in the PTE when VMM
|
||||
* gains support for PAT / PCD flags.
|
||||
*/
|
||||
uint64_t phys = (uint64_t)e->address;
|
||||
uintptr_t virt = (uintptr_t)phys + MEM_PHYS_OFFSET;
|
||||
/* The HHDM loop in vmm_init already covered this range; if not,
|
||||
* uncomment the explicit map call below: */
|
||||
/* vmm_map_page(kernel_pagemap, virt, phys,
|
||||
PAGE_READ | PAGE_WRITE | PAGE_NO_EXECUTE, Size4KiB); */
|
||||
io->base = (volatile uint32_t *)virt;
|
||||
|
||||
/* Read version register to discover number of redirection entries */
|
||||
uint32_t ver = ioapic_read(io, IOAPIC_REG_VER);
|
||||
io->gsi_count = ((ver >> 16) & 0xFF) + 1; /* bits [23:16] = max entry index */
|
||||
|
||||
printf("[IOAPIC] MADT[1] ID=%u phys=0x%08x GSI base=%u entries=%u\n",
|
||||
e->id, e->address, io->gsi_base, io->gsi_count);
|
||||
|
||||
/*
|
||||
* ── Mask every redirection entry ─────────────────────────────
|
||||
*
|
||||
* We keep all entries masked at boot time. Legacy ISA IRQs are
|
||||
* handled by the i8259 → LAPIC LINT0 ExtINT path, not via the
|
||||
* IOAPIC. PCI devices can be connected later with ioapic_redirect().
|
||||
*/
|
||||
for (uint32_t n = 0; n < io->gsi_count; n++) {
|
||||
ioapic_write(io, IOAPIC_REDTBL_HI(n), 0);
|
||||
ioapic_write(io, IOAPIC_REDTBL_LO(n), IOAPIC_RTE_MASKED | 0xFF);
|
||||
}
|
||||
|
||||
g_ioapic_count++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* ── Type 2: Interrupt Source Override ──────────────────────────── */
|
||||
case 2: {
|
||||
const madt_iso_t *e = (const madt_iso_t *)entry_ptr;
|
||||
|
||||
/* flags bits [1:0]: 00/11 = conforms to bus (ISA = active high edge)
|
||||
* 01 = active high, 11 = active low
|
||||
* flags bits [3:2]: 00/11 = conforms to bus (ISA = edge)
|
||||
* 01 = edge, 11 = level */
|
||||
bool active_low = ((e->flags & 0x3) == 3);
|
||||
bool level = ((e->flags >> 2) & 0x3) == 3;
|
||||
|
||||
printf("[IOAPIC] MADT[2] ISA IRQ %u -> GSI %u %s %s\n",
|
||||
e->source, e->gsi,
|
||||
active_low ? "active-low" : "active-high",
|
||||
level ? "level" : "edge");
|
||||
|
||||
if (e->source < 16) {
|
||||
g_iso[e->source].present = true;
|
||||
g_iso[e->source].gsi = e->gsi;
|
||||
g_iso[e->source].active_low = active_low;
|
||||
g_iso[e->source].level = level;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* ── Type 4: Local APIC NMI ─────────────────────────────────────── */
|
||||
case 4: {
|
||||
const madt_nmi_t *e = (const madt_nmi_t *)entry_ptr;
|
||||
printf("[IOAPIC] MADT[4] NMI UID=0x%02x LINT%u\n",
|
||||
e->uid, e->lint);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printf("[IOAPIC] MADT entry type=%u length=%u (skipped)\n",
|
||||
hdr->type, hdr->length);
|
||||
break;
|
||||
}
|
||||
|
||||
entry_ptr += hdr->length;
|
||||
}
|
||||
|
||||
uacpi_table_unref(&madt_table);
|
||||
|
||||
printf("[IOAPIC] Init done: %d IOAPIC(s) found\n", g_ioapic_count);
|
||||
}
|
||||
void irq_redirect_to_apic(uint8_t isa_irq, uint8_t vector,
|
||||
uint8_t dest_lapic, bool masked)
|
||||
{
|
||||
if (isa_irq >= 16) {
|
||||
printf("[IRQ] irq_redirect_to_apic: ISA IRQ %u out of range\n", isa_irq);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t gsi = ioapic_gsi_for_isa_irq(isa_irq);
|
||||
|
||||
/* Get polarity/trigger from MADT ISO or use ISA defaults */
|
||||
bool active_low = false;
|
||||
bool level = false;
|
||||
|
||||
if (isa_irq < 16 && g_iso[isa_irq].present) {
|
||||
active_low = g_iso[isa_irq].active_low;
|
||||
level = g_iso[isa_irq].level;
|
||||
} else {
|
||||
/* Standard ISA: active-high, edge-triggered (except some like IRQ0/8) */
|
||||
if (isa_irq == 0 || isa_irq == 8) {
|
||||
level = true; /* often level on real hardware */
|
||||
}
|
||||
}
|
||||
|
||||
/* Mask in the 8259 so it stops firing through LINT0 */
|
||||
if (g_Driver) {
|
||||
g_Driver->Mask(isa_irq);
|
||||
}
|
||||
|
||||
/* Programme IOAPIC redirection entry */
|
||||
ioapic_redirect(gsi, vector, dest_lapic,
|
||||
active_low, level, masked);
|
||||
|
||||
printf("[IRQ] Redirected ISA IRQ %u -> GSI %u vector 0x%02x LAPIC %u %s %s\n",
|
||||
isa_irq, gsi, vector, dest_lapic,
|
||||
active_low ? "active-low" : "active-high",
|
||||
level ? "level" : "edge");
|
||||
|
||||
g_IOAPIC = true;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* I/O APIC driver
|
||||
*
|
||||
* The IOAPIC is found by parsing the ACPI MADT table via uACPI.
|
||||
* All redirection entries are masked at init time; use ioapic_redirect() /
|
||||
* ioapic_unmask_irq() to enable individual GSIs for PCI devices later.
|
||||
*
|
||||
* Legacy ISA IRQs (0-15) are intentionally left masked here because they are
|
||||
* delivered through the i8259 → LAPIC LINT0 ExtINT path instead.
|
||||
*/
|
||||
|
||||
/* Maximum IOAPICs supported (1 is typical for QEMU/BOCHS) */
|
||||
#define IOAPIC_MAX 4
|
||||
|
||||
/* ── IOAPIC MMIO register indices (written to IOREGSEL) ─────────────────── */
|
||||
#define IOAPIC_REG_ID 0x00 /* APIC ID */
|
||||
#define IOAPIC_REG_VER 0x01 /* Version / max redirection entries */
|
||||
#define IOAPIC_REG_ARB 0x02 /* Arbitration ID */
|
||||
#define IOAPIC_REDTBL_LO(n) (0x10 + (n) * 2) /* Redirection entry n, low */
|
||||
#define IOAPIC_REDTBL_HI(n) (0x10 + (n) * 2 + 1) /* Redirection entry n, high */
|
||||
|
||||
/* ── Redirection table entry flags (low 32-bit word) ────────────────────── */
|
||||
#define IOAPIC_RTE_MASKED (1u << 16) /* 1 = masked (disabled) */
|
||||
#define IOAPIC_RTE_LEVEL (1u << 15) /* 1 = level-triggered, 0 = edge */
|
||||
#define IOAPIC_RTE_ACTIVE_LOW (1u << 13) /* 1 = active low, 0 = active high */
|
||||
#define IOAPIC_RTE_LOGICAL (1u << 11) /* 1 = logical destination mode */
|
||||
#define IOAPIC_RTE_DM_FIXED (0u << 8) /* Fixed delivery */
|
||||
#define IOAPIC_RTE_DM_NMI (4u << 8) /* NMI */
|
||||
/* bits [7:0] hold the IDT vector */
|
||||
|
||||
/* ── Public API ──────────────────────────────────────────────────────────── */
|
||||
|
||||
/**
|
||||
* ioapic_init - Parse the ACPI MADT, locate all I/O APICs and their GSI
|
||||
* bases, record any ISA interrupt source overrides, then mask
|
||||
* every redirection entry.
|
||||
*
|
||||
* Must be called after uacpi_initialize() (needs MADT accessible).
|
||||
*/
|
||||
void ioapic_init(void);
|
||||
|
||||
/**
|
||||
* ioapic_redirect - Programme a single redirection table entry.
|
||||
*
|
||||
* @gsi Global System Interrupt number (from MADT or known fixed GSI).
|
||||
* @vector IDT vector the CPU will see (e.g. 0x20 + irq_number).
|
||||
* @dest_lapic Physical LAPIC ID of the target CPU.
|
||||
* @active_low true if device uses active-low polarity.
|
||||
* @level true if device uses level-triggered signalling.
|
||||
* @masked true to programme the entry but leave it masked.
|
||||
*/
|
||||
void ioapic_redirect(uint32_t gsi, uint8_t vector, uint8_t dest_lapic,
|
||||
bool active_low, bool level, bool masked);
|
||||
|
||||
/**
|
||||
* ioapic_mask_gsi - Mask (disable) a GSI redirection entry.
|
||||
* ioapic_unmask_gsi - Unmask (enable) a GSI redirection entry.
|
||||
*/
|
||||
void ioapic_mask_gsi(uint32_t gsi);
|
||||
void ioapic_unmask_gsi(uint32_t gsi);
|
||||
|
||||
/**
|
||||
* ioapic_gsi_for_isa_irq - Look up the GSI that corresponds to an ISA IRQ
|
||||
* number, accounting for any MADT interrupt source
|
||||
* overrides (e.g. ISA IRQ 0 → GSI 2 on BOCHS).
|
||||
*
|
||||
* Returns the GSI, or the IRQ number itself if no override is defined.
|
||||
*/
|
||||
uint32_t ioapic_gsi_for_isa_irq(uint8_t isa_irq);
|
||||
|
||||
void irq_redirect_to_apic(uint8_t isa_irq, uint8_t vector, uint8_t dest_lapic, bool masked);
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
#include "irq.h"
|
||||
#include "i8259.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include <stddef.h>
|
||||
#include "libk/arrays.h"
|
||||
#include "libk/stdio.h"
|
||||
#include "libk/debug.h"
|
||||
#include "apic.h"
|
||||
#include "ioapic.h"
|
||||
|
||||
#define PIC_REMAP_OFFSET 0x20
|
||||
#define MODULE "PIC"
|
||||
|
||||
IRQHandler g_IRQHandlers[16];
|
||||
static IRQHandler g_APICHandlers[256];
|
||||
const PICDriver* g_Driver = NULL;
|
||||
|
||||
extern bool g_IOAPIC;
|
||||
|
||||
|
||||
|
||||
void x86_64_IRQ_Handler(Registers *regs)
|
||||
{
|
||||
int irq = regs->interrupt - PIC_REMAP_OFFSET;
|
||||
|
||||
g_Driver->SendEndOfInterrupt(irq);
|
||||
|
||||
if (g_IRQHandlers[irq] != NULL)
|
||||
{
|
||||
// handle IRQ
|
||||
g_IRQHandlers[irq](regs);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_warn(MODULE, "Unhandled IRQ %d...", irq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void x86_64_APIC_IRQ_Handler(Registers* regs)
|
||||
{
|
||||
uint8_t vector = regs->interrupt;
|
||||
lapic_eoi();
|
||||
|
||||
if (g_APICHandlers[vector] != NULL) {
|
||||
g_APICHandlers[vector](regs);
|
||||
} else {
|
||||
log_warn("APIC", "Unhandled vector 0x%02x", vector);
|
||||
}
|
||||
|
||||
// ← This is the key difference from PIC!
|
||||
}
|
||||
|
||||
|
||||
void x86_64_IRQ_Initialize(void)
|
||||
{
|
||||
const PICDriver* drivers[] = {
|
||||
i8259_GetDriver(),
|
||||
};
|
||||
|
||||
for (int i = 0; i < SIZE(drivers); i++) {
|
||||
if (drivers[i]->Probe()) {
|
||||
g_Driver = drivers[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (g_Driver == NULL) {
|
||||
log_warn(MODULE, "No PIC found!");
|
||||
return;
|
||||
}
|
||||
|
||||
log_info(MODULE, "Found %s PIC.", g_Driver->Name);
|
||||
g_Driver->Initialize(PIC_REMAP_OFFSET, PIC_REMAP_OFFSET + 8, false);
|
||||
|
||||
|
||||
// register ISR handlers for each of the 16 irq lines
|
||||
for (int i = 0; i < 16; i++)
|
||||
x86_64_ISR_RegisterHandler(PIC_REMAP_OFFSET + i, x86_64_IRQ_Handler);
|
||||
|
||||
g_Driver->Unmask(0);
|
||||
}
|
||||
|
||||
void x86_64_IRQ_RegisterHandler(int irq, IRQHandler handler)
|
||||
{
|
||||
g_IRQHandlers[irq] = handler;
|
||||
}
|
||||
|
||||
void x86_64_APIC_IRQ_RegisterHandler(uint8_t vector, IRQHandler handler)
|
||||
{
|
||||
if (vector < 32) {
|
||||
printf("[APIC] Warning: vector %u is in reserved range!\n", vector);
|
||||
}
|
||||
g_APICHandlers[vector] = handler;
|
||||
x86_64_ISR_RegisterHandler(vector, x86_64_APIC_IRQ_Handler);
|
||||
}
|
||||
|
||||
void x86_64_APIC_IRQ_RedirectAndRegister(uint8_t isa_irq,
|
||||
uint8_t vector,
|
||||
IRQHandler handler)
|
||||
{
|
||||
x86_64_APIC_IRQ_RegisterHandler(vector, handler);
|
||||
irq_redirect_to_apic(isa_irq, vector, lapic_id(), false);
|
||||
}
|
||||
|
||||
void x86_64_IRQ_Unmask(int irq)
|
||||
{
|
||||
if (g_Driver) g_Driver->Unmask(irq);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include "arch/x86_64/boot/isr.h"
|
||||
|
||||
|
||||
typedef void (*IRQHandler)(Registers* regs);
|
||||
|
||||
void x86_64_IRQ_Initialize();
|
||||
void x86_64_IRQ_RegisterHandler(int irq, IRQHandler handler);
|
||||
void x86_64_IRQ_Unmask(int irq);
|
||||
void x86_64_APIC_IRQ_RegisterHandler(uint8_t vector, IRQHandler handler);
|
||||
void x86_64_APIC_IRQ_RedirectAndRegister(uint8_t isa_irq,
|
||||
uint8_t vector,
|
||||
IRQHandler handler);
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "pic.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include <stdbool.h>
|
||||
#include "arch/x86_64/fw/madt.h"
|
||||
|
||||
static void pic_disable(void) {
|
||||
x86_64_outb(0xA1, 0xFF);
|
||||
x86_64_outb(0x21, 0xFF);
|
||||
}
|
||||
|
||||
void pic_init(void) {
|
||||
// There isn't any PIC
|
||||
if (!(madt->flags & 1)) {
|
||||
return;
|
||||
}
|
||||
// Remap the PIC
|
||||
x86_64_outb(0x20, 0x11);
|
||||
x86_64_outb(0xA0, 0x11);
|
||||
x86_64_outb(0x21, 0x20);
|
||||
x86_64_outb(0xA1, 0x28);
|
||||
x86_64_outb(0x21, 4);
|
||||
x86_64_outb(0xA1, 2);
|
||||
x86_64_outb(0x21, 1);
|
||||
x86_64_outb(0xA1, 1);
|
||||
x86_64_outb(0x21, 0);
|
||||
x86_64_outb(0xA1, 0);
|
||||
|
||||
pic_disable();
|
||||
}
|
||||
@@ -1,14 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
const char* Name;
|
||||
bool (*Probe)();
|
||||
void (*Initialize)(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi);
|
||||
void (*Disable)();
|
||||
void (*SendEndOfInterrupt)(int irq);
|
||||
void (*Mask)(int irq);
|
||||
void (*Unmask)(int irq);
|
||||
} PICDriver;
|
||||
void pic_init(void);
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "pit.h"
|
||||
#include "irq.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include <stdint.h>
|
||||
#include "libk/stdio.h"
|
||||
#include "e9.h"
|
||||
#include "limine.h"
|
||||
#include "apic.h"
|
||||
#include "sched/scheduler.h"
|
||||
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
volatile struct limine_date_at_boot_request boot_request = {
|
||||
.id = LIMINE_DATE_AT_BOOT_REQUEST_ID,
|
||||
.revision = 6,
|
||||
};
|
||||
|
||||
#define PIT_BASE_FREQUENCY 1193182
|
||||
|
||||
#define PIT_COMMAND_PORT 0x43
|
||||
#define PIT_CHANNEL0_PORT 0x40
|
||||
|
||||
volatile uint64_t g_Ticks = 0;
|
||||
volatile uint64_t ticks = 0;
|
||||
uint64_t g_Unixseconds = 0;
|
||||
extern bool g_IOAPIC;
|
||||
/* ========================= */
|
||||
/* IRQ0 Handler (Timer Tick) */
|
||||
/* ========================= */
|
||||
void PIT_IRQ_Handler(Registers* regs)
|
||||
{
|
||||
(void)regs;
|
||||
g_Ticks++;
|
||||
ticks++;
|
||||
if (ticks >= 1000) {
|
||||
g_Unixseconds++;
|
||||
ticks = 0;
|
||||
}
|
||||
|
||||
if (g_IOAPIC == true) {
|
||||
lapic_eoi();
|
||||
}
|
||||
|
||||
sched_tick();
|
||||
}
|
||||
|
||||
/* ========================= */
|
||||
/* Initialize PIT */
|
||||
/* ========================= */
|
||||
void x86_64_PIT_Initialize(uint32_t frequency)
|
||||
{
|
||||
uint16_t divisor = (uint16_t)(PIT_BASE_FREQUENCY / frequency);
|
||||
|
||||
printf("PIT divisor = %u\n", divisor);
|
||||
// Send command byte:
|
||||
// Channel 0 | lobyte/hibyte | mode 3 (square wave) | binary
|
||||
x86_64_outb(PIT_COMMAND_PORT, 0x36);
|
||||
|
||||
// Send divisor (low byte then high byte)
|
||||
x86_64_outb(PIT_CHANNEL0_PORT, divisor & 0xFF);
|
||||
x86_64_outb(PIT_CHANNEL0_PORT, (divisor >> 8) & 0xFF);
|
||||
|
||||
g_Unixseconds = boot_request.response->timestamp;
|
||||
|
||||
// Register IRQ0 handler (IRQ0 = timer)
|
||||
x86_64_IRQ_RegisterHandler(0, PIT_IRQ_Handler);
|
||||
}
|
||||
|
||||
/* ========================= */
|
||||
/* Get tick count */
|
||||
/* ========================= */
|
||||
uint64_t PIT_GetTicks(void)
|
||||
{
|
||||
return g_Ticks;
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "irq.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include "libk/stdio.h"
|
||||
#include "e9.h"
|
||||
|
||||
extern volatile uint64_t g_Ticks;
|
||||
extern uint64_t g_Unixseconds;
|
||||
#define PIT_DIVIDEND ((uint64_t)1193182)
|
||||
|
||||
void x86_64_PIT_Initialize(uint32_t frequency);
|
||||
uint64_t PIT_GetTicks(void);
|
||||
void PIT_IRQ_Handler(Registers* regs);
|
||||
uint16_t pit_counter_value(void);
|
||||
void pit_set_reload_value(uint16_t new_count);
|
||||
void pit_set_frequency(uint64_t frequency);
|
||||
void pit_init();
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "arch/x86_64/boot/gdt.h"
|
||||
|
||||
struct prcb {
|
||||
uint64_t cpu_number;
|
||||
uint64_t kernel_stack;
|
||||
uint64_t user_stack;
|
||||
struct thread *running_thread;
|
||||
uint64_t sched_ticks;
|
||||
struct tss cpu_tss;
|
||||
uint32_t lapic_id;
|
||||
size_t fpu_storage_size;
|
||||
void (*fpu_save)(void *);
|
||||
void (*fpu_restore)(void *);
|
||||
uint32_t tick_in_10ms;
|
||||
};
|
||||
|
||||
extern struct prcb *prcbs;
|
||||
|
||||
struct prcb *prcb_return_current_cpu(void);
|
||||
size_t prcb_return_installed_cpus(void);
|
||||
@@ -0,0 +1,127 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "pit.h"
|
||||
#include <limine.h>
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include "libk/time.h"
|
||||
#include "arch/x86_64/asm/asm.h"
|
||||
#include "mm/vmm.h"
|
||||
#include "hpet.h"
|
||||
#include "arch/x86_64/bus/mmio.h"
|
||||
#include "libk/debug.h"
|
||||
|
||||
static struct hpet_table *hpet_table = NULL;
|
||||
static struct hpet *hpet = NULL;
|
||||
static uint32_t clk = 0;
|
||||
static bool timer_installed_b = false;
|
||||
extern uint32_t smp_bsp_lapic_id;
|
||||
|
||||
|
||||
|
||||
static volatile struct limine_boot_time_request boot_time_request = {
|
||||
.id = LIMINE_BOOT_TIME_REQUEST, .revision = 0};
|
||||
|
||||
|
||||
bool hpet_init(void) {
|
||||
hpet_table = acpi_find_sdt("HPET");
|
||||
if (!hpet_table) {
|
||||
kprintf("HPET: No HPET found!\n");
|
||||
return false;
|
||||
}
|
||||
hpet = (struct hpet *)(hpet_table->address.base + MEM_PHYS_OFFSET);
|
||||
|
||||
kprintf("HPET: HPET at %p\n", (void *)hpet);
|
||||
|
||||
clk = hpet->general_capabilities >> 32;
|
||||
|
||||
/*
|
||||
* General Configuration Register
|
||||
* 0 - main counter is halted, timer interrupts are disabled
|
||||
* 1 - main counter is running, timer interrupts are allowed if enabled
|
||||
*/
|
||||
mmoutq(&hpet->general_configuration, 0);
|
||||
mmoutq(&hpet->main_counter_value, 0);
|
||||
mmoutq(&hpet->general_configuration, 1);
|
||||
timer_installed_b = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t hpet_counter_value(void) {
|
||||
return mminq(&hpet->main_counter_value);
|
||||
}
|
||||
|
||||
void hpet_sleep(uint64_t us) {
|
||||
uint64_t target = hpet_counter_value() + (us * 1000000000) / clk;
|
||||
while (hpet_counter_value() < target)
|
||||
pause();
|
||||
}
|
||||
|
||||
void pit_set_frequency(uint64_t frequency) {
|
||||
uint64_t new_divisor = PIT_DIVIDEND / frequency;
|
||||
if (PIT_DIVIDEND % frequency > frequency / 2) {
|
||||
new_divisor++;
|
||||
}
|
||||
pit_set_reload_value((uint16_t)new_divisor);
|
||||
}
|
||||
|
||||
void pit_set_reload_value(uint16_t new_count) {
|
||||
x86_64_outb(0x43, 0x34);
|
||||
x86_64_outb(0x40, (uint8_t)new_count);
|
||||
x86_64_outb(0x40, (uint8_t)(new_count >> 8));
|
||||
}
|
||||
|
||||
void pit_init(void) {
|
||||
timer_installed_b = true;
|
||||
pit_set_reload_value(0xffff);
|
||||
pit_set_frequency(TIMER_FREQ);
|
||||
}
|
||||
|
||||
|
||||
uint16_t pit_counter_value(void) {
|
||||
x86_64_outb(0x43, 0x00);
|
||||
uint8_t lo = x86_64_inb(0x40);
|
||||
uint8_t hi = x86_64_inb(0x40);
|
||||
return ((uint16_t)hi << 8) | lo;
|
||||
}
|
||||
|
||||
|
||||
void pit_sleep(uint64_t ms) {
|
||||
uint64_t target = pit_counter_value() + ms;
|
||||
while (pit_counter_value() < target)
|
||||
pause();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void timer_init(void) {
|
||||
struct limine_boot_time_response *boot_time_resp =
|
||||
boot_time_request.response;
|
||||
|
||||
time_realtime.tv_sec = boot_time_resp->boot_time;
|
||||
|
||||
if (hpet_init()) {
|
||||
return;
|
||||
}
|
||||
pit_init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool timer_installed(void) {
|
||||
return timer_installed_b;
|
||||
}
|
||||
|
||||
void timer_sleep(uint64_t ms) {
|
||||
if (hpet_table) {
|
||||
return hpet_sleep(ms * 1000);
|
||||
}
|
||||
pit_sleep(ms);
|
||||
}
|
||||
|
||||
uint64_t timer_count(void) {
|
||||
if (hpet_table) {
|
||||
return (hpet_counter_value() * clk) / (1000000000000);
|
||||
}
|
||||
return pit_counter_value();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
bool timer_installed(void);
|
||||
void timer_init(void);
|
||||
void timer_sleep(uint64_t ms);
|
||||
uint64_t timer_count(void);
|
||||
void timer_stop_sched(void);
|
||||
void timer_sched_oneshot(uint8_t isr, uint32_t us);
|
||||
+31
-22
@@ -1,49 +1,58 @@
|
||||
#include <stdint.h>
|
||||
#include "arch/x86_64/sys/pit.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include "libk/stdio.h"
|
||||
#include "tsc.h"
|
||||
|
||||
extern uint64_t PIT_GetTicks(void);
|
||||
#include "libk/debug.h"
|
||||
#include "arch/x86_64/asm/asm.h"
|
||||
#include "libk/time.h"
|
||||
|
||||
volatile uint64_t tsc_cycles_per_us = 0;
|
||||
|
||||
uint64_t rdtsc(void)
|
||||
inline uint64_t rdtsc(void)
|
||||
{
|
||||
uint32_t lo, hi;
|
||||
|
||||
__asm__ volatile ("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
|
||||
return ((uint64_t)hi << 32) | lo;
|
||||
}
|
||||
|
||||
|
||||
void calibrate_tsc(void)
|
||||
{
|
||||
// Use a stable PIT rate for calibration
|
||||
const uint32_t pit_freq = 1000; // 1000 Hz = 1ms per tick
|
||||
const uint32_t calibration_ticks = 1000; // 1 second total
|
||||
// We measure over one full PIT cycle (~54.9 ms at max reload)
|
||||
const uint16_t pit_start = 0xFFFF;
|
||||
|
||||
pit_set_reload_value(pit_start);
|
||||
|
||||
|
||||
// Wait for PIT to stabilize
|
||||
uint64_t start_ticks = PIT_GetTicks();
|
||||
while (PIT_GetTicks() == start_ticks)
|
||||
;
|
||||
|
||||
// latch initial state
|
||||
uint64_t start_tsc = rdtsc();
|
||||
uint64_t target_ticks = start_ticks + calibration_ticks;
|
||||
uint16_t start = pit_counter_value();
|
||||
|
||||
// Wait for known number of PIT ticks
|
||||
while (PIT_GetTicks() < target_ticks)
|
||||
;
|
||||
uint16_t current;
|
||||
|
||||
// wait for wrap-around (start > current)
|
||||
do {
|
||||
current = pit_counter_value();
|
||||
pause();
|
||||
} while (current <= start);
|
||||
|
||||
uint64_t end_tsc = rdtsc();
|
||||
|
||||
// Compute elapsed time
|
||||
uint64_t tsc_delta = end_tsc - start_tsc;
|
||||
uint16_t ticks = (start - current);
|
||||
|
||||
uint64_t elapsed_us = 1000000ULL;
|
||||
// PIT frequency = 1193182 Hz
|
||||
// so each tick = 1 / 1193182 seconds
|
||||
// convert PIT ticks -> microseconds:
|
||||
|
||||
uint64_t elapsed_us =
|
||||
(ticks * 1000000ULL) / PIT_DIVIDEND;
|
||||
|
||||
uint64_t tsc_delta = end_tsc - start_tsc;
|
||||
|
||||
tsc_cycles_per_us = tsc_delta / elapsed_us;
|
||||
|
||||
printf("TSC calibration complete: %lu cycles/us\n", tsc_cycles_per_us);
|
||||
kprintf("TSC calibrated: %lu cycles/us\n", tsc_cycles_per_us);
|
||||
|
||||
// restore PIT frequency for system timer
|
||||
pit_set_frequency(TIMER_FREQ);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <stdint.h>
|
||||
#include "arch/x86_64/sys/pit.h"
|
||||
#include "arch/x86_64/cpu/io.h"
|
||||
#include "libk/stdio.h"
|
||||
uint64_t rdtsc(void);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user