Commit Graph

22 Commits

Author SHA1 Message Date
Justin C. Miller
9f54927a82 [util] Remove enum_bitfields
The enum_bitfields system never worked quite right, and always had edge cases where name
resolution for the SFINAE would fail. Move everything over to use util::bitset, which can
be constexpr and boils down to inline integer bitops in release mode.

Improved util::bitset itself, moving the array-backed base implementation into a new
util::sized_bitset, and making the single-inttype backed implementation the base case.
Also added a distinction between | or |= (which work with real bit values) and + or +=
(which work with bit indexes).
2024-02-25 23:40:14 -08:00
Justin C. Miller
f5208d1641 [all] Remove dependencies on non-freestanding libc
This is the first of two rather big changes to clean up includes
throughout the project. In this commit, the implicit semi-dependency on
libc that bonnibel adds to every module is removed. Previously, I was
sloppy with includes of libc headers and include directory order. Now,
the freestanding headers from libc are split out into libc_free, and an
implicit real dependency is added onto this module, unless `no_libc` is
set to `True`. The full libc needs to be explicitly specified as a
dependency to be used.

Several things needed to change in order to do this:

- Many places use `memset` or `memcpy` that cannot depend on libc. The
  kernel has basic implementations of them itself for this reason. Now
  those functions are moved into the lower-level `j6/memutils.h`, and
  libc merely references them. Other modules are now free to reference
  those functions from libj6 instead.
- The kernel's `assert.h` was renamed kassert.h (matching its `kassert`
  function) so that the new `util/assert.h` can use `__has_include` to
  detect it and make sure the `assert` macro is usable in libutil code.
- Several implementation header files under `__libj6/` also moved under
  the new libc_free.
- A new `include_phase` property has been added to modules for Bonnibel,
  which can be "normal" (default) or "late" which uses `-idirafter`
  instead of `-I` for includes.
- Since `<utility>` and `<new>` are not freestanding, implementations of
  `remove_reference`, `forward`, `move`, and `swap` were added to the
  `util` namespace to replace those from `std`, and `util/new.h` was
  added to declare `operator new` and `operator delete`.
2023-07-12 19:38:31 -07:00
Justin C. Miller
2b3c276f33 [util] Abstract out radix_tree class from page_tree
Generalized the radix tree code from page_tree as util::radix_tree so
that it can be used elsewhere.
2023-07-04 17:43:23 -07:00
Justin C. Miller
ed95574c24 [kernel] Add (wip) futex syscalls
Add the syscalls j6_futex_wait and j6_futex_wake. Currently marking this
as WIP as they need more testing.

Added to support futexes:
- vm_area and vm_space support for looking up physical address for a
  virtual address
- libj6 mutex implementation using futex system calls
2023-03-16 19:56:14 -07:00
Justin C. Miller
ada660deeb [kernel] Move log buffer to its own memory section
In prep for the coming change to keep log entries as a true ring buffer,
move the log buffer from bss into its own memory section.

Related changes in this commit:
- New vm_area_ring, which maps a set of pages twice to allow easy linear
  reading of data from a ring buffer when it wraps around the end.
- logger_init() went away, and the logger ctor is called from
  mem::initialize()
- Instead of an event object, the logger just has a bare wait_queue
- util::counted::from template type changed slightly to allow easy
  conversion from an intptr_t as well as a pointer
- Previously added debugcon_logger code removed - this will be added in
  a separate file in a followup commit
2023-02-08 09:21:52 -08: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
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
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
c1d9b35e7c [bootproto] Create new bootproto lib
This is a rather large commit that is widely focused on cleaning things
out of the 'junk drawer' that is src/include. Most notably, several
things that were put in there because they needed somewhere where both
the kernel, boot, and init could read them have been moved to a new lib,
'bootproto'.

- Moved kernel_args.h and init_args.h to bootproto as kernel.h and
  init.h, respectively.

- Moved counted.h and pointer_manipulation.h into util, renaming the
  latter to util/pointers.h.

- Created a new src/include/arch for very arch-dependent definitions,
  and moved some kernel_memory.h constants like frame size, page table
  entry count, etc to arch/amd64/memory.h. Also created arch/memory.h
  which detects platform and includes the former.

- Got rid of kernel_memory.h entirely in favor of a new, cog-based
  approach. The new definitions/memory_layout.csv lists memory regions
  in descending order from the top of memory, their sizes, and whether
  they are shared outside the kernel (ie, boot needs to know them). The
  new header bootproto/memory.h exposes the addresses of the shared
  regions, while the kernel's memory.h gains the start and size of all
  the regions. Also renamed the badly-named page-offset area the linear
  area.

- The python build scripts got a few new features: the ability to parse
  the csv mentioned above in a new memory.py module; the ability to add
  dependencies to existing source files (The list of files that I had to
  pull out of the main list just to add them with the dependency on
  memory.h was getting too large. So I put them back into the sources
  list, and added the dependency post-hoc.); and the ability to
  reference 'source_root', 'build_root', and 'module_root' variables in
  .module files.

- Some utility functions that were in the kernel's memory.h got moved to
  util/pointers.h and util/misc.h, and misc.h's byteswap was renamed
  byteswap32 to be more specific.
2022-01-03 17:44:13 -08:00
Justin C. Miller
5f88f5ed02 [kernel] Move kassert out of kutil
Continuing moving things out of kutil. The assert as implemented could
only ever work in the kernel, so remaining kutil uses of kassert have
been moved to including standard C assert instead.

Along the way, kassert was broken out into panic::panic and kassert,
and the panic.serial namespace was renamed panicking.
2022-01-02 01:38:04 -08:00
Justin C. Miller
d60f8ed8d5 [kernel] Improve VMA lifecycle
The vm_area objects had a number of issues I have been running into when
working on srv.init:

