Commit Graph

221 Commits

Author SHA1 Message Date
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
41bb97b179 [util] Add node_set container
Add a new node_set container that is backed by a node_map internally.
Also switch node_map to use the new allocator interface.
2022-10-10 21:04:51 -07:00
Justin C. Miller
531e160136 [util] Fix node_map growth
When node_map grew, it was not properly applying the fixup routine to
non-moved elements. This fixes the grow algorithm to:

1. Realloc the array and set all new slots to empty/invalid
2. Check each old slot and remove/reinsert the item if it exists and its
   optimal slot is later in the array than its current slot
3. Reverse-iterate the original slots and call fixup() on empty slots to
   keep items from being located after a more-optimal empty slot

Also fixed the fixup() function to not need to be called in a loop
anymore, as it's only used the one way - on a given empty slot, looping
until it hits an empty slot or optimally-placed item.
2022-10-10 20:58:31 -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
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
1d4c66a9a0 [util] Make bitset more constexpr-friendly
In order to more easily express constants as bitsets, add more constexpr
to util::bitset. This allows expressing uint64_t constants as bitsets in
the code instead, without changing the generated assembly, to make code
more readable.
2022-09-11 14:07:21 -07:00
Justin C. Miller
31c2053c1c [libc] Implement some math.h functions with builtins
This commit adds implementation of some of the basic math.h functions
with compiler builtins.
2022-03-13 18:11:45 -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
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
e2eaf43b4a [util] Add templated bitset class
Add a new bitset class which allows for arbitrarily-large bit sets, with
specializations for 32 and 64 bit sets.

Eventually the enum_bitfields code should probably be reconsidered and
moved to bitsets, since it doesn't work everywhere.
2022-03-13 17:26:29 -07:00
Justin C. Miller
8b5aedd463 [libc] Stub out math.h
Stub out math.h in order to include c++ headers that include it but
don't actually call any math functions.
2022-02-28 20:34:32 -08:00
Justin C. Miller
17dcb961ec [srv.init] Serve a service locator protocol from init
The init process now serves as a service locator for its children,
passing all children a mailbox handle on which it is serving the service
locator protocol.
2022-02-28 20:23:18 -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
19105542e5 [libc] Change memcpy back to rep movsb
Influenced by other libc implementations, I had tried to make memcpy
smarter for differently-sized ranges, but my benchmarks showed no real
change. So change memcpy back to the simple rep movsb implementation.
2022-02-28 18:56:38 -08:00
Justin C. Miller
467c2408c4 [util] Specialize util::hash() for more integer types
There was a specialization of util::hash() for uint64_t (which just
returns the integer value), but other integer sizes did not previously
have similar specializations.

