From ac5339453ba777eb5d396b61a1f306b2d24a8f6d Mon Sep 17 00:00:00 2001 From: Matheus Date: Fri, 12 Aug 2022 22:11:59 -0300 Subject: [PATCH] per cpu timer queue --- src/arch/x86_64/apic.c | 15 +++-- src/arch/x86_64/cputimer.c | 22 ++++++ src/arch/x86_64/gdt.c | 8 +-- src/arch/x86_64/include/arch/apic.h | 4 +- src/arch/x86_64/include/arch/cls.h | 4 +- src/arch/x86_64/include/arch/cputimer.h | 10 +++ src/arch/x86_64/isr.c | 2 + src/arch/x86_64/main.c | 7 +- src/arch/x86_64/smp.c | 4 ++ src/include/kernel/timer.h | 22 ++++++ src/sys/timer.c | 89 +++++++++++++++++++++++++ 11 files changed, 174 insertions(+), 13 deletions(-) create mode 100644 src/arch/x86_64/cputimer.c create mode 100644 src/arch/x86_64/include/arch/cputimer.h create mode 100644 src/include/kernel/timer.h create mode 100644 src/sys/timer.c diff --git a/src/arch/x86_64/apic.c b/src/arch/x86_64/apic.c index 107b2b0f..b3166126 100644 --- a/src/arch/x86_64/apic.c +++ b/src/arch/x86_64/apic.c @@ -190,22 +190,27 @@ void apic_timerinterruptset(uint8_t vector){ lapic_writereg(APIC_TIMER_LVT, vector); } -void apic_timerstop(){ +size_t apic_timerstop(){ + + size_t ticksremaining = lapic_readreg(APIC_TIMER_COUNT); + lapic_writereg(APIC_TIMER_INITIALCOUNT, 0); + + return ticksremaining; } -size_t apic_timercalibrate(size_t ms){ - +size_t apic_timercalibrate(size_t us){ + lapic_writereg(APIC_TIMER_INITIALCOUNT, 0xFFFFFFFF); lapic_writereg(APIC_TIMER_DIVIDE, 0b111); // no divider - hpet_wait_ms(ms); + hpet_wait_ms(us); size_t ticks = 0xFFFFFFFF - lapic_readreg(APIC_TIMER_COUNT); apic_timerstop(); - return ticks; + return ticks / 1000; } diff --git a/src/arch/x86_64/cputimer.c b/src/arch/x86_64/cputimer.c new file mode 100644 index 00000000..c8b038a3 --- /dev/null +++ b/src/arch/x86_64/cputimer.c @@ -0,0 +1,22 @@ +#include +#include +#include + +size_t arch_cputimer_init(){ + // XXX invariant TSC? + + size_t ticks = apic_timercalibrate(1); + + apic_timerinterruptset(VECTOR_TIMER); + + return ticks; + +} + +size_t arch_cputimer_stop(){ + return apic_timerstop(); +} + +void arch_cputimer_fire(size_t ticks){ + apic_timerstart(ticks); +} diff --git a/src/arch/x86_64/gdt.c b/src/arch/x86_64/gdt.c index 18f01019..16d44103 100644 --- a/src/arch/x86_64/gdt.c +++ b/src/arch/x86_64/gdt.c @@ -2,7 +2,7 @@ #include #include -static void setseg(segdesc __seg_gs *seg, uint32_t limit, uint32_t offset, uint8_t flags, uint8_t access){ +static void setseg(segdesc *seg, uint32_t limit, uint32_t offset, uint8_t flags, uint8_t access){ seg->limit = limit & 0xFFFF; seg->offset1 = offset & 0xFFFF; @@ -14,7 +14,7 @@ static void setseg(segdesc __seg_gs *seg, uint32_t limit, uint32_t offset, uint8 } -static void setsys64(sys64 __seg_gs *e, uint32_t limit, uint64_t offset, uint8_t flags, uint8_t access){ +static void setsys64(sys64 *e, uint32_t limit, uint64_t offset, uint8_t flags, uint8_t access){ e->limit = limit & 0xFFFF; e->offset1 = offset & 0xFFFF; @@ -32,14 +32,14 @@ gdtr_t gdtr; static void reloadgdtr(){ -gdtr.offset = (uint64_t)&cls->gdt + arch_getcls(); +gdtr.offset = &arch_getcls()->gdt; gdtr.size = sizeof(gdt_t) - 1; asm("lgdt (%%rax)" : : "a"(&gdtr) : "memory"); } void gdt_init(){ - gdt_t __seg_gs *gdt = &cls->gdt; + gdt_t* gdt = &arch_getcls()->gdt; setseg(&gdt->null, 0, 0, 0, 0); diff --git a/src/arch/x86_64/include/arch/apic.h b/src/arch/x86_64/include/arch/apic.h index 82b81c44..e75b0d36 100644 --- a/src/arch/x86_64/include/arch/apic.h +++ b/src/arch/x86_64/include/arch/apic.h @@ -6,10 +6,10 @@ void apic_sendipi(uint8_t cpu, uint8_t vec, uint8_t dest, uint8_t mode, uint8_t level); void apic_eoi(); -void apic_timerstop(); +size_t apic_timerstop(); void apic_timerstart(size_t ticks); void apic_timerinterruptset(uint8_t vector); -size_t apic_timercalibrate(size_t ms); +size_t apic_timercalibrate(size_t us); 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 a3253674..59b1f63d 100644 --- a/src/arch/x86_64/include/arch/cls.h +++ b/src/arch/x86_64/include/arch/cls.h @@ -7,6 +7,7 @@ #include #include #include +#include // cpu level storage // this will be pointed to by GS and will contain per cpu info @@ -19,7 +20,8 @@ typedef struct{ arch_regs *laststate; vmm_context *context; thread_t* thread; - size_t schedtimerticksperms; + size_t timerticksperus; + timer_req* timerfirstreq; } cls_t; void bsp_setcls(); diff --git a/src/arch/x86_64/include/arch/cputimer.h b/src/arch/x86_64/include/arch/cputimer.h new file mode 100644 index 00000000..6c2ad066 --- /dev/null +++ b/src/arch/x86_64/include/arch/cputimer.h @@ -0,0 +1,10 @@ +#ifndef _CPUTIMER_H_INCLUDE +#define _CPUTIMER_H_INCLUDE + +#include + +size_t arch_cputimer_init(); +size_t arch_cputimer_stop(); +void arch_cputimer_fire(size_t ticks); + +#endif diff --git a/src/arch/x86_64/isr.c b/src/arch/x86_64/isr.c index 63daeb90..db9cbe26 100644 --- a/src/arch/x86_64/isr.c +++ b/src/arch/x86_64/isr.c @@ -2,6 +2,7 @@ #include #include #include +#include void isr_general(arch_regs *reg){ _panic("Unhandled interrupt", reg); @@ -30,5 +31,6 @@ void isr_mmuinval(){ } void isr_timer(arch_regs* reg){ + timer_irq(reg); apic_eoi(); } diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index eed8f6d4..9739695c 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -16,6 +16,7 @@ #include #include #include +#include static volatile struct limine_terminal_request liminettyr = { .id = LIMINE_TERMINAL_REQUEST, @@ -42,7 +43,9 @@ void kmain(){ console_setwritehook(liminewrite); bsp_setcls(); + gdt_init(); + idt_bspinit(); pmm_init(); @@ -62,6 +65,8 @@ void kmain(){ hpet_init(); + timer_init(); + vfs_init(); printf("Mounting tmpfs in /\n"); @@ -76,7 +81,7 @@ void kmain(){ pci_enumerate(); smp_init(); - + _panic("End of kmain()", 0); } diff --git a/src/arch/x86_64/smp.c b/src/arch/x86_64/smp.c index 62468f58..a6529029 100644 --- a/src/arch/x86_64/smp.c +++ b/src/arch/x86_64/smp.c @@ -28,6 +28,8 @@ static void apstartup(struct limine_smp_info *info){ arch_mmu_apinit(); apic_lapicinit(); + + timer_init(); printf("CPU %lu ready!\n", info->lapic_id); @@ -62,6 +64,8 @@ void smp_init(){ apcls = pmm_hhdmalloc(sizeof(cls_t)*cpucount/PAGE_SIZE+1); + memset(apcls, 0, sizeof(cls_t)*cpucount/PAGE_SIZE+1); + printf("System has %lu CPUs\n", cpucount); sem = sem_init(-cpucount + 2, 0); diff --git a/src/include/kernel/timer.h b/src/include/kernel/timer.h new file mode 100644 index 00000000..0eb2f4c1 --- /dev/null +++ b/src/include/kernel/timer.h @@ -0,0 +1,22 @@ +#ifndef _TIMER_H_INCLUDE +#define _TIMER_H_INCLUDE + +#include +#include + +typedef struct _timer_req{ + // values callee should care about + void* (*func)(arch_regs*, void*); + void* argptr; + // internal values + struct _timer_req* next; + size_t ticks; +} timer_req; + +void timer_init(); +void timer_add(timer_req* req, size_t us); +void timer_resume(); +void timer_stop(); +void timer_irq(arch_regs* ctx); + +#endif diff --git a/src/sys/timer.c b/src/sys/timer.c new file mode 100644 index 00000000..67198c90 --- /dev/null +++ b/src/sys/timer.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +void timer_init(){ + cls_t* cls = arch_getcls(); + cls->timerticksperus = arch_cputimer_init(); + printf("CPU%d: CPUTIMER tick: %lu per us\n", cls->lapicid, cls->timerticksperus); +} + +void timer_irq(arch_regs* ctx){ + timer_req* pendingreq = arch_getcls()->timerfirstreq; + timer_req* iter = pendingreq->next; + + arch_getcls()->timerfirstreq = iter; + + while(iter){ + iter->ticks -= pendingreq->ticks; + iter = iter->next; + } + + pendingreq->func(ctx, pendingreq->argptr); + + if(!arch_getcls()->timerfirstreq) return; + + arch_cputimer_fire(arch_getcls()->timerfirstreq->ticks); + +} + +void timer_resume(){ + arch_cputimer_fire(arch_getcls()->timerfirstreq->ticks); +} + +void timer_stop(){ + + size_t remainingticks = arch_cputimer_stop(); + timer_req* iter = arch_getcls()->timerfirstreq; + size_t subticks = iter->ticks - remainingticks; + while(iter){ + iter->ticks -= subticks; + iter = iter->next; + } +} + +void timer_add(timer_req* req, size_t us){ + + size_t remainingticks = arch_cputimer_stop(); + + timer_req* iter = arch_getcls()->timerfirstreq; + + + req->ticks = us*arch_getcls()->timerticksperus; + + if(!iter){ + arch_getcls()->timerfirstreq = req; + req->next = NULL; + arch_cputimer_fire(req->ticks); + printf("ticks3: %lu", req->ticks); + return; + } + + size_t subticks = iter->ticks - remainingticks; + + while(iter){ + iter->ticks -= subticks; + iter = iter->next; + } + + iter = arch_getcls()->timerfirstreq; + + if(iter->ticks > req->ticks){ + req->next = arch_getcls()->timerfirstreq; + arch_getcls()->timerfirstreq = req; + arch_cputimer_fire(req->ticks); + printf("ticks2: %lu", req->ticks); + return; + } + + while(iter->next && iter->next->ticks <= req->ticks) + iter = iter->next; + + req->next = iter->next; + iter->next = req; + + printf("ticks: %lu", arch_getcls()->timerfirstreq->ticks); + arch_cputimer_fire(arch_getcls()->timerfirstreq->ticks); + +}