Commit Graph

508 Commits

Author SHA1 Message Date
Justin C. Miller
ab31825ab3 [boot] Restructure boot paging and program loading
Restructuring paging into an object that carries its page cache with it
and makes for simpler code. Program loading is also changed to not copy
the pages loaded from the file into new pages - we can impose a new
constraint that anything loaded by boot have a simple, page-aligned
layout so that we can just map the existing pages into the right
addresses. Also included are some linker script changes to help
accommodate this.
2023-02-05 22:02:41 -08:00
Justin C. Miller
86d458fc6c [util] Move remaining *printf impementations to util::format
I added util::format as a replacement for other printf implementations
last year, but it sat there only being used by the kernel all this time.
Now I've templated it so that it can be used by the bootloader, and
removed printf from panic.serial as well.
2023-02-03 23:42:35 -08:00
Justin C. Miller
eba0127645 [bonnibel] Allow modules to list ld scripts in definition
Previously, to add a custom linker script, a module would need to modify
its variables after the fact to add to ldflags. Now module constructors
take a new keyword `ld_script` and handle the ldflags and dependencies
properly.
2023-01-31 23:57:39 -08:00
Justin C. Miller
5ea5978ee8 [kernel] Hide kernel symbols by default
Using `-fvisibility=hidden` when building the kernel, and then
`--discard-all` when stripping it, we shave almost 100KiB off of the
resulting ELF file.

Also dropped some unused symbols from the linker script, and rearranged
the sections so that the file is able to be mapped directly into memory
instead of having each section copied.
2023-01-29 20:27:21 -08:00
Justin C. Miller
1b0c0b6dbe [util] Add missing <new> header
The <new> header was previously in one of the util headers, masking that
it was missing from these files.
2023-01-14 18:33:34 -08:00
Justin C. Miller
e93f48e2f7 [kernel] Track capability reference counts
First pass at reference-counting capabilities.
2023-01-14 15:43:07 -08:00
Justin C. Miller
28cd3bb625 [kernel] Rename kernel main.cpp
Having main.cpp in the kernel and in the application being debugged is
annoying when setting breakpoints, so just like with main() vs
kernel_main(), kernel/main.cpp is now kernel/kernel_main.cpp.
2023-01-14 15:43:07 -08:00
Justin C. Miller
6ac4ec601d [kernel] standardize static constexpr order in kobject headers
The kobject headers flip-flopped the class constants between "static
constexpr" and "constexpr static".
2023-01-14 15:43:07 -08:00
Justin C. Miller
372bc1d2e6 [kernel] Store object ids instead of full koids
In preparation for futexes, I wanted to make kobjects a bit lighter.
Storing 32 bits of object id, and 8 bits of type (and not ending the
class in a ushort for handle count, which meant all kobjects were likely
to have a bunch of pad bytes), the kobject class data is now just one 8
byte word.

Also from this, change logs that mention threads or processes from
printing the full koid to just 2 bytes of object id from both process
and thread, which makes following the logs much easier.
2022-10-20 22:41:16 -07:00
Justin C. Miller
2703080df2 [kernel] Add thread_join syscall
Thread joining is an important primitive that I seem to have totally
forgotten to implement previously.
2022-10-20 21:58:10 -07:00
Justin C. Miller
194776d226 [kernel] Remove status code from thread exit
The status code from thread exit had too many issues, (eg, how does it
relate to process exit code? what happens when different threads exit
with different exit codes?) and not enough value, so I'm getting rid of
it.
2022-10-20 21:49:40 -07:00
Justin C. Miller
c02aa084d1 [kernel] Allow for not passing handles in new mailbox calls
In the new mailbox structure, passing a j6_handle_invalid with a message
would result in a permission denied result, as the process did not have
a handle "0".
2022-10-14 21:55:46 -07:00
Justin C. Miller
f5f2076db5 [kernel] Lock the heap allocator for part of reallocate
heap_allocator::reallocate relies on the allocate and free methods so
mostly doesn't need locking, but it does touch the tracking map, so
needs to protect that with a lock.
2022-10-14 01:07:37 -07:00
Justin C. Miller
1a04310f80 [kernel] Simplify mailbox code, and messages
A number of simplifications of mailboxes now that the interface is much
simpler, and synchronous.

