Commit Graph

33 Commits

Author SHA1 Message Date
Bananymous 12489a4c6b Kernel: Fix 32 bit target compile and runtime
Apparently I have to reload stack in the fork trampoline. Not sure why
or why not on x86_64. Also sse builtins did not compile
2026-01-09 17:06:57 +02:00
Bananymous 74f70ae4bd Kernel/LibC: Use builtin functions over inline asm
Getting flags and saving/restoring sse state and reading TSC can be done
using compiler builtins
2026-01-09 15:39:19 +02:00
Bananymous a9ceab0415 Kernel: Use syscall/sysret for syscalls in x86_64 2026-01-09 15:18:58 +02:00
Bananymous 9eb3834ae5 Kernel: Add syscall-less clock_gettime
If the processor has invariant TSC it can be used to measure time. We
keep track of the last nanosecond and TSC values and offset them based
on the current TSC. This allows getting current time in userspace.

The implementation maps a single RO page to every processes' address
space. The page contains the TSC info which gets updated every 100 ms.
If the processor does not have invariant TSC, this page will not
indicate the capability for TSC based timing.

There was the problem about how does a processor know which cpu it is
running without doing syscall. TSC counters may or may not be
synchronized between cores, so we need a separate TSC info for each
processor. I ended up adding sequence of bytes 0..255 at the start of
the shared page. When a scheduler gets a new thread, it updates the
threads gs/fs segment to point to the byte corresponding to the current
cpu.

This TSC based timing is also used in kernel. With 64 bit HPET this
probably does not bring much of a benefit, but on PIT or 32 bit HPET
this removes the need to aquire a spinlock to get the current time.

This change does force the userspace to not use gs/fs themselves and
they are both now reserved. Other one is used for TLS (this can be
technically used if user does not call libc code) and the other for
the current processor index (cannot be used as kernel unconditionally
resets it after each load balance).

I was looking at how many times timer's current time was polled
(userspace and kernel combined). When idling in window manager, it was
around 8k times/s. When running doom it peaked at over 1 million times
per second when loading and settled at ~30k times/s.
2026-01-08 17:13:59 +02:00
Bananymous 706c0816dd Kernel: Move smp_initialized flag after schedulers are initialized
Before this real hardware failed to boot with smp enabled. Allocating
the idle thread does a page mapping which ends up broadcasting TLB
shootdown to other processes. This ends up failing somewhere halting the
processors never allowing them to initialize their scheduler
2026-01-03 23:39:07 +02:00
Bananymous 89c0ff1a9d Kernel/LibC: Replace SYS_{GET,SET}_TLS with SYS_{SET,GET}_{FS,GS}BASE
This allows userspace to use both registers
2025-11-13 04:20:53 +02:00
Bananymous a8bb07052e Kernel: Rewrite SMP message code
Remove locks and map smp buffer as uncached
2025-08-28 15:55:40 +03:00
Bananymous f926e599fa Kernel: Zero initialize Processors
This moves processor array to .bss reducing data size by 8192 bytes :)

This needed GCC updated to 15.2.0 because of an internal compiler error
I found :)
2025-08-25 18:29:14 +03:00
Bananymous 9a6eae69ba Kernel: Replace all occurances of BSB with BSP 2025-08-25 17:11:32 +03:00
Bananymous 83c0ef3514 Kernel: Implement CLOCK_{PROCESS,THREAD}_CPUTIME_ID 2025-06-28 16:55:13 +03:00
Bananymous 32c35a822b BuildSystem: binutils1.39->1.44, gcc12.2.0->15.1.0 2025-06-19 19:00:50 +03:00
Bananymous 7a645b8555 Kernel: Add SMP message StackTrace
This event is sent when user presses ctrl+{F1-F12} and it will dump the
corresponding processor's stack trace. This is really helpful for
detecting deadlocks in the system
2025-06-02 11:39:18 +03:00
Bananymous c5b0d0235f Kenrel: Allow Processor::send_smp_message to send event to current CPU 2025-06-02 11:39:18 +03:00
Bananymous 6542a037df Kernel: Make spinlocks more safe
Kernel now makes sure thread is not holding any spinlocks when it tries
to lock a mutex or yield. Spinlocks are supposed to be only used for
short times without the possibility of yielding
2025-06-01 13:48:03 +03:00
Bananymous d1bb72f6fb Kernel: Don't allow CPU load printing underflow 2025-05-13 10:19:13 +03:00
Bananymous cc7c1ad30d Kernel: Add per terminal palette for TerminalDriver
This allows better color approximation on text mode and in future will
allow user to possibly change the palette
2025-04-23 18:44:37 +03:00
Bananymous 554b13ac50 Kernel: Restructure terminal initialization
This is still very ugly and will be rewritten in the future :D
2025-04-18 01:19:59 +03:00
Bananymous 4bcd3ed86f Kernel: Start working on TLS, add SYS_{SET,GET}_TLS 2025-04-15 23:31:17 +03:00
Bananymous 2d11ce9669 Kernel: Fix interrupt system
I had not understood how MSIs work and I was unnecessarily routing them
through IOAPIC. This is not necessary and should not be done :D

