diff options
author | Anton Kling <anton@kling.gg> | 2024-07-03 01:21:16 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-07-03 01:21:28 +0200 |
commit | dd9aece19f93c1cafe07dfc0e63e1599a06db04b (patch) | |
tree | af5ef66b2eba21d0eaa2d3a00abcfec64cea98b4 | |
parent | 5751b4ff0baf41fd3f38b30b0cb58d09631e9bc0 (diff) |
Kernel: Add simple support for timer using TSC
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/arch/i386/asm_tsc.s | 63 | ||||
-rw-r--r-- | kernel/arch/i386/tsc.h | 4 | ||||
-rw-r--r-- | kernel/drivers/pit.c | 17 |
4 files changed, 83 insertions, 3 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 45e898e..e6626d8 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 +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 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 new file mode 100644 index 0000000..963687e --- /dev/null +++ b/kernel/arch/i386/asm_tsc.s @@ -0,0 +1,63 @@ +.intel_syntax noprefix + +.global get_tsc +.global 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: + rdtsc + ret + +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 + inb al, 0x61 + and al, 0xFE + or al, 0x1 + outb 0x61, al + + # Set mode + mov al, 0b10110010 + outb 0x43, al + + # 0x2e9b = 11931 which is close to the PIT Hz divided by 100 + mov al, 0x9b + outb 0x42, al + mov al, 0x2e + outb 0x42, al + + rdtsc + mov ecx, eax + mov esi, edx + + # Set the gate for channel 2 + inb al, 0x61 + or al, 0x1 + outb 0x61, al + + # The fifth bit will(seems to) flip when the count is low. + and al, 0x20 + jnz none_zero_check + +zero_check: + inb al, 0x61 + andb al, 0x20 + cmp al, 0 + jz zero_check + jmp end + +none_zero_check: + inb al, 0x61 + andb al, 0x20 + cmp al, 0 + jnz none_zero_check +end: + rdtsc + + sub eax, ecx + sub edx, esi + ret diff --git a/kernel/arch/i386/tsc.h b/kernel/arch/i386/tsc.h new file mode 100644 index 0000000..2e29cf3 --- /dev/null +++ b/kernel/arch/i386/tsc.h @@ -0,0 +1,4 @@ +#include <typedefs.h> + +u64 get_tsc(); +u64 get_hz(); diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c index db9cd2a..ac4e555 100644 --- a/kernel/drivers/pit.c +++ b/kernel/drivers/pit.c @@ -1,4 +1,5 @@ #include "pit.h" +#include <arch/i386/tsc.h> #define PIT_IO_CHANNEL_0 0x40 #define PIT_IO_MODE_COMMAND 0x43 @@ -8,8 +9,9 @@ u32 pit_counter = 0; u32 switch_counter = 0; u16 hertz; +u64 cpu_mhz = 0; u64 pit_num_ms(void) { - return clock_num_ms_ticks; + return (get_tsc()) / (cpu_mhz * 1000); } u16 read_pit_count(void) { @@ -24,6 +26,8 @@ u16 read_pit_count(void) { } void set_pit_count(u16 _hertz) { + cpu_mhz = get_hz() / 10000; + hertz = _hertz; u16 divisor = 1193180 / hertz; @@ -45,9 +49,18 @@ void set_pit_count(u16 _hertz) { int last_flush = 0; +u64 last_tsc = 0; + extern int is_switching_tasks; void int_clock(reg_t *regs) { - clock_num_ms_ticks += 5; + 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) { tcp_flush_acks(); |