Also, two minor semi-related changes to util::map - skip copying empty
nodes when growing the map, and assert that the hash is non-zero when
inserting a new node.
2022-02-28 18:52:18 -08:00
Justin C. Miller
2640cea175 [util] Update constexpr hash to be FNV-1a
The constexpr_hash.h header has fallen out of use. As constexpr hashing
will be used for IDs with the service locator protocol, update these
hashes to be 32 and 64 bit FNV-1a, and replace the _h user-defined
literal with _id (a 64-bit hash), and _id8 (a 32-bit hash folded down to
8 bits). These are now in the util/hash.h header along with the runtime
hash functions.
2022-02-22 00:20:00 -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
69a3b6dad7 [test_runner] Add handle test suite
For now this just tests handle cloning and basic capability checking.
2022-02-22 00:11:38 -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
Justin C. Miller
b46b6363ff [libc] Run the .preinit_array as well in __init_libc
The __init_libc function was already running the .init_array functions,
but was never running the .preinit_array functions. Now it runs them
both, in the correct order.
2022-02-13 00:09:36 -08:00
Justin C. Miller
6dea9a4b63 [libc] Fix memset off-by-half error
The first bug caught by test_runner! Due to a single-character typo,
memset was only ever setting about half of the buffer it was given.
2022-02-12 21:36:51 -08:00
Justin C. Miller
d20c77c618 [libc] Call global ctors in user code
This change adds a new __init_libc function which calls all the global
ctors in .init_array, and is called from _start.
2022-02-12 13:55:07 -08:00
Justin C. Miller
d7bf156b30 [libc] Move getenv back to stdlib
Why was I trying to put getenv in stdio? It belongs in stdlib.
2022-02-12 01:29:57 -08:00
Justin C. Miller
195b635f74 [libc] Implement atexit et al
This commit joins the implementation of exit, _Exit, and abort into a
single translation unit, and also adds atexit, at_quick_exit, and
quick_exit. While this does go against the ideal of all libc functions
being in their own translation unit, their implementations are very
related, and so I think this makes sense.
2022-02-10 20:36:04 -08:00
Justin C. Miller
c0ae77cd64 [libc] Add stubbed-out stdio and libdl functions
In order to fix link errors with libunwind, stub out these functions for
now.
2022-02-09 18:51:02 -08:00
Justin C. Miller
57b2d6dbd8 [libc] Fix noreturn c++ compatibility
Stop using bare "noreturn" with library functions, and use the more
cross-compatible "_Noreturn" instead.
2022-02-09 18:49:16 -08:00
Justin C. Miller
4e3ba66b0c [libc] Consolidate ctype
The ctype functions are now both macros and functions (as allowed by the
spec). They're now implemented in the ctype_b style of glibc, as
libunwind wants __ctype_b_loc to work.
2022-02-09 18:48:53 -08:00
Justin C. Miller
68a6007fd9 [kernel] Add "noreturn" syscall option
The new "noreturn" option tag on syscall methods causes those methods to
be generated with [[noreturn]] / _Noreturn to avoid clang complaining
that other functions marked noreturn, like exit(), because it can't tell
that the syscall never returns.
2022-02-06 21:41:05 -08:00
Justin C. Miller
346c172b32 [libc] Add new libc
This new libc is mostly from scratch, with *printf() functions provided
by Marco Paland and Eyal Rozenberg's tiny printf library, and malloc and
friends provided by dlmalloc.
2022-02-06 21:39:04 -08:00
Justin C. Miller
5ddac353a0 [libc] Remove old libc
Removing the very old PDCLib-based libc, in preparation for adding the
new one.
2022-02-06 12:26:48 -08:00
Justin C. Miller
4545256b49 [build] Move headers out of target dirs
The great header shift: It didn't make sense to regenerate headers for
the same module for every target (boot/kernel/user) it appeared in. And
now that core headers are out of src/include, this was going to cause
problems for the new libc changes I've been working on. So I went back
to re-design how module headers work.

Pre-requisites:
- A module's public headers should all be available in one location, not
  tied to target.
- No accidental includes. Another module should not be able to include
  anything (creating an implicit dependency) from a module without
  declaring an explicit dependency.
- Exception to the previous: libc's headers should be available to all,
  at least for the freestanding headers.

New system:
- A new "public_headers" property of module declares all public headers
  that should be available to dependant modules
- All public headers (after possible processing) are installed relative
  to build/include/<module> with the same path as their source
- This also means no "include" dir in modules is necessary. If a header
  should be included as <j6/types.h> then its source should be
  src/libraries/j6/j6/types.h - this caused the most churn as all public
  header sources moved one directory up.
- The "includes" property of a module is local only to that module now,
  it does not create any implicit public interface

Other changes:
- The bonnibel concept of sources changed: instead of sources having
  actions, they themselves are an instance of a (sub)class of Source,
  which provides all the necessary information itself.
- Along with the above, rule names were standardized into <type>.<ext>,
  eg "compile.cpp" or "parse.cog"
- cog and cogflags variables moved from per-target scope to global scope
  in the build files.