* call and respond can now only transfer one handle at a time
* mailbox objects got rid of the message queue, and just have
  wait_queues of blocked threads, and a reply_to map.
* threads now have a message_data struct on them for use by mailboxes
2022-10-14 01:02:56 -07:00
Justin C. Miller
e830a3d37b [kernel] Move slab_allocated items to the heap
Allocate the slabs for slab-allocated items to the heap, now that heap
regions are aligned. This also lets the slab sizes be non-page-sized.
2022-10-11 18:52:19 -07:00
Justin C. Miller
c9bcc87511 [kernel] Simplify mailbox interface to call/respond
The only real usage of mailbox was mailbox_call or
mailbox_respond_receive. This change simplifies the interface to just
these syscalls.
2022-10-11 17:42:04 -07:00
Justin C. Miller
9ac4e51224 [kernel] Make capabilities/handles global
Instead of handles / capabilities having numeric ids that are only valid
for the owning process, they are now global in a system capabilities
table. This will allow for specifying capabilities in IPC that doesn't
need to be kernel-controlled.

Processes will still need to be granted access to given capabilities,
but that can become a simpler system call than the current method of
sending them through mailbox messages (and worse, having to translate
every one into a new capability like was the case before). In order to
track which handles a process has access to, a new node_set based on
node_map allows for an efficient storage and lookup of handles.
2022-10-10 21:19:25 -07:00
Justin C. Miller
ba0ce13fe3 [util] Add util allocator.h interface
The allocator is a interface for types that expose allocator functions
for use in container templates like node_map (usage coming soon).

Also added an implementation for the kernel heap allocator.
2022-10-10 20:54:30 -07:00
Justin C. Miller
48e3f9f9d2 [kernel] Fix freelist-clobber bug in heap allocator
The heap_allocator::get_free(order) function returns a reference to the
head pointer of the given freelist, so that it can be manipulated.
However, split_off was also taking a reference to a pointer for an out
param - passing the freelist pointer in here caused split_off to modify
the freelist.

I cleaned up a bunch of the places the freelist pointers were being
touched to make the usage more explicit.
2022-10-10 20:50:08 -07:00
Justin C. Miller
6b20f1fb19 [kernel] Make sure high bits are 0 writing SFMASK MSR
QEMU handles bits bring written in the (reserved) high bits of SFMASK
just fine, but KVM gives a #GP exception.
2022-10-04 20:10:41 -07:00
Justin C. Miller
e90647d498 [kernel] Change heap alloc for better alignment
Created a new util/node_map.h that implements a map that grows in-place.
Now this is used for tracking blocks' size orders, instead of a header
at the start of the memory block. This allows the whole buddy block to
be allocated, allowing for page-aligned (or greater) blocks to be
requested from the heap.
2022-10-02 17:32:26 -07:00
Justin C. Miller
11b61ab345 [kernel] Change kernel log levels
The kernel log levels are now numerically reversed so that more-verbose
levels can be added to the end. Replaced 'debug' with 'verbose', and
added new 'spam' level.
2022-09-25 17:25:43 -07:00
Justin C. Miller
7b8fd76af0 [libj6] Move caps.h to cap_flags.h
This file is just the generated cap flag constants. Move it to not
collide with more capability code to be added.
2022-09-25 17:23:14 -07:00
Justin C. Miller
a2b876825a [kernel] Move mispalced slab_allocated.h
slab_allocated.h had accidentally been placed in src/kernel/objects
2022-09-25 17:15:00 -07:00
Justin C. Miller
9f981ada41 [kernel] Save rsp0 to a process' TSS too
On task switch a process' rsp0 value in its TSS was not getting updated.
2022-09-16 19:39:32 -07:00
Justin C. Miller
5c26308b23 [kernel] Fix inverted block flag in mailbox_receive
The `block` flag was operating the opposite of its intended behavior.
2022-09-11 14:14:39 -07:00
Justin C. Miller
7fd39e91c1 [kernel] Pull block_allocator out into separate class
The vm_area_guarded code to keep a list of used/free block addresses
will be useful elsewhere.
2022-09-11 14:12:18 -07:00
Justin C. Miller
e2f4dad288 [kernel] Interrupt vector priority rearrangement
Rearranging of the ISR vectors for eventual TPR priority. Also removed
excess IRQs - if we need to support more than 64 IRQ vectors, we can add
some more back in.