Also MSIs were reserving interrupts that IOAPIC was capable of
generating. Now IOAPIC and MSIs use different set of interrupts so
IOAPIC can use more interrupts if needed.
2024-09-27 15:31:31 +03:00
Bananymous bb1738db8c Kernel: Make thread unblocking O(1)
This is still bit broken. VirtualBox seems to freeze sometimes, but I
could not recreate this on qemu (with and without kvm) or real hardware.
2024-07-24 00:31:01 +03:00
Bananymous 539afb329a Kernel: All processors use LAPIC timer when running with APIC
This makes scheduler preemption much cleaner as bsb does not have to
send smp messages to notify other processes about timer interrupt.

Also PIT percision is now "full" 0.8 us instead of 1 ms that I was using
before.
2024-07-23 02:28:52 +03:00
Bananymous 3e0150f847 Kernel: Pressing F1 now toggles rendering of CPU loads to the terminal
This can be nice for seeing the performance and problems on the load
balancing algorithm.
2024-07-22 00:43:13 +03:00
Bananymous f8261c60c0 Kernel: Rewrite the whole scheduler and re-architecture SMP handling
Change Semaphore -> ThreadBlocker
  This was not a semaphore, I just named it one because I didn't know
  what semaphore was. I have meant to change this sooner, but it was in
  no way urgent :D

Implement SMP events. Processors can now be sent SMP events through
IPIs. SMP events can be sent either to a single processor or broadcasted
to every processor.

PageTable::{map_page,map_range,unmap_page,unmap_range}() now send SMP
event to invalidate TLB caches for the changed pages.

Scheduler no longer uses a global run queue. Each processor has its own
scheduler that keeps track of the load on the processor. Once every
second schedulers do load balancing. Schedulers have no access to other
processors' schedulers, they just see approximate loads. If scheduler
decides that it has too much load, it will send a thread to another
processor through a SMP event.

Schedulers are currently run using the timer interrupt on BSB. This
should be not the case, and each processor should use its LAPIC timer
for interrupts. There is no reason to broadcast SMP event to all
processors when BSB gets timer interrupt.

Old scheduler only achieved 20% idle load on qemu. That was probably a
very inefficient implementation. This new scheduler seems to average
around 1% idle load. This is much closer to what I would expect. On my
own laptop idle load seems to be only around 0.5% on each processor.
2024-07-22 00:33:50 +03:00
Bananymous 5050047cef Kernel: Rewrite whole scheduler
Current context saving was very hacky and dependant on compiler
behaviour that was not consistent. Now we always use iret for
context saving. This makes everything more clean.
2024-03-29 18:02:12 +02:00
Bananymous 1943c3e7a1 Kernel: Unify IDT and GDT code between x86_64 and x86_32
The code is pretty much the same, so there are just couple macros
differiating initialization.
2024-03-26 16:42:02 +02:00
Bananymous 7f029b2713 Kernel: Allow Processor compilation for i386 targets
This is achieved by rewriting some inline assembly and changing
ProcessorID to be 32 bit value. For some reason if processor id
is 8 bits gcc runs out of 8 bit registers on i386.
2024-03-22 15:41:15 +02:00
Bananymous 55d2a64f54 Kernel: Map interrupt handlers for all processors
This doesn't mean that processors will actually handle the irqs
2024-03-09 23:50:57 +02:00
Bananymous 2420886c2c Kernel: Move current and idle thread to Processor 2024-03-08 23:39:29 +02:00
Bananymous 29fd682672 Kernel: Store current processor pointer in IA32_GS_BASE
This allows easier access to processors fields
2024-03-07 16:05:29 +02:00
Bananymous 76b0f80169 Kernel: Move IDT to Processor 2024-03-06 00:45:54 +02:00
Bananymous f84df175ce Kernel: Save BSB id 2024-03-06 00:36:09 +02:00
Bananymous 58aca68726 Kernel: Move GDT to Processor 2024-03-06 00:35:45 +02:00
Bananymous 8141b9977d Kernel: Per processor information is now stored in class Processor
This allows us to allocate processor stacks, and other per processor
structures dynamically in runtime. Giving processor stack to
ap_trampoline feels super hacky, but it works for now.
2024-03-03 22:30:06 +02:00