- It was impossible to map a VMA, fill it, unmap it, and hand it to
  another process. Unmapping the VMA in this process would cause all the
  pages to be freed, since it was removed from its last mapping.
- If a VMA was marked with vm_flag::zero, it would be zeroed out _every
  time_ it was mapped into a vm_space.
- The vm_area_open class was leaking its page_tree nodes.

In order to fix these issues, the different VMA types all work slightly
differently now:

- Physical pages allocated for a VMA are now freed when the VMA is
  deleted, not when it is unmapped.
- A knock-on effect from the first point is that vm_area_guarded is now
  based on vm_area_open, instead of vm_area_untracked. An untracked area
  cannot free its pages, since it does not track them.
- The vm_area_open type now deletes its root page_tree node. And
  page_tree nodes will delete child nodes or free physical pages in
  their dtors.
- vm_flag::zero has been removed; pages will need to be zeroed out
  further at a higher level.
- vm_area also no longer deletes itself only on losing its last handle -
  it will only self-delete when all handles _and_ mappings are gone.
2021-09-12 21:55:02 -07:00
F in Chat for Tabs
8f529046a9 [project] Lose the battle between tabs & spaces
I'm a tabs guy. I like tabs, it's an elegant way to represent
indentation instead of brute-forcing it. But I have to admit that the
world seems to be going towards spaces, and tooling tends not to play
nice with tabs. So here we go, changing the whole repo to spaces since
I'm getting tired of all the inconsistent formatting.
2021-08-01 17:46:16 -07:00
Justin C. Miller
72787c0652 [kernel] Make sure all vma types have (virtual) dtors 2021-02-07 23:45:07 -08:00
Justin C. Miller
634a1c5f6a [kernel] Implement VMA page tracking
The previous method of VMA page tracking relied on the VMA always being
mapped at least into one space and just kept track of pages in the
spaces' page tables. This had a number of drawbacks, and the mapper
system was too complex without much benefit.

Now make VMAs themselves keep track of spaces that they're a part of,
and make them responsible for knowing what page goes where. This
simplifies most types of VMA greatly. The new vm_area_open (nee
vm_area_shared, but there is now no reason for most VMAs to be
explicitly shareable) adds a 64-ary radix tree for tracking allocated
pages.

The page_tree cannot yet handle taking pages away, but this isn't
something jsix can do yet anyway.
2021-01-31 22:18:44 -08:00
Justin C. Miller
e3ebaeb2c8 [kernel] Add new vm_area_fixed
Add a new vm_area type, vm_area_fixed, which is sharable but not
allocatable. Useful for mapping things like MMIO to process spaces.
2021-01-28 01:05:21 -08:00
da38006f44 [kernel] Remove obsolete 'mappings' list from VMAs
The vm_area_shared type of VMA used to track mappings in a separate
array, which doubled information and wasted space. This was no longer
used, and is now removed.
2020-09-27 21:47:35 -07:00
2d44e8112b [kernel] Remove 'allowed' page table flag
The allowed flag was janky and easy to get lost when doing page table
manipulation. All allocation goes throug vm_area now, so 'allowed' can
be dropped.
2020-09-27 16:06:25 -07:00
f7f8bb3f45 [kernel] Replace buffer_cache with vm_area_buffers
In order to reduce the amount of tracked state, now use the
vm_area_buffers instead of a VMA with buffer_cache on top.
2020-09-27 15:34:24 -07:00
13aee1755e [kernel] Spit out vm_area types
The vm_space allow() functionality was a bit janky; using VMAs for all
regions would be a lot cleaner. To that end, this change:

- Adds a "static array" ctor to kutil::vector for setting the kernel
  address space's VMA list. This way a kernel heap VMA can be created
  without the heap already existing.
- Splits vm_area into different subclasses depending on desired behavior
- Splits out the concept of vm_mapper which maps vm_areas to vm_spaces,
  so that some kinds of VMA can be inherently single-space
- Implements VMA resizing so that userspace can grow allocations.
- Obsolete page_table_indices is removed

Also, the following bugs were fixed:

- kutil::map iterators on empty maps no longer break
- memory::page_count was doing page-align, not page-count

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

Tags:
2020-09-26 21:47:15 -07:00
0e0975e5f6 [kernel] Add VMA interface
Finished the VMA kobject and added the related syscalls. Processes can
now allocate memory! Other changes in this commit:

- stop using g_frame_allocator and add frame_allocator::get()
- make sure to release all handles in the process dtor
- fix kutil::map::iterator never comparing to end()
2020-09-23 00:29:05 -07:00
113d14c440 [kernel] Get rid of page_manager
page_manager is dead - final uses replaced in vm_space (page_in and
clear). Removed the header and cpp, and other lingering references.
2020-09-20 16:16:23 -07:00
9aa08a70cf [kernel] Begin replacing page_manager with vm_space
This is the first commit of several reworking the VM system. The main
focus is replacing page_manager's global functionality with objects
representing individual VM spaces. The main changes in this commit were:

- Adding the (as yet unused) vm_area object, which will be the main
  point of control for programs to allocate or share memory.
- Replace the old vm_space with a new one based on state in its page
  tables. They will also be containers for vm_areas.
- vm_space takes over from page_manager as the page fault handler
- Commented out the page walking in memory_bootstrap; I'll probably need
  to recreate this functionality, but it was broken as it was.
- Split out the page_table.h implementations from page_manager.cpp into
  the new page_table.cpp, updated it, and added page_table::iterator as
  well.
2020-09-17 00:48:17 -07:00