- libc gained a more dynamic .module file
2022-02-06 10:18:51 -08:00
Justin C. Miller
0e80c19d3d [kernel] Add test mode, controlled by manifest
The manifest can now supply a list of boot flags, including "test".
Those get turned into the bootproto::args::flags field by the
bootloader. The kernel takes those and uses the test flag to control
enabling syscalls with the new "test" attribute, like the new
test_finish syscall, which lets automated tests call back to the kernel
to shut down the system.
2022-02-03 19:45:46 -08:00
Justin C. Miller
e3ecd73cd8 [util] Add constexpr log2/is_pow2 helpers
I didn't end up using these, but constexpr log2 and is_pow2 functions
might be helpful.
2022-01-30 21:02:32 -08:00
Justin C. Miller
5dfc6ae62e [kernel] Add event syscalls
The event object was missing any syscalls. Furthermore, kobject had an
old object_signal implementation (the syscall itself no longer exists),
which was removed. User code should only be able to set signals on
events.
2022-01-30 21:00:46 -08:00
Justin C. Miller
343622d4e5 [kernel] Fix up formatting
Two minor issues: scheduler::prune wasn't formatted correctly, and
j6/caps.h was not using the ull prefix when shifting 64 bit numbers.
(It's doubtful an object would get more than 32 caps any time soon, but
better to be correct.)
2022-01-30 20:52:43 -08:00
Justin C. Miller
a7245116b6 [util] Add util::deque container
Adding the util::deque container, implemented with the util::linked_list
of arrays of items.

Also, use the deque for a kobject's blocked thread list to maintain
order instead of a vector using remove_swap().
2022-01-30 20:42:49 -08:00
Justin C. Miller
b6218a1121 [kernel] Allow 7+ argument syscalls
The syscall interface is designed to closely follow the System V amd64
calling convention, so that as much as possible, the call into the
assembly trampoline for the syscall sets up the call correctly. Before
this change, the only exception was using r10 (a caller-saved register
already) to stash the contents of rcx, which gets clobbered by the
syscall instruction. However, this only preserves registers for the
function call, as the stack is switched upon kernel entry, and
additional call frames have been added by the time the syscall gets back
into C++ land.

This change adds a new parameter to the syscall in rbx. Since rbx is
callee-saved, the syscall trampoline pushes it to the stack, and then
puts the address of the stack-passed arguments into rbx. Now that the
syscall implementations are wrapped in the _syscall_verify_* functions,
we can piggy-back on those to also set up the extra arguments from the
user stack.

Now, for any syscall with 7 or more arguments, the verify wrapper takes
the first six arguments normally, then gets a stack pointer (the rbx
value) as its 7th and final argument. It's then the job of the verify
wrapper to get the remaining arguments from that stack pointer and pass
them to the implementation function as normal arguments.
2022-01-30 12:25:11 -08:00
Justin C. Miller
cd037aca15 [kernel] Let objects inherit caps from superclasses
The main point of this change is to allow "global" capabilities defined
on the base object type. The example here is the clone capability on all
objects, which governs the ability to clone a handle.

Related changes in this commit:
- Renamed `kobject` to `object` as far as the syscall interface is
  concerned. `kobject` is the cname, but j6_cap_kobject_clone feels
  clunky.
- The above change made me realize that the "object <type>" syntax for
  specifying object references was also clunky, so now it's "ref <type>"
- Having to add `.object` on everywhere to access objects in
  interface.exposes or object.super was cumbersome, so those properties
  now return object types directly, instead of ObjectRef.
- syscall_verify.cpp.cog now generates code to check capabilities on
  handles if they're specified in the definition, even when not passing
  an object to the implementation function.
2022-01-29 15:56:33 -08:00
Justin C. Miller
f1246f84e0 [kernel] Add capabilities to handles
This change finally adds capabilities to handles. Included changes:

- j6_handle_t is now again 64 bits, with the highest 8 bits being a type
  code, and the next highest 24 bits being the capability mask, so that
  programs can check type/caps without calling the kernel.
- The definitions grammar now includes a `capabilities [ ]` section on
  objects, to list what capabilities are relevant.
