Browse Source

timer irq 100 Hz, ns clock, removed apic timer callbacks

master
Mathieu Serandour 1 year ago
parent
commit
43349b87fe
  1. 4
      kernel/drivers/hpet.c
  2. 2
      kernel/drivers/hpet.h
  3. 10
      kernel/drivers/terminal/terminal.c
  4. 115
      kernel/int/apic.c
  5. 16
      kernel/int/apic.h
  6. 2
      kernel/int/irq.c
  7. 2
      kernel/int/irq.h
  8. 1
      kernel/int/irq.s
  9. 3
      kernel/int/isr.c
  10. 4
      kernel/lib/time.c

4
kernel/drivers/hpet.c

@ -60,13 +60,13 @@ void hpet_init(void) {
hpet_period = base->capabilities >> 32;
}
void hpet_prepare_wait_ms(unsigned ms) {
void hpet_prepare_wait_ns(uint64_t ns) {
hpet_period = base->capabilities >> 32;
// deactivate hpet timer
base->general_config &= ~1;
base->main_counter_value =
- ((uint64_t)ms * 0xe8d4a51000llu / hpet_period);
- ((uint64_t)ns * 0xF4240llu / hpet_period);
}
//t * 1000 / (T * 1e15) *

2
kernel/drivers/hpet.h

@ -3,7 +3,7 @@
#include <stdint.h>
void hpet_init(void);
void hpet_prepare_wait_ms(unsigned);
void hpet_prepare_wait_ns(uint64_t);
// enables HPET, busy wait until the main counteur
// reaches 0, and returns without disabling HPET!

10
kernel/drivers/terminal/terminal.c

@ -55,7 +55,6 @@ struct data {
uint32_t current_fgcolor;
uint32_t current_bgcolor;
unsigned margin_left, margin_top;
unsigned timerID;
// this buffer keeps a copy of the framebuffer
};
@ -185,12 +184,6 @@ char terminal_install(driver_t* this) {
d->cur_px_buffer = 0;
//d->timerID = apic_create_timer(
// (timer_callback_t)terminal_update,
// UPDATE_PERIOD_MS,
// this);
//
if(terminals++ == 0)
loadBMP_24b_1b(&_binary_charmap_bmp, &charmap);
@ -215,9 +208,6 @@ void terminal_remove(driver_t* this) {
//free(d->char_buffer);
if(d->timerID != INVALID_TIMER_ID)
apic_delete_timer(d->timerID);
// the allocation of data also
// contains the char buffer
free(d);

115
kernel/int/apic.c

@ -1,6 +1,7 @@
#include <stdint.h>
#include "idt.h"
#include "irq.h"
#include "apic.h"
#include "../lib/assert.h"
@ -10,6 +11,9 @@
#include "../drivers/hpet.h"
#include "../lib/string.h"
#include "../memory/heap.h"
#include "../sched/sched.h"
struct APICRegister
{
@ -57,106 +61,29 @@ static_assert(sizeof(struct APICConfig) == 0x400);
static volatile struct APICConfig* apic_config = (void *)APIC_VADDR;
static uint64_t apic_timer_clock_count = 0;
// 1 ms
#define CLOCK_FREQUENCY 1
typedef struct {
unsigned period;
unsigned counter;
char exists;
void (*func)(void*);
void* param;
} timer_t;
// realloc(NULL, s) ~ malloc(s)
timer_t* timers = NULL;
static unsigned n_timers = 0;
static void timers_realloc(void) {
static unsigned buffsize = 0;
if(n_timers == 0) {
// performs a free
buffsize = 0;
}
if(n_timers > buffsize)
buffsize *= 2;
else if(n_timers < buffsize / 2)
buffsize /= 2;
timers = realloc(timers, buffsize*sizeof(timer_t));
}
unsigned apic_create_timer(timer_callback_t fun, int millisecs, void* param) {
unsigned id = n_timers++;
timers_realloc();
timers[id].counter = 0;
timers[id].period = millisecs * CLOCK_FREQUENCY;
timers[id].func = fun;
timers[id].func = param;
timers[id].exists = 1;
return id;
}
int apic_delete_timer(unsigned id) {
if(id >= n_timers)
return 0;
timers[id].exists = 0;
// check if we can free the end of the list
// end of the list:
// timers[timer_end -> n_timers-1].exist = 0
unsigned timer_end = 0;
for(unsigned i = 0; i < n_timers; i++) {
if(timers[i].exists)
timer_end = i+1;
}
if(n_timers != timer_end) {
n_timers = timer_end;
timers_realloc();
}
return 1;
}
// acknowledge an apic IRQ
void apic_eoi(void) {
apic_config->end_of_interrupt.reg = 0;
}
__attribute__((interrupt))
void lapic_timer_handler(struct IFrame* frame) {
(void) frame;
++apic_timer_clock_count;
static uint64_t timer_offset = 0;
void lapic_timer_handler(void* arg) {
(void)arg;
timer_offset += 1000 * 1000 * 1000 / LAPIC_IRQ_FREQ;
for(unsigned i = 0; i < n_timers; i++) {
if(++timers[i].counter >= timers[i].period) {
timers[i].func(timers[i].param);
timers[i].counter = 0;
}
}
apic_eoi();
schedule();
}
uint64_t clock(void) {
return apic_timer_clock_count;
uint64_t clock_ns(void) {
return timer_offset + apic_config->timer_current_count.reg;
}
@ -183,17 +110,22 @@ void apic_setup_clock(void) {
assert(apic_config != NULL);
set_irq_handler(48, lapic_timer_handler);
register_irq(IRQ_APIC_TIMER, (void*)lapic_timer_handler, NULL);
// enable apic and set spurious int to 0xff
apic_config->spurious_interrupt_vector.reg = 0x100 | LAPIC_SPURIOUS_IRQ;
apic_config->spurious_interrupt_vector.reg = 0x100 | IRQ_LAPIC_SPURIOUS;
// masks the irq, one shot mode
apic_config->LVT_timer.reg = 0x20000;
apic_config->timer_divide_configuration.reg = 3; // divide by 16
hpet_prepare_wait_ms(1);
hpet_prepare_wait_ns(1000 * 1000 * 1000 / LAPIC_IRQ_FREQ);
apic_config->timer_initial_count.reg = UINT32_MAX;
@ -209,6 +141,5 @@ void apic_setup_clock(void) {
apic_config->LVT_timer.reg = 0x20000 | 48;
hpet_disable();
}

16
kernel/int/apic.h

@ -4,20 +4,16 @@
#include <stdint.h>
#include "../lib/assert.h"
#define LAPIC_SPURIOUS_IRQ 0xff
#define INVALID_TIMER_ID ((unsigned)-1)
#define IRQ_LAPIC_SPURIOUS 0xff
#define IRQ_APIC_TIMER 48
void apic_setup_clock(void);
uint64_t clock(void);
typedef void (* timer_callback_t)(void *);
// return the id of the created timer
unsigned apic_create_timer(timer_callback_t, int millisecs, void* param);
// in Hz
#define LAPIC_IRQ_FREQ 100
// zero if it couldn't be deleted
int apic_delete_timer(unsigned id);
void apic_setup_clock(void);
uint64_t clock_ns(void);
// acknowledge an apic IRQ
void apic_eoi(void);

2
kernel/int/irq.c

@ -38,6 +38,7 @@ void register_irq(
irqs[irq_number].handler = handler;
irqs[irq_number].driver = driver;
}
unsigned install_irq(irq_handler_t handler,
@ -59,7 +60,6 @@ void release_irq(unsigned n) {
assert(n >= IRQ_BEGIN);
// replace the handler by the dummy one
set_irq_handler(n, IRQ_dummy_handler);
// mark it as free
irqs[n - IRQ_BEGIN].handler = NULL;

2
kernel/int/irq.h

@ -5,7 +5,7 @@
struct driver;
#define IRQ_BEGIN 32
#define IRQ_END 47
#define IRQ_END 48
typedef void(* irq_handler_t)(struct driver *);

1
kernel/int/irq.s

@ -46,6 +46,7 @@ create_irq 44
create_irq 45
create_irq 46
create_irq 47
create_irq 48
common_stub:

3
kernel/int/isr.c

@ -198,8 +198,9 @@ void setup_isrs(void) {
set_irq_handler(45, _irq_handler45);
set_irq_handler(46, _irq_handler46);
set_irq_handler(47, _irq_handler47);
set_irq_handler(48, _irq_handler48);
for(int i = 48; i <= 254; i++)
for(int i = 49; i <= 254; i++)
set_irs_handler(i, IRQ_dummy_handler);

4
kernel/lib/time.c

@ -2,8 +2,8 @@
#include "../int/apic.h"
void sleep(unsigned ms) {
uint64_t begin = clock();
uint64_t begin = clock_ns();
while (clock() < begin + ms)
while (clock_ns() < begin + (uint64_t)ms * 1000000)
asm volatile("hlt");
}
Loading…
Cancel
Save