From 1a2486caddce6d7f6ce149f3e9deff2d25c1698e Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 7 Aug 2022 12:50:17 -0300 Subject: [PATCH] scheduler timer abstraction of a timer that is local to each cpu and is used for scheduling --- src/arch/x86_64/apic.c | 39 +++++++++++++++++++++-- src/arch/x86_64/idt.c | 3 ++ src/arch/x86_64/include/arch/apic.h | 6 ++++ src/arch/x86_64/include/arch/cls.h | 1 + src/arch/x86_64/include/arch/cpuid.h | 13 ++++++++ src/arch/x86_64/include/arch/isr.h | 1 + src/arch/x86_64/include/arch/schedtimer.h | 12 +++++++ src/arch/x86_64/isr.asm | 7 ++-- src/arch/x86_64/isr.c | 4 +++ src/arch/x86_64/main.c | 2 ++ src/arch/x86_64/schedtimer.c | 23 +++++++++++++ src/arch/x86_64/smp.c | 7 ++-- 12 files changed, 107 insertions(+), 11 deletions(-) create mode 100644 src/arch/x86_64/include/arch/cpuid.h create mode 100644 src/arch/x86_64/include/arch/schedtimer.h create mode 100644 src/arch/x86_64/schedtimer.c diff --git a/src/arch/x86_64/apic.c b/src/arch/x86_64/apic.c index d591d830..83dbbade 100644 --- a/src/arch/x86_64/apic.c +++ b/src/arch/x86_64/apic.c @@ -9,7 +9,10 @@ #define APIC_REGISTER_ID 0x20 #define APIC_REGISTER_EOI 0xB0 #define APIC_REGISTER_SPURIOUS 0xF0 - +#define APIC_TIMER_LVT 0x320 +#define APIC_TIMER_INITIALCOUNT 0x380 +#define APIC_TIMER_COUNT 0x390 +#define APIC_TIMER_DIVIDE 0x3E0 #define TYPE_LAPIC 0 #define TYPE_IOAPIC 1 @@ -148,11 +151,38 @@ static void ioapic_writeiored(ioapic_descriptor* ioapic, uint8_t irq, uint8_t ve } static inline uint32_t lapic_readreg(size_t reg){ - return *(uint32_t* volatile)(lapicaddr + reg); + return *(uint32_t volatile*)(lapicaddr + reg); } static inline void lapic_writereg(size_t reg, uint32_t data){ - *(uint32_t* volatile)(lapicaddr + reg) = data; + *(uint32_t volatile*)(lapicaddr + reg) = data; +} + +void apic_timerstart(size_t ticks){ + lapic_writereg(APIC_TIMER_INITIALCOUNT, ticks); +} + +void apic_timerinterruptset(uint8_t vector){ + lapic_writereg(APIC_TIMER_LVT, vector); +} + +void apic_timerstop(){ + lapic_writereg(APIC_TIMER_INITIALCOUNT, 0); +} + +size_t apic_timercalibrate(size_t ms){ + + lapic_writereg(APIC_TIMER_INITIALCOUNT, 0xFFFFFFFF); + lapic_writereg(APIC_TIMER_DIVIDE, 0b111); // no divider + + hpet_wait_ms(ms); + + size_t ticks = 0xFFFFFFFF - lapic_readreg(APIC_TIMER_COUNT); + + apic_timerstop(); + + return ticks; + } void apic_lapicinit(){ @@ -161,7 +191,10 @@ void apic_lapicinit(){ arch_getcls()->lapicid >>= 24; lapic_writereg(APIC_REGISTER_SPURIOUS, 0x1FF); + lapic_writereg(APIC_TIMER_LVT, 1 << 16); // mask timer interrupt off + + } void apic_init(){ diff --git a/src/arch/x86_64/idt.c b/src/arch/x86_64/idt.c index d3ca382c..9ca48d7d 100644 --- a/src/arch/x86_64/idt.c +++ b/src/arch/x86_64/idt.c @@ -2,6 +2,7 @@ #include #include #include +#include idtentry_t idt[256]; @@ -35,6 +36,8 @@ void idt_bspinit(){ } idt_setentry(&idt[VECTOR_PF], asmisr_pagefault, 0x28, FLAGS_PRESENT | FLAGS_TYPE_TRAP, 0); + + idt_setentry(&idt[SCHEDTIMER_VECTOR], asmisr_schedtimer, 0x28, FLAGS_PRESENT | FLAGS_TYPE_INTERRUPT, 0); idt_reload(); diff --git a/src/arch/x86_64/include/arch/apic.h b/src/arch/x86_64/include/arch/apic.h index 4319cda0..4cafb38f 100644 --- a/src/arch/x86_64/include/arch/apic.h +++ b/src/arch/x86_64/include/arch/apic.h @@ -1,7 +1,13 @@ #ifndef _APIC_H_INCLUDE #define _APIC_H_INCLUDE +#include +#include +void apic_timerstop(); +void apic_timerstart(size_t ticks); +void apic_timerinterruptset(uint8_t vector); +size_t apic_timercalibrate(size_t ms); void apic_lapicinit(); void apic_init(); diff --git a/src/arch/x86_64/include/arch/cls.h b/src/arch/x86_64/include/arch/cls.h index 0097ab54..3ad078e6 100644 --- a/src/arch/x86_64/include/arch/cls.h +++ b/src/arch/x86_64/include/arch/cls.h @@ -16,6 +16,7 @@ typedef struct{ int lapicid; arch_regs *laststate; vmm_context *context; + size_t schedtimerticksperms; } cls_t; void bsp_setcls(); diff --git a/src/arch/x86_64/include/arch/cpuid.h b/src/arch/x86_64/include/arch/cpuid.h new file mode 100644 index 00000000..5482ae7a --- /dev/null +++ b/src/arch/x86_64/include/arch/cpuid.h @@ -0,0 +1,13 @@ +#ifndef _CPUID_H_INCLUDE +#define _CPUID_H_INCLUDE + +#include +#include + +static inline uint64_t cpuid(){ + uint32_t eax, unused, edx; + __get_cpuid(1, &eax, &unused, &unused, &edx); + return ((uint64_t)edx << 32) + eax; +} + +#endif diff --git a/src/arch/x86_64/include/arch/isr.h b/src/arch/x86_64/include/arch/isr.h index 3f478b45..235a31d6 100644 --- a/src/arch/x86_64/include/arch/isr.h +++ b/src/arch/x86_64/include/arch/isr.h @@ -3,6 +3,7 @@ #include +extern void asmisr_schedtimer(arch_regs*); extern void asmisr_general(arch_regs*); extern void asmisr_except(arch_regs*); extern void asmisr_pagefault(arch_regs*); diff --git a/src/arch/x86_64/include/arch/schedtimer.h b/src/arch/x86_64/include/arch/schedtimer.h new file mode 100644 index 00000000..3685d71d --- /dev/null +++ b/src/arch/x86_64/include/arch/schedtimer.h @@ -0,0 +1,12 @@ +#ifndef _SCHEDTIMER_H_INCLUDE +#define _SCHEDTIMER_H_INCLUDE + +#include + +#define SCHEDTIMER_VECTOR 0x50 + +void arch_schedtimer_run(size_t ms); +void arch_schedtimer_stop(); +void arch_schedtimer_calibrate(); + +#endif diff --git a/src/arch/x86_64/isr.asm b/src/arch/x86_64/isr.asm index 29c4741e..4d3af8e2 100644 --- a/src/arch/x86_64/isr.asm +++ b/src/arch/x86_64/isr.asm @@ -126,6 +126,7 @@ section .text iretq %endmacro -except asmisr_pagefault, isr_pagefault -isr asmisr_general, isr_general -except asmisr_except, isr_except +except asmisr_pagefault, isr_pagefault +isr asmisr_general, isr_general +except asmisr_except, isr_except +isr asmisr_schedtimer, isr_schedtimer diff --git a/src/arch/x86_64/isr.c b/src/arch/x86_64/isr.c index 33fd7f6b..41c83bc4 100644 --- a/src/arch/x86_64/isr.c +++ b/src/arch/x86_64/isr.c @@ -2,6 +2,10 @@ #include #include +void isr_schedtimer(arch_regs *reg){ + printf("schedtimer irq\n"); +} + void isr_general(arch_regs *reg){ _panic("Unhandled interrupt", reg); asm("hlt"); diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index 7f69d928..243e19f5 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -72,6 +72,8 @@ void kmain(){ pci_enumerate(); hpet_init(); + + arch_schedtimer_calibrate(); smp_init(); diff --git a/src/arch/x86_64/schedtimer.c b/src/arch/x86_64/schedtimer.c new file mode 100644 index 00000000..575266cb --- /dev/null +++ b/src/arch/x86_64/schedtimer.c @@ -0,0 +1,23 @@ +#include +#include +#include + +void arch_schedtimer_waitms(size_t ms){ + + apic_timerstart(cls->schedtimerticksperms * ms); + +} + +void arch_schedtimer_stop(){ + + apic_timerstop(); + +} + +void arch_schedtimer_calibrate(){ + + cls->schedtimerticksperms = apic_timercalibrate(1); + + apic_timerinterruptset(SCHEDTIMER_VECTOR); + +} diff --git a/src/arch/x86_64/smp.c b/src/arch/x86_64/smp.c index 6427411a..63c99cf2 100644 --- a/src/arch/x86_64/smp.c +++ b/src/arch/x86_64/smp.c @@ -18,8 +18,6 @@ static size_t cpucount = 1; static void apstartup(struct limine_smp_info *info){ - spinlock_acquire(&lock); - arch_setcls(&apcls[info->processor_id]); gdt_init(); @@ -29,12 +27,11 @@ static void apstartup(struct limine_smp_info *info){ arch_mmu_apinit(); apic_lapicinit(); + + arch_schedtimer_calibrate(); printf("CPU %lu ready!\n", info->lapic_id); - spinlock_release(&lock); - - asm("cli;hlt");