summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/arch/i386/asm_tsc.s8
-rw-r--r--kernel/arch/i386/tsc.h6
-rw-r--r--kernel/cpu/syscall.c11
-rw-r--r--kernel/drivers/pit.c14
-rw-r--r--kernel/drivers/pit.h1
-rw-r--r--kernel/fs/ext2.c5
-rw-r--r--kernel/init/kernel.c8
-rw-r--r--kernel/sched/scheduler.c5
-rw-r--r--kernel/timer.c69
-rw-r--r--kernel/timer.h8
11 files changed, 106 insertions, 31 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 03d2641..a82983b 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -1,6 +1,6 @@
CC="i686-sb-gcc"
AS="i686-sb-as"
-OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o kubsan.o drivers/serial.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o elf.o ksbrk.o sched/scheduler.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o math.o signal.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o lib/ringbuffer.o lib/relist.o arch/i386/tsc.o arch/i386/asm_tsc.o drivers/cmos.o
+OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o kubsan.o drivers/serial.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o elf.o ksbrk.o sched/scheduler.o libc/string/copy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o math.o signal.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o lib/ringbuffer.o lib/relist.o arch/i386/tsc.o arch/i386/asm_tsc.o drivers/cmos.o timer.o
CFLAGS = -std=c99 -O0 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Wextra -Wno-int-conversion -Wno-unused-parameter -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
LDFLAGS=
INCLUDE=-I./includes/ -I../include/ -I./libc/include/
diff --git a/kernel/arch/i386/asm_tsc.s b/kernel/arch/i386/asm_tsc.s
index 963687e..5f9d858 100644
--- a/kernel/arch/i386/asm_tsc.s
+++ b/kernel/arch/i386/asm_tsc.s
@@ -1,17 +1,17 @@
.intel_syntax noprefix
-.global get_tsc
-.global get_hz
+.global tsc_get
+.global tsc_get_hz
# 1.193182 MHz
# So 0xFFFF is roughly 0.05492 seconds
# So take the result times 18 and you got your Hz
-get_tsc:
+tsc_get:
rdtsc
ret
-get_hz:
+tsc_get_hz:
cli
# Disable the gate for channel 2 so the clock can be set.
# This should only matter if the channel already has count
diff --git a/kernel/arch/i386/tsc.h b/kernel/arch/i386/tsc.h
index 2e29cf3..1a9e317 100644
--- a/kernel/arch/i386/tsc.h
+++ b/kernel/arch/i386/tsc.h
@@ -1,4 +1,6 @@
#include <typedefs.h>
-u64 get_tsc();
-u64 get_hz();
+void tsc_init(void);
+u64 tsc_get(void);
+u64 tsc_get_mhz(void);
+u64 tsc_calculate_ms(u64 tsc);
diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c
index 78d35fe..a74adfd 100644
--- a/kernel/cpu/syscall.c
+++ b/kernel/cpu/syscall.c
@@ -19,6 +19,7 @@
#include <random.h>
#include <socket.h>
#include <string.h>
+#include <timer.h>
#include <typedefs.h>
struct two_args {
@@ -137,9 +138,7 @@ int syscall_chdir(const char *path) {
int syscall_clock_gettime(clockid_t clock_id, struct timespec *tp) {
// FIXME: Actually implement this
if (tp) {
- u64 ms = pit_num_ms();
- tp->tv_sec = ms / 1000;
- tp->tv_nsec = ms * 1000 * 1000;
+ timer_get(tp);
}
return 0;
}
@@ -226,7 +225,9 @@ void *syscall_mmap(SYS_MMAP_PARAMS *args) {
}
void syscall_msleep(u32 ms) {
- current_task->sleep_until = pit_num_ms() + ms;
+ struct timespec t;
+ timer_get(&t);
+ current_task->sleep_until = timer_get_ms() + ms;
switch_task();
}
@@ -371,7 +372,7 @@ int syscall_socket(SYS_SOCKET_PARAMS *args) {
}
u32 syscall_uptime(void) {
- return (u32)pit_num_ms();
+ return timer_get_uptime();
}
int syscall_write(int fd, const char *buf, size_t count) {
diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c
index ac4e555..70dc0f9 100644
--- a/kernel/drivers/pit.c
+++ b/kernel/drivers/pit.c
@@ -9,11 +9,6 @@ u32 pit_counter = 0;
u32 switch_counter = 0;
u16 hertz;
-u64 cpu_mhz = 0;
-u64 pit_num_ms(void) {
- return (get_tsc()) / (cpu_mhz * 1000);
-}
-
u16 read_pit_count(void) {
u16 count = 0;
@@ -26,8 +21,6 @@ u16 read_pit_count(void) {
}
void set_pit_count(u16 _hertz) {
- cpu_mhz = get_hz() / 10000;
-
hertz = _hertz;
u16 divisor = 1193180 / hertz;
@@ -53,13 +46,6 @@ u64 last_tsc = 0;
extern int is_switching_tasks;
void int_clock(reg_t *regs) {
- u64 current_tsc = get_tsc();
-
- u64 delta = (current_tsc - last_tsc) / (cpu_mhz * 1000);
-
- clock_num_ms_ticks += delta;
-
- last_tsc = current_tsc;
switch_counter++;
if (clock_num_ms_ticks - last_flush > 50) {
diff --git a/kernel/drivers/pit.h b/kernel/drivers/pit.h
index ec48cc3..90fddf4 100644
--- a/kernel/drivers/pit.h
+++ b/kernel/drivers/pit.h
@@ -8,5 +8,4 @@
void pit_install(void);
void set_pit_count(u16 hertz);
-u64 pit_num_ms(void);
#endif
diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c
index 1eeafce..a61d5f2 100644
--- a/kernel/fs/ext2.c
+++ b/kernel/fs/ext2.c
@@ -6,6 +6,7 @@
#include <math.h>
#include <string.h>
#include <sys/stat.h>
+#include <timer.h>
#include <typedefs.h>
#define EXT2_SUPERBLOCK_SECTOR 2
@@ -52,7 +53,7 @@ void cached_read_block(u32 block, void *address, size_t size, size_t offset) {
continue;
}
if (cache[i].block_num == block) {
- cache[i].last_use = pit_num_ms();
+ cache[i].last_use = timer_get_uptime();
memcpy(address, cache[i].block + offset, size);
return;
}
@@ -77,7 +78,7 @@ void cached_read_block(u32 block, void *address, size_t size, size_t offset) {
}
c->is_used = 1;
c->block_num = block;
- c->last_use = pit_num_ms();
+ c->last_use = timer_get_uptime();
c->has_write = 0;
raw_vfs_pread(mount_fd, c->block, block_byte_size, block * block_byte_size);
cached_read_block(block, address, size, offset);
diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c
index 83f4af8..90be3ab 100644
--- a/kernel/init/kernel.c
+++ b/kernel/init/kernel.c
@@ -28,6 +28,7 @@
#include <stddef.h>
#include <stdio.h>
#include <string.h>
+#include <timer.h>
#include <typedefs.h>
#if defined(__linux__)
@@ -76,6 +77,8 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
ata_init();
klog(LOG_SUCCESS, "ATA Initalized");
+ timer_init();
+
tasking_init();
klog(LOG_SUCCESS, "Tasking Initalized");
@@ -96,6 +99,9 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
add_stdout();
add_serial();
add_random_devices();
+
+ timer_add_clock();
+
shm_init();
setup_random();
@@ -123,7 +129,7 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
}
}
for (;;) {
- current_task->sleep_until = pit_num_ms() + 100000000;
+ current_task->sleep_until = timer_get_ms() + 100000000;
wait_for_interrupt();
}
}
diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c
index c8ee0a1..10ecd73 100644
--- a/kernel/sched/scheduler.c
+++ b/kernel/sched/scheduler.c
@@ -7,7 +7,9 @@
#include <errno.h>
#include <fs/vfs.h>
#include <interrupts.h>
+#include <sched/scheduler.h>
#include <signal.h>
+#include <timer.h>
// FIXME: Use the process_t struct instead or keep this contained in it.
TCB *current_task_TCB;
@@ -432,6 +434,7 @@ extern PageDirectory *active_directory;
process_t *next_task(process_t *s) {
process_t *c = s;
+ u64 ms_time = timer_get_ms();
c = c->next;
for (;; c = c->next) {
if (!c) {
@@ -440,7 +443,7 @@ process_t *next_task(process_t *s) {
if (s == c) {
// wait_for_interrupt();
}
- if (c->sleep_until > pit_num_ms()) {
+ if (c->sleep_until > ms_time) {
continue;
}
if (c->is_interrupted) {
diff --git a/kernel/timer.c b/kernel/timer.c
new file mode 100644
index 0000000..46a30d3
--- /dev/null
+++ b/kernel/timer.c
@@ -0,0 +1,69 @@
+#include <arch/i386/tsc.h>
+#include <drivers/cmos.h>
+#include <fs/devfs.h>
+#include <math.h>
+#include <time.h>
+#include <typedefs.h>
+
+i64 start_unix_time;
+u64 start_tsc_time;
+
+void timer_init(void) {
+ tsc_init();
+ start_tsc_time = tsc_get();
+ start_unix_time = cmos_get_time();
+}
+
+u64 timer_get_uptime(void) {
+ return tsc_calculate_ms(tsc_get());
+}
+
+void timer_get(struct timespec *tp) {
+ u64 offset_tsc = tsc_get() - start_tsc_time;
+ i64 current_unix_time_seconds =
+ start_unix_time + tsc_calculate_ms(offset_tsc) / 1000;
+ tp->tv_sec = current_unix_time_seconds;
+ tp->tv_nsec = tsc_calculate_ms(offset_tsc);
+}
+
+u64 timer_get_ms(void) {
+ u64 offset_tsc = tsc_get() - start_tsc_time;
+ return start_unix_time * 1000 + tsc_calculate_ms(offset_tsc);
+}
+
+int clock_read(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
+ (void)offset;
+ u64 r = timer_get_ms();
+ u64 l = min(len, sizeof(u64));
+ memcpy(buffer, &r, l);
+ return l;
+}
+
+int clock_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
+ (void)offset;
+ if (len != sizeof(i64)) {
+ return 0;
+ }
+
+ i64 new_value_ms;
+ memcpy(&new_value_ms, buffer, sizeof(i64));
+ i64 new_value_seconds = new_value_ms / 1000;
+
+ u64 offset_tsc = tsc_get() - start_tsc_time;
+ i64 current_unix_time_seconds =
+ start_unix_time + tsc_calculate_ms(offset_tsc) / 1000;
+
+ i64 delta = new_value_seconds - current_unix_time_seconds;
+ start_unix_time += delta;
+ cmos_set_time(new_value_seconds);
+ return sizeof(i64);
+}
+
+int always_has_data(vfs_inode_t *inode);
+int always_can_write(vfs_inode_t *inode);
+
+int timer_add_clock(void) {
+ devfs_add_file("/clock", clock_read, clock_write, NULL, always_has_data,
+ always_can_write, FS_TYPE_CHAR_DEVICE);
+ return 1;
+}
diff --git a/kernel/timer.h b/kernel/timer.h
new file mode 100644
index 0000000..33c04ce
--- /dev/null
+++ b/kernel/timer.h
@@ -0,0 +1,8 @@
+#include <arch/i386/tsc.h>
+#include <drivers/cmos.h>
+
+void timer_init(void);
+void timer_get(struct timespec *tp);
+u64 timer_get_uptime(void);
+u64 timer_get_ms(void);
+int timer_add_clock(void);