- j6/caps.h is auto-generated from object capability lists
- init_libj6 again sets __handle_self and __handle_sys, this is a bit
  of a hack.
- A new syscall, j6_handle_list, will return the list of existing
  handles owned by the calling process.
- syscall_verify.cpp.cog now actually checks that the needed
  capabilities exist on handles before allowing the call.
2022-01-28 01:54:45 -08:00
Justin C. Miller
42d7f4245d [kernel] Remove placement-new declaration from memory.h.cog
Finishing the trend of using `#include <new>` to define new, get rid of
the last bits of custom-declared operator new.
2022-01-27 22:04:06 -08:00
Justin C. Miller
0394f29f70 [util] Add release() and reaquire() to scoped_lock
Added methods for releasing the lock held in a scoped_lock early, as
well as reacquiring it after. Useful when, eg a thread is about to block
and should not be holding the lock while blocked.
2022-01-23 19:40:00 -08:00
Justin C. Miller
2750ec8ef9 [util] Fix bip_buffer concurrency bug
If a bip_buffer's A buffer is in the middle of being appended to, but
that append has not yet been committed, and all committed A data has
been read, the buffer would get into a bad state where m_start_r pointed
to the end of the previous A buffer, but that data is no longer
connected to either A or B. So now we make sure to check m_size_r before
considering A "done".
2022-01-23 17:43:30 -08:00
Justin C. Miller
1d30322820 [kernel] Pass objects not handles to syscall impls
This commit contains a couple large, interdependent changes:

- In preparation for capability checking, the _syscall_verify_*
  functions now load most handles passed in, and verify that they exist
  and are of the correct type. Lists and out-handles are not converted
  to objects.
- Also in preparation for capability checking, the internal
  representation of handles has changed. j6_handle_t is now 32 bits, and
  a new j6_cap_t (also 32 bits) is added. Handles of a process are now a
  util::map<j6_handle_t, handle> where handle is a new struct containing
  the id, capabilities, and object pointer.
- The kernel object definition DSL gained a few changes to support auto
  generating the handle -> object conversion in the _syscall_verify_*
  functions, mostly knowing the object type, and an optional "cname"
  attribute on objects where their names differ from C++ code.
  (Specifically vma/vm_area)
- Kernel object code and other code under kernel/objects is now in a new
  obj:: namespace, because fuck you <cstdlib> for putting "system" in
  the global namespace. Why even have that header then?
- Kernel object types constructed with the construct_handle helper now
  have a creation_caps static member to declare what capabilities a
  newly created object's handle should have.
2022-01-17 23:23:04 -08:00
Justin C. Miller
44d3918e4f [util] Add try_aquire to spinlock
Also added a scoped_trylock class that mirrors scoped_lock, but uses
try_aquire and has a scoped_lock::locked() accessor.
2022-01-15 17:51:55 -08:00
Justin C. Miller
19f9496889 [kernel] Add a timeout to endpoint recieve syscalls
This also required adding support for multiple wait conditions on a
thread, so wait_type is an enum_bitfield now.

I really need a real clock.
2022-01-15 17:48:19 -08:00
Justin C. Miller
7bb6b21c65 [kernel] Simplify kernel logger
The logger had a lot of code that was due to it being in kutil instead
of the kernel. Simplifying it a bit here in order to make the uart
logger easier and eventual paring down of the logger easier.

- Log areas are no longer hashes of their names, just an enum
- Log level settings are no longer saved in 4 bits, just a byte
- System signal updating is done in the logger now
2022-01-15 10:00:13 -08:00
Justin C. Miller
b3aaddadc8 [kernel] Expose a sysconf page to userspace
A structure, system_config, which is dynamically defined by the
definitions/sysconf.yaml config, is now mapped into every user address
space. The kernel fills this with information about itself and the
running machine.

User programs access this through the new j6_sysconf fake syscall in
libj6.

See: Github bug #242
See: [frobozz blog post](https://jsix.dev/posts/frobozz/)

Tags:
2022-01-13 22:08:35 -08:00