Also clean up the legacy PIC init/masking code.
2022-03-13 20:00:49 -07:00
Justin C. Miller
d759aae318 [kernel] Add new threads to different CPUs
Previously, when adding a new thread, we only ever added it to the
current CPU and relied on work stealing to balance the CPUs. This commit
has the scheduler schedule new tasks round-robin across CPUs in hopes of
having to steal fewer tasks.

Also adds the run_queue.prev pointer for debugging what task was just
running on the given CPU.
2022-03-13 18:07:08 -07:00
Justin C. Miller
bb0d30610e [util] Add util::format replacement for snprintf
The printf library I have been using, while useful, has way more than I
need in it, and had comparably huge stack space requirements. This
change adds a new util::format() which is a replacement for snprintf,
but with only the features used by kernel logging.

The logger has been changed to use it, as well as the few instances of
snprintf in the interrupt handling code before calling kassert.

Also part of this change: the logger's (now vestigial) immediate output
handling code is removed, as well as the "sequence" field on log
message headers.
2022-03-13 17:59:56 -07:00
Justin C. Miller
24f324552a [kernel] Get rid of fake stack frame in isr_prelude
The isr_prelude (and its IRQ equivalent) had been pushing RIP and RBP in
order to create a fake stack frame. This was in an effor to make GDB
display tracebacks more reliably, but GDB has other reasons for being
finnicky about stack frames, so this was just wasted. This commit gets
rid of it to make looking at the stack clearer.
2022-03-13 17:54:27 -07:00
Justin C. Miller
5c3943bf38 [kernel] Make grabbing an IST stack atomic
In the beginning of the interrupt handler, we had previously checked if
the current handler had grabbed an IST stack from the IDT/TSS. If it
was, it saved this value and set it to 0 in the IDT, then restored it at
the end.

Now this is an atomic action. This is unlikely to make a difference
unless the interrupt handler is itself interrupted by an exception
before being able to swap the IDT value, but such a situation is now
impossible.
2022-03-13 17:49:29 -07:00
Justin C. Miller
90663a674a [kernel] Unify CPUs' control register settings
Previously, the CPU control registers were being set in a number of
different ways. Now, since the APs' need this to be set in the CPU
initialization code, always do it there. This removes some of the
settings from the bootloader, and some unused ones from smp.s.
Additionally, the control registers' flags are now enums in cpu.h and
manipulated via util::bitset.
2022-03-13 17:45:16 -07:00
Justin C. Miller
1cc22e78e2 [kernel] Save all cpu_data pointers in global array
For the sake of introspection and debugging, I created a new g_cpu_data
pointer, which points to an array of cpu_data pointers.
2022-03-13 17:40:19 -07:00
Justin C. Miller
95252e793c [kernel] Fix incorrect BSP idle rsp0
In bsp_early_init(), the BSP cpu_data's rsp0 was getting initialized to
the _value_ at the idle_stack_end symbol, instead of its address. I
don't believe this was causing any actual harm, but it was a red herring
when debugging.
2022-03-13 17:36:33 -07:00
Justin C. Miller
54aef00913 [cpu] Reimplement CPUID features as util::bitset
The cpu::cpu_id class no longer looks up all known features in the
constructor, but instead provides access to the map of supported
features as a bitset from the verify() method. It also exposes the
brand_name() method instead of loading the brand name string in the
constructor and storing it as part of the object.
2022-03-13 17:33:16 -07:00
Justin C. Miller
d08e5dabe4 [kernel] Fix AP idle stack overflow
This bug has been making me tear my hair out for weeks. When creating
the idle thread for each CPU, we were previously sharing stack areas
with other CPUs' idle threads in an effort to save memory. However, this
caused stack corruption that was very hard to track down. The kernel
stacks are in a vm_area_guarded to better detect this exact kind of
issue, but splitting stacks like this skirts that protection. It's not
worth saving a few KiB per CPU.
2022-03-13 16:58:57 -07:00
Justin C. Miller
ef307e8ec6 [kernel] Fix mailbox bugs
This commit contains a number of related mailbox issues:

