summaryrefslogtreecommitdiff
path: root/kc
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2022-02-17 13:40:55 +0000
committerAda Christine <adachristine18@gmail.com>2022-02-17 13:40:55 +0000
commit9b63c0000b2e0d9d0a306e56dbc7bc28403e5549 (patch)
tree17ef5aa53d37c4232f8efcca97c5f118a96fb96f /kc
parentb8ef8b401d9dd1e15f2703eb997fb79a70ae531a (diff)
many changes have happned
- updates to panic() interface - genericized timer interface - (yet unused) additions to task management
Diffstat (limited to 'kc')
-rw-r--r--kc/core/Makefile2
-rw-r--r--kc/core/cpu/cpu.c2
-rw-r--r--kc/core/kc_main.c2
-rw-r--r--kc/core/memory.c12
-rw-r--r--kc/core/panic.c12
-rw-r--r--kc/core/panic.h6
-rw-r--r--kc/core/pic8259.c2
-rw-r--r--kc/core/pit8253.c75
-rw-r--r--kc/core/pit8253.h11
-rw-r--r--kc/core/task.c44
-rw-r--r--kc/core/timer.c8
-rw-r--r--kc/core/timer.h21
12 files changed, 150 insertions, 47 deletions
diff --git a/kc/core/Makefile b/kc/core/Makefile
index fd5c984..cd440a1 100644
--- a/kc/core/Makefile
+++ b/kc/core/Makefile
@@ -13,7 +13,7 @@ SOBJS :=
GOBJS := entry_x86_64.o reloc_x86_64.o kprint.o serial.o port.o mmu.o \
kc_main.o memory.o memset.o memcpy.o memmove.o memcmp.o cpu.o \
vm_tree.o exceptions.o panic.o msr.o task.o cpu_task.o irq.o \
- kcc_memory.o string.o pic8259.o pic8259_isr.o pit8253.o timer.o
+ kcc_memory.o string.o pic8259.o pic8259_isr.o pit8253.o
IOBJS :=
# __attribute__((interrupt)) requires -mgeneral-regs-only
diff --git a/kc/core/cpu/cpu.c b/kc/core/cpu/cpu.c
index 7b48e30..d33d8a4 100644
--- a/kc/core/cpu/cpu.c
+++ b/kc/core/cpu/cpu.c
@@ -241,7 +241,7 @@ void isr_install(int vec, void (*isr)(void), int trap, unsigned ist)
}
else if (ist && ist > 7)
{
- panic(GENERAL_PANIC);
+ PANIC(GENERAL_PANIC);
}
}
diff --git a/kc/core/kc_main.c b/kc/core/kc_main.c
index 6d73cea..1136e0a 100644
--- a/kc/core/kc_main.c
+++ b/kc/core/kc_main.c
@@ -28,7 +28,7 @@ unsigned long kc_main(struct kc_boot_data *data)
kprintf("integer test %d %u\n", 3, 3);
memory_init();
pic8259_init();
- pit8253_init();
+ pit8253_timer_source.init();
task_init();
return 0;
diff --git a/kc/core/memory.c b/kc/core/memory.c
index 0319246..2dac707 100644
--- a/kc/core/memory.c
+++ b/kc/core/memory.c
@@ -320,7 +320,7 @@ static void init_vm_node(
else
{
kputs("fatal: attempt to insert overlapping vm node\n");
- panic(GENERAL_PANIC);
+ PANIC(GENERAL_PANIC);
}
}
@@ -544,7 +544,7 @@ int anonymous_page_handler(uint32_t code, void *address)
kputs("can't fault a present page\n");
// there's no reason a protection violation should happen
// in anonymous space
- panic(UNHANDLED_FAULT);
+ PANIC(UNHANDLED_FAULT);
}
// kernel page mappings are built different
if (address >= (void *)&kc_image_base)
@@ -567,7 +567,7 @@ int anonymous_page_handler(uint32_t code, void *address)
}
else
{
- panic(OUT_OF_MEMORY);
+ PANIC(OUT_OF_MEMORY);
}
}
@@ -605,13 +605,13 @@ int page_fault_handler(uint8_t vector, uint32_t code)
}
if (result)
{
- panic(UNHANDLED_FAULT);
+ PANIC(UNHANDLED_FAULT);
}
}
else
{
kputs("didn't find memory object\n");
- panic(UNHANDLED_FAULT);
+ PANIC(UNHANDLED_FAULT);
}
return 0;
@@ -623,7 +623,7 @@ int general_protection_handler(uint8_t vector, uint32_t code)
(void)vector;
(void)code;
kputs("general protection violation\n");
- panic(UNHANDLED_FAULT);
+ PANIC(UNHANDLED_FAULT);
return 0;
}
diff --git a/kc/core/panic.c b/kc/core/panic.c
index 6fd5581..2f46a6a 100644
--- a/kc/core/panic.c
+++ b/kc/core/panic.c
@@ -6,17 +6,22 @@
static char const *reason_strings[] = {
"general panic",
"unhandled fault",
- "out of memory"
+ "out of memory",
+ "dead-end routine"
};
-noreturn void panic(enum panic_reason reason)
+noreturn void panic(const char *file, int line, enum panic_reason reason)
{
// TODO: kprintf() and friends
if (reason > sizeof(reason_strings) / sizeof(*reason_strings))
{
reason = 0;
}
- kprintf("kernel panic: %s\n", reason_strings[reason]);
+ kprintf(
+ "kernel panic:%s:%u %s\n",
+ file,
+ line,
+ reason_strings[reason]);
halt();
}
@@ -25,3 +30,4 @@ noreturn void halt(void)
__asm__ ("cli\n\t");
while (true) __asm__ ("hlt\n\t");
}
+
diff --git a/kc/core/panic.h b/kc/core/panic.h
index 0cfd7c2..1ace5ba 100644
--- a/kc/core/panic.h
+++ b/kc/core/panic.h
@@ -2,12 +2,16 @@
#include <stdnoreturn.h>
+#define PANIC(reason) panic(__FILE__, __LINE__, reason)
+
enum panic_reason
{
GENERAL_PANIC,
UNHANDLED_FAULT,
OUT_OF_MEMORY,
+ DEAD_END
};
-noreturn void panic(enum panic_reason reason);
+noreturn void panic(const char *file, int line, enum panic_reason reason);
noreturn void halt(void);
+
diff --git a/kc/core/pic8259.c b/kc/core/pic8259.c
index b1de903..4317d0c 100644
--- a/kc/core/pic8259.c
+++ b/kc/core/pic8259.c
@@ -184,7 +184,7 @@ void pic8259_irq_begin(uint8_t irq)
}
else
{
- kprintf("%s of irq%hhu\n", "unhandled activation", irq);
+ kprintf("unhandled irq%hhu\n", irq);
}
pic8259_irq_end(irq);
diff --git a/kc/core/pit8253.c b/kc/core/pit8253.c
index 0cf5232..4728020 100644
--- a/kc/core/pit8253.c
+++ b/kc/core/pit8253.c
@@ -3,6 +3,8 @@
#include "port.h"
#include "kprint.h"
+#include <stdatomic.h>
+
#define PIT8253_DATA0 0x40
#define PIT8253_CMD 0x43
@@ -13,51 +15,86 @@
#define CONFIG_CHANNEL_0 (SEL_CHANNEL0|ACC_LOHI|MODE_RATE|BIN_COUNT)
+#define PIT_IRQ 0
#define PIT_HZ 1193182U
+#define PIT_HZ_MIN (PIT_HZ/0xffff)
+
+static void pit8253_set_divisor(uint16_t divisor);
-static uint64_t count = 0;
+static atomic_uint_fast64_t count = 0;
+static uint16_t divisor = 0;
+
+const struct timer_source pit8253_timer_source =
+{
+ "pit8253",
+ pit8253_init,
+ pit8253_start,
+ pit8253_stop,
+
+ pit8253_set_frequency,
+ pit8253_get_frequency,
+
+ pit8253_nanoseconds_elapsed,
+ pit8253_nanoseconds_delta
+};
int pit8253_callback(uint8_t irq)
{
(void)irq;
count++;
- if (!(count % (185)))
- {
- kprintf("it's been about %lu seconds since starting\n", count / 18);
- }
-
return 0;
}
void pit8253_init(void)
{
- kprintf(
- "initializing timer to an approximate frequency of %uHz\n",
- PIT_HZ / 0xffff);
- outb(PIT8253_CMD, CONFIG_CHANNEL_0);
- outb(PIT8253_DATA0, 0xff);
- outb(PIT8253_DATA0, 0xff);
-
- pic8259_irq_install(0, pit8253_callback);
- pic8259_irq_unmask(0);
+ pic8259_irq_install(PIT_IRQ, pit8253_callback);
}
void pit8253_start(void)
{
+ pic8259_irq_unmask(PIT_IRQ);
}
void pit8253_stop(void)
{
+ pic8259_irq_mask(PIT_IRQ);
}
-uint64_t pit8253_count(void)
+void pit8253_set_frequency(uint32_t frequency)
{
- return count;
+ uint32_t d = PIT_HZ / frequency;
+
+ if (d > UINT16_MAX)
+ {
+ kprintf("warning: %uHz is too slow for 8253 pit\n", PIT_HZ/d);
+ d = UINT16_MAX;
+ kprintf("warning: set timer to minimum frequency\n");
+ }
+
+ pit8253_set_divisor(d);
+}
+
+uint32_t pit8253_get_frequency(void)
+{
+ return PIT_HZ/divisor;
+}
+
+uint64_t pit8253_nanoseconds_elapsed(void)
+{
+ return pit8253_nanoseconds_delta() * count;
+}
+
+uint64_t pit8253_nanoseconds_delta(void)
+{
+ return (TIMER_NANOSECOND * divisor)/PIT_HZ;
}
-void pit8253_set_hz(uint16_t hz)
+static void pit8253_set_divisor(uint16_t d)
{
- (void)hz;
+ outb(PIT8253_CMD, CONFIG_CHANNEL_0);
+ outb(PIT8253_DATA0, (uint8_t)d);
+ outb(PIT8253_DATA0, (uint8_t)(d >> 8));
+ divisor = d;
}
diff --git a/kc/core/pit8253.h b/kc/core/pit8253.h
index 25861f7..32cb9b1 100644
--- a/kc/core/pit8253.h
+++ b/kc/core/pit8253.h
@@ -1,10 +1,17 @@
#pragma once
+#include "timer.h"
#include <stdint.h>
void pit8253_init(void);
void pit8253_start(void);
void pit8253_stop(void);
-uint64_t pit8253_count(void);
-void pit8253_set_hz(uint16_t hz);
+
+void pit8253_set_frequency(uint32_t frequency);
+uint32_t pit8253_get_frequency(void);
+
+uint64_t pit8253_nanoseconds_elapsed(void);
+uint64_t pit8253_nanoseconds_delta(void);
+
+extern const struct timer_source pit8253_timer_source;
diff --git a/kc/core/task.c b/kc/core/task.c
index 79fae5f..13263d8 100644
--- a/kc/core/task.c
+++ b/kc/core/task.c
@@ -6,9 +6,16 @@
#include "kprint.h"
#include "cpu/irq.h"
+#include "pit8253.h"
+
+#include <stdatomic.h>
+#include <stdbool.h>
+
struct kc_thread *current_task = NULL;
struct kc_thread *first_ready_task = NULL;
struct kc_thread *last_ready_task = NULL;
+struct kc_thread *sleeping_tasks = NULL;
+struct kc_thread *blocked_tasks = NULL;
static void lock_scheduler(void);
static void unlock_scheduler(void);
@@ -18,9 +25,14 @@ static void idle_task_thread(void);
extern uint64_t *get_tss_rsp0(void);
static uint64_t last_count = 0;
+const struct timer_source * timesource;
+
+static atomic_int preempt_switch_count = 0;
+static volatile atomic_bool preempt_switch_flag = false;
+
void update_time_used(void)
{
- uint64_t current_count = timer_ticks();
+ uint64_t current_count = timesource->nanoseconds_elapsed();
uint64_t elapsed = current_count - last_count;
last_count = current_count;
current_task->time_elapsed += elapsed;
@@ -29,13 +41,23 @@ void update_time_used(void)
void task_set_thread(struct kc_thread *task)
{
// wrapper around cpu_set_thread
+ if (preempt_switch_count)
+ {
+ preempt_switch_flag = true;
+ return;
+ }
uint64_t *rsp0 = get_tss_rsp0();
cpu_set_thread(&current_task->state, &task->state, rsp0);
}
void task_schedule(void)
{
- kprintf("task_schedule() called @%lu ticks\n", last_count);
+ if (preempt_switch_count)
+ {
+ preempt_switch_flag = true;
+ return;
+ }
+
update_time_used();
if (first_ready_task)
{
@@ -49,10 +71,22 @@ void task_schedule(void)
static void lock_scheduler(void)
{
irq_lock();
+ preempt_switch_count++;
}
static void unlock_scheduler(void)
{
+ if (preempt_switch_count >= 1)
+ {
+ preempt_switch_count--;
+ }
+
+ if (!preempt_switch_count && preempt_switch_flag)
+ {
+ preempt_switch_flag = false;
+ task_schedule();
+ }
+
irq_unlock();
}
@@ -94,8 +128,11 @@ static void idle_task_thread(void)
noreturn void task_init(void)
{
lock_scheduler();
+ timesource = &pit8253_timer_source;
+ timesource->start();
char *kernel_rsp0 = vm_alloc(4096);
// TODO: make it so this isn't demand-allocated.
+ // TODO: decouple the task management code from cpu-dependent task code
kernel_rsp0[1] = 0;
*get_tss_rsp0() = (uintptr_t)kernel_rsp0;
char *first_task = vm_alloc(16384);
@@ -104,6 +141,7 @@ noreturn void task_init(void)
idle_thread->state.stack = (uintptr_t)idle_thread;
idle_thread->state.stack_top = (uintptr_t)kernel_rsp0;
+ // XXX: this is kindof a train wreck
__asm__ volatile
(
"mov %%cr3, %%rax\n\t"
@@ -118,6 +156,6 @@ noreturn void task_init(void)
);
// shouldn't ever get here
- panic(GENERAL_PANIC);
+ PANIC(DEAD_END);
}
diff --git a/kc/core/timer.c b/kc/core/timer.c
deleted file mode 100644
index 2b7d5f6..0000000
--- a/kc/core/timer.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "timer.h"
-#include "pit8253.h"
-
-uint64_t timer_ticks(void)
-{
- return pit8253_count();
-}
-
diff --git a/kc/core/timer.h b/kc/core/timer.h
index 702d7b6..b70cd70 100644
--- a/kc/core/timer.h
+++ b/kc/core/timer.h
@@ -1,6 +1,25 @@
#pragma once
#include <stdint.h>
-uint64_t timer_ticks(void);
+#define TIMER_MILLISECOND 1000ULL
+#define TIMER_MICROSECOND 1000000ULL
+#define TIMER_NANOSECOND 1000000000ULL
+
+struct timer_source
+{
+ const char *name;
+ void (*init)(void);
+ void (*start)(void);
+ void (*stop)(void);
+
+ void (*set_frequency)(uint32_t frequency);
+ uint32_t (*get_frequency)(void);
+ uint64_t (*nanoseconds_elapsed)(void);
+ uint64_t (*nanoseconds_delta)(void);
+};
+
+uint64_t timer_ticks(void);
+void timer_sleep(uint64_t usec);
+void timer_sleep_until(uint64_t ticks);