- Add extra parameters to mailbox_respond_receive to allow both the
  number of bytes/handles passed in, and the size of the byte/handle
  buffers to be passed in.
- Don't delete mailbox messages on receipt if the caller is waiting on
  reply
- Correctly pass status messages along with a mailbox::replyer object
- Actually wake the calling thread in the mailbox::replyer dtor
- Make sure to release locks _before_ calling thread::wake() on blocked
  threads, as that may cause them to be scheduled ahead of the current
  thread.
2022-02-28 20:16:42 -08:00
Justin C. Miller
b8684777e0 [kernel] Allow blocking on empty channels
This commit adds a new flag, j6_channel_block, and a new flags param to
the channel_receive syscall. When the block flag is specified, the
caller will block waiting for data on the channel if the channel is
empty.
2022-02-28 20:10:56 -08:00
Justin C. Miller
446025fb65 [kernel] Add clear() method to wait_queue
Allow objects to clear out the wait_queue earlier than waiting for the
destructor by moving that functionality into wait_queue::clear().
2022-02-28 20:06:49 -08:00
Justin C. Miller
f87a4fcd4e [kernel] Don't delete system object on no handles
The system object should never be deleted, so override on_no_handles()
to do nothing.
2022-02-28 18:50:59 -08:00
Justin C. Miller
9120318594 [kernel] Change thread_sleep arg from time to duration
It seems more common to want to sleep for a duration than to sleep to a
specific time. Change the implementation to not make the process look up
the current time first. (Plus, there's no current syscall to do so)
2022-02-28 18:43:20 -08:00
Justin C. Miller
982442eb00 [kernel] Add an IPI to tell a CPU to run the scheduler
When waking another thread, if that thread has a more urgent priority
than the current thread on the same CPU, send that CPU an IPI to tell it
to run its scheduler.

Related changes in this commit:

- Addition of the ipiSchedule isr (vector 0xe4) and its handler in
  isr_handler().
- Change the APIC's send_ipi* functions to take an isr enum and not an
  int for their vector parameter
- Thread TCBs now contain a pointer to their current CPU's cpu_data
  structure
- Add the maybe_schedule() call to the scheduler, which sends the
  schedule IPI to the given thread's CPU only when that CPU is running a
  less-urgent thread.
- Move the locking of a run queue lock earlier in schedule() instead of
  taking the lock in steal_work() and again in schedule().
2022-02-26 14:04:14 -08:00
Justin C. Miller
40274f5fac [kernel] Fix logger::get_entry() blocking bug
The new logger event object for making get_entry() block when no logs
are available was consuming the event's notification even if the thread
did not need to block. This was causing excessive blocking - if multiple
logs had been added since the last call to get_entry(), only one would
be returned, and the next call would block until yet another log was
added.

Now only call event::wait() to block the calling thread if there are no
logs available.
2022-02-26 13:46:11 -08:00
Justin C. Miller
a03804b09d [kernel] Add RAII profiler object
Added profiler.h which defines classes and macros for defining profiler
objects. Also added gdb command j6prof for printing profile data. Added
the syscall_profiles profiler class and auto wrapping of syscalls with
profile objects.

Other changes in this commit:

- Made the gdb command `j6threads` argument for specifying a CPU
  optional. Without an argument, it loops through all CPUs.
- Switched to -mcmodel=kernel for kernel code, which makes `call`
  instructions easier to follow when debugging / looking at disassembly.
2022-02-26 13:19:21 -08:00
Justin C. Miller
a9f40cf608 [panic] Improve panic register display
A few changes to the panic handler's display:

- Change rdi and rsi to match other general-purpose registers. (They
  were previously blue, matching the stack/base pointer registers.)
- Change the ordering of r8-r15 to be column-major instead of row-major.
  I find myself wanting to read down the columns to find the register
  I'm looking for, and rax-rdx are already this way.
- Make the flags register yellow, matching the ss and cs registers
- Comment out the call to print_rip() call, as it's only occasionally
  helpful and can cause the panic handler to page fault.
2022-02-26 13:14:16 -08:00
Justin C. Miller
82025bacad [kernel] Make bsp_idle a separate symbol
When debugging, or in panic callstacks, the BSP idle thread used to be
reported as `_kernel_start`, because it was just the loop at the end of
that assembly function. Now, wrap that loop in a separate symbol called
`bsp_idle` to make it clearer that the cpu is in the idle thread.
2022-02-26 13:04:21 -08:00
Justin C. Miller
63265728d4 [kernel] Fix build breakage
Three issues that caused build breaks when regenerating the build
directory after the previous commits:

- system.def was including endpoint.def
- syscalls/vm_area.cpp was including j6/signals.h
- util/util.h was missing an include of stddef.h
2022-02-22 00:12:07 -08:00
Justin C. Miller
30aed15090 [kernel] Replace endpoint with new mailbox API
The new mailbox kernel object API offers asynchronous message-based IPC
for sending data and handles between threads, as opposed to endpoint's
synchronous model.
2022-02-22 00:06:14 -08:00
Justin C. Miller
f7ae2e2220 [kernel] Re-design thread blocking
In preparation for the new mailbox IPC model, blocking threads needed an
overhaul. The `wait_on_*` and `wake_on_*` methods are gone, and the
`block()` and `wake()` calls on threads now pass a value between the
waker and the blocked thread.

As part of this change, the concept of signals on the base kobject class
was removed, along with the queue of blocked threads waiting on any
given object. Signals are now exclusively the domain of the event object
type, and the new wait_queue utility class helps manage waiting threads
when an object does actually need this functionality. In some cases (eg,
logger) an event object is used instead of the lower-level wait_queue.

Since this change has a lot of ramifications, this large commit includes
the following additional changes:

- The j6_object_wait, j6_object_wait_many, and j6_thread_pause syscalls
  have been removed.
- The j6_event_clear syscall has been removed - events are "cleared" by
  reading them now. A new j6_event_wait syscall has been added to read
  events.
- The generic close() method on kobject has been removed.
- The on_no_handles() method on kobject now deletes the object by
  default, and needs to be overridden by classes that should not be.
- The j6_system_bind_irq syscall now takes an event handle, as well as a
  signal that the IRQ should set on the event. IRQs will cause a waiting
  thread to be woken with the appropriate bit set.
- Threads waking due to timeout is simplified to just having a
  wake_timeout() accessor that returns a timestamp.
- The new wait_queue uses util::deque, which caused the disovery of two
  bugs in the deque implementation: empty deques could still have a
  single array allocated and thus return true for empty(), and new
  arrays getting allocated were not being zeroed first.
- Exposed a new erase() method on util::map that takes a node pointer
  instead of a key, skipping lookup.
2022-02-22 00:00:15 -08:00