Compare commits

..

860 Commits

Author SHA1 Message Date
f77aa65dc5 Kernel: Cleanup accessing userspace memory
Instead of doing page validiation and loading manually we just do simple
memcpy and handle the possible page faults
2026-04-02 16:36:33 +03:00
9589b5984d Kernel: Move USERSPACE_END to lower half
This allows calculating distance to USERSPACE_END from lower half
address
2026-04-02 16:34:47 +03:00
32806a5af3 LibC: Allow "t" in stdio mode 2026-04-02 15:44:50 +03:00
876fbe3d7c LibC: Fix sem_{,timed}wait 2026-04-02 15:43:34 +03:00
c1b8f5e475 LibC: Add and cleanup network definitions 2026-04-02 15:42:00 +03:00
cf31ea9cbe LibC: Add _SC_PHYS_PAGES and _SC_AVPHYS_PAGES 2026-04-02 15:41:26 +03:00
7e6b8c93b4 LibC: Implement strsep 2026-04-02 15:40:23 +03:00
dd2bbe4588 LibC: Implement sched_getcpu 2026-04-02 15:39:36 +03:00
e01e35713b LibC: Allow including assert.h multiple times
Some shit seems to depend on this
2026-04-02 15:38:06 +03:00
82d5d9ba58 LibC: Write memchr, memcmp and strlen with sse 2026-04-02 15:35:03 +03:00
d168492462 WindowServer: bind volume up/down to volume control 2026-04-02 15:24:02 +03:00
6f2e8320a9 TaskBar: Show current volume level 2026-04-02 15:22:42 +03:00
bf4831f468 AudioServer: Add support for volume control 2026-04-02 15:21:38 +03:00
5647cf24d2 Kernel: Implement volume control to audio drivers 2026-04-02 15:14:27 +03:00
85f61aded5 BAN: Use builtins for math overflow 2026-04-02 14:49:12 +03:00
21639071c2 kill: Allow killing with process name 2026-04-02 05:02:05 +03:00
68506a789a Kernel: Add support for volume control keys 2026-04-02 05:02:05 +03:00
d9ca25b796 LibC: Add FNM_CASEFOLD and FNM_IGNORECASE
These are part of POSIX issue 8
2026-03-25 04:27:00 +02:00
e9c81477d7 BAN/LibC: Implement remainder
This is basically just fmod but with fprem1 instead of fprem
2026-03-25 01:06:45 +02:00
5c20d5e291 Kernel: HDAudio hide unusable pins and cleanup path finding 2026-03-24 01:16:47 +02:00
f89d690716 Kernel: HDAudio only probe codecs in STATESTS
This removes unnecessary probing that lead to timeouts. Also cap codec
address at 14 instead of 15. My test laptop was duplicating codec 0 at
address 15 leading to duplicate devices.
2026-03-24 00:49:47 +02:00
c563efcd1c AudioServer: Query pins of the asked device and not the current one 2026-03-23 22:57:49 +02:00
dedeebbfbe Kernel: Use ByteRingBuffer with audio buffers 2026-03-23 22:12:40 +02:00
35e2a70de0 AudioServer: Handle client data before disconnecting clients 2026-03-23 20:41:13 +02:00
81d5c86a7a WindowServer: Automatically launch xbanan if installed 2026-03-23 19:39:08 +02:00
db6644bae9 BuildSystem: Set glib-compile- binaries in meson cross file 2026-03-23 19:34:00 +02:00
14f1c1a358 LibC: Implement vsyslog 2026-03-23 19:13:38 +02:00
5be9bc64a2 ports/libxml2: Configure with -shared-libgcc
otherwise it doesn't seem to find libiconv due to __divdc3
2026-03-23 19:09:33 +02:00
64d3a5c8b7 ports: Update zlib 1.3.1->1.3.2
1.3.1 is no longer available at zlib.net
2026-03-23 18:54:57 +02:00
ccb4d13a82 Kernel: Compile EventFD file 2026-03-23 18:25:18 +02:00
cbe835a2c8 DynamicLoader: Add missing strlen definition 2026-03-23 18:23:31 +02:00
6a77754adf LibC: Don't link against libstdc++
This prevented building the toolchain
2026-03-23 18:22:42 +02:00
7d7d5ba734 LibC: Compile eventfd file 2026-03-23 18:22:04 +02:00
684fa1c4b0 ports: Add pixman port
This fixes cairo dependencies
2026-03-23 17:58:39 +02:00
a98d851fde ports: Add gtk3 port 2026-03-23 17:58:39 +02:00
9c3e2dab40 ports: Add pango port 2026-03-23 17:58:39 +02:00
eddb68f2fa ports/mesa: Build with x support 2026-03-23 17:55:57 +02:00
791091174a ports/cairo: Build with x support 2026-03-23 17:50:35 +02:00
dd9280c6ea ports/expat: Add support for shared libraries 2026-03-23 17:48:19 +02:00
a4d83f9fdb ports: Add xbanan port
This allows running x apps on top of my own GUI interface!
2026-03-23 17:47:11 +02:00
f42c5c4a5b ports: Add a lot of x library ports + xeyes/xclock 2026-03-23 17:45:59 +02:00
186fa4f1a1 ports: Update git 2.52.0->2.53.0 2026-03-23 17:35:08 +02:00
09292bb87e BAN: Cleanup math code and add SSE sqrt
We should prefer SSE instructions when they are easily available. For
other functions x87 is just simpler. It's hard to write faster and close
to as accurate approximations with SSE.

This does not use xmmintrin.h as clangd does not like that file and
starts throwing errors in every file that includes this :)
2026-03-22 22:07:48 +02:00
d18a0de879 Kernel: Fix mprotext for partial regions
if mprotected are did not contain the start of the region, mprotect
would exit early
2026-03-17 23:33:05 +02:00
cdc45935b5 Kernel: Don't allow chdir into non-directories 2026-03-17 22:57:17 +02:00
43e18148a6 LibC: Define SSP things 2026-03-17 20:30:25 +02:00
b0db645248 LibC: Add basic elf.h 2026-03-17 20:25:38 +02:00
07712758a7 BAN: Add default constructor to ipv4address 2026-03-17 20:24:48 +02:00
c1a424a635 Kernel: Implement linux's eventfd 2026-03-17 20:24:06 +02:00
a49588dbc7 DynamicLoader: Fix library lookup for already loaded files 2026-03-17 20:05:05 +02:00
1f22b9b982 DynamicLinker: Implement RTLD_NOLOAD 2026-03-17 20:04:48 +02:00
1d07d8e08e LibC/DynamicLoader: Add support for dynamically loaded TLS
Previously I failed to dlopen if any of the objects contained TLS
section
2026-03-17 20:01:51 +02:00
05b2424fca LibC: Implement more proper random number generator 2026-03-17 19:53:43 +02:00
07201c711e LibC: set endp in string to float conversion error 2026-03-17 19:50:12 +02:00
8fac88c9a6 LibC: Add sincos{,f,l} 2026-03-17 19:42:53 +02:00
c9aafa78ec DynamicLoader: Fix RO section mprotect arguments 2026-03-05 17:57:03 +02:00
e1c337a483 LibC: Fix compile and link flags
We were linking with -nostdlib and manually linked against libgcc. This
does not link with crtbegin and crtend which provides __dso_handle
preventing use of some global C++ constructors inside libc.

Now we just don't link against libc fixing this issue
2026-03-05 16:25:06 +02:00
acebe68dfa DynamicLoader: Fix copy relocation and TLS initialization 2026-03-04 23:04:19 +02:00
eeef945c25 Kernel: Make tty use the new byte ring buffer 2026-02-28 14:53:15 +02:00
a602753bda Kernel: Add front/back/pop_back to ByteRingBuffer 2026-02-28 14:51:35 +02:00
812ae77cd7 Kernel: Make TCP sockets use the new ring buffer
Also fix race condition that sometimes prevented window updates not
being sent after zero window effectively hanging the whole socket
2026-02-28 14:22:08 +02:00
8b8af1a9d9 Kernel: Rewrite pipes using the new ring buffer 2026-02-28 14:20:52 +02:00
493b5cb9b1 Kernel: Implement byte ring buffer
This maps the ring twice right next to each other so we don't have to
care about wrapping around when doing memcpy or accessing the data
2026-02-28 14:18:23 +02:00
1ecd7cc2fe Kernel: Allow protocol specific socket options
I had forgot to remove this condition on the syscall
2026-02-27 19:20:22 +02:00
5c38832456 Kernel: use wake_with_waketime in epoll
We already have the wake time so there is no reason to calculate the
timeout
2026-02-27 19:14:35 +02:00
d16f07a547 Kernel: Print thread id when writing to /dev/debug 2026-02-27 19:12:35 +02:00
54acb05131 Kernel: Don't print "./" prefix with debug functions 2026-02-27 19:10:51 +02:00
9ddf19f605 Kernel: Optimize networking code
Remove buffering from network layer and rework loopback interface.
loopback now has a separate recieve thread to allow concurrent sends and
prevent deadlocks
2026-02-27 19:08:08 +02:00
ff378e4538 Kernel: Cleanup and optimize TCP
We now only send enough data to fill other ends window, not past that.
Previous logic had a but that allowed sending too much data leading to
retransmissions.

When the target sends zero window and later updates window size,
immediately retransmit non-acknowledged bytes.

Don't validate packets through listeing socket twice. The actual socket
will already verify the checksum so the listening socket does not have
to.
2026-02-24 16:20:23 +02:00
2ea0a24795 Kernel: Fix TCP SYN option propagation
Listening socket now forwards TCP options to the newly created socket
2026-02-23 23:00:47 +02:00
acf28d8170 Kernel: Use ring buffers for TCP windows
This speeds up TCP networkign a ton as it doesnt have to do unnecessary
memmoves for each send/receive
2026-02-23 21:10:13 +02:00
666a7bb826 Kernel: Rework TCP window size reporting
We now report actually available window size when sending packets. If
the available window size grows significantly we send an ACK to reflect
this to the remote.
2026-02-23 21:10:13 +02:00
1ac20251cf Kernel: Fix TCP stack crash on retransmission 2026-02-23 17:48:16 +02:00
a318a19fe2 LibGUI/WindowServer: Add fullscreen events
When window's fullscreen state changes we now generate events!
2026-02-23 16:06:48 +02:00
f4a7aec167 LibGUI/WindowServer: Add support for custom cursor origin 2026-02-23 16:06:48 +02:00
9445332499 Kernel: Remove unnecessary interface lookup
This prevented connecting to local sockets listening on INADDR_ANY
2026-02-23 16:06:48 +02:00
8edd63d115 Kernel: Cleanup {set,get}sockopt debug prints 2026-02-23 16:06:48 +02:00
304ace1172 LibInput: Export keyboard layout keymaps 2026-02-23 16:06:48 +02:00
a5cdf0640f BAN: Add value_type to String{,View} 2026-02-23 16:06:48 +02:00
1fc2e43881 BAN: Add support for string format padding 2026-02-23 16:06:48 +02:00
0964c9f928 BAN: Remove unnecessary assert from span 2026-02-23 16:06:48 +02:00
8b1e820869 BAN: Add reallocator support to Vector 2026-02-21 04:03:11 +02:00
9edc6966db BAN: Add reallocator definition
for the moment this does not exist in kernel, kmalloc rewrite soon™️
2026-02-21 04:03:11 +02:00
12207dcb77 BAN: Add is_trivially_copyable trait 2026-02-21 04:03:11 +02:00
2255e36810 LibDEFLATE: Add GZip support
This allows compressing and decompressing with data using GZip headers
and footers
2026-02-21 04:03:11 +02:00
5abddd448e LibC: Fix typo/bug in fnmatch
* would stop matching at '0' instead of end of string
2026-02-19 22:12:59 +02:00
f022a1b08f Shell: Fix crash when executing semicolon
This fixes #4
2026-02-13 17:52:54 +02:00
b3bbfaeff0 LibC: Fix posix_spawnattr_t definition 2026-02-10 01:22:25 +02:00
679a3d4209 LibGUI: Add Texture::clear{,_rect} 2026-02-08 19:45:01 +02:00
a0211d88e7 Kernel: Don't include TCP header in MSS 2026-02-08 19:44:30 +02:00
e216fc7798 Kernel: Fix port allocation endianness 2026-02-08 19:43:08 +02:00
c648ea12f2 Kernel: Cleanup and fix UNIX sockets
EPOLLOUT is now sent to the correct socket and buffer is now a ring
buffer to avoid unnecessary memmove on every packet
2026-02-08 19:38:28 +02:00
2e59373a1e Kernel: Fix non blocking sockets blocking :D 2026-02-08 19:33:28 +02:00
a51a81b6cd Kernel: Move {set,get}sockopt to sockets
Sockets can now actually implement socket options :D
2026-02-08 19:27:16 +02:00
9809f87010 LibC: Fix {read,write}v return value for partial actions 2026-02-08 18:45:29 +02:00
8794122c2d BAN: Variant allow copy/move from empty 2026-02-07 18:54:31 +02:00
8fb2270ecf DynamicLoader: map RO sections actually read only
I was mapping everything RW as i did not have mprotect when I
implemented the dynamic loader.
2026-02-04 23:21:06 +02:00
c304133224 LibC: Indicate regex support in unistd.h 2026-01-25 01:47:30 +02:00
7843d3de62 LibC: Support attrs and file actions in posix spawn
Apparently GCC wants to use posix_spawn now that it is available, this
patch adds support for the missing fields. POSIX Issue 8 did add some
fields that are not supported here
2026-01-25 01:45:47 +02:00
aef536fff3 Kernel: Fix SharedMemoryObject cloning on deleted keys 2026-01-25 01:42:17 +02:00
d472e1ac0e Kernel: Remove obsolete FIXMEs and null pointer checks 2026-01-24 22:42:18 +02:00
120c08fb75 Kernel: Implement fcntl based locks 2026-01-24 22:38:34 +02:00
ba6229b92d Kernel: Fix TCP accept bind address
I was accidentally binding the new socket to the target address instead
of the listening socket's address
2026-01-24 00:33:05 +02:00
3d2362cb5f ports/xash3d-fwgs: Don't apply vorbis patch
I removed the pathes a while ago
2026-01-21 19:20:02 +02:00
a08b9b82a6 Kernel: Fix yield stack pointer value
Stack pointer was pointing to value of return address on return instead
of past it. This did not affect anything as ig Processor::yield() didn't
use stack after calling the trampoline
2026-01-19 00:47:00 +02:00
5d62fa3f10 Kernel: Clenup stacktrace printing on exception
Start from current ip and bp. This removes kernel call stack to debug
printing function from the stack trace
2026-01-16 16:31:35 +02:00
d3df00f0ba Kernel: Make Processor structure default to zero
This moves processor info to bss instead of having it in data section
2026-01-16 16:24:47 +02:00
34e84f8b07 Kernel: Reduce the number of TLB invalidations
Invalidations are not done if mapping or unmapping previously unmapped
page. TLB invalidate IPIs are now ignored if they don't affect the
currently mapped address space
2026-01-16 16:22:29 +02:00
1143dc3cae Kernel: Rework syscall memory validation and locking
Process's memory regions are now behind an rwlock instead of using the
full process lock. This allows most pointer validations to not block as
write operations to memory regions are rare.

Thread's userspace stack is now part of process's memory regions. This
simplifies code that explicitly looped over threads to see if the
accessed address was inside a thread's stack.

Only drawback of this is that MemoryRegions don't support guard pages,
so userspace stackoverflow will be handeled as cleanly as it was prior
to this.

This patch also fixes some unnecessary locking of the process lock and
moves locking to the internal helper functions instead of asserting that
the lock is held. Also we now make sure loaded ELF regions are in sorted
order as we previously expected.
2026-01-16 16:09:38 +02:00
0299d4d44e Kernel/LibC: remove SYS_TERMID
This syscall is not needed. /dev/tty is already a symlink to the
controlling terminal. Also this syscall did not handle pseudo terminals
2026-01-16 15:57:36 +02:00
1d07151743 ports/xash-fwgs: Cleanup patches
Remove patches that are no longer needed and cleanup the general support
patch
2026-01-13 20:51:58 +02:00
a83fa6f4c6 Kernel: Optimize futexes
Eeach futex object now has its own mutex to prevent unnecessary locking
of the process/global futex lock. This basically removes sys_futex from
profiles when running software with llvmpipe
2026-01-13 19:18:52 +02:00
c30fc9d60f LibGUI: Rewrite using epoll
select is slow :^)
2026-01-12 23:53:11 +02:00
311a68160c Kernel: Don't delete futex objects after they are not used anymore
Hashmap insertions and deletions made futex very slow to use. When
running SuperTuxKart, ~15% of cpu time was spent doing these.

Never freeing objects is not great either but at least the performance
is usable now :)
2026-01-12 23:52:04 +02:00
343aef31c3 AudioServer: Rewrite using epoll
select is slow :^)
2026-01-12 23:46:51 +02:00
3ac8f7e14f WindowServer: Rewrite using epoll
Looking at profiles, select is a very slow syscall as it has to allocate
a temporary epoll instance
2026-01-12 23:46:03 +02:00
0cef66d155 Kernel: Fix epoll reporting multiple of the same event 2026-01-12 23:45:17 +02:00
9ffbb9fbf0 LibC: Fix clock_gettime return value 2026-01-11 22:44:03 +02:00
c9a8f5b456 Kernel: Fix ext2 fileystem super block backups
Check if rev >= 1 sets sparse superblock feature instead of assuming it
is set
2026-01-11 19:55:10 +02:00
4e3831e380 Kernel: ACHI use ext commands for LBAs >=24 bits
AFAICS non extended commands are supposed to support 27 bit LBAs but
qemu seems to ignore bits 27:24. Maybe I'm just doing something wrong
but this seems to fix this.

This fixes using big disks :D ATM using using disks >= 8 GiB (with 512
byte LBAs) returned wrong data on reads, failing the boot :D
2026-01-11 15:15:58 +02:00
cae2b3bd14 Kernel: Cleanup ext2 indirect block lookup
If we are not allocating and the block is null, add a fast path to
delete it. This also prevents possibly blocking filesystem block wrapper
allocation
2026-01-11 04:00:04 +02:00
5637b8602b Kernel: Fix setting ext2 symbolic link target
If a link was >= 60 bytes but got shrinked to 60 bytes, reading it would
rebort garbage and unlinking it would leak blocks
2026-01-11 03:58:48 +02:00
4af9699b22 Kernel: Only save/load sse state when it is used
There is no need to save and load sse state on every interrupt. Instead
we can use CR0.TS to make threads trigger an interrupt when they use sse
instructions. This can be used to only save and load sse state when
needed.

Processor now keeps track of its current "sse thread" and the scheduler
either enabled or disabled sse based on which thread it is starting up.
When a thread dies, it checks if it was the current sse thread to avoid
use after free bugs. When load balancing, processor has to save the
thread's sse state before sending it to a new processor (if it was the
current sse thread). This ensures thread's sse state will be correct
when the new processor ends up loading it.
2026-01-11 03:06:39 +02:00
35c97e2ff8 Kernel: optimize yielding
Doing a yield no longer raises a software interrupt. Instead it just
saves all the callee saved registers, ip, sp and return value. Because
yield is only called in the kernel, it can just restore registers and
jump to the target address. There is never a need to use iret :)
2026-01-11 01:31:09 +02:00
83e5cb81e8 ports: Cleanup projects using cmake
There is no need to use $BANAN_CMAKE because our own toolchain directory
is added to path.
2026-01-10 19:32:48 +02:00
7a49a0d986 BuildSystem: Install meson as part of the toolchain
Debian based distros have meson 0.6x in their repositories. These cause
some obscure error messages when building meson based ports.
2026-01-10 19:32:48 +02:00
78cd054d59 BuildSystem: Write my own disk image perm updater
If user's bash does not have bultin stat, updating image perms was
terribly slow. This patch adds a simple c program that does the job
without exec overhead
2026-01-10 17:57:21 +02:00
d33a8eac9c ports/mesa: Download prebuilt llvm instead of building it
compiling llvm takes too long :D
2026-01-10 16:40:12 +02:00
9355ab1656 ports: Add cairo port
This is needed by harfbuzz
2026-01-10 16:21:12 +02:00
1f87bfbf2e ports/SuperTuxKart: Don't disable configure :D 2026-01-10 16:00:24 +02:00
e06429da87 ports: Add SuperTuxKart port 2026-01-10 13:35:07 +02:00
26058763df ports: Add harfbuzz port 2026-01-10 13:32:20 +02:00
1f03d23dae Kernel: Fix load balancing
My code to find least loaded processor used processor index instead of
processor id to index the array. Most of the time this lead to wrong
processor returned as the least loaded, leaving some processors
basically idle.
2026-01-10 01:46:08 +02:00
2eea074473 Kernel: Remove unnecessary page table loads
loading a page table is slow as it invalidates the whole tlb
2026-01-10 01:13:48 +02:00
ed82a18e2a Kernel: Fix deadlock in ext2 filesystem
If multiple threads were waiting for more block buffers without anyone
releasing them, they ended up in a deadlock.

Now we store 6 blocks for 8 threads. If a thread already has a block
buffer, it will not have to wait for a new one. Only if there are more
than 8 threads using blocks, will it block until there are free slots
for a thread available.
2026-01-10 00:30:30 +02:00
2961a49dc7 Kernel: Optimize futexes
Add support for processor local futexes. These work the exact same way
as global ones, but only lock a process specific lock and use a process
specific hash map.

Also reduce the time futex lock is held. There was no need to hold the
global lock while validating addresses in the process' address space.
2026-01-09 22:27:59 +02:00
5c9151d3e9 LibC: Add stubs for {init,set}state
Some port wanted these as it detected we had {,s}random
2026-01-09 22:08:32 +02:00
90deb9fb43 BAN: Make debug output thread safe
Now file lock is only acquired once per message, not once per character
2026-01-09 20:30:35 +02:00
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
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
a9ceab0415 Kernel: Use syscall/sysret for syscalls in x86_64 2026-01-09 15:18:58 +02:00
94bd74d0bb BuildSystem: Update qemu script
Default to intel-hda instead of ac97 for audio

If we are accelerating with kvm, use host cpu and disable migratable to
allow invariant TSC
2026-01-08 17:16:20 +02:00
b2d8199480 ports/openal-soft: Add SDL2 as a dependency 2026-01-08 17:13:59 +02:00
e60f3711f8 ports: Update openssl 3.3.1->3.6.0 2026-01-08 17:13:59 +02:00
6ec9e4f7b8 ports: Update freetype 2.13.3->2.14.1 2026-01-08 17:13:59 +02:00
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
ee57cf3e9a Kernel: Expose usb device's device descriptor
This is used by the joystick detection code but i forgot to commit this
:D
2026-01-08 13:46:11 +02:00
fea5d1d82b BAN: Fix wrong include in heap 2026-01-07 22:12:20 +02:00
c84a30d4dd ports/SDL2: Update to new joystick interface 2026-01-07 19:07:42 +02:00
24d91eee90 Kernel/LibInput: Rework Joystick handling
Joystick axis and buttons are now named to standard values, this allows
interfacing multiple different controllers (only DS3 is supported)

Add ioctl calls for userspace to set joystick player leds and rumble

Only use DS3 code paths when we detect that the attached device is
actually an DS3 controller

update test-joystick program to the new interface and add support to
control rumble and player leds
2026-01-07 19:01:07 +02:00
a5318448f5 userspace: Add audioctl utility to configure audio server 2026-01-06 22:26:11 +02:00
b7c40eeb57 AudioServer: Handle multiple audio devices with multiple pins
This makes audio server configurable during runtime!
2026-01-06 22:26:11 +02:00
e7c9be1875 AudioServer: Increase send buffer size and hardcode volume to 20% 2026-01-06 22:26:11 +02:00
8f1b314802 Kernel: Add ioctls to select audio device's output pin 2026-01-06 22:26:11 +02:00
da6794c8ce Kernel: Implement HD audio driver
This is very basic and does not support a lot of stuff (like changing
the output pin :D)
2026-01-06 22:26:10 +02:00
e926beba5a test-mouse: Fix mouse fd cleanup
I was creating a local variable shadowing the global one. This prevented
cleanup to close it. (this is not really necessary as the program dies
anyway)
2026-01-06 21:58:56 +02:00
3ad053cf6d image: Add option to change resize algoritm
Also benchmark timing is now done cpu clock, not monotonic one
2026-01-06 21:58:56 +02:00
bc11469a0b mkdir: Fix mkdir error handling 2026-01-06 21:58:56 +02:00
a00695bdac LibC: Add stubs that I have locally
I'm not sure if these are used by anything but I would assume so as I
have added them :D

functions added:
- getprotobyname
- open_memstream
- munlock
- lockf
- nice
- crypt
- getsid
- wcstoul
2026-01-06 21:58:56 +02:00
89959b800c LibC: Implement random and srandom 2026-01-06 21:58:56 +02:00
3e19c3b62e LibC: Fix timeradd and timersub overflow/underflow 2026-01-06 21:58:56 +02:00
d970debb4d LibC: Define MAXPATHLEN in sys/param.h
This file is not POSIX, but some software seems to rely on it
2026-01-06 21:58:56 +02:00
d0ba52073f LibC: Add stubs for shm_* functions 2026-01-06 21:58:56 +02:00
943e3b6f51 LibC: Define IN_CLASS* macros
These are not POSIX but some software seems to rely on them
2026-01-06 21:58:56 +02:00
25d43682aa LibC: Bump FOPEN_MAX 16->64 2026-01-06 21:58:56 +02:00
ad16de59f8 Kernel: Implement basic F_{GET,SET}LK{,W}
At the moment these lock the whole file which is not what is supposed to
happen. Some port was trying to use these and this seems to work for
that. This may cause deadlocks but that should be easy enough to find
the reason because of the debug warnings
2026-01-06 21:58:56 +02:00
8634bbb792 Kernel: Don't save/restore sse or reschedule on spurious interrupts
I think these should be just fully ignored :D
2026-01-06 21:58:56 +02:00
60ec5d30fd init: Start Clipboard server on startup
I had forgotten to commit this when I added the clipboard server :D
2026-01-06 21:58:56 +02:00
7667fe6ca5 LibC: Implement sem_timedwait 2026-01-06 21:58:56 +02:00
4b5a8196c3 Kernel: Fix bitmap byte index calculation in PMM
No idea how I had not crashed here earlier, but running on real hw with
a bit initrd ended up crashing :D
2026-01-04 01:16:43 +02:00
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
a8aa89362d ports/SDL2: Add support for game controllers
SuperTux and tuxracer now work with controller support!
2026-01-03 20:42:42 +02:00
7964698ae5 userspace: Add simple joystick test app 2026-01-03 20:42:42 +02:00
65664b0d65 Kernel: Add support for DualShock 3 controllers
This driver accepts any HID joystick devices but button and axis
mappings will only work on a PS3 controller
2026-01-03 20:07:08 +02:00
08bfa0971e Kernel: Rework storage device and disk cache locking
Syncing the disk cache no longer blocks the underlying storage device
and the disk cache itself during sync
2026-01-02 18:06:56 +02:00
912c5ea0bf Kernel: Implement basic RWLock 2026-01-02 17:50:22 +02:00
6cdf5a5a7f Kernel: Make AHCI controller thread safe 2026-01-02 17:50:22 +02:00
50ba743faf Terminal: Cleanup CSI handling and add =c,>c,c,E,F 2026-01-02 17:13:46 +02:00
e26aac3067 Kernel: Decrease the number of syncs done by ext2 inodes
Each allocated inode used to call sync(). Each sync reads and writes
a block from the filesystem. Doing a 1 MiB write ended up syncing around
257 times
2026-01-01 23:54:09 +02:00
941e8aa5d5 Kernel: Optimize ext2 filesystem
block lookup can now also allocate blocks so there is no need to do
multiple lookups of the block did not exist
2026-01-01 23:15:35 +02:00
33b6536e6b Kernel: Make disk cache entry lookup O(log n)
I have absolutely no idea why i was doing a linear lookup here :D
2026-01-01 20:40:38 +02:00
9fbd9288b2 Kernel: Fix symlink deletion from tmpfs
Small symlinks store their target in inline storage of data block
indices. Freeing blocks did not account for this and tried to interpret
the link target as block inidices to delete
2026-01-01 20:40:38 +02:00
bef1a56007 ports: Update git 2.48.1->2.52.0
also remove curl link hack as updating curl port fixed the issue
2026-01-01 20:40:38 +02:00
bc71ff5e81 ports: Update curl 8.11.1->8.17.0
This fixes broken DT_NEEDED dependencies in curl!
2026-01-01 20:40:38 +02:00
bd50444d06 ports: Update ca-certificates 2024-07-02 -> 2025-12-02 2025-12-31 19:28:55 +02:00
2efd6f92b2 rm: add -f and -i options
rm *should* now be posix compatible
2025-12-31 19:28:55 +02:00
7fdfad4088 Kernel: Mount /tmp with sticky bit set 2025-12-31 19:28:55 +02:00
31a1968798 Kernel: Cleanup scheduling while idling
If there are no threads in the run queue and we are idle, attempt to
wake up threads from the sleep queue
2025-12-31 19:28:55 +02:00
b0bd4ad546 Kernel: Fix dup2 return value
We returned the wrong fd number :D
2025-12-31 19:28:55 +02:00
dc454b9a6a Kernel: Fix SA_RESETHAND handling order
if SA_RESETHAND was set, alt stack would not get used
2025-12-31 19:28:55 +02:00
f06e5d33e7 Kernel: Rework socket binding to an address
Sockets are no longer bound to an interface, but an ipv4 address. This
allows servers at 0.0.0.0 talk to multiple different interfaces
2025-12-31 19:28:55 +02:00
efdbd1576f ports/SDL2: disable static lib and enable semaphores
Also add libiconv as a dep so SDL_iconv_string etc works
2025-12-28 15:30:02 +02:00
0421fbdc25 LibC: Implement sem_getvalue 2025-12-28 15:29:37 +02:00
bd426199f8 Kernel: Remove unused (and broken) code from signal trampoline 2025-12-28 03:53:38 +02:00
8e00b3d110 ports: Add ffmpeg port
This allows basic video and audio playback on banan-os!
2025-12-28 00:12:03 +02:00
6fbf1469aa LibC: define static_assert in assert.h
This is needed from C11 until C23
2025-12-28 00:12:03 +02:00
280d3fd919 LibC: Fix assert.h include guard 2025-12-28 00:12:03 +02:00
40ce95b87f LibC: Add definition for TCP_MAXSEG
This is not implemented yet
2025-12-27 23:37:03 +02:00
e7d644b874 AudioServer: Fix rounding the number of samples when resampling
If client tried to play a single sample at lower frequency as the
kenrel, audio server would never play it leading to the client hanging

This makes calculations round the number of samples always up to fix
this
2025-12-18 16:05:28 +02:00
c64159d5c3 AudioServer: Fix resampling math
This caused resampled audio to freeze the whole audio system after few
minutes of playing (like doom)
2025-12-18 14:59:55 +02:00
e2ccc3026f BAN: Remove unnecessary c++ header inclusion 2025-12-16 16:44:42 +02:00
2af6066ee3 LibC: Fix sysconf(_SC_OPEN_MAX) 2025-12-16 05:20:18 +02:00
fc16b5331c LibC: Fix backtrace compilation
Also dump backtrace on SIGABRT
2025-12-16 05:20:00 +02:00
b2723a0c5f aoc2025: Implement day12 solution 2025-12-15 19:06:17 +02:00
01042a24f0 aoc2025: Implement day11 solution 2025-12-15 17:57:45 +02:00
f9643b3881 aoc2025: Implement day10 solution 2025-12-15 14:42:03 +02:00
d2d18bea5d aoc2025: Implement day9 solution 2025-12-13 03:09:15 +02:00
87e595b83e aoc2025: Implement day8 solution 2025-12-12 22:37:03 +02:00
08031b1227 aoc2025: Implement day7 solution 2025-12-12 21:15:22 +02:00
9a87c1f734 aoc2025: Implement day6 solution 2025-12-12 20:17:12 +02:00
edeb667ead aoc2025: Implement day5 solution 2025-12-12 06:30:03 +02:00
db2aa495b8 aoc2025: Implement day4 solution 2025-12-12 06:08:00 +02:00
ddfb591094 aoc2025: Implement day3 solution 2025-12-12 04:34:40 +02:00
e8f1ba3722 aoc2025: Implement day2 solution 2025-12-12 02:49:33 +02:00
19c4f34ccb aoc2025: Implement day1 solution 2025-12-12 02:49:10 +02:00
5d9e9c021a aoc2025: Prepare programming environment 2025-12-12 02:48:40 +02:00
6a924db68c Kernel: Implement FIONREAD for tty and pty 2025-11-24 18:15:10 +02:00
9d0990e5e8 Kernel: Implement /proc/<n>/fd 2025-11-24 00:19:51 +02:00
3207f5d61f Kernel: Fix possible page fault on file lookup 2025-11-23 19:49:07 +02:00
c72b351bba LibC: Implement glob{,free} 2025-11-23 05:33:44 +02:00
1f9b296ae7 cp: Add -r/--recursive flag 2025-11-23 02:25:05 +02:00
e3e2e7b4df userspace: Implement mv utility 2025-11-23 02:24:52 +02:00
4ec8f4a4bf Kernel/LibC: Implement rename{,at} 2025-11-22 23:55:10 +02:00
05d59a05df Kernel: Remove obsolete kprint
This hasn't been in use in 3 years :)
2025-11-22 06:21:50 +02:00
11ccbe6506 ports/SDL2: Add clipboard support 2025-11-22 01:24:06 +02:00
673711a246 ports/mesa: Require llvm
I dont't really even want to suppot softpipe as that is so slow
2025-11-22 00:40:14 +02:00
fff5139d80 Kernel: Add /proc/<n>/cwd
Also update /proc/<n>/* permissions to match what linux does :D
2025-11-18 05:40:36 +02:00
812e70c626 ports: Add zsh port 2025-11-18 05:40:36 +02:00
db7ffcf9d5 Kernel/Terminal: Add support for bracketed paste mode
This gets rid of annoying warnings when running some programs like bash
2025-11-18 05:40:36 +02:00
8f6cb9c057 Terminal: Add selection and clipboard support
text can now be copied with ctrl+shift+c and pasted with ctrl+shift+v
2025-11-18 05:40:36 +02:00
291f298d19 userspace: Implement LibClipboard and ClipboardServer
programs can now connect to the clipboard server using libclipboard and
get and set the clipboard of the current user
2025-11-18 05:40:36 +02:00
d60f12d3b8 Kernel: Add support for SCM_CREDENTIALS and fix recvmsg
recvmsg was broken when receiving into more than a single iovec
2025-11-18 05:40:36 +02:00
b8a2573bb4 userspace: Implement ImageViewer utility
This supports viewing images and doing basic zooming and panning
2025-11-17 20:58:12 +02:00
7ce8e610f5 stat: Fix handling of symlinks 2025-11-17 05:26:07 +02:00
839b9c8f07 Kernel: Check parent's sticky bit in unlink 2025-11-17 05:26:07 +02:00
db20801521 Shell: Add exec builtin 2025-11-17 05:26:07 +02:00
160a9278c9 LibC: Fix RTLD_* definitions 2025-11-17 05:26:07 +02:00
ee507de154 LibC: Implement posix regex
This is an almost complete implementation, it does not support
alternations or collating elements and it is restricted to the ASCII
character set
2025-11-17 05:26:07 +02:00
dc0fa49de2 ports/tuxracer: Add sound support and fix compiling 2025-11-17 05:26:07 +02:00
b678541427 ports: Add SDL_mixer port 2025-11-17 05:26:07 +02:00
6c4cd0d8cb ports: Add libmikmod port 2025-11-17 05:26:07 +02:00
c096d3cd42 ports/sdl12-compat: Define that banan-os has alloca.h 2025-11-17 05:26:07 +02:00
dcdab4df21 ports/sdl12-compat: Remove unnecessary patch
This is not needed as our SDL2 library is in the expected form
2025-11-17 05:26:07 +02:00
9803209ba1 WindowServer: Make clients nonblock
Also dont allow freezed windows to "steal" focus and lock up the window
server :D
2025-11-17 05:26:07 +02:00
f166cb09ec Kernel: Fail xHCI initialization if page size != 4096
Also zero out scratchapd buffers as the spec says
2025-11-17 05:26:07 +02:00
2dd8b76289 BuildSystem: Automatically delete libtool files
Half of the ports had a manual post_install step to delete libtool files
this is now done automatically and there is no need for it!

Libtool files have to be deleted as libtool doesn't work while
cross-compiling (at least out of the box)
2025-11-17 05:26:07 +02:00
2bf7c67767 LibC: Add backtrace signal handlers for SIG{FPE,ILL,BUS,SEGV}
This allows programs to dump better backtraces on crashes compared to
what kernel can as libc can resolve symbols and libraries' dynamic bases
2025-11-17 05:26:07 +02:00
dd636ffcb2 Kernel: Add support for SA_SIGINFO 2025-11-17 05:26:07 +02:00
a44c45ff9e LibC: Cleanup signal.h
Make sa_handler and sa_sigaction be part of an union

Add definitions of SIGIO TRAP_BRKPT TRAP_TRACE
2025-11-17 05:26:07 +02:00
dc2a455395 Kernel: Optimize processes' memory management
Memory regions are now stored in a sorted array. This allows O(nlogn)
lookup for address validation instead of the old linear lookup.

Now inserting new regions is also O(nlogn) instead of the old constant
time, but lookups are **much** more frequent
2025-11-17 05:26:07 +02:00
c700d9f714 Kernel: Implement connect for UDP socket 2025-11-17 05:26:07 +02:00
59cfc339b0 Kernel: Ignore MSG_NOSIGNAL and invalid flags 2025-11-17 05:26:07 +02:00
e06c07ca89 ports: Update binutils 2.44->2.45
Now we don't have to keep patches for both versions around :D
2025-11-17 05:26:07 +02:00
6facd54a7e LibC: Add ru_maxrss to struct rusage
This is not required by posix but some ports use it
2025-11-17 05:26:07 +02:00
6f8d850726 BuildSystem: Cleanup port building script
All dependencies are now installed only ones. If a port depends on for
examle zlib and one of its other dependencies depends on zlib, zlib will
now get installe only once.

Accept .tgz archives as the main download file
2025-11-17 05:26:07 +02:00
f3beee9874 Kernel: Cleanup userspace pointer validation 2025-11-17 02:33:00 +02:00
35e063bdaf Kernel: Dump r8-r15 on x86_64 exceptions 2025-11-17 02:33:00 +02:00
09175d1799 Kernel: Fix 32 bit target
Rewrite some assembly and add some required casts
2025-11-17 02:33:00 +02:00
46f9a9053f DynamicLoader: Use canonical path for the main executable 2025-11-13 04:20:53 +02:00
bb86520094 Kernel: Set message flags in UDP and TCP recvmsg 2025-11-13 04:20:53 +02:00
c1e2c660bf LibC: Define caddr_t
This is used by some ports
2025-11-13 04:20:53 +02:00
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
7a68ce7e94 DynamicLoader: Fix testing for possible base address
Replace MAP_FIXED with MAP_FIXED_NOREPLACE and only attempt to map
program headers with PT_LOAD
2025-11-13 04:20:53 +02:00
9537922acc Kernel: Implement proper memory region splitting
Memory regions are now splitted when they get munmapped, mprotected, or
mmapped with MAP_FIXED. This is used by couple of ports, and without
this we were just leaking up memory or straight up crashing programs.
2025-11-13 04:20:53 +02:00
a39aa73e21 Kernel: Allow munmap on non-page aligned address 2025-11-12 00:06:36 +02:00
f1d12c330e Kernel/LibC: Implement MMAP_FIXED_NOREPLACE
This is a handy thing from linux

Also fix MMAP_FIXED validation and error reporting
2025-11-12 00:06:36 +02:00
82c8eeb4be ports/openssh: Update to 10.2p1 and enable fd passing 2025-11-12 00:06:36 +02:00
3a951f4830 LibC: Define IN_LOOPBACKNET
some ports expect this to exist
2025-11-12 00:06:36 +02:00
998ea25fb9 LibC: Add netinet/in_systm.h compatibility header 2025-11-12 00:06:36 +02:00
7b580b8f56 Kernel: Implement fd passing with SCM_RIGTHS 2025-11-12 00:06:36 +02:00
641ccfdd47 LibC: Add BSD compatibility defines S_I{READ,WRITE,EXEC}
These just map to S_I{R,W,X}USR respectively
2025-11-10 01:40:33 +02:00
4288f70d04 LibC: Make poll and epoll macros match with each other
This was an assertion in one of my ports and I couldn't be bothered to
write a patch for it :D
2025-11-10 01:40:33 +02:00
95fda5dfb7 LibC: Add definitions for IPPROTO_ICMPV6 and IP_TOS 2025-11-10 01:40:33 +02:00
1903c5e0c6 Kernel: Use user given address hint in mmap if possible 2025-11-10 01:40:33 +02:00
362501a097 LibC: Make x86_64 crt0 PIE compatible
Instead of pushing addresses of functions directly, use rip relative
addressing
2025-11-10 01:40:33 +02:00
72982e3c2b Kernel/LibC: Take fcntl extra field as uintptr_t
This allows passing pointers to fcntl
2025-11-10 01:40:33 +02:00
04d24bce70 Kernel/LibC: Implement {recv,send}msg as syscalls
This also removes the now old recvfrom and sendto syscalls. These are
now implemented as wrappers around recvmsg and sendmsg.

Also replace unnecessary spinlocks from unix socket with mutexes
2025-11-10 01:40:33 +02:00
2f38306c6b LibC: Implement simple posix_spawn{,p}
This does not support file_actions or attributes
2025-11-10 01:40:33 +02:00
4b36e5197d LibC: Implement execvpe
This is not part of posix but it seems handy
2025-11-09 16:12:29 +02:00
b755cf3e42 LibC: Add sockatmark stub 2025-11-07 14:57:00 +02:00
3acad7c911 LibC: Add ifreq.ifr_{flags,mtu} and fix defines
compatibility defines for ifr_{netmask,gwaddr,hwaddr} were wrong
2025-11-07 14:55:30 +02:00
f3319016c4 LibC: Implement if_{,free}nameindex 2025-11-07 14:54:53 +02:00
4e14f7d483 LibC: Implement {,l,ll}{abs,div} 2025-11-06 23:20:35 +02:00
979059c804 Kernel: Implement ext2 symlinks with >= 60 byte target 2025-11-06 17:21:36 +02:00
bdf4423512 ports/freetype: Add missing dependencies 2025-11-04 23:06:13 +02:00
c6ef4b5840 userspace: Implement kill utility 2025-11-04 19:19:46 +02:00
acd792d8b4 userspace: Implement pwd utility 2025-11-04 18:46:13 +02:00
fc730679ed userspace: Implement uname utility 2025-11-04 18:45:20 +02:00
00e5749e20 ports: Add SuperTux port 2025-11-02 22:47:02 +02:00
7b4d349574 ports: Add glm port 2025-11-02 22:47:02 +02:00
dc0cccfb6c ports: Add physfs port 2025-11-02 22:47:02 +02:00
fdc1daefb6 ports: Add libvorbis port 2025-11-02 22:47:02 +02:00
c9159b81c8 ports: Add libogg port 2025-11-02 22:47:02 +02:00
9233049356 ports: Add openal-soft port 2025-11-02 22:47:02 +02:00
bd9015e474 ports: Add libsndfile port 2025-11-02 22:47:02 +02:00
3a79540d2d ports: Add SDL2_image port 2025-11-02 22:47:02 +02:00
9e500dc387 ports: Add boost port 2025-11-02 22:47:02 +02:00
e05a735589 DynamicLoader: Honour STB_LOCAL binding 2025-11-02 22:47:02 +02:00
0be18c4a53 DynamicLoader: Make everything thread safe
This is kinda dumb implementation, but it works. We grap a global lock
on functions :)
2025-11-02 22:47:02 +02:00
e258fde25a LibC: Implement unnamed semaphores 2025-11-02 21:11:16 +02:00
7367672570 Kernel: Default initialize flock as unlocked
This caused unlocked flock's to hang on lock
2025-11-02 21:10:13 +02:00
b822d42889 LibC: Define ESHUTDOWN
This is not used but some ports expect it to exist
2025-11-02 21:09:48 +02:00
10084ff1bb LibC: Define FIONBIO
This doesn't do anything but some ports expect it to exist
2025-11-02 21:07:26 +02:00
c3c69ac727 LibC: Update _POSIX_* definitions and extern environ
environ is externed by other operating systems so some ports expect it
to be there
2025-10-30 16:49:12 +02:00
0cfda6f6a7 LibC: Add posix_fadvise as no-op 2025-10-30 16:34:03 +02:00
dc51ce9e92 LibC: Implement readdir_r and fix memory leak 2025-10-30 16:33:17 +02:00
aa0de2b00e LibC: Fix stack_t::ss_sp type from void** -> void* 2025-10-30 15:43:25 +02:00
5f61581e1d Kernel: Show QR code with panic logs on kernel panic
This makes debugging on real hardware easier!
2025-10-28 05:50:19 +02:00
f519cb2cc0 Kernel: Expose boot framebuffer device 2025-10-28 05:50:19 +02:00
37aef630d2 BAN: Fix Array and Vector span constness 2025-10-28 05:50:19 +02:00
d93fcff5db userspace: Add LibQR
This library can be used to generate QR codes
2025-10-28 05:50:19 +02:00
4952a82af5 LibImage: Use LibDEFLATE instead of builtin DEFLATE decompressor 2025-10-28 05:50:19 +02:00
fecda6a034 userspace: Add LibDEFLATE
This can be used to compress and decompress DEFLATE data either in raw
or zlib format
2025-10-28 05:50:19 +02:00
9f0addbd8b BAN: Implement simple priority queue
This is just a wrapper around BAN::Vector and heap functions
2025-10-26 00:32:00 +03:00
7f8ea6b8e0 BAN: Move heap functions to Heap.h
This also adds push_heap and pop_heap, similar to what C++ standard
library provides
2025-10-26 00:31:06 +03:00
9d3ea6fed7 BAN: Use new it_value_type_t in sorting functions 2025-10-26 00:30:51 +03:00
703b3eda56 BAN: Add it_value_type_t
This is a template that resolves into T for pointers to T and T::value_type otherwise. It allows using the underlaying type of an iterator or pointer for range based algorithms
2025-10-26 00:22:35 +03:00
84006e1e77 BuildSystem: Don't set symlink mode
Only call chmod if the file is not a symlink. Older versions of chmod
(shipped with ubuntu) don't support the -h flag.
2025-10-02 17:05:20 +03:00
73fb085a41 LibC: Add inet_pton for IPv4 addresses 2025-10-02 16:19:49 +03:00
c89780178f LibC: Add sys/polls.h as wrapper for poll.h
some ports require this
2025-10-02 16:02:07 +03:00
2ac3976924 ports/libiconv: Fix download url
remove /pub/ part of url as mirrors don't seem to accept it
2025-10-02 15:54:55 +03:00
ac9dbd24e4 ports/vim: Fix compilation on new toolchain 2025-09-30 16:15:05 +03:00
3af9830a2e ports/tuxraces: Cleanup cflag passing 2025-09-30 16:14:40 +03:00
da6b8eb2ab BuildSystem: Use ftpmirror.gnu.org for downloads
ftp.gnu.org is really slow :(
2025-09-30 16:13:38 +03:00
da39e98adf Kernel: Make F11 drop disk cache
This can be useful to detect memory leaks or something
2025-08-31 00:36:59 +03:00
791a541381 Kernel: Implement process stopping and continuing 2025-08-31 00:34:52 +03:00
56684e753b Kernel: Fix PS/2 legacy controller detection
This was wrong for devices without FADT or pre revision 3 FADT
2025-08-29 21:07:33 +03:00
c7298edf65 Kernel: Clone executable path on fork
Before this forked processes had empty executables
2025-08-29 01:41:18 +03:00
30215963b2 Kernel: Fix /proc/<pid>/exe permissions 2025-08-29 01:40:56 +03:00
f15f88ebd6 TaskBar: Don't leak fds when reading battery info 2025-08-28 15:57:10 +03:00
391fc0c4c2 Kernel: Don't crash if Ext2 filesystem doing too many fileops
I had a hardlimit of 10 block buffers and if they ran out, the kernel
would crash. this patchs increases the number of buffers to 16 and
removes the crash condition when they run out :D
2025-08-28 15:55:40 +03:00
948ef2c820 Kernel: Fix race condition when destroying threads 2025-08-28 15:55:40 +03:00
c1b6b6b76a Kernel: Fix string validation in unlink syscall 2025-08-28 15:55:40 +03:00
a8bb07052e Kernel: Rewrite SMP message code
Remove locks and map smp buffer as uncached
2025-08-28 15:55:40 +03:00
6976a2dae7 Kernel: Add hardlink support to USTAR
Also handle file types L and K for long file names and link names
2025-08-28 15:55:40 +03:00
51cd951b4c Kernel: Add hardlink support to tmpfs 2025-08-28 15:55:40 +03:00
16a5a234c1 Kernel: Cleanup hardlink creation 2025-08-28 15:55:40 +03:00
f994210927 LibC: Fix sigsetjmp (again)
I was using a wrong register for signal mask storage...
2025-08-28 15:55:40 +03:00
aaa8760d09 Kernel: Don't wait for ps2 timeout when flushing buffer
This speeds up boot time by a second :dd:
2025-08-28 15:55:40 +03:00
cea19ecc31 Kernel: Fix possible crash during exec 2025-08-28 15:55:40 +03:00
706cfeb443 Kernel: Allow file backed mapping be larger than inode size
This is only allowed if the mapping does **not** exceed a page boundary.
Some port was doing an exactly two-page-mapping on a file that was one
and a half page long
2025-08-28 15:55:40 +03:00
d9c91589f0 Kernel: Don't limit /tmp max size 2025-08-28 15:55:40 +03:00
9854691265 LibC: Don't leak fds on rename 2025-08-28 15:55:40 +03:00
32afa33a06 LibC: Make sure FILE's buffer does not get overflown 2025-08-28 15:55:40 +03:00
c6946d0145 LibC: Use pthread_mutex on FILE instead of atomics 2025-08-28 15:55:40 +03:00
abbe7b79d6 Kernel: Add /proc/<pid>/exe 2025-08-28 15:55:40 +03:00
e4abe75043 Kernel: Add /proc/self 2025-08-28 15:55:40 +03:00
b904503691 ports: Update GCC 15.1.0->15.2.0 2025-08-28 15:55:40 +03:00
2db42dfb2e BuildSystem: Don't download config.sub every hour
There isn't really any need to :D
2025-08-25 22:16:23 +03:00
10bd24e585 Kernel: Fix signal delivery without an alternate stack
I had only tested that sigaltstack worked, so I didn't notice my normal
signals broke :D
2025-08-25 22:16:23 +03:00
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
e7b518ba67 BuildSystem: binutils 2.44->2.45, gcc 15.1.0->15.2.0 2025-08-25 18:25:36 +03:00
a4698f0bde Kernel: Fix IOAPIC max redirection entry fetching
Also max redirection entry is an index, not count so comparisons should
check for equality :)
2025-08-25 17:15:55 +03:00
9a6eae69ba Kernel: Replace all occurances of BSB with BSP 2025-08-25 17:11:32 +03:00
0ff365c7f0 ports: Add qemu port 2025-08-21 03:11:16 +03:00
214e7a5672 ports: Add glib port 2025-08-21 03:11:16 +03:00
24b69a6dea ports: Add libffi port 2025-08-21 03:11:16 +03:00
699235147c ports: Add pcre2 port 2025-08-21 03:11:16 +03:00
72ad413a61 ports/SDL2: Handle window focus events 2025-08-21 03:11:16 +03:00
f11bb082e4 WindowServer/LibGUI: Add window focus events 2025-08-21 03:11:16 +03:00
2f3fd6867d Kernel: Add VERY HACKY MAP_FIXED fix
This definitely will break stuff but I don't think anything depends on
this (except maybe dynamic loader)

This WILL get fixed soon (I hope :D)
2025-08-21 03:11:16 +03:00
350ae90bb6 Kernel: Make all futexes shared
Some stuff tries to use shared futexes so make them all shared. Private
futexes would be faster as they are process specific but supporting both
would need some reworks
2025-08-21 02:56:17 +03:00
fb61cab70d LibC: Rewrite pthread_mutex using a futex 2025-08-21 02:52:49 +03:00
1d6c08478d LibC: Fix sigsetjmp
the call from C sigsetjmp messed up rbp, now sigsetjmp is also written
in assembly.

I did not test the 32 bit code, just ported the tested 64 bit version
over :D
2025-08-21 02:52:49 +03:00
0dfe0b7023 Kernel/LibC: Implement sigaltstack 2025-08-21 02:52:49 +03:00
def236b7cd Kernel/LibC: Implement sigwait 2025-08-20 20:16:19 +03:00
247743ef9c Kernel/LibC: Implement sigsuspend 2025-08-20 20:14:54 +03:00
49122cf729 Kernel: Allow adding signals to thread that are blocked 2025-08-20 18:35:18 +03:00
84f579be81 ports: Add nano port 2025-08-19 17:00:14 +03:00
3d5f23a1b2 LibC: Implement wctomb 2025-08-19 16:44:18 +03:00
8b26b6604d LibC: Make mbstate_t into int
This is not used, but makes more sense than an empty struct
2025-08-19 16:29:46 +03:00
f88e55ffa8 ports: Add nyancat port 2025-08-19 16:23:30 +03:00
34bdcb12e5 Kernel: Fix termios and enter key handling
Enter key now produces expected \r which gets converted to \n by default
by the ICRNL input flag.

Also input flags are now handled always, not just when ICANON is set.
I don't know why I though ICANON should disable input handling
2025-08-19 16:23:30 +03:00
95b353dae5 LibInput: Fix numpad keycode generation
I had made this function with broken PS/2 scancode set 3, so it seemed
like it worked
2025-08-19 16:23:30 +03:00
6560f229b1 Kernel: Fix PS/2 scancode set 3 numpad keys 2025-08-19 16:23:30 +03:00
8c9ab2d68c WindowServer: Fix crash when window closes while being "button window" 2025-08-19 16:23:30 +03:00
8496726ab1 Terminal: Ignore some control characters 2025-08-19 16:23:30 +03:00
32d7f429f8 Kernel: Fix default ignored signals
SIGWINCH and SIGCANCEL ended up interrupting functions even when they
were marked as SIG_DFL. Now resizing the userspace terminal emulator
does not get interrupted!
2025-08-19 16:23:30 +03:00
0f52f49188 Terminal: Remove unused code 2025-08-19 16:23:30 +03:00
b334259a07 AudioServer: Don't allow client to fully halt audio 2025-08-19 16:23:30 +03:00
74af4e9150 ports/SDL2_mixer: Add MIDI support 2025-08-19 16:23:30 +03:00
8b7790ded2 Kernel: Fix userspace pointer checks
Some syscalls were unconditionally validating optional paramenters which
were allowed to be null pointers
2025-08-19 16:23:30 +03:00
3e97a82af0 Kernel: Allow getgroups with size
This can be used to query the number of groups
2025-08-19 16:23:30 +03:00
0066b20413 Kernel: Fix spinlock leaks with unix sockets 2025-08-19 16:23:30 +03:00
9d6656451a LibC: Make time_t signed integer
Some port like python3 assumes this is the case
2025-08-19 16:23:30 +03:00
32f980e259 Kernel: Fix ACPI namespace lookup for multi segment names 2025-08-19 16:23:30 +03:00
ca9361abc1 DynamicLoader: Add support for dladdr 2025-08-19 16:23:30 +03:00
36cb3d56fe LibC: Define Dl_info_t and add stub for dladdr 2025-08-19 16:23:30 +03:00
0bece8a54c Kernel: Add missing ACPI resource header 2025-08-19 16:23:30 +03:00
70bbdbd8f5 LibC: Cleanup syslog output
add ": " after the identification and formatted output. syslog does not
require trailing newline so add it in case it is missing.
2025-08-16 22:56:03 +03:00
df8365f0c7 ports/openssh: Configure with --disable-fd-passing
I though this wasn't needed because of my patch, but I didn't actually
test the code
2025-08-16 22:55:53 +03:00
974aae2ebe ports: Add openssh port 2025-08-16 22:32:37 +03:00
ceca93c8b1 LibC: Cleanup memmove and memcpy for x86_64 2025-08-16 14:05:21 +03:00
b6793cc6f2 Kernel: Add AML ConcatResOp 2025-08-15 18:54:17 +03:00
809d07546a Kernel: Remove minimum timeout of 100 ms from epoll
This is not actually needed and was just temporary code to make sure i
notified the epoll everywhere
2025-08-15 18:28:11 +03:00
804cbeb1a7 Kernel: Increment kmalloc storage size to 64 MiB
I really don't want to do this, but rewriting kmalloc to be dynamic
would require me to rewrite 32 bit paging and I really don't want to.
2025-08-15 17:02:15 +03:00
c07188a60e Kernel: Look for PS/2 devices in the ACPI namespace
This allows finding the PS/2 controller on newer machines that don't
have the 8042 bit set in FADT.
2025-08-15 17:02:15 +03:00
3804d4332b Kernel: Make _SEG, _BBN and _ADR lookup absolute 2025-08-15 17:02:15 +03:00
064aaef6c3 Kernel: Don't fail on creating reserved opregion 2025-08-15 17:02:15 +03:00
ce262a5d2d Kernel: Allow ReturnOp in global scope 2025-08-15 17:02:15 +03:00
d128f4d70b Kernel: Fix AML CreateField debug print 2025-08-15 17:02:15 +03:00
46d1ada708 Kernel: Allow AML package->package conversion 2025-08-15 17:02:15 +03:00
2819e5f647 Kernel: Make _STA and _INI lookup absolute 2025-08-15 17:02:15 +03:00
c2017a5181 Kernel: Allow looking up devices with multiple eisa ids
Also match against _CIDs in addition to _HID
2025-08-15 17:02:15 +03:00
58ad839136 Kernel: Add support for ACPI Embedded Controllers 2025-08-15 17:02:15 +03:00
8ed5a71c45 Kernel: Register IDT handlers from a vector
This drops code size by a lot :D
2025-08-13 18:27:46 +03:00
57050a83ba ports/timidity: Fix compilation
Precalculating newton coefficients does not work as the buildsystem
tries to run a banan-os binary. This patch enables coefficient
calculation code for the runtime!
2025-08-13 12:20:21 +03:00
6ed0e84421 LibC: Fix mktime argument updating 2025-08-11 19:00:23 +03:00
9b09d2b47a LibC: Update struct tm to be POSIX issue 8 compliant 2025-08-11 18:59:20 +03:00
1a6c5deb4b LibC: Add {AF,PF}_LOCAL as aliases to {AF,PF}_UNIX 2025-08-11 18:48:24 +03:00
45a73b00de LibC: Make glob_t a typedef 2025-08-11 18:47:55 +03:00
59fff26a5f LibC: Remove our iconv.h header and add libiconv port
If I ever end up writing my own iconv, i will drop the port :D
2025-08-11 18:46:15 +03:00
fde4d4662e LibC: Implement getopt_long{,_only}
Few ports attempt to use this so lets add them :D
2025-08-11 18:36:46 +03:00
c9355ad94a BuildSystem: Fix file permission bits on image creation
If a file had setuid/setgid/sticky bits set, they were not copied to the
sysroot
2025-08-11 14:48:57 +03:00
bad3b8b3e2 ports/binutils: Fix compilation when zstd is installed
binutils uses pkg-config to find zstd for the host when building. If our
zstd port is installed, it finds it instead and ends up including our
own sysroot which is incompatible with host's.

unsetting pkg-config related variables fixes this and allows binutils to
build fine even when zstd is installed. We can now make it a dependency.
2025-08-11 14:07:37 +03:00
0b81bb9b10 ports/quake2: Use SDL2 instead of our own frontend 2025-08-11 14:07:37 +03:00
f61c78efd5 ports/tinygb: Use SDL2 instead of our own frontend 2025-08-11 14:07:37 +03:00
6b2307ab22 ports/doom: Use SDL2 instead of our own frontend
This allows doom to play sounds!
2025-08-11 14:07:37 +03:00
9ccb381c31 ports: Add SDL2_mixer port
This allows some ports to use audio :D

I did not port any audio libraries so loading sounds probably doesn't
work :D
2025-08-11 14:07:37 +03:00
71133236f8 ports: Add timidity port 2025-08-11 14:07:37 +03:00
e5786fe435 init: Start AudioServer on boot 2025-08-11 14:07:37 +03:00
ef6ee78fd1 Kernel/LibC: Implement chroot 2025-08-11 14:07:37 +03:00
695262624d Kernel: Fix potential UB in AML OpRegion initialization 2025-08-11 03:45:38 +03:00
c96c264801 LibC: Implement fnmatch 2025-08-10 19:57:31 +03:00
af0bca74e4 Kernel/LibC: Implement {get,set,init}groups
This allows dropping /etc/group parsing from the kernel :D
2025-08-10 19:57:31 +03:00
f41e254e35 Kernel: Fix dead lock on process exit 2025-08-10 19:57:31 +03:00
7e472a9c1d Kernel: Fix USB FS device default max packet size
Apparently this is a common non spec compliant issue on many
controllers/devices.

thanks @sasdallas
2025-08-10 19:57:31 +03:00
ee3f10313a BuildSystem: Flip USB_ARGS and DISK_ARGS in qemu.sh
This allows attaching usb disk :D
2025-08-10 19:57:31 +03:00
5b587d199e Kernel/LibC: Implement FIONREAD for tcp and udp sockets 2025-08-10 19:57:31 +03:00
009b073892 LibC: Add IN6_IS_ADDR_* and IN_MULTICAST macros
These are assumed to exist by some ports
2025-08-10 19:57:31 +03:00
92e962430b LibC: Make sockaddr and sockaddr_in compatible with other systems
sockaddr:
make sa_data is 14 bytes on all systems

sockaddr_in:
add sin_zero
2025-08-10 19:57:31 +03:00
3aa20a3a32 Kernel: Fix ACPI _GPE calling
This adds patch adds support for extended GPEs and the second GPE
register block.
2025-08-07 19:35:13 +03:00
de7c3d3d29 Kernel: Don't try to create . in USTAR
Our build system adds . entry to the tar archive and it should be
handled as an no-op
2025-08-07 19:35:13 +03:00
3f89df338e IDT: Remove stack OOB check
This makes debugging easier when you can see the actual register values
and what is mapped and where
2025-08-07 19:35:13 +03:00
c7f89c9b77 ports: Update SDL2 2.30.11 -> 2.32.8 2025-08-07 16:43:05 +03:00
a107e463e8 ports/SDL2: Add audio support 2025-08-07 16:43:05 +03:00
7a5cfe1728 LibAudio/AudioServer: Add support for playing real time audio 2025-08-07 16:43:05 +03:00
7ad3f967db Kernel: Don't stop audio processing after each entry in AC97 2025-08-07 16:43:05 +03:00
d1c814cf9d Kernel: Optimize consecutive absolute mouse move events
This is a hack to make window server usable without kvm :D
2025-08-07 16:43:05 +03:00
72f85dce2b Kernel: Make userspace stack on-demand allocated
Also bump the hardlimit of stack size from 512 KiB->32 MiB. This still
feels quite low but is much better than before :D
2025-08-07 16:43:05 +03:00
f5bbcc017c Kernel: Only send one smp message when reserving a range
This was causing some kernel panic because processors ran out of smp
message storage when reserving large areas.

Also most of the time there is no need to actually send the SMP message.
If process is mapping something to just its own address space, there is
no need for a TLB shootdown. Maybe this should be only limited to kernel
memory and threads across the same process. I'm not sure what the best
approach here and it is better to send too many invalidations that too
few!
2025-08-07 16:43:05 +03:00
2980173c8e ports: Fix config.sub downloading 2025-08-07 16:28:09 +03:00
a84c348045 LibC: Add shm_{open,unlink} stubs
These are needed for our llvm port
2025-08-07 16:28:09 +03:00
d845ecc811 LibC: Add wcstok, wcstol and swprintf stubs
These are needed for our python3 port
2025-08-07 16:28:09 +03:00
064d9009a2 LibC: Add clock_getres stub
This is needed for our python3 port
2025-08-07 02:50:24 +03:00
b6aa5bdfab LibC: Implement if_indextoname and if_nametoindex
These are needed for our cmake port
2025-08-07 02:50:24 +03:00
a3bdf0456e LibC: Add getpriority stub
This is needed for our cmake port
2025-08-07 02:50:24 +03:00
e3ecf05866 LibC: Add stubs for {get,free}ifaddrs
These are needed for our libuv port
2025-08-07 02:50:24 +03:00
6240374dd1 LibC: Add semaphore stubs
These are needed for our bochs port
2025-08-07 02:50:24 +03:00
e17ee831a7 LibC: Add times stub
This is needed for our openssl port
2025-08-07 02:50:24 +03:00
aef9bd6357 LibC: Add mk{nod,fifo}{,at} stubs
These are needed for our tcl port
2025-08-07 02:50:24 +03:00
8857227a35 LibC: Add getservbyname stub
This is needed by our tcl port
2025-08-07 02:50:24 +03:00
937250c681 userspace: Add dummy libdl
This allows ports to link against without needing to patch it out
2025-08-07 02:50:24 +03:00
66d3a1d025 ls: Output in columns 2025-08-07 02:50:24 +03:00
647fedfa19 Kernel: Add missing multiboot.h 2025-08-05 17:12:26 +03:00
c593d3ed75 LibC: Add missing libintl.h 2025-08-05 17:10:43 +03:00
bd885a01e5 ports/expat: Remove libtool file 2025-08-05 03:47:52 +03:00
628825fdff ports: Don't set CMAKE_TOOLCHAIN_FILE environment variable
This doesn't allow llvm to build native tablegen
2025-08-05 03:47:16 +03:00
46dd411273 LibC: fflush stdout when reading from stdin
This is the *intended behaviour* per ISO C specification
2025-08-05 03:32:59 +03:00
2e2ee11452 LibC: Add more reasonable values to stack size constants 2025-08-05 03:32:59 +03:00
ce0df333b3 LibC: Make sa_data in sock_addr zero sized 2025-08-05 03:32:59 +03:00
8bbda78272 ports/xash3d-fwgs: Don't disable opengl and patch output
Manually link against libxash.so. My current dlopen does not support
loading ELF files that contain TLS
2025-08-05 03:32:59 +03:00
945509fc93 ports/mesa: Use llvm pipe instead of softpipe if llvm is compiled 2025-08-05 03:32:59 +03:00
b586917930 ports: Add llvm port
This can be compiled before mesa to make mesa use llvmpipe instead of
softpipe. llvmpipe is at least 10x faster :D
2025-08-05 03:09:24 +03:00
45ad6082bc DynamicLoader: Support dlopen(NULL, ...) 2025-08-05 03:09:24 +03:00
f27823babe Kernel: Move stacks to the top of userspace address space 2025-08-05 03:09:24 +03:00
95cfac471a Kernel: Rename loopback adapter lo0 -> lo 2025-08-05 03:09:24 +03:00
f7c1084c3e Kernel: Expose boot command line in /proc/cmdline 2025-08-05 03:09:24 +03:00
cf96bb6cc3 Kernel: Add support for multiboot
I don't know why I did it but it works now :D
2025-08-05 03:09:24 +03:00
f1369c8fd6 Kernel/LibC: Implement mprotect
There may be some race conditions with this but i think this is good
enough to start with
2025-08-05 03:09:24 +03:00
eb7922ab88 LibC: Implement pthread_cond_* using a futex 2025-08-05 03:09:24 +03:00
dfdfb7cdaf Kernel: check all threads in validate_pointer_access 2025-08-05 03:09:24 +03:00
1cc0fb9c01 Kernel: Reschedule if idle after IPI
This allows starting thread execution right after thread is received
from load balancing
2025-08-05 03:09:24 +03:00
a51b589bc9 Kernel: Allow any signal flags and support SA_RESETHAND 2025-08-05 03:09:24 +03:00
5940e912b3 Kernel/LibC: Implement simple futex 2025-08-05 03:09:24 +03:00
658a001d91 LibC: Make pthread_barrier safe
It used to deadlock and it was not safe if more threads than the target
were attempting to wait on it.
2025-08-05 03:09:24 +03:00
57c9f5a8a8 LibC: lock mutex when pthread_cond_timedwait times out 2025-08-05 03:09:24 +03:00
fa7b58057c LibC: Add MAP_ANON as synonym for MAP_ANONYMOUS
This is part of POSIX issue 8 and some things only check MAP_ANON
2025-08-05 03:09:24 +03:00
0e0f5295cf LibC: Make {,__cxa_}atexit thread safe 2025-08-05 03:09:24 +03:00
284c9e5f61 Kernel: Don't kill process if stack pointer is OOB
This can be valid if process is using green threads or for some other
reason using its own stack
2025-08-05 03:09:24 +03:00
927fbda1e8 Kernel: Make on-demand paging thread safe 2025-08-05 03:09:24 +03:00
d25a5034db LibC: Update thread id on fork 2025-08-05 03:09:24 +03:00
f197d39aaf LibC: Don't allow pthread_join to return EINTR 2025-08-05 03:09:24 +03:00
4a95343936 LibC: Make _get_uthread a macro
This allows nice inlining :)
2025-08-05 03:09:24 +03:00
4e705a91af LibC: Fix pthread keys
I had misunderstood how these are supposed to work :D
2025-08-05 03:09:24 +03:00
82b351469b DynamicLoader: Setup thread id when initializing TLS
This allows pre-libc code use pthread functions

(__cxa_guard_release calls pthread_cond_broadcast)
2025-08-05 03:09:24 +03:00
ea91bdcce7 WindowServer: Make relative mouse no-op with absolute mouse 2025-08-05 03:09:24 +03:00
256c9daefd ports/SDL2: Optimize rendering and fix cursor
Remove the unnecessary framebuffer layer, we can just use the window's
own framebuffer.

Set default cursor on mouse initialization, this fixes cursor hiding in
tuxracer

defined SetRelativeMouseMode instead of SetMouseCapture. This is what
the behaviour was :D
2025-08-05 03:09:24 +03:00
af0a46e79c LibGUI/WindowServer: Rename mouse capture -> mouse relative
My terminology was incorrect and this is more correct
2025-08-05 03:09:24 +03:00
4519c48284 WindowServer: Fix custom cursors
Custom cursor is now only set if the cursor is in the client area
instead of anyehere in the window. This makes hidden cursor visible
when it is on top of the title bar!
2025-08-05 03:09:24 +03:00
8ea32c7650 WindowServer: Fix relative mouse vertical flip 2025-08-05 03:09:24 +03:00
5972d40ced ports: Update zstd 1.5.6 -> 1.5.7
Also build using cmake because we can :)
2025-08-05 03:09:24 +03:00
f35a6b3922 BuildSystem: Fix meson toolchain file
sed to replace SYSROOT did not work because paths contain /

also add cmake to allow cmake based library detection
2025-08-05 03:09:24 +03:00
21009c37b4 BuildSystem: Remove unnecessary variables from cmake toolchain 2025-08-05 03:09:24 +03:00
11a2d15003 BuildSystem: Optimize disk image creation
disk image is now created with rsync so there is no need for copying the
whole sysroot twice.
2025-08-05 03:09:24 +03:00
d8a695a88d Kernel: Don't fail ustar unpack when creation fails 2025-08-05 03:09:24 +03:00
f82390424b ports: Add cmake port 2025-08-05 03:09:24 +03:00
08ed405a5b ports: Add libuv port 2025-08-05 03:09:24 +03:00
8c598a6902 LibC: Include stdint.h instead of inttypes.h in network headers 2025-08-05 03:09:24 +03:00
8e9c40caa4 LibC: Pump OPEN_MAX to 128
cmake seems to use around 70 when checking compiler. That seems quite a
lot but could be "normal"
2025-07-31 22:47:40 +03:00
8c29036fbf Kernel: Fix EAGAIN on hungup pipe 2025-07-31 22:47:40 +03:00
b46337d376 BuildSystem: Add banan-os cmake platform 2025-07-31 22:47:40 +03:00
56d701492b ports/ncurses: Add c++ bindings 2025-07-31 22:47:40 +03:00
07e4e764a0 LibC: Implement mbtowc 2025-07-31 22:47:40 +03:00
66fe2f2e50 LibC: Fix readv and writev 2025-07-31 22:47:40 +03:00
fda0ced72e LibC: Implement getpw{nam,uid}_r 2025-07-31 22:47:40 +03:00
654e8bb7f6 LibC: Implement getgr{gid,nam}_r 2025-07-31 22:47:40 +03:00
80ffde5e1e LibC: Implement aligned_malloc
This is part of POSIX issue 8
2025-07-31 22:47:40 +03:00
52309e0754 LibC: Add in6addr_{any,loopback} definitions 2025-07-31 22:47:40 +03:00
31e411f8f1 LibC: Implement recvmsg and sendmsg
These just wrap recvfrom and sendto so ancillary data is not supported
2025-07-31 22:47:40 +03:00
de45b760b5 LibC: Implement alphasort and scandir 2025-07-31 22:47:40 +03:00
ff29e9c4d6 LibC: Implement {,f}pathconf
This just return minimum values specified by posix
2025-07-31 22:47:40 +03:00
cc04bd0f06 LibC/Kernel: Implement ttyname_r 2025-07-31 22:47:40 +03:00
e72e1e4e43 LibC: Add _SC_NPROCESSORS_{CONF,ONLN) 2025-07-31 22:47:40 +03:00
987cc3c237 3000th COMMIT: ports: Add halflife port 2025-07-31 22:47:34 +03:00
935f69e011 ports: Add freetype port 2025-07-31 22:47:29 +03:00
9f0c2fb6e2 ports: Apply only patches ending in .patch 2025-07-31 22:47:29 +03:00
9b18bda9c8 Kernel: Make epoll always check for HUP and ERR 2025-07-31 22:47:29 +03:00
7831c74e8c DynamicLoader: Add support for LD_LIBRARY_PATH
Also fix a bug with dlopen with TLS
2025-07-31 22:47:29 +03:00
c1978f9133 Shell: Implement redirections
This works well enough. At the moment redirections can appear anywhere
in the command **after** environment variables and possible alias
command. This means commands like `>foo echo hello` are not supported.
I don't think this is big enough problem for now (99% time redirections
are given after arguments) that i would rewrite the environment and
alias parsing.
2025-07-22 16:54:06 +03:00
05affda20c ports: Add python3 port 2025-07-22 14:11:09 +03:00
e2eb555ca0 LibC: Add dummy libintl support
This doesn't really do anything but allows some ports to use it :D
2025-07-22 13:26:53 +03:00
418c3c9cfa ports: Remove unneeded libtool files after install 2025-07-22 10:32:52 +03:00
bc66e181a5 ports: Update to new config.sub syntax
There is no longer need to manually patch config.sub files!
2025-07-22 10:31:56 +03:00
6971f76bd3 ports: Add support for downloading upstream config.sub
banan-os is now in the upstream config.sub. This means no more
config.sub patches!
2025-07-22 10:13:41 +03:00
1e65f02ff7 Terminal: Handle bell and warn on unimplemented control characters 2025-07-21 14:28:09 +03:00
4efaf65d3f BuildSystem: Use usb-tablet instead of usb-mouse
This allows sharing mouse between host and guest!
2025-07-19 18:02:07 +03:00
aa0249fadb WindowServer: Support absolute position mouse 2025-07-19 18:01:23 +03:00
2c65590134 Kernel: Add support for absolute position mouse 2025-07-19 18:00:39 +03:00
a0d1a9ad67 Kernel: Fix PIT::prescheduler_sleep_ns
I don't even know what I was doing here :D
2025-07-19 01:25:46 +03:00
5df6270e32 Kernel: Clobber flags in rdrand 2025-07-18 19:36:37 +03:00
7af6e1cd34 Kernel: Ignore HID main item tag 0
This for some reason exists in vmware's usb devices
2025-07-18 19:11:12 +03:00
cceb066284 Kernel: Don't use IST on 32 bit target
This only exists in 64 bit
2025-07-18 19:10:48 +03:00
7a054787ca Kernel: Don't print error if root is empty
This is used when loading filesystem from initrd
2025-07-18 19:09:43 +03:00
d27891c79f Kernel: Fix correct IOAPIC lookup based on gsi 2025-07-18 19:09:20 +03:00
5874fd640e Kernel: Fix TmpFS for 32 bit target
There was a problem when sizeof(size_t) != sizeof(PageInfo)
2025-07-18 19:07:32 +03:00
11ae220dbe LibImage: Optimize image resizing algorithms 2025-07-18 18:20:37 +03:00
22542a3a71 BuildSystem: Enable sse and sse2 for all programs and libraries
This is default on x86_64 but not on the 32 bit target. banan-os
already requires the CPU to support SSE even on 32 bit platforms.
2025-07-18 18:20:37 +03:00
e16fb6a8e9 Kernel: Don't validate allowed null pointers on syscalls 2025-07-17 22:14:04 +03:00
d941e6d70b General: Update README features and environment variables 2025-07-17 21:45:48 +03:00
b65068dc7d BuildSystem: Add support for building initrd image
This is nice for testing when there isn't xhci controller available or
my usb stack fails :)
2025-07-17 21:45:48 +03:00
d5301508ec Kernel: Increase kernel thread stack size
HACK HACK HACK

This is just to make banan-os boot on one razer laptop where AML
triggers a stack overflow :)
2025-07-17 21:21:14 +03:00
793cca423b Kernel: Fix system timer disabling
I was actually not disabling system timer (HPET, PIT) when using lapic
timers for scheduling. This made BSB get too many timer interrupts :D
2025-07-16 20:02:04 +03:00
3960687f9d Kernel: Parse PCIConfig opregion address on read/write
I was testing on some hardware and _ADR does not have to exist in the
namespace when opregion is parsed :)
2025-07-16 15:34:36 +03:00
3ec7aad432 Kernel: Increase PS/2 timeout and detect more keyboards
I was testing on a old T61
2025-07-16 15:29:27 +03:00
84f1ad4f26 ports: Fix doom compilation with the new toolchain 2025-07-15 16:12:03 +03:00
6b9dbf625d userspace: Add audio utility to play audio files 2025-07-15 16:12:03 +03:00
3aea2c007d Userspace: Add simple AudioServer and LibAudio 2025-07-15 16:12:03 +03:00
85d195212a BuildSystem: Update qemu script and add ac97 2025-07-15 14:17:49 +03:00
8a663cb94f Kernel: Implement basic AC97 driver 2025-07-15 14:17:49 +03:00
674e194a91 Kernel: Don't fail PCI interrupt allocation with PCIe and no PCI 2025-07-15 14:17:49 +03:00
c57f0abb56 BuildSystem: Order source list alphabetically 2025-07-15 14:17:49 +03:00
163fdcd582 LibC: Fix exec family function path resolution 2025-07-15 14:17:49 +03:00
3be17c6117 BAN: Add clear and access by index to CircularQueue 2025-07-10 17:24:40 +03:00
995dfa1455 Kernel: Fix AML PCIConfig OpRegion accesses
Apparently I'm not supposted to calculate device/function from the
offset, but parse them from the acpi namespace :)

This allows PCI PIN interrupt routing actually work
2025-07-04 13:21:02 +03:00
544c8dbc13 Kernel: Optimize AML interpreter stack usage
There is a very hacky no-inline hack that I am not proud of but it drops
the stack usage of few functions A LOT.

Previously Virtual Box could not boot with our 8 page stack, but these
changes allow it to boot on 5!
2025-07-03 00:49:23 +03:00
8da4f80453 Kernel: Add custom stack to double fault handler
This prevents triple faults!
2025-07-02 23:14:52 +03:00
6084aae603 Kernel: Add guard pages to kernel and userspace stacks 2025-07-02 23:12:36 +03:00
e1319a06f2 Kernel: Remove accidentally commited debug prints 2025-07-02 23:09:57 +03:00
51fd7a607d Kernel: Fix IDE controller waiting
We did not correctly wait until controller is ready to receive data on
write command. Also remove possible kernel panic if controller sends
unexpected interrupts
2025-07-02 22:04:41 +03:00
8aff315c7b LibC: fflush file in setvbuf before updating the buffer 2025-07-02 01:54:03 +03:00
8e0d79f301 ports: Fix make compilation with new toolchain 2025-07-02 01:54:03 +03:00
8a0269d29e Kernel: Remove kernel processes
Kernel can just use raw threads, pretty muchs the only thing that
process provides is syscalls which kernel threads of course don't
need.

Also this makes init process have pid 1 :D
2025-07-02 01:54:03 +03:00
892e16dfb1 Kernel: Increase PS2 timeout to 300 ms, load PS2 in separate thread
PS/2 seems to hit command timeout sometimes on slow emulation so
increase the timeouts.

Also move PS/2 device initialization to a different thread because
device indentification waits for timeouts.
2025-07-02 00:17:42 +03:00
92e4078287 Kernel: Rewrite ThreadBlocker
This gets rid of a very old bug where kernel panics when thread is being
woken up and unblocked at the same time on different cores. This
required adding a new lock to SchedulerQueue::Node and adding a cap to
how many threads a threadblocker can simultaneously block. I don't think
I ever block more than five threads on the same ThreadBlocker so this
should be fine.
2025-07-02 00:17:42 +03:00
41e1819072 Kernel: Align argv and envp to pointer boundary
This bug was found with ubsan
2025-07-02 00:17:42 +03:00
fb7e9719a1 Kernel: Add fast fill method to framebuffer device
This makes `clear` much faster when running without kvm!
2025-07-02 00:17:42 +03:00
c2d09b64ca Kernel: Drop 24 bpp support from double buffer
I don't even know why this was supported, I am not planning on making
the fb anything other than 32 bpp
2025-07-02 00:17:42 +03:00
1b2aa6c2da Kernel: Fix unaligned access in AML
Found with ubsan
2025-07-02 00:17:42 +03:00
a5b4cee298 Kernel: Load USTAR from a boot module if loading root partition fails
This allows banan-os to boot on hardware where we don't have working
storage driver or the storage driver fails (pretty common with my usb
mass storage drivers...)
2025-07-02 00:17:42 +03:00
17f1ac10e3 Kernel: Don't ignore modules passed with multiboot2 2025-07-02 00:17:42 +03:00
c67198032f Kernel: Rewrite TmpFS block and inode allocation
This makes creating files and appending to then A LOT faster. Some code
I tested took 40 seconds in the previous implementation and less than a
second on the new one!

This code is really sketcy, I hope I'll never have to touch it again :)
2025-07-02 00:17:42 +03:00
107b092982 Kernel: Allow arbitrary sized tmpfs files
The 2 block limit started to get annoying :D
2025-07-02 00:17:42 +03:00
bac06e45a4 Kernel: Fix TmpSymlinkInode target getting/setting 2025-07-02 00:17:42 +03:00
0e8a68831c Kernel: Fix TmpInode chmod not preserving file type 2025-07-02 00:17:42 +03:00
5912abd541 Kernel: Add error reporting for readonly mounted filesystems 2025-07-02 00:17:42 +03:00
13d33995cb Kernel: Make sure PageTable::fast_page gets passed page aligned addr 2025-06-30 01:48:47 +03:00
c8c05f62b4 Kernel: Remove unused FileSystem::dev 2025-06-29 00:29:03 +03:00
944b045885 Toolchain: Set CMAKE_STAGING_PREFIX in toolchain file 2025-06-28 23:34:11 +03:00
19897ffa26 userspace: Compile test utility :D 2025-06-28 22:40:00 +03:00
42a10b21c7 userspace: Implement true and false utilities 2025-06-28 22:39:19 +03:00
5df0e25c1f userspace: Implement chown utility 2025-06-28 21:32:59 +03:00
ebf2b16d09 Kernel: Implement chown to ext2 and tmpfs 2025-06-28 21:28:54 +03:00
f2eaab6e43 ports: Add tuxracer port
THIS IS SUPER SLOW
2025-06-28 20:54:45 +03:00
a847823411 ports: Add tcl port 2025-06-28 20:54:45 +03:00
fe9a8b542a ports: Add bochs port
THIS IS SUPER SLOW
2025-06-28 20:54:45 +03:00
cd101b6844 ports: Add sdl12-compat port 2025-06-28 20:54:45 +03:00
69229102c4 ports: Add SDL2 port 2025-06-28 20:52:33 +03:00
4bc3630d19 ports: Add glu port 2025-06-28 20:52:20 +03:00
ab00686ac9 ports: Add mesa port 2025-06-28 20:51:29 +03:00
c3004a038f ports: Add bash port 2025-06-28 20:48:13 +03:00
9cf9d8847b ports: Add lua port 2025-06-28 20:48:13 +03:00
0a3c10566b ports: vim update to 9.1 2025-06-28 20:48:13 +03:00
c94243e107 ports: Update some ports to new syntax 2025-06-28 20:48:13 +03:00
505388b9fa ports: Add pre_install and post_install to install.sh 2025-06-28 20:25:35 +03:00
7314cf708c Kernel: Only restart certain syscalls with SA_RESTART
SA_RESTART is not supposted to restart every function.
2025-06-28 20:25:35 +03:00
3e6a4f2b16 LibC: Add getgroups stub 2025-06-28 20:25:35 +03:00
c7c3dd7662 init/ports: Fix environment variables in init/ncurses
init no longer sets NCURSES_NO_UTF8_ACS
ncurses no longer sets TERM
2025-06-28 20:25:35 +03:00
e4f025edd6 LibC: Implement deprecated bcmp, bcopy, bzero 2025-06-28 20:25:35 +03:00
96f3efbf86 LibC: Fix enviroment variable allocation 2025-06-28 20:25:35 +03:00
2b2130ff42 toolchain/ports: Use strip install targets
I just found that these exist. This is much cleaner than manually
stripping the executables!
2025-06-28 20:25:35 +03:00
463ce05da0 ports: Allow specifying custom make targets 2025-06-28 20:25:35 +03:00
fa4095ba95 ports: Add pre_configure to build system
We have post_configure, so why not this :)
2025-06-28 20:25:35 +03:00
db571b4859 Kernel: Allow relockign mutex even when holding a spinlock
Only reason mutex locking is now allowed with spinlocks is to prevent
yield.

Also try_lock can be now safely used while holding a spinlock
2025-06-28 19:40:54 +03:00
e8491b34b8 Kernel/LibC: Rework TIOC{G,S}WINSZ more linux like
Userspace can freely set terminal size, kernel just updates it when for
example new font is loaded. Also SIGWINCH is now sent by kernel instead
of userspace.
2025-06-28 19:40:54 +03:00
521457eb92 DynamicLoader: Add support for calling destructors
After all libraries are initialized, their destructors are registered
using atexit
2025-06-28 16:55:13 +03:00
f26a445ce6 LibC: Make malloc actually allign to s_malloc_default_align boundary 2025-06-28 16:55:13 +03:00
f73bb242f3 Kernel: Save fpu state and flags in signal handler
This was causing some weird crashes :D
2025-06-28 16:55:13 +03:00
9e895e5286 Kernel: Use fxsave64 and fxrstor64 on 64 bit target 2025-06-28 16:55:13 +03:00
5b0e5512a8 Kernel: Don't block in send until full message is sent
Only block until some data was sent. This allows select + send to be
actually non blocking if used correctly.

Also fixes a bug with non blocking sockets that could not send the full
message is one try.
2025-06-28 16:55:13 +03:00
850b3284ac Terminal: Fix screen clearing when scrolling 2025-06-28 16:55:13 +03:00
05a727979a Kernel: Make sse initialization thread safe 2025-06-28 16:55:13 +03:00
d68c88c3f9 LibC: Implement rewinddir 2025-06-28 16:55:13 +03:00
5f07d53034 WindowServer: Send mod key to clients
Also roll back accidental mod key update from super->alt
2025-06-28 16:55:13 +03:00
fe62ce4bae Kernel: Fix spurious wakeup from SYS_SLEEP 2025-06-28 16:55:13 +03:00
fb09aa4d06 LibInput: Correctly resize keyboard layout maps 0xFF->0x100 2025-06-28 16:55:13 +03:00
4d080b30ab LibInput: Pass raw scancode in KeyEvent 2025-06-28 16:55:13 +03:00
2d314e72fe LibGUI: Implement basic message box 2025-06-28 16:55:13 +03:00
cf07b747fe LibGUI/WindowServer: Implement per-window custom cursors 2025-06-28 16:55:13 +03:00
273e9bbc92 LibGUI/WindowServer: Implement per-window cursor hiding 2025-06-28 16:55:13 +03:00
7dcf1797e9 WindowServer: Cleanup packet callback calling 2025-06-28 16:55:13 +03:00
7aa24b6157 LibGUI: Implement serialization for BAN::Vector 2025-06-28 16:55:13 +03:00
d73a667437 LibGUI: Implement very bad widget system :D 2025-06-28 16:55:13 +03:00
4695fa061d Kernel: Don't panic if UNIX socket is already bound but deleted 2025-06-28 16:55:13 +03:00
7bf7bfbe13 Texture: Add invisible color when copying textures
This should probably support proper alpha blending but I'm lazy :)
2025-06-28 16:55:13 +03:00
397219c22e LibC: Implement very hacky dlopen/dlsym/dclose
If ELF loading fails, this will just crash the program :D

And there is no support for RTLD_LOCAL
2025-06-28 16:55:13 +03:00
83c0ef3514 Kernel: Implement CLOCK_{PROCESS,THREAD}_CPUTIME_ID 2025-06-28 16:55:13 +03:00
4fa40de557 WindowServer: Fix crash when moving mouse out of bounds 2025-06-28 16:55:13 +03:00
bc06926702 LibC: Implement gethostbyaddr 2025-06-28 16:55:13 +03:00
9de27110e2 LibC: Add alloca.h 2025-06-28 16:55:13 +03:00
93e5d09a63 Kernel/LibC: Implement flock 2025-06-28 16:55:13 +03:00
0cbc39698c WindowServer: Ignore SIGPIPE so we don't crash unexpectedly 2025-06-28 16:55:13 +03:00
83069e433f LibGUI/WindowServer: Implement window showing/hiding 2025-06-28 16:55:13 +03:00
bbb490b24f LibGUI: Implement set_max_size
I already support set_min_size so why not this :)
2025-06-28 16:55:13 +03:00
85f200bd86 LibC: Add sched_get_priority_{min,max}
I don't support priority scheduling so these are just no-ops
2025-06-28 16:55:13 +03:00
0f2c02fb04 LibC: Add stubs for pthread_{get,set}schedparam 2025-06-28 16:55:13 +03:00
6d3d41abe2 Kernel: Fix possible division by zero in scheduler 2025-06-28 16:55:13 +03:00
6fa7fe26dc ports: Add support for meson build systems 2025-06-28 16:55:13 +03:00
fe804c123d ports: Add expat port 2025-06-28 16:55:13 +03:00
dba32fb95d ports: Add SONAME to zlib's dynamic library 2025-06-28 16:55:13 +03:00
7dc187fdb1 ports: Update gcc 12.2.0->15.1.0
Also enable threading :)
2025-06-28 16:55:13 +03:00
ee5a627952 ports: Update mpfr 4.2.1->4.2.2 2025-06-28 16:53:06 +03:00
3b83561309 ports: Fix gmp port to compile with gcc 15.1.0 2025-06-28 16:53:06 +03:00
6fb0b5203a ports: Update binutils 2.39->2.44 2025-06-28 16:53:06 +03:00
4677d7a1c6 LibC: Update RAND_MAX INT32_MAX -> INT_MAX 2025-06-19 19:06:24 +03:00
3283359ac8 Kernel: Cleanup ANSI DSR 2025-06-19 19:05:49 +03:00
fff16f6b8c Kernel: don't directly access user memory in mmap 2025-06-19 19:04:20 +03:00
a347ceba74 Kernel: Cleanup sys_wait sleep/signal handling 2025-06-19 19:03:42 +03:00
05836fab4c Kernel: Allow accessing fd's inode without having read/search access
I have no idea what the point of this was. VFS is already verifying
read and search access
2025-06-19 19:02:28 +03:00
15e84f28ed LibC: Include strings.h in string.h 2025-06-19 19:01:45 +03:00
32c35a822b BuildSystem: binutils1.39->1.44, gcc12.2.0->15.1.0 2025-06-19 19:00:50 +03:00
9c86e5e54d Kernel: Add ANSI SGR 39 and 49
Also debug log unimplemented ANSI SRGs, this makes finding missing
commonly used ANSI SGR codes more easy
2025-06-18 20:34:55 +03:00
87f348b48e LibC: Fix my ugly and hacked posix_memalign 2025-06-18 14:17:17 +03:00
ff289b25b6 LibC: Implement {,v}asprintf
These were added in POSIX issue 8
2025-06-17 13:56:30 +03:00
a9f58e96d2 LibC: Add endian.h
This is part of POSIX issue 2024 and some software depends on it
2025-06-17 13:15:42 +03:00
c61ded8a1e toolchain: Update gcc patch to add pthread driver
This makes gcc recognize -pthread argument
2025-06-17 12:49:59 +03:00
7651ca747d LibC: Allow searching null char with wcschr 2025-06-16 15:09:55 +03:00
7ff7a4aa87 LibC: Fix locale handling in wcrtomb and mbrtowc 2025-06-16 15:09:39 +03:00
cdcd226b1a LibC: Fix mbstowcs and add wcstombs 2025-06-16 15:08:49 +03:00
f9451915b9 LibC: Use pause in pthread spinlock locking 2025-06-16 15:07:58 +03:00
5e4e174d61 tests: Add tls test 2025-06-16 15:07:26 +03:00
4a00cb7d55 DynamicLoader: Add few more TLS relocations 2025-06-16 15:06:48 +03:00
b97c123764 BAN: Make WeakPtr::lock const
There is no reason why it would not be :)

Also this prevented upstream from compiling
2025-06-11 16:53:43 +03:00
69bdff6b7e ports: Add links port
We now have graphical browser on banan-os :O
2025-06-11 16:02:00 +03:00
8574fcf6e1 ports: Add libwebp port 2025-06-11 16:01:47 +03:00
f4f424bf04 ports: Add libtiff port 2025-06-11 16:01:47 +03:00
ac745bfa3d ports: Add libjpeg port 2025-06-11 16:01:47 +03:00
aa691f236e ports: Add libpng port 2025-06-11 16:01:47 +03:00
a0a9d49d81 ports: Update toolchain triple and add post_configure
post_configure is called after default configure. This can be used for
port specific customization when using default configure function
2025-06-11 16:01:47 +03:00
125f8b591d Kernel: Don't crash if socket tries to reconnect
:D
2025-06-11 01:54:41 +03:00
c97b60e7e5 LibGUI: Remove parameters I had forgot in function declarations 2025-06-11 01:53:31 +03:00
8a73414e3e LibGUI: Add support for clip area to texture 2025-06-11 01:53:31 +03:00
ac22e006a4 Shell: Don't get stuck on broken state when failing to build command 2025-06-10 11:03:02 +03:00
30d5d85d1d userspace: Add test utility 2025-06-08 23:56:39 +03:00
6f74f3c386 BAN: Allow constexpr construction of StringView 2025-06-07 18:29:32 +03:00
515918329c ports: Add SpecSeek port 2025-06-06 17:41:59 +03:00
8ea0a67280 Terminal: Add support for tabs 2025-06-06 16:41:06 +03:00
5ad7d7edb1 DynamicLoader: Fix TLS on 32 bit platform
There were two problems with my previous implementation
- TLS was not allocated if nothing used it. There is a fallback
  initialization in _init_libc, but this was not enough if one of the
  init functions tried to access errno.
- __tls_get_addr was not resolved. If __tls_get_addr was called through
  a plt entry, everything would just break :(
2025-06-06 16:27:07 +03:00
00c6820825 LibC: Make {open,sys,close}log use their own FILE instead of stddbg 2025-06-06 11:59:15 +03:00
6beaafcf11 LibC: Define std{in,out,err,dbg} with their actual names 2025-06-06 11:56:39 +03:00
e92f039a17 Kernel: Fix tcp sending with already sent unacknowledged bytes 2025-06-06 11:55:44 +03:00
ef76ffa1c1 Kernel: Remove unnecessary hack
This is no longer needed as thread unlocks its spinlock before calling
Process::exit() on terminating signal
2025-06-06 11:13:55 +03:00
652eb2346c Kernel: Fix syscall interrupt disabling
If thread had a terminating signal, syscall leaving would try to lock
process's mutex while not having interrupts enabled
2025-06-06 11:12:48 +03:00
66726090ec Kenrel: Fix TCP connection closing
If TCP socket was connected with connect() instead of accept() it would
never send FIN to other end when it was closed.
2025-06-06 11:10:29 +03:00
b668173cba Kernel: Fix pseudo terminal writability 2025-06-06 11:09:50 +03:00
a7e20d6e85 LibC: Fix getnameinfo port endianness 2025-06-06 06:52:56 +03:00
c6ded82406 Kernel: Fix a deadlock when thread is executing terminating signal 2025-06-06 06:52:27 +03:00
a76c6faffc Kernel: Fix a deadlock when process is exiting 2025-06-06 06:52:02 +03:00
81ff71a97f Kernel: Track the number of recursive spinlocks a thread is holding 2025-06-06 06:51:15 +03:00
56db0efe58 Kernel: Add missing file for race condition fixes :) 2025-06-06 04:03:37 +03:00
5eefd98e1b Kernel: Add debugging macro to dump syscalls that take a long time 2025-06-06 04:00:57 +03:00
eecdad50a6 Kernel: Fix most of mutex + block race conditions
All block functions now take an optional mutex parameter that is
atomically unlocked instead of having the user unlock it before hand.
This prevents a ton of race conditions everywhere in the code!
2025-06-06 03:59:22 +03:00
96d5ed9cc7 Kernel: Fix E1000 driver interrupts
I have no idea why, but E1000 seems to be missing interrupts frequently
when clearing ICR only at the end of the interrupt handler
2025-06-06 03:45:35 +03:00
73090ecb37 Kernel: TTY set EPOLLOUT 2025-06-05 22:04:51 +03:00
8812704601 Kernel: Make sure IPv4 and ARP packets are not missed
This is a really hacky solution but will do until i get atomic
unblocking with respect to locks
2025-06-05 22:03:15 +03:00
0f189d410e Kernel: Fix unix socket recv from
If connection on unix socket was closed and other end tries to recvfrom,
the thread would enter a fucked up state where it held the socket's
spinlock when returning to userspace.
2025-06-05 22:02:53 +03:00
cfeabc4580 Kernel/Terminal: Fix ANSI SGR 8 bit color parsing 2025-06-05 20:43:57 +03:00
49f203d61d Terminal: Add ANSI CSI P and ANSI SGR 22 2025-06-05 02:41:48 +03:00
a912a4dc67 LibGUI: Remove fill_color from texture copy API
Nothing was using this and it just overcomplicated everything
2025-06-05 02:40:51 +03:00
f79db874bf Kernel: Fix ANSI CSI 1J
I was accidentally clearing the whole screen when I needed to clear from
cursor to the end of the screen
2025-06-05 02:38:57 +03:00
8de19aff3c Kernel/Terminal: Fix 24 bit ANSI SGR color parsing 2025-06-05 02:38:07 +03:00
bf41b448d6 Kernel: Fix TCP sending
- Fix race condition when adding packet to send buffer before other end
  has acknowledged it
- Allow sending multiple packets before receiving ACK for previous ones
2025-06-04 22:21:35 +03:00
448632cf11 Kernel: Add fast path to pselect and ppoll
If events are available right away, don't create epoll object to wait
on. Also fix pselect return value to the number of bits set. Previously
return value could've been greater than that if epoll return EPOLLERR or
EPOLLHUP for events that were not listened to
2025-06-04 17:51:22 +03:00
11174bfa14 BuildSystem: Rename toolchain -> x86_64-pc-banan_os 2025-06-03 23:02:10 +03:00
84b1f3990c LibC: Fix getnameinfo
How was i doing everything so wrong :D
2025-06-03 16:36:39 +03:00
943069b2a3 Kernel: Socket EPIPE and send SIGPIPE on write after hang up 2025-06-03 10:24:44 +03:00
e305698e6b Kernel: Fix epoll EPOLLHUP and EPOLLERR reporting 2025-06-03 10:23:53 +03:00
4c0b7d44b4 Kernel: Enable ECHOE and ECHOK, support VKILL, fix VEOF 2025-06-02 16:26:53 +03:00
775c77c0fa Shell: Get default backspace key from c_cc[VERASE] 2025-06-02 15:55:20 +03:00
fb466b5af7 Kernel: use termios c_cc values instead of hardcoded characters 2025-06-02 15:54:11 +03:00
e473118ec8 userspace: Add nologin "shell" 2025-06-02 12:26:16 +03:00
755d41ca4e LibC: Add pw_passwd and pw_gecos to passwd structure
This information is available in /etc/passwd either way so why not
expose it to the user. Practically all UNIX-likes have these either way
2025-06-02 12:23:06 +03:00
bbff9f89b0 BuildSystem: Don't invoke ninja directly, but use cmake --build 2025-06-02 11:45:06 +03:00
fdcb38ac1f Shell: Accept '\r' as enter
This happens with some terminals and i don't want to bother with fixing
my termios :D
2025-06-02 11:42:06 +03:00
fac742c038 test-sort: Add qsort test 2025-06-02 11:41:34 +03:00
5a6b43fc90 LibC: Remove debug printing from getnameinfo 2025-06-02 11:39:18 +03:00
317f413746 LibC: Implement very hacky posix_memalign
I did not even test this and i know the code is super hacky. I could not
bother with writing proper code for this xD
2025-06-02 11:39:18 +03:00
895909b7fa LibC: Add CMSG_* definitions to sys/socket.h 2025-06-02 11:39:18 +03:00
2ee8b6c8b4 LibC: Add more definitions to netinet/in.h
These are non-standard but a lot of UNIX-likes have them networking
software attempts to use them
2025-06-02 11:39:18 +03:00
022bb69782 LibC: Implement inet_aton
This is not POSIX but IMO it makes sense to have the counter part to
inet_ntoa
2025-06-02 11:39:18 +03:00
be6da3e0db BuildSystem: Compile gcc with threading support 2025-06-02 11:39:18 +03:00
1f07e02298 BuildSystem: Fix cmake toolchain file processor 2025-06-02 11:39:18 +03:00
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
c5b0d0235f Kenrel: Allow Processor::send_smp_message to send event to current CPU 2025-06-02 11:39:18 +03:00
b7948551ff userspace: Add empty libm and libpthread
These making porting stuff easier. I could not find a way to tell CMake
that the system does not have threads library
2025-06-02 11:39:18 +03:00
e109b5cff6 Kernel: Remove unnecessary locks from Pipe
Inode already locks its own mutex when read/write is called there is no
need to explicitly lock them in read_impl/write_impl
2025-06-02 11:39:18 +03:00
9883fb7bf6 Kernel: Rewrite epoll notifying system
This removes the need to lock epoll's mutex when notifying epoll. This
prevents a ton of deadlocks when epoll is notified from an interrupt
handler or otherwise with interrupts disabled
2025-06-02 11:39:18 +03:00
e9f8471a28 BAN: Return UTF::invalid from byte_length instead of 0 2025-06-02 11:39:18 +03:00
4656b11256 LibC: actually use ATEXIT_MAX for atexit limit 2025-06-02 10:43:49 +03:00
f2ccab2df7 ports/openssl: Fix openssl
New unistd.h definitions (or something) makes openssl think recvmsg is
available, disable it manually.
2025-06-01 19:51:33 +03:00
b2e3aefa72 Kernel: Don't crash when terminating process with signal 2025-06-01 16:59:02 +03:00
2b48933f29 LibC: Implement all functions from complex.h 2025-06-01 13:48:03 +03:00
4ac6cbe70e LibC: Add some missing wchar.h functions
isw* functions are just wrappers to is*
tow* functions are just wrappers to to*
2025-06-01 13:48:03 +03:00
cc07c3df94 LibC: Add basic strxfrm{,_l} 2025-06-01 13:48:03 +03:00
31bcad2535 LibC: Implement truncate 2025-06-01 13:48:03 +03:00
b75970958e Kernel/LibC: Implement unlinkat 2025-06-01 13:48:03 +03:00
91756c057e LibC: Add all of the missing POSIX definitions in unistd.h and limits.h 2025-06-01 13:48:03 +03:00
df7f245cf8 LibC: Implement pthread_atfork
Again this code is not tested but *feels* right :D
2025-06-01 13:48:03 +03:00
dbdefa0f4a LibC: Implement pthread cancelation
This code is not tested at all but it looks correct xD
2025-06-01 13:48:03 +03:00
56fdf6002c Kernel/LibC: Implement pthread_kill 2025-06-01 13:48:03 +03:00
c957f1ddca LibC: Cleanup pthread code and add some pthread_attr functions
errno, pthread cleanup and pthread id are now stored in uthread. This
allows using these without TLS
2025-06-01 13:48:03 +03:00
423386a052 LibC: Add memory.h that just includes string.h
There are a lot of ports trying to include memory.h. This is not posix
but glibc just includes string.h. I think this is just to privide mem*
functionss...?
2025-06-01 13:48:03 +03:00
1c882ea361 DynamicLoader: Don't print TODOs on PT_GNU_ headers
These should be either handled by kernel or just used as optimizations.
There is no requirement to handle them in dynamic loader
2025-06-01 13:48:03 +03:00
b1065fa01d Kernel/LibC: Add ppoll syscall and fix poll
poll is now using its own syscall instead of wrapping aroung pselect.
This adds less overhead on top of poll and adds support for POLLHUP
2025-06-01 13:48:03 +03:00
8ff9c030bf Kernel: Add better termios support
I'm not sure if this is correct but at least it's better than before :)
2025-06-01 13:48:03 +03:00
9b875fb930 Kernel: Make epoll work with different fds pointing to same inode 2025-06-01 13:48:03 +03:00
857bac4b78 Kernel: Disable unused interrupt methods in PCI devices 2025-06-01 13:48:03 +03:00
30074c290d Kernel: Add more descriptive names to sockets types 2025-06-01 13:48:03 +03:00
60d1c26114 Kernel: Fix race condition in FileBackedRegion creation 2025-06-01 13:48:03 +03:00
692ba43182 Kernel: Fix spinlock bugs found by the new spinlock security 2025-06-01 13:48:03 +03:00
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
9f4b451501 Kernel: Fix epoll deadlock
If epoll_wait and epoll_notify were called at the same time, there was a
possible deadlock when epoll was confirming the event from the inode
2025-06-01 13:48:03 +03:00
1bd454b8fd Kernel/LibC: Implement utime* family functions
This patch adds *working*
 - utime
 - utimes
 - utimensat
 - futimens
2025-06-01 13:48:03 +03:00
8392472bac ports: Add git port
This commit is pushed from banan-os :D
2025-05-29 00:31:40 +00:00
cd5b351ce4 Kernel: Fix fchmodat mode handling
Ignore file type bits instead of returning EINVAL if they are set
2025-05-29 03:24:31 +03:00
50024fbf8b ports/vim: Set EDITOR=vim in .shellrc 2025-05-29 01:20:30 +03:00
4d4fb3b6ec Kernel: Cleanup and fix pipe
pipe now sends SIGPIPE and returns EPIPE when writing and no readers are
open
2025-05-29 01:02:22 +03:00
37dea8aee7 userspace: Implement basic less program
This is very simple and only supports couple of flags and scrolling
2025-05-29 01:00:28 +03:00
69c4940b27 LibC: Fix signal return value
signal was returning `func` when it should've returned the old handler
2025-05-29 00:58:30 +03:00
7691b019e2 LibC: Fix printf %c modifier for null byte 2025-05-28 03:10:01 +03:00
f55d6b11c5 LibC: Implement mblen 2025-05-28 03:10:01 +03:00
f52877abb4 LibC: Implement readv and writev 2025-05-28 03:10:01 +03:00
ee7c9b6731 LibC: Add simple getnameinfo
This doesn't actually do any name resolution but just formats input to
string.
2025-05-28 03:10:01 +03:00
4721344518 LibC: Don't fail getaddrinfo if node is null 2025-05-28 03:10:01 +03:00
e0d986dcd7 LibC: Add missing u_char and u_short types 2025-05-28 03:10:01 +03:00
c7be3dcd5b LibC: Add timer{add,sub,clear,isset,cmp}
These are not POSIX but used by used by some ports
2025-05-28 03:10:01 +03:00
89c9bfd052 Kernel/LibC: Implement socketpair for UNIX sockets 2025-05-28 03:10:01 +03:00
12b93567f7 Kernel/LibC: Implement getpeername 2025-05-28 03:10:01 +03:00
2f37776614 Kernel: Notify epoll on new TCP connections 2025-05-28 03:10:01 +03:00
f778bca3f2 Kernel: Remove accidentally commited debug code :) 2025-05-28 03:10:01 +03:00
a945d19750 Kernel: Partially fix PCI PIN interrupt routing
Don't fail early if the first device is not the one we are looking for
2025-05-28 03:10:01 +03:00
7f04b2c96c Kernel: Fix E1000 interrupt handling
E1000 does not support MSI-X and thus does not generate RxQ0 interrupts.
2025-05-28 03:10:01 +03:00
8aa4e4ff1e LibC: Implement clearenv
This is GNU extension but seems nice to have :D
2025-05-28 03:10:01 +03:00
7eade002a7 LibC: Fix mktime
yday calculation was off so results were always off for march-december
2025-05-28 03:10:01 +03:00
a8f8d27f4e LibC: Implement basic tzset()
I still don't have timezone support so this just sets values to UTC
2025-05-28 03:10:01 +03:00
356935bd4f LibC: Fix strtou{,l,ll} for negative values
Also set endp if base is invalid
2025-05-28 03:10:01 +03:00
bce3dd045f LibC: Fix strncat return value 2025-05-28 03:10:01 +03:00
79a2b84c81 Kernel: Fix process exit when there are multiple threads 2025-05-28 03:10:01 +03:00
44b762f916 Kernel/LibC: Implement pwrite and make pread non-locking 2025-05-28 03:10:01 +03:00
5d80c880c8 LibC: Fix FILE buffering once again :D 2025-05-28 03:10:01 +03:00
b907263f35 LibC: Implement basic tmpfile 2025-05-28 03:10:01 +03:00
0f0accf82c LibC: Don't use false in pthread initializers 2025-05-28 03:10:01 +03:00
ddcf414107 LibC: Fix netinet/in.h and arpa/inet.h definitions 2025-05-28 03:10:01 +03:00
6be3b1d7f2 commit from banan-os :D 2025-05-27 23:57:43 +00:00
0e0d7016b3 Kernel: Rename has_hangup -> has_hungup 2025-05-17 12:39:23 +03:00
553c76ab0f Kernel: Add locking to inode's epoll list
This was prone to crashing :)
2025-05-17 12:36:36 +03:00
b90cfa8e5c test-window: poll events instead of sleeping 2025-05-13 10:19:13 +03:00
e7f0cd0c4b stat: Fix return value when one of stats fails 2025-05-13 10:19:13 +03:00
0661b339a0 test-tcp: Fix name resolution
Comparison was the wrong way around so hostname lookup always failed.
2025-05-13 10:19:13 +03:00
d1bb72f6fb Kernel: Don't allow CPU load printing underflow 2025-05-13 10:19:13 +03:00
1bcd1edbf5 Kernel/LibC: Implement basic epoll
This implementation is on top of inodes instead of fds as linux does it.
If I start finding ports/software that relies on epoll allowing
duplicate inodes, I will do what linux does.

I'm probably missing multiple epoll_notify's which may cause hangs but
the system seems to work fine :dd:
2025-05-13 10:18:05 +03:00
143a00626b Kernel: Fix fork cmdline copying and copy environ 2025-05-13 10:16:21 +03:00
0eb981f51c Kernel: Fix Random.h includes 2025-05-13 10:16:21 +03:00
6cc01349f7 Kernel: Fix unblocking recv through read 2025-05-13 10:16:21 +03:00
a7bd4acd46 Kernel: Remove static variables from virtual tty 2025-05-13 10:16:21 +03:00
8e0a56b49a Kernel: Implement loopback network interface 2025-05-13 10:16:21 +03:00
a8844ddd28 WindowServer: Send mouse release to same window as mouse press 2025-05-13 10:16:21 +03:00
c18fefd5f3 BuildSystem: Cleanup cmake library linking 2025-05-07 18:42:37 +03:00
3040940e35 ports/tcc: Fix 32 bit build and add version name
tcc was using "Linux" for machine name in version string if it was not
explicitly specified.
2025-05-07 18:33:39 +03:00
df3d2d57c3 ports/quake2: Update to new LibGUI interface 2025-05-07 17:23:15 +03:00
92d26f2216 ports/doom: Update to new LibGUI interface 2025-05-07 17:21:29 +03:00
0380c68f89 ports/tinygb: Update to new LibGUI interface 2025-05-07 17:21:29 +03:00
2a6dc6a7b7 LibGUI: Add missing Texture files 2025-05-07 17:21:29 +03:00
40617f0d5c WindowServer: Make mod+d open program launcher 2025-05-06 00:42:15 +03:00
09745a7835 userspace: Implement program launcher
This is kinda useless as I only have Terminal and test-window
implemented. Also the code is really messy as I don't have GUI widgets.
2025-05-06 00:41:22 +03:00
57f6f50939 Terminal: Implement dumb font bolding
This is just drawing character twice at one pixel offset
2025-05-05 23:09:53 +03:00
f959905adf LibGUI: Rework window rendering
Abstract drawing surface to Texture. All windows now contain a texture
matching its size.
2025-05-05 23:08:01 +03:00
f78c7e7926 LibGUI: Add API to block until window events are available 2025-05-05 22:33:00 +03:00
96496da0ab Kernel: Allow USB mouse to send extra2 button events 2025-05-05 22:32:26 +03:00
2dc4733ac1 test: improve pthread test 2025-05-05 19:21:47 +03:00
f14774d034 libc: fix tmpnam when no name is found 2025-05-05 19:17:16 +03:00
c08c63f420 libc: reorder destructor and fflush in exit 2025-05-05 19:16:52 +03:00
eb79c6c47c mkdir: Add -p option 2025-05-05 19:16:29 +03:00
bf1cbb4cde Terminal: Update terminal size and send SIGWINCH on resize 2025-05-05 19:09:21 +03:00
592675022e Kernel: Allow tcgetpgrp on pseudo terminal masters 2025-05-05 19:09:01 +03:00
b2e10d7e6e Kernel: Remove unnecessary locks 2025-05-05 19:08:57 +03:00
0689954433 Terminal: Set minimum size to 8x2 cells 2025-05-05 18:20:22 +03:00
5c37f198cb WindowServer/LibGUI: Allow windows to set minimum size 2025-05-05 18:19:59 +03:00
3b02a9d4fe WindowServer: Resize from closest corner 2025-05-05 18:19:19 +03:00
c9057aa498 WindowServer: Cleanup code and resize on fullscreen 2025-05-05 16:42:15 +03:00
2b0d198b05 Terminal: Allow resizing of the terminal 2025-05-05 03:15:30 +03:00
7798145c74 WindowServer: Implement window resizing
windows can now set resizable attribute which allows window server to
resize them
2025-05-05 03:14:50 +03:00
fcfadd7c74 LibGUI: Add background color for windows
This is used when resizing a window to fill the empty space
2025-05-05 03:12:31 +03:00
c0181820a9 ports/tinygb: Set title like sdl frontend does 2025-05-05 01:10:41 +03:00
76d4e6bd18 LibGUI: Add support for changing window title 2025-05-05 01:10:05 +03:00
ccb81de85d snake: Use box drawing characters
This makes it look much better.

Also fix bug with apples generating on top of snake's tail
2025-05-05 00:30:58 +03:00
82f4975f45 LibC: Save callee saved registers on setjmp 2025-05-04 13:54:35 +03:00
d457e6ad6a LibC: Fix printf e/E modifier for negative exponents 2025-05-04 13:42:17 +03:00
abf7c8e68a LibC: Implement difftime 2025-05-04 13:42:17 +03:00
1a38d0c31e LibC: Add g/G modifiers to printf 2025-05-04 13:42:17 +03:00
9ff9d679e9 Kernel: Fix text mode cursor
Apparently text mode renders cursor in the *foreground* color. My
current clear function used the same color for foreground and background
making the cursor effectively invisible.

Also cursor hiding is now done by moving the cursor off bounds (0, height)
some website I read said this to be valid even on VGA compatible cards
without disable bit.

http://www.osdever.net/FreeVGA/vga/textcur.htm
2025-04-25 02:31:33 +03:00
9f3f8f950a Kernel: Add better panic message for failed shutdown
ACPI shutdown does not work on the web emulator and running `poweroff`
crashes on `ASSERT_NOT_REACHED()`.
2025-04-25 01:52:33 +03:00
006a196e4a LibC: optimize strpbrk, str{,c}spn, strtok{,_r}
These matches are now detected with bitmasks instead of looping over the
second string
2025-04-24 01:39:49 +03:00
418678466c Kernel: Fix text mode palette
ANSI and text mode color indices are not in the same order
2025-04-23 23:07:47 +03:00
9f4cb5c4dd Kernel: Make pseudo terminals not overwrite old data
If pseudo terminal buffer was filled, old implementation would overwrite
old data. This is bad if producer is capable of producing more data than
consumer can handle.
2025-04-23 22:03:53 +03:00
73f9de6635 Terminal: Add support for ANSI SGR 8bit and 24bit 2025-04-23 22:03:53 +03:00
12b9c82086 Terminal: Don't wrap cursor right after x == cols
This prevents scrolling when bottom right scroll is written to
2025-04-23 22:03:53 +03:00
a8edb8870e Kernel: Add support for 8bit and 24bit ANSI SGR 2025-04-23 22:03:53 +03:00
dabc3c6cc4 Kernel: Don't wrap cursor immediatly at cols()
This prevents unwanted scrolling when writing to bottom right cell
2025-04-23 22:03:53 +03:00
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
4d840a8d9a BAN: Make Array more constexpr 2025-04-23 18:40:20 +03:00
95a80bfe81 ports: Add tinygb port
This is awesome!
2025-04-23 13:19:28 +03:00
53e9eab0cd ports/tcc: Fix building on 32 bit 2025-04-23 08:43:27 +03:00
35b3c3c98c Kernel: Fix scheduler load balancing
I was not updating the current queue of the thread which lead to blocked
threads think they were in run queue
2025-04-23 08:09:51 +03:00
20e17a28cf Kernel: Fix \b handling
Don't clear the character, only move cursor backwards
2025-04-23 06:33:11 +03:00
28bf2d6374 Kernel/Terminal: Add support for ANSI DSR 2025-04-23 06:14:56 +03:00
8a00b53050 Kernel/Terminal: Fix ANSI SGR m for multiple values 2025-04-23 05:29:22 +03:00
8834241417 LibC: Fix scanf %n modifier
Old code was always returning off by one
2025-04-22 09:55:38 +03:00
96740d6be4 LibC: Make inet_addr spec compliant
I was not doing any error checking, basically i validated anything that
started with atleast a single digit.
2025-04-22 09:40:46 +03:00
b853d29992 Kernel: Fix unix domain socket close detection 2025-04-22 08:36:44 +03:00
33a0f562d3 resolver: Add support for CNAME
Also rework resolver's send format and convert test-tcp and nslookup to
use getaddrinfo
2025-04-22 08:36:44 +03:00
f8e3ae0525 Kernel: Fix deadlock caused by multithreading
This allows multiple threads to concurrently call the most common
blocking syscalls:
- read
- write
- accept
- connect
- sendto
- recv
- pselect

This prevents a dead lock when for example process is waiting on a pipe,
but unable to write to it since process is locked.

This is the beginning of starting to remove processes own lock from
syscall and locking only necessary parts.
2025-04-22 04:51:53 +03:00
c790bad667 Kernel: Make OpenFileDescriptorSet thread safe
Also this allows concurrent calling of read/write/send/recv
2025-04-22 04:31:18 +03:00
d54489bbcb Kernel: Implement MemoryRegion pinning
This allows process to pin a MemoryRegion into users memory space for
syscall duration without allowing user to munmap the region.
2025-04-22 04:30:07 +03:00
808c97020a Kernel/LibC: Implement SA_RESTART
I have been thinking how to do this for a long time but I finally
figured out a semi-clean way
2025-04-22 02:42:44 +03:00
34e680d792 ports/ncurses: Set some needed environment variables
ncurses depends on these being set to function properly
2025-04-22 01:56:34 +03:00
32d543943b ports: Add lynx port
I have had this for a while but apparently never commited :D
2025-04-22 01:44:49 +03:00
2632507980 ports/ca-certificates: Add symlink to /etc/ssl/cert.pem
Some ports try to use this file
2025-04-22 01:44:02 +03:00
f467a9a309 resolver: Resolve hostname to loopback address
We don't currently support loopback adapters, but some ports were trying
to resolve it.
2025-04-22 00:48:26 +03:00
5c9710c78b LibC: Implement strcoll_l 2025-04-22 00:48:26 +03:00
815 changed files with 46755 additions and 9482 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@
build/
base/
script/fakeroot-context
tools/update-image-perms

View File

@@ -18,78 +18,78 @@ namespace BAN
using const_iterator = ConstIteratorSimple<T, Array>;
public:
Array() = default;
Array(const T&);
constexpr Array() = default;
constexpr Array(const T&);
iterator begin() { return iterator(m_data); }
iterator end() { return iterator(m_data + size()); }
const_iterator begin() const { return const_iterator(m_data); }
const_iterator end() const { return const_iterator(m_data + size()); }
const T& operator[](size_type) const;
T& operator[](size_type);
constexpr const T& operator[](size_type) const;
constexpr T& operator[](size_type);
const T& back() const;
T& back();
const T& front() const;
T& front();
constexpr const T& back() const;
constexpr T& back();
constexpr const T& front() const;
constexpr T& front();
Span<T> span() { return Span(m_data, size()); }
const Span<T> span() const { return Span(m_data, size()); }
Span<const T> span() const { return Span(m_data, size()); }
constexpr size_type size() const;
const T* data() const { return m_data; }
T* data() { return m_data; }
constexpr const T* data() const { return m_data; }
constexpr T* data() { return m_data; }
private:
T m_data[S] {};
};
template<typename T, size_t S>
Array<T, S>::Array(const T& value)
constexpr Array<T, S>::Array(const T& value)
{
for (size_type i = 0; i < S; i++)
m_data[i] = value;
}
template<typename T, size_t S>
const T& Array<T, S>::operator[](size_type index) const
constexpr const T& Array<T, S>::operator[](size_type index) const
{
ASSERT(index < S);
return m_data[index];
}
template<typename T, size_t S>
T& Array<T, S>::operator[](size_type index)
constexpr T& Array<T, S>::operator[](size_type index)
{
ASSERT(index < S);
return m_data[index];
}
template<typename T, size_t S>
const T& Array<T, S>::back() const
constexpr const T& Array<T, S>::back() const
{
ASSERT(S != 0);
return m_data[S - 1];
}
template<typename T, size_t S>
T& Array<T, S>::back()
constexpr T& Array<T, S>::back()
{
ASSERT(S != 0);
return m_data[S - 1];
}
template<typename T, size_t S>
const T& Array<T, S>::front() const
constexpr const T& Array<T, S>::front() const
{
ASSERT(S != 0);
return m_data[0];
}
template<typename T, size_t S>
T& Array<T, S>::front()
constexpr T& Array<T, S>::front()
{
ASSERT(S != 0);
return m_data[0];

View File

@@ -34,6 +34,11 @@ namespace BAN
const T& back() const;
T& back();
const T& operator[](size_t index) const;
T& operator[](size_t index);
void clear();
size_type size() const { return m_size; }
bool empty() const { return size() == 0; }
bool full() const { return size() == capacity(); }
@@ -53,8 +58,7 @@ namespace BAN
template<typename T, size_t S>
CircularQueue<T, S>::~CircularQueue()
{
for (size_type i = 0; i < m_size; i++)
element_at((m_first + i) % capacity())->~T();
clear();
}
template<typename T, size_t S>
@@ -115,6 +119,28 @@ namespace BAN
return *element_at((m_first + m_size - 1) % capacity());
}
template<typename T, size_t S>
const T& CircularQueue<T, S>::operator[](size_t index) const
{
ASSERT(index < m_size);
return *element_at((m_first + index) % capacity());
}
template<typename T, size_t S>
T& CircularQueue<T, S>::operator[](size_t index)
{
ASSERT(index < m_size);
return *element_at((m_first + index) % capacity());
}
template<typename T, size_t S>
void CircularQueue<T, S>::clear()
{
for (size_type i = 0; i < m_size; i++)
element_at((m_first + i) % capacity())->~T();
m_size = 0;
}
template<typename T, size_t S>
const T* CircularQueue<T, S>::element_at(size_type index) const
{

View File

@@ -9,29 +9,35 @@
#include <BAN/Formatter.h>
#include <stdio.h>
#define __debug_putchar [](int c) { putc(c, stddbg); }
#define __debug_putchar [](int c) { putc_unlocked(c, stddbg); }
#define dprintln(...) \
do { \
flockfile(stddbg); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar,"\r\n"); \
BAN::Formatter::print(__debug_putchar,"\n"); \
fflush(stddbg); \
funlockfile(stddbg); \
} while (false)
#define dwarnln(...) \
do { \
flockfile(stddbg); \
BAN::Formatter::print(__debug_putchar, "\e[33m"); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
fflush(stddbg); \
funlockfile(stddbg); \
} while(false)
#define derrorln(...) \
do { \
flockfile(stddbg); \
BAN::Formatter::print(__debug_putchar, "\e[31m"); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
fflush(stddbg); \
funlockfile(stddbg); \
} while(false)
#define dprintln_if(cond, ...) \

89
BAN/include/BAN/Heap.h Normal file
View File

@@ -0,0 +1,89 @@
#pragma once
#include <BAN/Iterators.h>
#include <BAN/Swap.h>
#include <BAN/Traits.h>
namespace BAN
{
namespace detail
{
template<typename It, typename Comp>
void heapify_up(It begin, size_t index, Comp comp)
{
size_t parent = (index - 1) / 2;
while (parent < index)
{
if (comp(*(begin + index), *(begin + parent)))
break;
swap(*(begin + parent), *(begin + index));
index = parent;
parent = (index - 1) / 2;
}
}
template<typename It, typename Comp>
void heapify_down(It begin, size_t index, size_t len, Comp comp)
{
for (;;)
{
const size_t lchild = 2 * index + 1;
const size_t rchild = 2 * index + 2;
size_t child = 0;
if (lchild < len && !comp(*(begin + lchild), *(begin + index)))
{
if (rchild < len && !comp(*(begin + rchild), *(begin + lchild)))
child = rchild;
else
child = lchild;
}
else if (rchild < len && !comp(*(begin + rchild), *(begin + index)))
child = rchild;
else
break;
swap(*(begin + child), *(begin + index));
index = child;
}
}
}
template<typename It, typename Comp = less<it_value_type_t<It>>>
void make_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
if (len <= 1)
return;
size_t index = (len - 2) / 2;
while (index < len)
detail::heapify_down(begin, index--, len, comp);
}
template<typename It, typename Comp = less<it_value_type_t<It>>>
void push_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
detail::heapify_up(begin, len - 1, comp);
}
template<typename It, typename Comp = less<it_value_type_t<It>>>
void pop_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
swap(*begin, *(begin + len - 1));
detail::heapify_down(begin, 0, len - 1, comp);
}
template<typename It, typename Comp = less<it_value_type_t<It>>>
void sort_heap(It begin, It end, Comp comp = {})
{
while (begin != end)
pop_heap(begin, end--, comp);
}
}

View File

@@ -9,6 +9,10 @@ namespace BAN
struct IPv4Address
{
constexpr IPv4Address()
: IPv4Address(0)
{ }
constexpr IPv4Address(uint32_t u32_address)
{
raw = u32_address;

View File

@@ -36,12 +36,11 @@ namespace BAN::Math
template<integral T>
inline constexpr T gcd(T a, T b)
{
T t;
while (b)
{
t = b;
T temp = b;
b = a % b;
a = t;
a = temp;
}
return a;
}
@@ -66,25 +65,20 @@ namespace BAN::Math
return (x & (x - 1)) == 0;
}
template<BAN::integral T>
static constexpr bool will_multiplication_overflow(T a, T b)
template<integral T>
__attribute__((always_inline))
inline constexpr bool will_multiplication_overflow(T a, T b)
{
if (a == 0 || b == 0)
return false;
if ((a > 0) == (b > 0))
return a > BAN::numeric_limits<T>::max() / b;
else
return a < BAN::numeric_limits<T>::min() / b;
T dummy;
return __builtin_mul_overflow(a, b, &dummy);
}
template<BAN::integral T>
static constexpr bool will_addition_overflow(T a, T b)
template<integral T>
__attribute__((always_inline))
inline constexpr bool will_addition_overflow(T a, T b)
{
if (a > 0 && b > 0)
return a > BAN::numeric_limits<T>::max() - b;
if (a < 0 && b < 0)
return a < BAN::numeric_limits<T>::min() - b;
return false;
T dummy;
return __builtin_add_overflow(a, b, &dummy);
}
template<typename T>
@@ -98,6 +92,19 @@ namespace BAN::Math
return sizeof(T) * 8 - __builtin_clzll(x) - 1;
}
// This is ugly but my clangd does not like including
// intrinsic headers at all
#if !defined(__SSE__) || !defined(__SSE2__)
#pragma GCC push_options
#ifndef __SSE__
#pragma GCC target("sse")
#endif
#ifndef __SSE2__
#pragma GCC target("sse2")
#endif
#define BAN_MATH_POP_OPTIONS
#endif
template<floating_point T>
inline constexpr T floor(T x)
{
@@ -159,7 +166,23 @@ namespace BAN::Math
"jne 1b;"
: "+t"(a)
: "u"(b)
: "ax"
: "ax", "cc"
);
return a;
}
template<floating_point T>
inline constexpr T remainder(T a, T b)
{
asm(
"1:"
"fprem1;"
"fnstsw %%ax;"
"testb $4, %%ah;"
"jne 1b;"
: "+t"(a)
: "u"(b)
: "ax", "cc"
);
return a;
}
@@ -167,7 +190,7 @@ namespace BAN::Math
template<floating_point T>
static T modf(T x, T* iptr)
{
const T frac = BAN::Math::fmod<T>(x, 1);
const T frac = BAN::Math::fmod<T>(x, (T)1.0);
*iptr = x - frac;
return frac;
}
@@ -175,15 +198,15 @@ namespace BAN::Math
template<floating_point T>
inline constexpr T frexp(T num, int* exp)
{
if (num == 0.0)
if (num == (T)0.0)
{
*exp = 0;
return 0.0;
return (T)0.0;
}
T _exp;
asm("fxtract" : "+t"(num), "=u"(_exp));
*exp = (int)_exp + 1;
T e;
asm("fxtract" : "+t"(num), "=u"(e));
*exp = (int)e + 1;
return num / (T)2.0;
}
@@ -251,6 +274,7 @@ namespace BAN::Math
"fstp %%st(1);"
: "+t"(x)
);
return x;
}
@@ -263,18 +287,9 @@ namespace BAN::Math
template<floating_point T>
inline constexpr T pow(T x, T y)
{
asm(
"fyl2x;"
"fld1;"
"fld %%st(1);"
"fprem;"
"f2xm1;"
"faddp;"
"fscale;"
: "+t"(x), "+u"(y)
);
return x;
if (x == (T)0.0)
return (T)0.0;
return exp2<T>(y * log2<T>(x));
}
template<floating_point T>
@@ -310,16 +325,27 @@ namespace BAN::Math
template<floating_point T>
inline constexpr T sqrt(T x)
{
asm("fsqrt" : "+t"(x));
return x;
if constexpr(BAN::is_same_v<T, float>)
{
using v4sf = float __attribute__((vector_size(16)));
return __builtin_ia32_sqrtss((v4sf) { x, 0.0f, 0.0f, 0.0f })[0];
}
else if constexpr(BAN::is_same_v<T, double>)
{
using v2df = double __attribute__((vector_size(16)));
return __builtin_ia32_sqrtsd((v2df) { x, 0.0 })[0];
}
else if constexpr(BAN::is_same_v<T, long double>)
{
asm("fsqrt" : "+t"(x));
return x;
}
}
template<floating_point T>
inline constexpr T cbrt(T value)
{
if (value == 0.0)
return 0.0;
return pow<T>(value, 1.0 / 3.0);
return pow<T>(value, (T)1.0 / (T)3.0);
}
template<floating_point T>
@@ -346,30 +372,21 @@ namespace BAN::Math
inline constexpr T tan(T x)
{
T one, ret;
asm(
"fptan"
: "=t"(one), "=u"(ret)
: "0"(x)
);
asm("fptan" : "=t"(one), "=u"(ret) : "0"(x));
return ret;
}
template<floating_point T>
inline constexpr T atan2(T y, T x)
{
asm(
"fpatan"
: "+t"(x)
: "u"(y)
: "st(1)"
);
asm("fpatan" : "+t"(x) : "u"(y) : "st(1)");
return x;
}
template<floating_point T>
inline constexpr T atan(T x)
{
return atan2<T>(x, 1.0);
return atan2<T>(x, (T)1.0);
}
template<floating_point T>
@@ -378,10 +395,10 @@ namespace BAN::Math
if (x == (T)0.0)
return (T)0.0;
if (x == (T)1.0)
return numbers::pi_v<T> / (T)2.0;
return +numbers::pi_v<T> / (T)2.0;
if (x == (T)-1.0)
return -numbers::pi_v<T> / (T)2.0;
return (T)2.0 * atan<T>(x / (T(1.0) + sqrt<T>((T)1.0 - x * x)));
return (T)2.0 * atan<T>(x / ((T)1.0 + sqrt<T>((T)1.0 - x * x)));
}
template<floating_point T>
@@ -411,7 +428,7 @@ namespace BAN::Math
template<floating_point T>
inline constexpr T tanh(T x)
{
const T exp_px = exp<T>(x);
const T exp_px = exp<T>(+x);
const T exp_nx = exp<T>(-x);
return (exp_px - exp_nx) / (exp_px + exp_nx);
}
@@ -440,4 +457,9 @@ namespace BAN::Math
return sqrt<T>(x * x + y * y);
}
#ifdef BAN_MATH_POP_OPTIONS
#undef BAN_MATH_POP_OPTIONS
#pragma GCC pop_options
#endif
}

View File

@@ -9,10 +9,12 @@
namespace BAN
{
#if defined(__is_kernel)
static constexpr void*(&allocator)(size_t) = kmalloc;
static constexpr void(&deallocator)(void*) = kfree;
static constexpr void*(*allocator)(size_t) = kmalloc;
static constexpr void*(*reallocator)(void*, size_t) = nullptr;
static constexpr void(*deallocator)(void*) = kfree;
#else
static constexpr void*(&allocator)(size_t) = malloc;
static constexpr void(&deallocator)(void*) = free;
static constexpr void*(*allocator)(size_t) = malloc;
static constexpr void*(*reallocator)(void*, size_t) = realloc;
static constexpr void(*deallocator)(void*) = free;
#endif
}

View File

@@ -0,0 +1,64 @@
#pragma once
#include "BAN/Errors.h"
#include <BAN/Vector.h>
#include <BAN/Heap.h>
namespace BAN
{
template<typename T, typename Comp = less<T>>
class PriorityQueue
{
public:
PriorityQueue() = default;
PriorityQueue(Comp comp)
: m_comp(comp)
{ }
ErrorOr<void> push(const T& value)
{
TRY(m_data.push_back(value));
push_heap(m_data.begin(), m_data.end());
return {};
}
ErrorOr<void> push(T&& value)
{
TRY(m_data.push_back(move(value)));
push_heap(m_data.begin(), m_data.end());
return {};
}
template<typename... Args>
ErrorOr<void> emplace(Args&&... args) requires is_constructible_v<T, Args...>
{
TRY(m_data.emplace_back(forward<Args>(args)...));
push_heap(m_data.begin(), m_data.end());
return {};
}
void pop()
{
pop_heap(m_data.begin(), m_data.end());
m_data.pop_back();
}
BAN::ErrorOr<void> reserve(Vector<T>::size_type size)
{
return m_data.reserve(size);
}
T& top() { return m_data.front(); }
const T& top() const { return m_data.front(); }
bool empty() const { return m_data.empty(); }
Vector<T>::size_type size() const { return m_data.size(); }
Vector<T>::size_type capacity() const { return m_data.capacity(); }
private:
Comp m_comp;
Vector<T> m_data;
};
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include <BAN/Heap.h>
#include <BAN/Math.h>
#include <BAN/Swap.h>
#include <BAN/Traits.h>
@@ -8,7 +9,7 @@
namespace BAN::sort
{
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void exchange_sort(It begin, It end, Comp comp = {})
{
for (It lhs = begin; lhs != end; ++lhs)
@@ -42,7 +43,7 @@ namespace BAN::sort
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void quick_sort(It begin, It end, Comp comp = {})
{
if (distance(begin, end) <= 1)
@@ -52,14 +53,14 @@ namespace BAN::sort
quick_sort(++mid, end, comp);
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void insertion_sort(It begin, It end, Comp comp = {})
{
if (distance(begin, end) <= 1)
return;
for (It it1 = next(begin, 1); it1 != end; ++it1)
{
typename It::value_type x = move(*it1);
auto x = move(*it1);
It it2 = it1;
for (; it2 != begin && comp(x, *prev(it2, 1)); --it2)
*it2 = move(*prev(it2, 1));
@@ -67,83 +68,7 @@ namespace BAN::sort
}
}
namespace detail
{
template<typename It, typename Comp>
void push_heap(It begin, size_t hole_index, size_t top_index, typename It::value_type value, Comp comp)
{
size_t parent = (hole_index - 1) / 2;
while (hole_index > top_index && comp(*next(begin, parent), value))
{
*next(begin, hole_index) = move(*next(begin, parent));
hole_index = parent;
parent = (hole_index - 1) / 2;
}
*next(begin, hole_index) = move(value);
}
template<typename It, typename Comp>
void adjust_heap(It begin, size_t hole_index, size_t len, typename It::value_type value, Comp comp)
{
const size_t top_index = hole_index;
size_t child = hole_index;
while (child < (len - 1) / 2)
{
child = 2 * (child + 1);
if (comp(*next(begin, child), *next(begin, child - 1)))
child--;
*next(begin, hole_index) = move(*next(begin, child));
hole_index = child;
}
if (len % 2 == 0 && child == (len - 2) / 2)
{
child = 2 * (child + 1);
*next(begin, hole_index) = move(*next(begin, child - 1));
hole_index = child - 1;
}
push_heap(begin, hole_index, top_index, move(value), comp);
}
}
template<typename It, typename Comp = less<typename It::value_type>>
void make_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
if (len <= 1)
return;
size_t parent = (len - 2) / 2;
while (true)
{
detail::adjust_heap(begin, parent, len, move(*next(begin, parent)), comp);
if (parent == 0)
break;
parent--;
}
}
template<typename It, typename Comp = less<typename It::value_type>>
void sort_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
if (len <= 1)
return;
size_t last = len;
while (last > 1)
{
last--;
typename It::value_type x = move(*next(begin, last));
*next(begin, last) = move(*begin);
detail::adjust_heap(begin, 0, last, move(x), comp);
}
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void heap_sort(It begin, It end, Comp comp = {})
{
make_heap(begin, end, comp);
@@ -167,7 +92,7 @@ namespace BAN::sort
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void intro_sort(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
@@ -190,10 +115,10 @@ namespace BAN::sort
}
template<typename It, size_t radix = 256>
requires is_unsigned_v<typename It::value_type> && (radix > 0 && (radix & (radix - 1)) == 0)
requires is_unsigned_v<it_value_type_t<It>> && (radix > 0 && (radix & (radix - 1)) == 0)
BAN::ErrorOr<void> radix_sort(It begin, It end)
{
using value_type = typename It::value_type;
using value_type = it_value_type_t<It>;
const size_t len = distance(begin, end);
if (len <= 1)
@@ -231,7 +156,7 @@ namespace BAN::sort
return {};
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void sort(It begin, It end, Comp comp = {})
{
return intro_sort(begin, end, comp);

View File

@@ -69,7 +69,6 @@ namespace BAN
value_type* data() const
{
ASSERT(m_data);
return m_data;
}
@@ -84,7 +83,6 @@ namespace BAN
Span slice(size_type start, size_type length = ~size_type(0)) const
{
ASSERT(m_data);
ASSERT(start <= m_size);
if (length == ~size_type(0))
length = m_size - start;

View File

@@ -14,6 +14,7 @@ namespace BAN
{
public:
using size_type = size_t;
using value_type = char;
using iterator = IteratorSimple<char, String>;
using const_iterator = ConstIteratorSimple<char, String>;
static constexpr size_type sso_capacity = 15;
@@ -352,10 +353,9 @@ namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const String& string, const ValueFormat&)
void print_argument(F putc, const String& string, const ValueFormat& format)
{
for (String::size_type i = 0; i < string.size(); i++)
putc(string[i]);
print_argument(putc, string.sv(), format);
}
}

View File

@@ -14,6 +14,7 @@ namespace BAN
{
public:
using size_type = size_t;
using value_type = char;
using const_iterator = ConstIteratorSimple<char, StringView>;
public:
@@ -21,7 +22,8 @@ namespace BAN
constexpr StringView(const char* string, size_type len = -1)
{
if (len == size_type(-1))
len = strlen(string);
for (len = 0; string[len];)
len++;
m_data = string;
m_size = len;
}
@@ -245,10 +247,12 @@ namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const StringView& sv, const ValueFormat&)
void print_argument(F putc, const StringView& sv, const ValueFormat& format)
{
for (StringView::size_type i = 0; i < sv.size(); i++)
putc(sv[i]);
for (int i = sv.size(); i < format.fill; i++)
putc(' ');
}
}

View File

@@ -61,6 +61,9 @@ namespace BAN
template<typename T> struct is_move_constructible { static constexpr bool value = is_constructible_v<T, T&&>; };
template<typename T> inline constexpr bool is_move_constructible_v = is_move_constructible<T>::value;
template<typename T> struct is_trivially_copyable { static constexpr bool value = __is_trivially_copyable(T); };
template<typename T> inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
template<typename T> struct is_integral { static constexpr bool value = requires (T t, T* p, void (*f)(T)) { reinterpret_cast<T>(t); f(0); p + t; }; };
template<typename T> inline constexpr bool is_integral_v = is_integral<T>::value;
template<typename T> concept integral = is_integral_v<T>;
@@ -139,6 +142,10 @@ namespace BAN
template<typename T> using make_signed_t = typename make_signed<T>::type;
#undef __BAN_TRAITS_MAKE_SIGNED_CV
template<typename T> struct it_value_type { using value_type = T::value_type; };
template<typename T> struct it_value_type<T*> { using value_type = T; };
template<typename T> using it_value_type_t = typename it_value_type<T>::value_type;
template<typename T> struct less { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; } };
template<typename T> struct equal { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; } };
template<typename T> struct greater { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs > rhs; } };

View File

@@ -18,7 +18,7 @@ namespace BAN::UTF8
return 3;
if ((first_byte & 0xF8) == 0xF0)
return 4;
return 0;
return UTF8::invalid;
}
template<typename T> requires (sizeof(T) == 1)

View File

@@ -126,14 +126,16 @@ namespace BAN
Variant(Variant&& other)
: m_index(other.m_index)
{
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
if (other.has_value())
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
other.clear();
}
Variant(const Variant& other)
: m_index(other.m_index)
{
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
if (other.has_value())
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
}
template<typename T>
@@ -157,12 +159,13 @@ namespace BAN
Variant& operator=(Variant&& other)
{
if (m_index == other.m_index)
if (m_index == other.m_index && m_index != invalid_index())
detail::move_assign<Ts...>(m_index, other.m_storage, m_storage);
else
{
clear();
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
if (other.has_value())
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
m_index = other.m_index;
}
other.clear();
@@ -171,12 +174,13 @@ namespace BAN
Variant& operator=(const Variant& other)
{
if (m_index == other.m_index)
if (m_index == other.m_index && m_index != invalid_index())
detail::copy_assign<Ts...>(m_index, other.m_storage, m_storage);
else
{
clear();
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
if (other.has_value())
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
m_index = other.m_index;
}
return *this;

View File

@@ -56,7 +56,7 @@ namespace BAN
bool contains(const T&) const;
Span<T> span() { return Span(m_data, m_size); }
const Span<T> span() const { return Span(m_data, m_size); }
Span<const T> span() const { return Span(m_data, m_size); }
const T& operator[](size_type) const;
T& operator[](size_type);
@@ -381,19 +381,46 @@ namespace BAN
template<typename T>
ErrorOr<void> Vector<T>::ensure_capacity(size_type size)
{
static_assert(alignof(T) <= alignof(max_align_t), "over aligned types not supported");
if (m_capacity >= size)
return {};
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
for (size_type i = 0; i < m_size; i++)
const size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
if constexpr (BAN::is_trivially_copyable_v<T>)
{
new (new_data + i) T(move(m_data[i]));
m_data[i].~T();
if constexpr (BAN::reallocator)
{
auto* new_data = static_cast<T*>(BAN::reallocator(m_data, new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
m_data = new_data;
}
else
{
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
memcpy(new_data, m_data, m_size * sizeof(T));
BAN::deallocator(m_data);
m_data = new_data;
}
}
BAN::deallocator(m_data);
m_data = new_data;
else
{
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
for (size_type i = 0; i < m_size; i++)
{
new (new_data + i) T(move(m_data[i]));
m_data[i].~T();
}
BAN::deallocator(m_data);
m_data = new_data;
}
m_capacity = new_cap;
return {};
}

View File

@@ -20,7 +20,7 @@ namespace BAN
class WeakLink : public RefCounted<WeakLink<T>>
{
public:
RefPtr<T> try_lock()
RefPtr<T> try_lock() const
{
#if __is_kernel
Kernel::SpinLockGuard _(m_weak_lock);
@@ -44,7 +44,7 @@ namespace BAN
private:
T* m_ptr;
#if __is_kernel
Kernel::SpinLock m_weak_lock;
mutable Kernel::SpinLock m_weak_lock;
#endif
friend class RefPtr<WeakLink<T>>;
};
@@ -99,7 +99,7 @@ namespace BAN
return *this;
}
RefPtr<T> lock()
RefPtr<T> lock() const
{
if (m_link)
return m_link->try_lock();

View File

@@ -29,12 +29,12 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# include headers of ${library} to ${target}
function(banan_include_headers target library)
target_include_directories(${target} PRIVATE $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
target_include_directories(${target} PUBLIC $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
endfunction()
# include headers and link ${library} to ${target}
function(banan_link_library target library)
target_link_libraries(${target} PRIVATE ${library})
target_link_libraries(${target} PUBLIC ${library})
banan_include_headers(${target} ${library})
endfunction()

View File

@@ -23,7 +23,7 @@ If you want to try out DOOM, you should first enter the GUI environment using th
- [x] Basic graphical environment
- [x] Terminal emulator
- [x] Status bar
- [ ] Program launcher
- [x] Program launcher
- [ ] Some nice apps
- [x] ELF dynamic linking
- [x] copy-on-write memory
@@ -118,6 +118,8 @@ To change the bootloader you can set environment variable BANAN\_BOOTLOADER; sup
To run with UEFI set environment variable BANAN\_UEFI\_BOOT=1. You will also have to set OVMF\_PATH to the correct OVMF (default */usr/share/ovmf/x64/OVMF.fd*).
To build an image with no physical root filesystem, but an initrd set environment variable BANAN\_INITRD=1. This can be used when testing on hardware with unsupported USB controller.
If you have corrupted your disk image or want to create new one, you can either manually delete *build/banan-os.img* and build system will automatically create you a new one or you can run the following command.
```sh
./bos image-full

Binary file not shown.

View File

@@ -1,11 +1,16 @@
set(KERNEL_SOURCES
font/prefs.psf.o
kernel/ACPI/ACPI.cpp
kernel/ACPI/BatterySystem.cpp
kernel/ACPI/AML/Namespace.cpp
kernel/ACPI/AML/Node.cpp
kernel/ACPI/AML/OpRegion.cpp
kernel/ACPI/BatterySystem.cpp
kernel/ACPI/EmbeddedController.cpp
kernel/APIC.cpp
kernel/Audio/AC97/Controller.cpp
kernel/Audio/Controller.cpp
kernel/Audio/HDAudio/AudioFunctionGroup.cpp
kernel/Audio/HDAudio/Controller.cpp
kernel/BootInfo.cpp
kernel/CPUID.cpp
kernel/Credentials.cpp
@@ -17,8 +22,10 @@ set(KERNEL_SOURCES
kernel/Device/RandomDevice.cpp
kernel/Device/ZeroDevice.cpp
kernel/ELF.cpp
kernel/Epoll.cpp
kernel/Errors.cpp
kernel/FS/DevFS/FileSystem.cpp
kernel/FS/EventFD.cpp
kernel/FS/Ext2/FileSystem.cpp
kernel/FS/Ext2/Inode.cpp
kernel/FS/FAT/FileSystem.cpp
@@ -30,6 +37,7 @@ set(KERNEL_SOURCES
kernel/FS/ProcFS/Inode.cpp
kernel/FS/TmpFS/FileSystem.cpp
kernel/FS/TmpFS/Inode.cpp
kernel/FS/USTARModule.cpp
kernel/FS/VirtualFileSystem.cpp
kernel/GDT.cpp
kernel/IDT.cpp
@@ -42,6 +50,8 @@ set(KERNEL_SOURCES
kernel/Interruptable.cpp
kernel/InterruptController.cpp
kernel/kernel.cpp
kernel/Lock/SpinLock.cpp
kernel/Memory/ByteRingBuffer.cpp
kernel/Memory/DMARegion.cpp
kernel/Memory/FileBackedRegion.cpp
kernel/Memory/Heap.cpp
@@ -55,6 +65,7 @@ set(KERNEL_SOURCES
kernel/Networking/E1000/E1000.cpp
kernel/Networking/E1000/E1000E.cpp
kernel/Networking/IPv4Layer.cpp
kernel/Networking/Loopback.cpp
kernel/Networking/NetworkInterface.cpp
kernel/Networking/NetworkLayer.cpp
kernel/Networking/NetworkManager.cpp
@@ -71,7 +82,6 @@ set(KERNEL_SOURCES
kernel/Processor.cpp
kernel/Random.cpp
kernel/Scheduler.cpp
kernel/ThreadBlocker.cpp
kernel/SSP.cpp
kernel/Storage/ATA/AHCI/Controller.cpp
kernel/Storage/ATA/AHCI/Device.cpp
@@ -94,6 +104,7 @@ set(KERNEL_SOURCES
kernel/Terminal/TTY.cpp
kernel/Terminal/VirtualTTY.cpp
kernel/Thread.cpp
kernel/ThreadBlocker.cpp
kernel/Timer/HPET.cpp
kernel/Timer/PIT.cpp
kernel/Timer/RTC.cpp
@@ -101,6 +112,7 @@ set(KERNEL_SOURCES
kernel/USB/Controller.cpp
kernel/USB/Device.cpp
kernel/USB/HID/HIDDriver.cpp
kernel/USB/HID/Joystick.cpp
kernel/USB/HID/Keyboard.cpp
kernel/USB/HID/Mouse.cpp
kernel/USB/Hub/HubDriver.cpp
@@ -127,6 +139,8 @@ if("${BANAN_ARCH}" STREQUAL "x86_64")
arch/x86_64/Signal.S
arch/x86_64/Syscall.S
arch/x86_64/Thread.S
arch/x86_64/User.S
arch/x86_64/Yield.S
)
elseif("${BANAN_ARCH}" STREQUAL "i686")
set(KERNEL_SOURCES
@@ -137,6 +151,8 @@ elseif("${BANAN_ARCH}" STREQUAL "i686")
arch/i686/Signal.S
arch/i686/Syscall.S
arch/i686/Thread.S
arch/i686/User.S
arch/i686/Yield.S
)
else()
message(FATAL_ERROR "unsupported architecure ${BANAN_ARCH}")
@@ -158,6 +174,12 @@ set(KLIBC_SOURCES
../userspace/libraries/LibC/arch/${BANAN_ARCH}/string.S
)
set(LIBDEFLATE_SOURCE
../userspace/libraries/LibDEFLATE/Compressor.cpp
../userspace/libraries/LibDEFLATE/Decompressor.cpp
../userspace/libraries/LibDEFLATE/HuffmanTree.cpp
)
set(LIBFONT_SOURCES
../userspace/libraries/LibFont/Font.cpp
../userspace/libraries/LibFont/PSF.cpp
@@ -168,18 +190,25 @@ set(LIBINPUT_SOURCE
../userspace/libraries/LibInput/KeyEvent.cpp
)
set(LIBQR_SOURCE
../userspace/libraries/LibQR/QRCode.cpp
)
set(KERNEL_SOURCES
${KERNEL_SOURCES}
${BAN_SOURCES}
${KLIBC_SOURCES}
${LIBDEFLATE_SOURCE}
${LIBFONT_SOURCES}
${LIBINPUT_SOURCE}
${LIBQR_SOURCE}
)
add_executable(kernel ${KERNEL_SOURCES})
target_compile_definitions(kernel PRIVATE __is_kernel)
target_compile_definitions(kernel PRIVATE __arch=${BANAN_ARCH})
target_compile_definitions(kernel PRIVATE LIBDEFLATE_AVOID_STACK=1)
target_compile_options(kernel PRIVATE
-O2 -g
@@ -233,9 +262,11 @@ add_custom_command(
banan_include_headers(kernel ban)
banan_include_headers(kernel libc)
banan_include_headers(kernel libfont)
banan_include_headers(kernel libdeflate)
banan_include_headers(kernel libelf)
banan_include_headers(kernel libfont)
banan_include_headers(kernel libinput)
banan_include_headers(kernel libqr)
banan_install_headers(kernel)
set_target_properties(kernel PROPERTIES OUTPUT_NAME banan-os.kernel)

View File

@@ -206,6 +206,7 @@ namespace Kernel
{
ASSERT(s_kernel);
ASSERT(paddr);
ASSERT(paddr % PAGE_SIZE == 0);
ASSERT(s_fast_page_lock.current_processor_has_lock());
@@ -220,7 +221,7 @@ namespace Kernel
ASSERT(!(pt[pte] & Flags::Present));
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
invalidate(fast_page(), false);
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
}
void PageTable::unmap_fast_page()
@@ -240,7 +241,7 @@ namespace Kernel
ASSERT(pt[pte] & Flags::Present);
pt[pte] = 0;
invalidate(fast_page(), false);
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
}
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
@@ -313,7 +314,8 @@ namespace Kernel
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = 1
.page_count = 1,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
}
@@ -342,8 +344,12 @@ namespace Kernel
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
pt[pte] = 0;
invalidate(vaddr, send_smp_message);
if (old_paddr != 0)
invalidate(vaddr, send_smp_message);
}
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
@@ -360,7 +366,8 @@ namespace Kernel
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = page_count
.page_count = page_count,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
}
@@ -416,9 +423,13 @@ namespace Kernel
uwr_flags &= ~Flags::Present;
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
pt[pte] = paddr | uwr_flags | extra_flags;
invalidate(vaddr, send_smp_message);
if (old_paddr != 0)
invalidate(vaddr, send_smp_message);
}
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
@@ -437,7 +448,8 @@ namespace Kernel
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = page_count
.page_count = page_count,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
}
@@ -496,13 +508,13 @@ namespace Kernel
return true;
}
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free)
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free, bool send_smp_message)
{
SpinLockGuard _(m_lock);
ASSERT(vaddr % PAGE_SIZE == 0);
if (only_free && !is_page_free(vaddr))
return false;
map_page_at(0, vaddr, Flags::Reserved);
map_page_at(0, vaddr, Flags::Reserved, MemoryType::Normal, send_smp_message);
return true;
}
@@ -516,7 +528,15 @@ namespace Kernel
if (only_free && !is_range_free(vaddr, bytes))
return false;
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
reserve_page(vaddr + offset);
reserve_page(vaddr + offset, true, false);
Processor::broadcast_smp_message({
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = bytes / PAGE_SIZE,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
return true;
}

View File

@@ -2,33 +2,72 @@
// stack contains
// return address
// return stack
// return rflags
// siginfo_t
// signal number
// signal handler
.global signal_trampoline
signal_trampoline:
pushl %esi // gregs
pushl %edi
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
pushl %ebp
movl %esp, %ebp
pusha
// FIXME: populate these
xorl %eax, %eax
pushl %eax // stack
pushl %eax
pushl %eax
pushl %eax // sigset
pushl %eax
pushl %eax // link
movl 40(%esp), %edi
movl 36(%esp), %eax
movl %esp, %edx // ucontext
leal 60(%esp), %esi // siginfo
movl 56(%esp), %edi // signal number
movl 52(%esp), %eax // handlers
// align stack to 16 bytes
movl %esp, %ebp
andl $-16, %esp
subl $12, %esp
subl $512, %esp
fxsave (%esp)
subl $4, %esp
pushl %edx
pushl %esi
pushl %edi
call *%eax
addl $16, %esp
fxrstor (%esp)
addl $512, %esp
// restore stack
movl %ebp, %esp
popa
addl $24, %esp
leave
addl $8, %esp
// restore registers
popl %ebp
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %edi
popl %esi
// skip handler, number, siginfo_t
addl $44, %esp
// restore flags
popf
movl (%esp), %esp
ret

View File

@@ -1,12 +1,6 @@
// arguments in EAX, EBX, ECX, EDX, ESI, EDI
.global asm_syscall_handler
asm_syscall_handler:
# save segment registers
pushw %ds
pushw %es
pushw %fs
pushw %gs
# save general purpose registers
pushl %ebx
pushl %ecx
@@ -18,13 +12,10 @@ asm_syscall_handler:
# align stack
movl %esp, %ebp
subl $15, %esp
andl $0xFFFFFFF0, %esp
andl $-16, %esp
# push arguments
subl $4, %esp
pushl %ebp
addl $32, (%esp)
subl $8, %esp
pushl %edi
pushl %esi
pushl %edx
@@ -44,6 +35,15 @@ asm_syscall_handler:
movl %ebp, %esp
# restore userspace segments
movw $(0x20 | 3), %bx
movw %bx, %ds
movw %bx, %es
movw $(0x30 | 3), %bx
movw %bx, %fs
movw $(0x38 | 3), %bx
movw %bx, %gs
# restore general purpose registers
popl %ebp
popl %esi
@@ -52,12 +52,6 @@ asm_syscall_handler:
popl %ecx
popl %ebx
# restore segment registers
popw %gs
popw %fs
popw %es
popw %ds
iret
.global sys_fork_trampoline

View File

@@ -31,25 +31,18 @@ start_kernel_thread:
subl $12, %esp
pushl %edi
call *%esi
addl $16, %esp
.global start_userspace_thread
start_userspace_thread:
call load_thread_sse
call get_thread_start_sp
movl %eax, %esp
# ds, es = user data
movw $(0x20 | 3), %bx
movw %bx, %ds
movw %bx, %es
# gs = thread local
movw $(0x30 | 3), %bx
movw %bx, %gs
# fs = 0
xorw %bx, %bx
movw %bx, %fs
movw $(0x38 | 3), %bx
movw %bx, %gs
iret

54
kernel/arch/i686/User.S Normal file
View File

@@ -0,0 +1,54 @@
# bool safe_user_memcpy(void*, const void*, size_t)
.global safe_user_memcpy
.global safe_user_memcpy_end
.global safe_user_memcpy_fault
safe_user_memcpy:
xorl %eax, %eax
xchgl 4(%esp), %edi
xchgl 8(%esp), %esi
movl 12(%esp), %ecx
movl %edi, %edx
rep movsb
movl 4(%esp), %edi
movl 8(%esp), %esi
incl %eax
safe_user_memcpy_fault:
ret
safe_user_memcpy_end:
# bool safe_user_strncpy(void*, const void*, size_t)
.global safe_user_strncpy
.global safe_user_strncpy_end
.global safe_user_strncpy_fault
safe_user_strncpy:
xchgl 4(%esp), %edi
xchgl 8(%esp), %esi
movl 12(%esp), %ecx
testl %ecx, %ecx
jz safe_user_strncpy_fault
.safe_user_strncpy_loop:
movb (%esi), %al
movb %al, (%edi)
testb %al, %al
jz .safe_user_strncpy_done
incl %edi
incl %esi
decl %ecx
jnz .safe_user_strncpy_loop
safe_user_strncpy_fault:
xorl %eax, %eax
jmp .safe_user_strncpy_return
.safe_user_strncpy_done:
movl $1, %eax
.safe_user_strncpy_return:
movl 4(%esp), %edi
movl 8(%esp), %esi
ret
safe_user_strncpy_end:

25
kernel/arch/i686/Yield.S Normal file
View File

@@ -0,0 +1,25 @@
.global asm_yield_trampoline
asm_yield_trampoline:
leal 4(%esp), %ecx
movl 4(%esp), %esp
pushl -4(%ecx)
pushl %ecx
pushl %eax
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
pushl %esp
call scheduler_on_yield
addl $4, %esp
popl %ebp
popl %edi
popl %esi
popl %ebx
popl %eax
movl 4(%esp), %ecx
movl 0(%esp), %esp
jmp *%ecx

View File

@@ -14,6 +14,23 @@
# multiboot2 header
.section .multiboot, "aw"
.align 8
multiboot_start:
.long 0x1BADB002
.long (1 << 2) # page align modules
.long -(0x1BADB002 + (1 << 2))
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long FB_WIDTH
.long FB_HEIGHT
.long FB_BPP
multiboot_end:
.align 8
multiboot2_start:
.long 0xE85250D6
.long 0
@@ -36,6 +53,12 @@ multiboot2_start:
.long 12
.long V2P(_start)
# page align modules
.align 8
.short 6
.short 0
.long 8
.align 8
.short 0
.short 0
@@ -53,10 +76,10 @@ bananboot_start:
bananboot_end:
.section .bss, "aw", @nobits
.align 4096
boot_stack_bottom:
.global g_boot_stack_top
g_boot_stack_bottom:
.skip 4096 * 4
boot_stack_top:
g_boot_stack_top:
.global g_kernel_cmdline
g_kernel_cmdline:
@@ -161,6 +184,13 @@ enable_sse:
movl %eax, %cr4
ret
enable_tsc:
# allow userspace to use RDTSC
movl %cr4, %ecx
andl $0xFFFFFFFB, %ecx
movl %ecx, %cr4
ret
initialize_paging:
# enable PAE
movl %cr4, %ecx
@@ -188,7 +218,7 @@ _start:
movl %ebx, V2P(bootloader_info)
# load boot stack
movl $V2P(boot_stack_top), %esp
movl $V2P(g_boot_stack_top), %esp
# load boot GDT
lgdt V2P(boot_gdtr)
@@ -203,10 +233,11 @@ gdt_flush:
# do processor initialization
call check_requirements
call enable_sse
call enable_tsc
call initialize_paging
# load higher half stack pointer
movl $boot_stack_top, %esp
movl $g_boot_stack_top, %esp
# jump to higher half
leal higher_half, %ecx
@@ -279,6 +310,7 @@ ap_protected_mode:
movb $1, AP_V2P(ap_stack_loaded)
leal V2P(enable_sse), %ecx; call *%ecx
leal V2P(enable_tsc), %ecx; call *%ecx
leal V2P(initialize_paging), %ecx; call *%ecx
# load boot gdt and enter long mode

View File

@@ -1,32 +1,33 @@
.macro push_userspace
pushw %gs
pushw %fs
pushw %es
pushw %ds
pushal
.endm
.macro maybe_load_kernel_segments, n
testb $3, \n(%esp)
jz 1f; jnp 1f
.macro load_kernel_segments
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw $0x28, %ax
movw %ax, %gs
1:
.endm
.macro pop_userspace
popal
popw %ds
popw %es
popw %fs
popw %gs
.macro maybe_load_userspace_segments, n
testb $3, \n(%esp)
jz 1f; jnp 1f
movw $(0x20 | 3), %bx
movw %bx, %ds
movw %bx, %es
movw $(0x30 | 3), %bx
movw %bx, %fs
movw $(0x38 | 3), %bx
movw %bx, %gs
1:
.endm
isr_stub:
push_userspace
load_kernel_segments
pushal
maybe_load_kernel_segments 44
cld
movl %cr0, %eax; pushl %eax
@@ -34,33 +35,39 @@ isr_stub:
movl %cr3, %eax; pushl %eax
movl %cr4, %eax; pushl %eax
movl %esp, %eax // register ptr
leal 64(%esp), %ebx // interrupt stack ptr
movl 60(%esp), %ecx // error code
movl 56(%esp), %edx // isr number
movl 48(%esp), %edi // isr number
movl 52(%esp), %esi // error code
leal 56(%esp), %edx // interrupt stack ptr
movl %esp, %ecx // register ptr
# stack frame for stack trace
leal 56(%esp), %eax
pushl (%eax)
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
pushl %eax
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
call cpp_isr_handler
movl %ebp, %esp
addl $16, %esp
addl $24, %esp
pop_userspace
maybe_load_userspace_segments 44
popal
addl $8, %esp
iret
irq_stub:
push_userspace
load_kernel_segments
pushal
maybe_load_kernel_segments 44
cld
movl 40(%esp), %edi # interrupt number
movl 32(%esp), %edi # interrupt number
movl %esp, %ebp
andl $-16, %esp
@@ -71,36 +78,15 @@ irq_stub:
movl %ebp, %esp
pop_userspace
addl $8, %esp
iret
.global asm_yield_handler
asm_yield_handler:
# This can only be called from kernel, so no segment saving is needed
pushal
cld
leal 32(%esp), %edi # interrupt stack ptr
movl %esp, %esi # interrupt registers ptr
movl %esp, %ebp
andl $-16, %esp
subl $8, %esp
pushl %esi
pushl %edi
call cpp_yield_handler
movl %ebp, %esp
maybe_load_userspace_segments 44
popal
addl $8, %esp
iret
.global asm_ipi_handler
asm_ipi_handler:
push_userspace
load_kernel_segments
pushal
maybe_load_kernel_segments 36
cld
movl %esp, %ebp
@@ -110,13 +96,14 @@ asm_ipi_handler:
movl %ebp, %esp
pop_userspace
maybe_load_userspace_segments 36
popal
iret
.global asm_timer_handler
asm_timer_handler:
push_userspace
load_kernel_segments
pushal
maybe_load_kernel_segments 36
cld
movl %esp, %ebp
@@ -126,7 +113,8 @@ asm_timer_handler:
movl %ebp, %esp
pop_userspace
maybe_load_userspace_segments 36
popal
iret
.macro isr n

View File

@@ -503,6 +503,7 @@ namespace Kernel
{
ASSERT(s_kernel);
ASSERT(paddr);
ASSERT(paddr % PAGE_SIZE == 0);
ASSERT(s_fast_page_lock.current_processor_has_lock());
@@ -520,7 +521,7 @@ namespace Kernel
ASSERT(!(pt[pte] & Flags::Present));
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
invalidate(fast_page(), false);
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
}
void PageTable::unmap_fast_page()
@@ -543,7 +544,7 @@ namespace Kernel
ASSERT(pt[pte] & Flags::Present);
pt[pte] = 0;
invalidate(fast_page(), false);
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
}
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
@@ -622,7 +623,8 @@ namespace Kernel
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = 1
.page_count = 1,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
}
@@ -657,8 +659,12 @@ namespace Kernel
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
pt[pte] = 0;
invalidate(vaddr, send_smp_message);
if (old_paddr != 0)
invalidate(vaddr, send_smp_message);
}
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
@@ -675,7 +681,8 @@ namespace Kernel
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = page_count
.page_count = page_count,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
}
@@ -741,9 +748,12 @@ namespace Kernel
if (!(flags & Flags::Present))
uwr_flags &= ~Flags::Present;
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
pt[pte] = paddr | uwr_flags | extra_flags;
invalidate(vaddr, send_smp_message);
if (old_paddr != 0)
invalidate(vaddr, send_smp_message);
}
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
@@ -764,7 +774,8 @@ namespace Kernel
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = page_count
.page_count = page_count,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
}
@@ -813,13 +824,13 @@ namespace Kernel
return page_data & s_page_addr_mask;
}
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free)
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free, bool send_smp_message)
{
SpinLockGuard _(m_lock);
ASSERT(vaddr % PAGE_SIZE == 0);
if (only_free && !is_page_free(vaddr))
return false;
map_page_at(0, vaddr, Flags::Reserved);
map_page_at(0, vaddr, Flags::Reserved, MemoryType::Normal, send_smp_message);
return true;
}
@@ -833,7 +844,15 @@ namespace Kernel
if (only_free && !is_range_free(vaddr, bytes))
return false;
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
reserve_page(vaddr + offset);
reserve_page(vaddr + offset, true, false);
Processor::broadcast_smp_message({
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = bytes / PAGE_SIZE,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
return true;
}
@@ -847,7 +866,7 @@ namespace Kernel
last_address -= rem;
ASSERT(is_canonical(first_address));
ASSERT(is_canonical(last_address));
ASSERT(is_canonical(last_address - 1));
const vaddr_t uc_vaddr_start = uncanonicalize(first_address);
const vaddr_t uc_vaddr_end = uncanonicalize(last_address);
@@ -929,7 +948,7 @@ namespace Kernel
last_address -= rem;
ASSERT(is_canonical(first_address));
ASSERT(is_canonical(last_address));
ASSERT(is_canonical(last_address - 1));
SpinLockGuard _(m_lock);

View File

@@ -2,55 +2,83 @@
// stack contains
// return address
// return stack
// return rflags
// siginfo_t
// signal number
// signal handler
.global signal_trampoline
signal_trampoline:
pushq %rax
pushq %rbx
pushq %rcx
pushq %rdx
pushq %rbp
pushq %rdi
pushq %rsi
pushq %r8
pushq %r9
pushq %r10
pushq %r11
pushq %r12
pushq %r13
pushq %r15 // gregs
pushq %r14
pushq %r15
pushq %r13
pushq %r12
pushq %r11
pushq %r10
pushq %r9
pushq %r8
pushq %rsi
pushq %rdi
pushq %rdx
pushq %rcx
pushq %rbx
pushq %rax
pushq %rbp
movq 128(%rsp), %rdi
movq 120(%rsp), %rax
// FIXME: populate these
xorq %rax, %rax
pushq %rax // stack
pushq %rax
pushq %rax
pushq %rax // sigset
pushq %rax // link
movq %rsp, %rdx // ucontext
leaq 176(%rsp), %rsi // siginfo
movq 168(%rsp), %rdi // signal number
movq 160(%rsp), %rax // handler
// align stack to 16 bytes
movq %rsp, %rbp
andq $-16, %rsp
subq $512, %rsp
fxsave64 (%rsp)
call *%rax
fxrstor64 (%rsp)
addq $512, %rsp
// restore stack
movq %rbp, %rsp
popq %r15
popq %r14
popq %r13
popq %r12
popq %r11
popq %r10
popq %r9
popq %r8
popq %rsi
popq %rdi
addq $40, %rsp
// restore registers
popq %rbp
popq %rdx
popq %rcx
popq %rbx
popq %rax
popq %rbx
popq %rcx
popq %rdx
popq %rdi
popq %rsi
popq %r8
popq %r9
popq %r10
popq %r11
popq %r12
popq %r13
popq %r14
popq %r15
addq $16, %rsp
// skip handler, number, siginfo_t
addq $72, %rsp
// return over red-zone
// restore flags
popfq
movq (%rsp), %rsp
// return over red-zone and siginfo_t
ret $128

View File

@@ -1,49 +1,26 @@
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
.global asm_syscall_handler
asm_syscall_handler:
pushq %rbx
pushq %rcx
pushq %rdx
pushq %rdi
pushq %rsi
pushq %rbp
pushq %r8
pushq %r9
pushq %r10
swapgs
movq %rsp, %rax
movq %gs:8, %rsp
pushq $(0x20 | 3)
pushq %rax
pushq %r11
pushq %r12
pushq %r13
pushq %r14
pushq %r15
cld
pushq $(0x28 | 3)
pushq %rcx
subq $8, %rsp
movq %rsi, %r8
movq %rdi, %r9
movq %rax, %rdi
movq %rbx, %rsi
xchgq %rcx, %rdx
leaq 112(%rsp), %rbx
pushq %rbx
movq %r10, %rcx
call cpp_syscall_handler
addq $8, %rsp
popq %r15
popq %r14
popq %r13
popq %r12
popq %r11
popq %r10
popq %r9
popq %r8
popq %rbp
popq %rsi
popq %rdi
popq %rdx
popq %rcx
popq %rbx
iretq
movq 8(%rsp), %rcx
movq 24(%rsp), %r11
movq 32(%rsp), %rsp
swapgs
sysretq
.global sys_fork_trampoline
sys_fork_trampoline:
@@ -56,7 +33,7 @@ sys_fork_trampoline:
call read_ip
testq %rax, %rax
je .reload_stack
je .done
movq %rax, %rsi
movq %rsp, %rdi
@@ -70,9 +47,3 @@ sys_fork_trampoline:
popq %rbp
popq %rbx
ret
.reload_stack:
call get_thread_start_sp
movq %rax, %rsp
xorq %rax, %rax
jmp .done

View File

@@ -27,9 +27,9 @@ start_kernel_thread:
.global start_userspace_thread
start_userspace_thread:
call load_thread_sse
call get_thread_start_sp
movq %rax, %rsp
swapgs
iretq

87
kernel/arch/x86_64/User.S Normal file
View File

@@ -0,0 +1,87 @@
# bool safe_user_memcpy(void*, const void*, size_t)
.global safe_user_memcpy
.global safe_user_memcpy_end
.global safe_user_memcpy_fault
safe_user_memcpy:
xorq %rax, %rax
movq %rdx, %rcx
rep movsb
incq %rax
safe_user_memcpy_fault:
ret
safe_user_memcpy_end:
# bool safe_user_strncpy(void*, const void*, size_t)
.global safe_user_strncpy
.global safe_user_strncpy_end
.global safe_user_strncpy_fault
safe_user_strncpy:
movq %rdx, %rcx
testq %rcx, %rcx
jz safe_user_strncpy_fault
.safe_user_strncpy_align_loop:
testb $0x7, %sil
jz .safe_user_strncpy_align_done
movb (%rsi), %al
movb %al, (%rdi)
testb %al, %al
jz .safe_user_strncpy_done
incq %rdi
incq %rsi
decq %rcx
jnz .safe_user_strncpy_align_loop
jmp safe_user_strncpy_fault
.safe_user_strncpy_align_done:
movq $0x0101010101010101, %r8
movq $0x8080808080808080, %r9
.safe_user_strncpy_qword_loop:
cmpq $8, %rcx
jb .safe_user_strncpy_qword_done
movq (%rsi), %rax
movq %rax, %r10
movq %rax, %r11
# https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
subq %r8, %r10
notq %r11
andq %r11, %r10
andq %r9, %r10
jnz .safe_user_strncpy_byte_loop
movq %rax, (%rdi)
addq $8, %rdi
addq $8, %rsi
subq $8, %rcx
jnz .safe_user_strncpy_qword_loop
jmp safe_user_strncpy_fault
.safe_user_strncpy_qword_done:
testq %rcx, %rcx
jz safe_user_strncpy_fault
.safe_user_strncpy_byte_loop:
movb (%rsi), %al
movb %al, (%rdi)
testb %al, %al
jz .safe_user_strncpy_done
incq %rdi
incq %rsi
decq %rcx
jnz .safe_user_strncpy_byte_loop
safe_user_strncpy_fault:
xorq %rax, %rax
ret
.safe_user_strncpy_done:
movb $1, %al
ret
safe_user_strncpy_end:

View File

@@ -0,0 +1,29 @@
.global asm_yield_trampoline
asm_yield_trampoline:
leaq 8(%rsp), %rcx
movq %rdi, %rsp
subq $8, %rsp
pushq -8(%rcx)
pushq %rcx
pushq %rax
pushq %rbx
pushq %rbp
pushq %r12
pushq %r13
pushq %r14
pushq %r15
movq %rsp, %rdi
call scheduler_on_yield
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbp
popq %rbx
popq %rax
movq 8(%rsp), %rcx
movq 0(%rsp), %rsp
jmp *%rcx

View File

@@ -14,6 +14,23 @@
# multiboot2 header
.section .multiboot, "aw"
.align 8
multiboot_start:
.long 0x1BADB002
.long (1 << 2) # page align modules
.long -(0x1BADB002 + (1 << 2))
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long FB_WIDTH
.long FB_HEIGHT
.long FB_BPP
multiboot_end:
.align 8
multiboot2_start:
.long 0xE85250D6
.long 0
@@ -36,6 +53,12 @@ multiboot2_start:
.long 12
.long V2P(_start)
# page align modules
.align 8
.short 6
.short 0
.long 8
.align 8
.short 0
.short 0
@@ -53,9 +76,10 @@ bananboot_start:
bananboot_end:
.section .bss, "aw", @nobits
boot_stack_bottom:
.skip 4096 * 64
boot_stack_top:
.global g_boot_stack_top
g_boot_stack_bottom:
.skip 4096 * 4
g_boot_stack_top:
.global g_kernel_cmdline
g_kernel_cmdline:
@@ -155,6 +179,13 @@ enable_sse:
movl %eax, %cr4
ret
enable_tsc:
# allow userspace to use RDTSC
movl %cr4, %ecx
andl $0xFFFFFFFB, %ecx
movl %ecx, %cr4
ret
initialize_paging:
# enable PAE
movl %cr4, %ecx
@@ -187,10 +218,11 @@ _start:
movl %eax, V2P(bootloader_magic)
movl %ebx, V2P(bootloader_info)
movl $V2P(boot_stack_top), %esp
movl $V2P(g_boot_stack_top), %esp
call check_requirements
call enable_sse
call enable_tsc
call initialize_paging
# flush gdt and jump to 64 bit
@@ -277,6 +309,7 @@ ap_protected_mode:
movb $1, AP_V2P(ap_stack_loaded)
leal V2P(enable_sse), %ecx; call *%ecx
leal V2P(enable_tsc), %ecx; call *%ecx
leal V2P(initialize_paging), %ecx; call *%ecx
# load boot gdt and enter long mode

View File

@@ -1,4 +1,12 @@
.macro pushaq
.macro swapgs_if_necessary, n
testb $3, \n(%rsp)
jz 1f; jnp 1f
swapgs
1:
.endm
.macro pushaq, n
swapgs_if_necessary \n
pushq %rax
pushq %rcx
pushq %rdx
@@ -16,7 +24,7 @@
pushq %r15
.endm
.macro popaq
.macro popaq, n
popq %r15
popq %r14
popq %r13
@@ -32,10 +40,11 @@
popq %rdx
popq %rcx
popq %rax
swapgs_if_necessary \n
.endm
isr_stub:
pushaq
pushaq 24
cld
movq %cr0, %rax; pushq %rax
movq %cr2, %rax; pushq %rax
@@ -49,43 +58,33 @@ isr_stub:
call cpp_isr_handler
addq $32, %rsp
popaq
popaq 24
addq $16, %rsp
iretq
irq_stub:
pushaq
pushaq 24
cld
movq 120(%rsp), %rdi # irq number
call cpp_irq_handler
popaq
popaq 24
addq $16, %rsp
iretq
.global asm_yield_handler
asm_yield_handler:
pushaq
cld
leaq 120(%rsp), %rdi # interrupt stack ptr
movq %rsp, %rsi # interrupt register ptr
call cpp_yield_handler
popaq
iretq
.global asm_ipi_handler
asm_ipi_handler:
pushaq
pushaq 8
cld
call cpp_ipi_handler
popaq
popaq 8
iretq
.global asm_timer_handler
asm_timer_handler:
pushaq
pushaq 8
cld
call cpp_timer_handler
popaq
popaq 8
iretq
.macro isr n

View File

@@ -2,6 +2,7 @@
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/Namespace.h>
#include <kernel/ACPI/EmbeddedController.h>
#include <kernel/ACPI/Headers.h>
#include <kernel/Memory/Types.h>
#include <kernel/ThreadBlocker.h>
@@ -35,8 +36,12 @@ namespace Kernel::ACPI
BAN::ErrorOr<void> poweroff();
BAN::ErrorOr<void> reset();
BAN::ErrorOr<void> register_gpe_handler(uint8_t gpe, void (*callback)(void*), void* argument);
void handle_irq() override;
BAN::Span<BAN::UniqPtr<EmbeddedController>> embedded_controllers() { return m_embedded_controllers.span(); }
private:
ACPI() = default;
BAN::ErrorOr<void> initialize_impl();
@@ -50,6 +55,12 @@ namespace Kernel::ACPI
BAN::ErrorOr<void> route_interrupt_link_device(const AML::Scope& device, uint64_t& routed_irq_mask);
BAN::ErrorOr<void> initialize_embedded_controller(const AML::Scope& embedded_controller);
BAN::ErrorOr<void> initialize_embedded_controllers();
BAN::Optional<GAS> find_gpe_block(size_t index);
bool enable_gpe(uint8_t gpe);
private:
paddr_t m_header_table_paddr = 0;
vaddr_t m_header_table_vaddr = 0;
@@ -68,8 +79,23 @@ namespace Kernel::ACPI
ThreadBlocker m_event_thread_blocker;
BAN::Vector<BAN::UniqPtr<EmbeddedController>> m_embedded_controllers;
struct GPEHandler
{
bool has_callback { false };
union {
AML::Reference* method;
struct
{
void (*callback)(void*);
void* argument;
};
};
};
bool m_has_any_gpes { false };
AML::Scope m_gpe_scope;
BAN::Array<AML::Reference*, 0xFF> m_gpe_methods { nullptr };
BAN::Array<GPEHandler, 0xFF> m_gpe_methods;
bool m_hardware_reduced { false };
AML::Namespace* m_namespace { nullptr };

View File

@@ -50,6 +50,7 @@ namespace Kernel::ACPI::AML
BAN::ErrorOr<void> for_each_child(const Scope&, const BAN::Function<BAN::Iteration(const Scope&, Reference*)>&);
BAN::ErrorOr<BAN::Vector<Scope>> find_device_with_eisa_id(BAN::StringView eisa_id);
BAN::ErrorOr<BAN::Vector<Scope>> find_device_with_eisa_id(BAN::Span<BAN::StringView> eisa_ids);
private:
BAN::ErrorOr<Scope> resolve_path(const Scope& scope, const NameString& name_string);

View File

@@ -89,6 +89,9 @@ namespace Kernel::ACPI::AML
GAS::AddressSpaceID address_space;
uint64_t offset;
uint64_t length;
alignas(Scope) uint8_t scope_storage[sizeof(Scope)];
Scope& scope() { return *reinterpret_cast<Scope*>(scope_storage); }
const Scope& scope() const { return *reinterpret_cast<const Scope*>(scope_storage); }
};
struct FieldUnit

View File

@@ -0,0 +1,69 @@
#pragma once
#include <BAN/Atomic.h>
#include <BAN/UniqPtr.h>
#include <kernel/ACPI/AML/Scope.h>
#include <kernel/Lock/Mutex.h>
#include <kernel/Thread.h>
namespace Kernel::ACPI
{
class EmbeddedController
{
public:
static BAN::ErrorOr<BAN::UniqPtr<EmbeddedController>> create(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, BAN::Optional<uint8_t> gpe);
~EmbeddedController();
BAN::ErrorOr<uint8_t> read_byte(uint8_t offset);
BAN::ErrorOr<void> write_byte(uint8_t offset, uint8_t value);
const AML::Scope& scope() const { return m_scope; }
private:
EmbeddedController(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, bool has_gpe)
: m_scope(BAN::move(scope))
, m_command_port(command_port)
, m_data_port(data_port)
, m_has_gpe(has_gpe)
{ }
private:
void wait_status_bit(uint8_t bit, uint8_t value);
uint8_t read_one(uint16_t port);
void write_one(uint16_t port, uint8_t value);
static void handle_gpe_wrapper(void*);
void handle_gpe();
BAN::ErrorOr<void> call_query_method(uint8_t notification);
void thread_task();
struct Command
{
uint8_t command;
BAN::Optional<uint8_t> data1;
BAN::Optional<uint8_t> data2;
uint8_t* response;
BAN::Atomic<bool> done;
};
BAN::ErrorOr<void> send_command(Command& command);
private:
const AML::Scope m_scope;
const uint16_t m_command_port;
const uint16_t m_data_port;
const bool m_has_gpe;
Mutex m_mutex;
ThreadBlocker m_thread_blocker;
BAN::Optional<Command*> m_queued_command;
Thread* m_thread { nullptr };
};
}

View File

@@ -0,0 +1,179 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/Debug.h>
#include <BAN/Optional.h>
namespace Kernel::ACPI
{
struct ResourceData
{
enum class Type
{
IRQ,
DMA,
IOPort,
FixedIOPort,
FixedDMA,
// TODO: large stuff the stuff :)
};
union {
struct {
uint16_t irq_mask;
union {
struct {
uint8_t edge_triggered : 1;
uint8_t : 2;
uint8_t active_low : 1;
uint8_t shared : 1;
uint8_t wake_capable : 1;
uint8_t : 2;
};
uint8_t raw;
};
} irq;
struct {
uint8_t channel_mask;
union {
struct {
uint8_t type : 2; // 0: 8 bit, 1: 8 and 16 bit, 2: 16 bit only
uint8_t bus_master : 1;
uint8_t : 2;
uint8_t channel_speed : 2; // 0: compatibility, 1: type A, 2: type B, 3: type F
uint8_t : 1;
};
uint8_t raw;
};
} dma;
struct {
uint16_t range_min_base;
uint16_t range_max_base;
uint8_t base_alignment;
uint8_t range_length;
} io_port;
struct {
uint16_t range_base;
uint8_t range_length;
} fixed_io_port;
struct {
uint16_t request_line;
uint16_t channel;
uint8_t transfer_width; // 0: 8 bit, 1: 16 bit, 2: 32 bit, 3: 64 bit, 4: 128 bit
} fixed_dma;
} as;
Type type;
};
class ResourceParser
{
public:
ResourceParser(BAN::ConstByteSpan buffer)
: m_buffer(buffer)
{}
BAN::Optional<ResourceData> get_next()
{
for (;;)
{
if (m_buffer.empty())
return {};
if (m_buffer[0] & 0x80)
{
dprintln("Skipping large resource 0x{2H}", m_buffer[0] & 0x7F);
const uint16_t length = (m_buffer[2] << 8) | m_buffer[1];
if (m_buffer.size() < static_cast<size_t>(3 + length))
return {};
m_buffer = m_buffer.slice(3 + length);
continue;
}
const uint8_t length = m_buffer[0] & 0x07;
if (m_buffer.size() < static_cast<size_t>(1 + length))
return {};
BAN::Optional<ResourceData> result;
switch ((m_buffer[0] >> 3) & 0x0F)
{
case 0x04:
if (length < 2)
break;
result = ResourceData {
.as = { .irq = {
.irq_mask = static_cast<uint16_t>((m_buffer[2] << 8) | m_buffer[1]),
.raw = (length >= 3) ? m_buffer[3] : static_cast<uint8_t>(1),
}},
.type = ResourceData::Type::IRQ,
};
break;
case 0x05:
if (length < 2)
break;
result = ResourceData {
.as = { .dma = {
.channel_mask = m_buffer[1],
.raw = m_buffer[2],
}},
.type = ResourceData::Type::DMA,
};
break;
case 0x08:
if (length < 7)
break;
result = ResourceData {
.as = { .io_port = {
.range_min_base = static_cast<uint16_t>(((m_buffer[3] << 8) | m_buffer[2]) & ((m_buffer[1] & 1) ? 0xFFFF : 0x03FF)),
.range_max_base = static_cast<uint16_t>(((m_buffer[5] << 8) | m_buffer[4]) & ((m_buffer[1] & 1) ? 0xFFFF : 0x03FF)),
.base_alignment = m_buffer[6],
.range_length = m_buffer[7],
}},
.type = ResourceData::Type::IOPort,
};
break;
case 0x09:
if (length < 3)
break;
result = ResourceData {
.as = { .fixed_io_port = {
.range_base = static_cast<uint16_t>(((m_buffer[2] << 8) | m_buffer[1]) & 0x03FF),
.range_length = m_buffer[3],
}},
.type = ResourceData::Type::FixedIOPort,
};
break;
case 0x0A:
if (length < 5)
break;
result = ResourceData {
.as = { .fixed_dma = {
.request_line = static_cast<uint16_t>((m_buffer[2] << 8) | m_buffer[1]),
.channel = static_cast<uint16_t>((m_buffer[4] << 8) | m_buffer[3]),
.transfer_width = m_buffer[5],
}},
.type = ResourceData::Type::FixedDMA,
};
break;
case 0x0F:
// End tag
return {};
case 0x06:
case 0x07:
case 0x0E:
dprintln("Skipping short resource 0x{2H}", (m_buffer[0] >> 3) & 0x0F);
break;
}
m_buffer = m_buffer.slice(1 + length);
if (result.has_value())
return result.release_value();
}
}
private:
BAN::ConstByteSpan m_buffer;
};
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <stdint.h>
namespace Kernel::API
{
enum SharedPageFeature : uint32_t
{
SPF_GETTIME = 1 << 0,
};
struct SharedPage
{
uint8_t __sequence[0x100];
uint32_t features;
struct
{
uint8_t shift;
uint64_t mult;
uint64_t realtime_seconds;
} gettime_shared;
struct
{
struct
{
uint32_t seq;
uint64_t last_ns;
uint64_t last_tsc;
} gettime_local;
} cpus[];
};
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include <kernel/Attributes.h>
#include <kernel/IDT.h>
#include <stdint.h>
#include <sys/syscall.h>
namespace Kernel
{
ALWAYS_INLINE long syscall(int syscall, uintptr_t arg1 = 0, uintptr_t arg2 = 0, uintptr_t arg3 = 0, uintptr_t arg4 = 0, uintptr_t arg5 = 0)
{
long ret;
#if ARCH(x86_64)
register uintptr_t r10 asm("r10") = arg3;
register uintptr_t r8 asm( "r8") = arg4;
register uintptr_t r9 asm( "r9") = arg5;
asm volatile(
"syscall"
: "=a"(ret)
, "+D"(syscall)
, "+S"(arg1)
, "+d"(arg2)
, "+r"(r10)
, "+r"(r8)
, "+r"(r9)
:: "rcx", "r11", "memory");
#elif ARCH(i686)
asm volatile(
"int %[irq]"
: "=a"(ret)
: [irq]"i"(static_cast<int>(IRQ_SYSCALL)) // WTF GCC 15
, "a"(syscall)
, "b"(arg1)
, "c"(arg2)
, "d"(arg3)
, "S"(arg4)
, "D"(arg5)
: "memory");
#endif
return ret;
}
}

View File

@@ -0,0 +1,59 @@
#pragma once
#include <kernel/Audio/Controller.h>
#include <kernel/Memory/DMARegion.h>
namespace Kernel
{
class AC97AudioController final : public AudioController, public Interruptable
{
public:
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
void handle_irq() override;
protected:
void handle_new_data() override;
uint32_t get_channels() const override { return 2; }
uint32_t get_sample_rate() const override { return 48000; }
uint32_t get_total_pins() const override { return 1; }
uint32_t get_current_pin() const override { return 0; }
BAN::ErrorOr<void> set_current_pin(uint32_t pin) override { if (pin != 0) return BAN::Error::from_errno(EINVAL); return {}; }
BAN::ErrorOr<void> set_volume_mdB(int32_t) override;
private:
AC97AudioController(PCI::Device& pci_device)
: m_pci_device(pci_device)
{ }
uint32_t get_volume_data() const;
BAN::ErrorOr<void> initialize();
BAN::ErrorOr<void> initialize_bld();
BAN::ErrorOr<void> initialize_interrupts();
bool queue_samples_to_bld();
private:
static constexpr size_t m_bdl_entries = 32;
static constexpr size_t m_samples_per_entry = 0x1000;
// We only store samples in 2 BDL entries at a time to reduce the amount of samples queued.
// This is to reduce latency as you cannot remove data already passed to the BDLs
static constexpr size_t m_used_bdl_entries = 2;
PCI::Device& m_pci_device;
BAN::UniqPtr<PCI::BarRegion> m_mixer;
BAN::UniqPtr<PCI::BarRegion> m_bus_master;
BAN::UniqPtr<DMARegion> m_bdl_region;
uint32_t m_bdl_tail { 0 };
uint32_t m_bdl_head { 0 };
};
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
namespace Kernel::AC97
{
struct BufferDescriptorListEntry
{
uint32_t address;
uint16_t samples;
uint16_t flags; // bit 14: last entry, bit 15: IOC
};
}

View File

@@ -0,0 +1,58 @@
#pragma once
#include <kernel/Device/Device.h>
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/PCI.h>
#include <sys/ioctl.h>
namespace Kernel
{
class AudioController : public CharacterDevice
{
public:
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
dev_t rdev() const override { return m_rdev; }
BAN::StringView name() const override { return m_name; }
protected:
AudioController();
BAN::ErrorOr<void> initialize();
virtual void handle_new_data() = 0;
virtual uint32_t get_channels() const = 0;
virtual uint32_t get_sample_rate() const = 0;
virtual uint32_t get_total_pins() const = 0;
virtual uint32_t get_current_pin() const = 0;
virtual BAN::ErrorOr<void> set_current_pin(uint32_t) = 0;
virtual BAN::ErrorOr<void> set_volume_mdB(int32_t) = 0;
bool can_read_impl() const override { return false; }
bool can_write_impl() const override { SpinLockGuard _(m_spinlock); return !m_sample_data->full(); }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
BAN::ErrorOr<long> ioctl_impl(int cmd, void* arg) override;
protected:
ThreadBlocker m_sample_data_blocker;
mutable SpinLock m_spinlock;
static constexpr size_t m_sample_data_capacity = 1 << 20;
BAN::UniqPtr<ByteRingBuffer> m_sample_data;
snd_volume_info m_volume_info {};
private:
const dev_t m_rdev;
char m_name[10] {};
};
}

View File

@@ -0,0 +1,80 @@
#pragma once
#include <kernel/Audio/Controller.h>
#include <kernel/Audio/HDAudio/Controller.h>
namespace Kernel
{
class HDAudioController;
class HDAudioFunctionGroup final : public AudioController
{
public:
static BAN::ErrorOr<BAN::RefPtr<HDAudioFunctionGroup>> create(BAN::RefPtr<HDAudioController>, uint8_t cid, HDAudio::AFGNode&&);
void on_stream_interrupt(uint8_t stream_index);
protected:
// FIXME: allow setting these :D
uint32_t get_channels() const override { return 2; }
uint32_t get_sample_rate() const override { return 48000; }
uint32_t get_total_pins() const override;
uint32_t get_current_pin() const override;
BAN::ErrorOr<void> set_current_pin(uint32_t) override;
BAN::ErrorOr<void> set_volume_mdB(int32_t) override;
void handle_new_data() override;
private:
HDAudioFunctionGroup(BAN::RefPtr<HDAudioController> controller, uint8_t cid, HDAudio::AFGNode&& afg_node)
: m_controller(controller)
, m_afg_node(BAN::move(afg_node))
, m_cid(cid)
{ }
~HDAudioFunctionGroup();
BAN::ErrorOr<void> initialize();
BAN::ErrorOr<void> initialize_stream();
BAN::ErrorOr<void> initialize_output();
BAN::ErrorOr<void> enable_output_path(uint8_t index);
BAN::ErrorOr<void> disable_output_path(uint8_t index);
void reset_stream();
BAN::ErrorOr<void> recurse_output_paths(const HDAudio::AFGWidget& widget, BAN::Vector<const HDAudio::AFGWidget*>& path);
uint16_t get_format_data() const;
size_t bdl_offset() const;
void queue_bdl_data();
private:
// use 6 512 sample BDL entries
// each entry is ~10.7 ms at 48 kHz
// -> total buffered audio is 64 ms
static constexpr size_t m_bdl_entry_sample_frames = 512;
static constexpr size_t m_bdl_entry_count = 6;
BAN::RefPtr<HDAudioController> m_controller;
const HDAudio::AFGNode m_afg_node;
const uint8_t m_cid;
BAN::Vector<BAN::Vector<const HDAudio::AFGWidget*>> m_output_paths;
BAN::Vector<const HDAudio::AFGWidget*> m_output_pins;
size_t m_output_path_index { SIZE_MAX };
uint8_t m_stream_id { 0xFF };
uint8_t m_stream_index { 0xFF };
BAN::UniqPtr<DMARegion> m_bdl_region;
size_t m_bdl_head { 0 };
size_t m_bdl_tail { 0 };
bool m_stream_running { false };
};
}

View File

@@ -0,0 +1,77 @@
#pragma once
#include <kernel/Audio/Controller.h>
#include <kernel/Audio/HDAudio/Definitions.h>
#include <kernel/Memory/DMARegion.h>
namespace Kernel
{
class HDAudioController : public Interruptable, public BAN::RefCounted<HDAudioController>
{
public:
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
BAN::ErrorOr<uint32_t> send_command(HDAudio::CORBEntry);
uint8_t get_stream_index(HDAudio::StreamType type, uint8_t index) const;
BAN::ErrorOr<uint8_t> allocate_stream_id();
void deallocate_stream_id(uint8_t id);
BAN::ErrorOr<uint8_t> allocate_stream(HDAudio::StreamType type, void* afg);
void deallocate_stream(uint8_t index);
PCI::BarRegion& bar0() { return *m_bar0; }
bool is_64bit() const { return m_is64bit; }
void handle_irq() override;
private:
HDAudioController(PCI::Device& pci_device)
: m_pci_device(pci_device)
{ }
BAN::ErrorOr<void> initialize();
BAN::ErrorOr<void> initialize_ring_buffers();
BAN::ErrorOr<void> reset_controller();
BAN::ErrorOr<HDAudio::Codec> initialize_codec(uint8_t codec);
BAN::ErrorOr<HDAudio::AFGNode> initialize_node(uint8_t codec, uint8_t node);
BAN::ErrorOr<HDAudio::AFGWidget> initialize_widget(uint8_t codec, uint8_t node);
private:
struct RingBuffer
{
vaddr_t vaddr;
uint32_t index;
uint32_t size;
};
private:
PCI::Device& m_pci_device;
BAN::UniqPtr<PCI::BarRegion> m_bar0;
bool m_is64bit { false };
bool m_use_immediate_command { false };
uint8_t m_output_streams { 0 };
uint8_t m_input_streams { 0 };
uint8_t m_bidir_streams { 0 };
void* m_allocated_streams[30] {};
// NOTE: stream ids are from 1 to 15
uint16_t m_allocated_stream_ids { 0 };
Mutex m_command_mutex;
SpinLock m_rb_lock;
ThreadBlocker m_rb_blocker;
RingBuffer m_corb;
RingBuffer m_rirb;
BAN::UniqPtr<DMARegion> m_ring_buffer_region;
};
}

View File

@@ -0,0 +1,90 @@
#pragma once
#include <BAN/Vector.h>
namespace Kernel::HDAudio
{
struct CORBEntry
{
union {
struct {
uint32_t data : 8;
uint32_t command : 12;
uint32_t node_index : 8;
uint32_t codec_address : 4;
};
uint32_t raw;
};
};
static_assert(sizeof(CORBEntry) == sizeof(uint32_t));
struct BDLEntry
{
paddr_t address;
uint32_t length;
uint32_t ioc;
};
static_assert(sizeof(BDLEntry) == 16);
struct AFGWidget
{
enum class Type
{
OutputConverter,
InputConverter,
Mixer,
Selector,
PinComplex,
Power,
VolumeKnob,
BeepGenerator,
};
Type type;
uint8_t id;
union
{
struct
{
bool input;
bool output;
bool display; // HDMI or DP
uint32_t config;
} pin_complex;
};
struct Amplifier
{
uint8_t offset;
uint8_t num_steps;
uint8_t step_size;
bool mute;
};
BAN::Optional<Amplifier> output_amplifier;
BAN::Vector<uint16_t> connections;
};
struct AFGNode
{
uint8_t id;
BAN::Vector<AFGWidget> widgets;
};
struct Codec
{
uint8_t id;
BAN::Vector<AFGNode> nodes;
};
enum class StreamType
{
Input,
Output,
Bidirectional,
};
}

View File

@@ -0,0 +1,50 @@
#pragma once
#include <stdint.h>
namespace Kernel::HDAudio
{
enum Regs : uint8_t
{
GCAP = 0x00,
VMIN = 0x02,
VMAJ = 0x03,
GCTL = 0x08,
STATESTS = 0x0E,
INTCTL = 0x20,
INTSTS = 0x24,
CORBLBASE = 0x40,
CORBUBASE = 0x44,
CORBWP = 0x48,
CORBRP = 0x4A,
CORBCTL = 0x4C,
CORBSTS = 0x4D,
CORBSIZE = 0x4E,
RIRBLBASE = 0x50,
RIRBUBASE = 0x54,
RIRBWP = 0x58,
RINTCNT = 0x5A,
RIRBCTL = 0x5C,
RIRBSTS = 0x5D,
RIRBSIZE = 0x5E,
ICOI = 0x60,
ICII = 0x64,
ICIS = 0x68,
SDCTL = 0x00,
SDSTS = 0x03,
SDLPIB = 0x04,
SDCBL = 0x08,
SDLVI = 0x0C,
SDFIFOD = 0x10,
SDFMT = 0x12,
SDBDPL = 0x18,
SDBDPU = 0x1C,
};
}

View File

@@ -41,6 +41,12 @@ namespace Kernel
Type type;
};
struct BootModule
{
paddr_t start;
size_t size;
};
struct BootInfo
{
BAN::String command_line;
@@ -48,6 +54,7 @@ namespace Kernel
RSDP rsdp {};
paddr_t kernel_paddr {};
BAN::Vector<BootModule> modules;
BAN::Vector<MemoryMapEntry> memory_map_entries;
};

View File

@@ -81,5 +81,6 @@ namespace CPUID
bool has_pge();
bool has_pat();
bool has_1gib_pages();
bool has_invariant_tsc();
}

View File

@@ -35,10 +35,8 @@ namespace Kernel
bool has_egid(gid_t) const;
BAN::ErrorOr<void> initialize_supplementary_groups();
private:
BAN::ErrorOr<BAN::String> find_username() const;
BAN::Span<const gid_t> groups() const { return m_supplementary.span(); }
BAN::ErrorOr<void> set_groups(BAN::Span<const gid_t> groups);
private:
uid_t m_ruid, m_euid, m_suid;

View File

@@ -70,10 +70,15 @@
#define DEBUG_USB_MOUSE 0
#define DEBUG_USB_MASS_STORAGE 0
#define DEBUG_HDAUDIO 0
namespace Debug
{
void dump_stack_trace();
void dump_stack_trace(uintptr_t ip, uintptr_t bp);
void dump_qr_code();
void putchar(char);
void print_prefix(const char*, int);

View File

@@ -3,7 +3,7 @@
namespace Kernel
{
class DebugDevice : public CharacterDevice
class DebugDevice final : public CharacterDevice
{
public:
static BAN::ErrorOr<BAN::RefPtr<DebugDevice>> create(mode_t, uid_t, gid_t);
@@ -24,6 +24,7 @@ namespace Kernel
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
const dev_t m_rdev;

View File

@@ -16,7 +16,11 @@ namespace Kernel
virtual bool is_partition() const { return false; }
virtual bool is_storage_device() const { return false; }
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) { (void)offset; (void)len; return BAN::Error::from_errno(EINVAL); }
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t, int status_flags)
{
(void)offset; (void)len; (void)status_flags;
return BAN::Error::from_errno(ENOTSUP);
}
virtual dev_t rdev() const override = 0;

View File

@@ -16,11 +16,14 @@ namespace Kernel
Debug,
Keyboard,
Mouse,
Joystick,
SCSI,
NVMeController,
NVMeNamespace,
Ethernet,
Loopback,
TmpFS,
AudioController,
};
}

View File

@@ -10,6 +10,7 @@ namespace Kernel
{
public:
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create_from_boot_framebuffer();
static BAN::RefPtr<FramebufferDevice> boot_framebuffer();
~FramebufferDevice();
uint32_t width() const { return m_width; }
@@ -17,6 +18,7 @@ namespace Kernel
uint32_t get_pixel(uint32_t x, uint32_t y) const;
void set_pixel(uint32_t x, uint32_t y, uint32_t rgb);
void fill(uint32_t rgb);
// positive rows -> empty pixels on bottom
// negative rows -> empty pixels on top
@@ -26,7 +28,7 @@ namespace Kernel
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) override;
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t, int status_flags) override;
virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::StringView name() const override { return m_name.sv(); }
@@ -38,6 +40,7 @@ namespace Kernel
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
FramebufferDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev, paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp);

View File

@@ -5,7 +5,7 @@
namespace Kernel
{
class NullDevice : public CharacterDevice
class NullDevice final : public CharacterDevice
{
public:
static BAN::ErrorOr<BAN::RefPtr<NullDevice>> create(mode_t, uid_t, gid_t);
@@ -26,6 +26,7 @@ namespace Kernel
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
const dev_t m_rdev;

View File

@@ -3,7 +3,7 @@
namespace Kernel
{
class RandomDevice : public CharacterDevice
class RandomDevice final : public CharacterDevice
{
public:
static BAN::ErrorOr<BAN::RefPtr<RandomDevice>> create(mode_t, uid_t, gid_t);
@@ -24,6 +24,7 @@ namespace Kernel
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
const dev_t m_rdev;

View File

@@ -3,7 +3,7 @@
namespace Kernel
{
class ZeroDevice : public CharacterDevice
class ZeroDevice final : public CharacterDevice
{
public:
static BAN::ErrorOr<BAN::RefPtr<ZeroDevice>> create(mode_t, uid_t, gid_t);
@@ -24,6 +24,7 @@ namespace Kernel
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
const dev_t m_rdev;

View File

@@ -20,6 +20,6 @@ namespace Kernel::ELF
BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions;
};
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode>, const Credentials&, PageTable&);
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> root, BAN::RefPtr<Inode> inode, const Credentials&, PageTable&);
}

View File

@@ -0,0 +1,109 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/CircularQueue.h>
#include <BAN/HashMap.h>
#include <BAN/HashSet.h>
#include <kernel/FS/Inode.h>
#include <limits.h>
#include <sys/epoll.h>
namespace Kernel
{
class Epoll final : public Inode
{
public:
static BAN::ErrorOr<BAN::RefPtr<Epoll>> create();
~Epoll();
BAN::ErrorOr<void> ctl(int op, int fd, BAN::RefPtr<Inode> inode, epoll_event event);
BAN::ErrorOr<size_t> wait(BAN::Span<epoll_event> events, uint64_t waketime_ns);
void notify(BAN::RefPtr<Inode> inode, uint32_t event);
private:
Epoll() = default;
public:
ino_t ino() const override { return 0; }
Mode mode() const override { return { Mode::IRUSR | Mode::IWUSR }; }
nlink_t nlink() const override { return 0; }
uid_t uid() const override { return 0; }
gid_t gid() const override { return 0; }
off_t size() const override { return 0; }
timespec atime() const override { return {}; }
timespec mtime() const override { return {}; }
timespec ctime() const override { return {}; }
blksize_t blksize() const override { return PAGE_SIZE; }
blkcnt_t blocks() const override { return 0; }
dev_t dev() const override { return 0; }
dev_t rdev() const override { return 0; }
bool is_epoll() const override { return true; }
const FileSystem* filesystem() const override { return nullptr; }
bool can_read_impl() const override { return false; }
bool can_write_impl() const override { return false; }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
BAN::ErrorOr<void> fsync_impl() override { return {}; }
private:
struct InodeRefPtrHash
{
BAN::hash_t operator()(const BAN::RefPtr<Inode>& inode)
{
return BAN::hash<const Inode*>()(inode.ptr());
}
};
struct ListenEventList
{
BAN::Array<epoll_event, OPEN_MAX> events;
uint32_t bitmap[(OPEN_MAX + 31) / 32] {};
bool has_fd(int fd) const
{
// For some reason having (fd < 0 || ...) makes GCC 15.1.0
// think bitmap access can be out of bounds...
if (static_cast<size_t>(fd) >= events.size())
return false;
return bitmap[fd / 32] & (1u << (fd % 32));
}
bool empty() const
{
for (auto val : bitmap)
if (val != 0)
return false;
return true;
}
void add_fd(int fd, epoll_event event)
{
ASSERT(!has_fd(fd));
bitmap[fd / 32] |= (1u << (fd % 32));
events[fd] = event;
}
void remove_fd(int fd)
{
ASSERT(has_fd(fd));
bitmap[fd / 32] &= ~(1u << (fd % 32));
events[fd] = {};
}
};
private:
ThreadBlocker m_thread_blocker;
SpinLock m_ready_lock;
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t, InodeRefPtrHash> m_ready_events;
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t, InodeRefPtrHash> m_processing_events;
BAN::HashMap<BAN::RefPtr<Inode>, ListenEventList, InodeRefPtrHash> m_listening_events;
};
}

View File

@@ -22,6 +22,7 @@ namespace Kernel
void add_inode(BAN::StringView path, BAN::RefPtr<TmpInode>);
void initiate_disk_cache_drop();
void initiate_sync(bool should_block);
private:
@@ -37,6 +38,10 @@ namespace Kernel
ThreadBlocker m_sync_done;
ThreadBlocker m_sync_thread_blocker;
volatile bool m_should_sync { false };
SpinLock m_disk_cache_lock;
ThreadBlocker m_disk_cache_thread_blocker;
BAN::Atomic<bool> m_should_drop_disk_cache { false };
};
}

View File

@@ -0,0 +1,52 @@
#pragma once
#include <kernel/FS/Inode.h>
namespace Kernel
{
class EventFD final : public Inode
{
public:
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(uint64_t initval, bool semaphore);
ino_t ino() const override { return 0; }
Mode mode() const override { return { Mode::IFCHR | Mode::IRUSR | Mode::IWUSR }; }
nlink_t nlink() const override { return ref_count(); }
uid_t uid() const override { return 0; }
gid_t gid() const override { return 0; }
off_t size() const override { return 0; }
timespec atime() const override { return {}; }
timespec mtime() const override { return {}; }
timespec ctime() const override { return {}; }
blksize_t blksize() const override { return 8; }
blkcnt_t blocks() const override { return 0; }
dev_t dev() const override { return 0; }
dev_t rdev() const override { return 0; }
const FileSystem* filesystem() const override { return nullptr; }
protected:
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
bool can_read_impl() const override { return m_value > 0; }
bool can_write_impl() const override { return m_value < UINT64_MAX - 1; }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
private:
EventFD(uint64_t initval, bool is_semaphore)
: m_is_semaphore(is_semaphore)
, m_value(initval)
{ }
private:
const bool m_is_semaphore;
uint64_t m_value;
ThreadBlocker m_thread_blocker;
};
}

View File

@@ -26,18 +26,32 @@ namespace Kernel
class BlockBufferWrapper
{
BAN_NON_COPYABLE(BlockBufferWrapper);
BAN_NON_MOVABLE(BlockBufferWrapper);
public:
BlockBufferWrapper(BAN::Span<uint8_t> buffer, bool& used)
BlockBufferWrapper(BAN::Span<uint8_t> buffer, void (*callback)(void*, const uint8_t*), void* argument)
: m_buffer(buffer)
, m_used(used)
{
ASSERT(m_used);
}
, m_callback(callback)
, m_argument(argument)
{ }
BlockBufferWrapper(BlockBufferWrapper&& other) { *this = BAN::move(other); }
~BlockBufferWrapper()
{
m_used = false;
if (m_callback == nullptr)
return;
m_callback(m_argument, m_buffer.data());
}
BlockBufferWrapper& operator=(BlockBufferWrapper&& other)
{
this->m_buffer = other.m_buffer;
this->m_callback = other.m_callback;
this->m_argument = other.m_argument;
other.m_buffer = {};
other.m_callback = nullptr;
other.m_argument = nullptr;
return *this;
}
size_t size() const { return m_buffer.size(); }
@@ -53,7 +67,8 @@ namespace Kernel
private:
BAN::Span<uint8_t> m_buffer;
bool& m_used;
void (*m_callback)(void*, const uint8_t*);
void* m_argument;
};
public:
@@ -62,8 +77,6 @@ namespace Kernel
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
virtual dev_t dev() const override { return m_block_device->rdev(); };
private:
Ext2FS(BAN::RefPtr<BlockDevice> block_device)
: m_block_device(block_device)
@@ -81,7 +94,7 @@ namespace Kernel
BAN::ErrorOr<void> sync_superblock();
BAN::ErrorOr<void> sync_block(uint32_t block);
BlockBufferWrapper get_block_buffer();
BAN::ErrorOr<BlockBufferWrapper> get_block_buffer();
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
BAN::ErrorOr<void> release_block(uint32_t block);
@@ -104,10 +117,13 @@ namespace Kernel
{
public:
BlockBufferManager() = default;
BlockBufferWrapper get_buffer();
BAN::ErrorOr<BlockBufferWrapper> get_buffer();
BAN::ErrorOr<void> initialize(size_t block_size);
private:
void destroy_callback(const uint8_t* buffer_ptr);
private:
struct BlockBuffer
{
@@ -115,8 +131,20 @@ namespace Kernel
bool used { false };
};
struct ThreadInfo
{
pid_t tid { 0 };
size_t buffers { 0 };
};
private:
BAN::Array<BlockBuffer, 10> m_buffers;
static constexpr size_t max_threads = 8;
static constexpr size_t max_buffers_per_thread = 6;
Mutex m_buffer_mutex;
ThreadBlocker m_buffer_blocker;
BAN::Array<BlockBuffer, max_threads * max_buffers_per_thread> m_buffers;
BAN::Array<ThreadInfo, max_threads> m_thread_infos;
};
private:

View File

@@ -37,6 +37,7 @@ namespace Kernel
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override;
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override;
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
@@ -46,29 +47,32 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
virtual BAN::ErrorOr<void> fsync_impl() override;
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
// Returns maximum number of data blocks in use
// NOTE: the inode might have more blocks than what this suggests if it has been shrinked
uint32_t max_used_data_block_count() const { return size() / blksize(); }
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block(uint32_t block, uint32_t index, uint32_t depth);
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index);
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block(uint32_t& block, uint32_t index, uint32_t depth, bool allocate);
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index, bool allocate);
BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name);
BAN::ErrorOr<void> remove_inode_from_directory(BAN::StringView name, bool cleanup_directory);
BAN::ErrorOr<bool> is_directory_empty();
BAN::ErrorOr<void> cleanup_indirect_block(uint32_t block, uint32_t depth);
BAN::ErrorOr<void> cleanup_default_links();
BAN::ErrorOr<void> cleanup_data_blocks();
BAN::ErrorOr<void> cleanup_from_fs();
BAN::ErrorOr<uint32_t> allocate_new_block_to_indirect_block(uint32_t& block, uint32_t index, uint32_t depth);
BAN::ErrorOr<uint32_t> allocate_new_block(uint32_t data_block_index);
BAN::ErrorOr<void> sync();
uint32_t block_group() const;
@@ -81,6 +85,26 @@ namespace Kernel
{}
static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t);
private:
struct ScopedSync
{
ScopedSync(Ext2Inode& inode)
: inode(inode)
, inode_info(inode.m_inode)
{ }
~ScopedSync()
{
if (memcmp(&inode.m_inode, &inode_info, sizeof(Ext2::Inode)) == 0)
return;
if (auto ret = inode.sync(); ret.is_error())
dwarnln("failed to sync inode: {}", ret.error());
}
Ext2Inode& inode;
Ext2::Inode inode_info;
};
private:
Ext2FS& m_fs;
Ext2::Inode m_inode;

View File

@@ -37,8 +37,6 @@ namespace Kernel
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
virtual dev_t dev() const override { return m_block_device->rdev(); };
BAN::ErrorOr<BAN::RefPtr<FATInode>> open_inode(BAN::RefPtr<FATInode> parent, const FAT::DirectoryEntry& entry, uint32_t cluster_index, uint32_t entry_index);
BAN::ErrorOr<void> inode_read_cluster(BAN::RefPtr<FATInode>, size_t index, BAN::ByteSpan buffer);
blksize_t inode_block_size(BAN::RefPtr<const FATInode>) const;

View File

@@ -44,11 +44,13 @@ namespace Kernel
//virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
//virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
//virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
//virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
FATInode(FATFS& fs, const FAT::DirectoryEntry& entry, ino_t ino, uint32_t block_count)

View File

@@ -26,8 +26,6 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<FileSystem>> from_block_device(BAN::RefPtr<BlockDevice>);
virtual BAN::RefPtr<Inode> root_inode() = 0;
virtual dev_t dev() const = 0;
};
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/LinkedList.h>
#include <BAN/RefPtr.h>
#include <BAN/String.h>
#include <BAN/StringView.h>
@@ -19,10 +20,9 @@
namespace Kernel
{
class FileSystem;
class FileBackedRegion;
class SharedFileData;
class FileSystem;
struct SharedFileData;
class Inode : public BAN::RefCounted<Inode>
{
@@ -85,6 +85,7 @@ namespace Kernel
virtual dev_t rdev() const = 0;
virtual bool is_device() const { return false; }
virtual bool is_epoll() const { return false; }
virtual bool is_pipe() const { return false; }
virtual bool is_tty() const { return false; }
@@ -96,6 +97,7 @@ namespace Kernel
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
BAN::ErrorOr<void> create_directory(BAN::StringView, mode_t, uid_t, gid_t);
BAN::ErrorOr<void> link_inode(BAN::StringView, BAN::RefPtr<Inode>);
BAN::ErrorOr<void> rename_inode(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView);
BAN::ErrorOr<void> unlink(BAN::StringView);
// Link API
@@ -107,9 +109,12 @@ namespace Kernel
BAN::ErrorOr<void> bind(const sockaddr* address, socklen_t address_len);
BAN::ErrorOr<void> connect(const sockaddr* address, socklen_t address_len);
BAN::ErrorOr<void> listen(int backlog);
BAN::ErrorOr<size_t> sendto(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len);
BAN::ErrorOr<size_t> recvfrom(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len);
BAN::ErrorOr<size_t> sendmsg(const msghdr& message, int flags);
BAN::ErrorOr<size_t> recvmsg(msghdr& message, int flags);
BAN::ErrorOr<void> getsockname(sockaddr* address, socklen_t* address_len);
BAN::ErrorOr<void> getpeername(sockaddr* address, socklen_t* address_len);
BAN::ErrorOr<void> getsockopt(int level, int option, void* value, socklen_t* value_len);
BAN::ErrorOr<void> setsockopt(int level, int option, const void* value, socklen_t value_len);
// General API
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
@@ -117,23 +122,33 @@ namespace Kernel
BAN::ErrorOr<void> truncate(size_t);
BAN::ErrorOr<void> chmod(mode_t);
BAN::ErrorOr<void> chown(uid_t, gid_t);
BAN::ErrorOr<void> utimens(const timespec[2]);
BAN::ErrorOr<void> fsync();
// Select/Non blocking API
bool can_read() const;
bool can_write() const;
bool has_error() const;
bool has_hungup() const;
BAN::ErrorOr<long> ioctl(int request, void* arg);
BAN::ErrorOr<void> add_epoll(class Epoll*);
void del_epoll(class Epoll*);
void epoll_notify(uint32_t event);
virtual void on_close(int status_flags) { (void)status_flags; }
virtual void on_clone(int status_flags) { (void)status_flags; }
protected:
// Directory API
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
// Link API
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
@@ -144,9 +159,12 @@ namespace Kernel
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> listen_impl(int) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
// General API
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
@@ -154,12 +172,14 @@ namespace Kernel
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> fsync_impl() = 0;
// Select/Non blocking API
virtual bool can_read_impl() const = 0;
virtual bool can_write_impl() const = 0;
virtual bool has_error_impl() const = 0;
virtual bool has_hungup_impl() const = 0;
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) { return BAN::Error::from_errno(ENOTSUP); }
@@ -168,9 +188,12 @@ namespace Kernel
private:
BAN::WeakPtr<SharedFileData> m_shared_region;
SpinLock m_epoll_lock;
BAN::LinkedList<class Epoll*> m_epolls;
friend class Epoll;
friend class FileBackedRegion;
friend class OpenFileDescriptorSet;
friend class SharedFileData;
friend struct SharedFileData;
friend class TTY;
};

View File

@@ -2,6 +2,7 @@
#include <BAN/Array.h>
#include <kernel/FS/Inode.h>
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/ThreadBlocker.h>
namespace Kernel
@@ -13,8 +14,9 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(const Credentials&);
virtual bool is_pipe() const override { return true; }
void clone_writing();
void close_writing();
void on_close(int status_flags) override;
void on_clone(int status_flags) override;
virtual ino_t ino() const override { return 0; } // FIXME
virtual Mode mode() const override { return { Mode::IFIFO | Mode::IRUSR | Mode::IWUSR }; }
@@ -37,9 +39,10 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; }
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
virtual bool can_read_impl() const override { return !m_buffer->empty(); }
virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_error_impl() const override { return m_reading_count == 0; }
virtual bool has_hungup_impl() const override { return m_writing_count == 0; }
private:
Pipe(const Credentials&);
@@ -52,11 +55,10 @@ namespace Kernel
timespec m_ctime {};
ThreadBlocker m_thread_blocker;
BAN::Array<uint8_t, PAGE_SIZE> m_buffer;
BAN::Atomic<size_t> m_buffer_size { 0 };
size_t m_buffer_tail { 0 };
BAN::UniqPtr<ByteRingBuffer> m_buffer;
BAN::Atomic<uint32_t> m_writing_count { 1 };
BAN::Atomic<uint32_t> m_reading_count { 1 };
};
}

View File

@@ -47,6 +47,7 @@ namespace Kernel
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
ProcROProcessInode(Process&, size_t (Process::*)(off_t, BAN::ByteSpan) const, TmpFileSystem&, const TmpInodeInfo&);
@@ -56,6 +57,31 @@ namespace Kernel
size_t (Process::*m_callback)(off_t, BAN::ByteSpan) const;
};
class ProcSymlinkProcessInode final : public TmpInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<ProcSymlinkProcessInode>> create_new(Process& process, BAN::ErrorOr<BAN::String> (Process::*callback)() const, TmpFileSystem&, mode_t);
~ProcSymlinkProcessInode() = default;
virtual uid_t uid() const override { return m_process.credentials().ruid(); }
virtual gid_t gid() const override { return m_process.credentials().rgid(); }
protected:
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
ProcSymlinkProcessInode(Process& process, BAN::ErrorOr<BAN::String> (Process::*)() const, TmpFileSystem&, const TmpInodeInfo&);
private:
Process& m_process;
BAN::ErrorOr<BAN::String> (Process::*m_callback)() const;
};
class ProcROInode final : public TmpInode
{
public:
@@ -72,6 +98,7 @@ namespace Kernel
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&);
@@ -80,4 +107,57 @@ namespace Kernel
size_t (*m_callback)(off_t, BAN::ByteSpan);
};
class ProcSymlinkInode final : public TmpInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> create_new(BAN::ErrorOr<BAN::String> (*)(void*), void (*)(void*), void* data, TmpFileSystem&, mode_t, uid_t, gid_t);
~ProcSymlinkInode();
protected:
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
ProcSymlinkInode(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem&, const TmpInodeInfo&);
private:
BAN::ErrorOr<BAN::String> (*m_callback)(void*);
void (*m_destructor)(void*);
void* m_data;
};
class ProcFDDirectoryInode final : public TmpInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<ProcFDDirectoryInode>> create_new(Process&, TmpFileSystem&, mode_t);
~ProcFDDirectoryInode() = default;
virtual uid_t uid() const override { return m_process.credentials().ruid(); }
virtual gid_t gid() const override { return m_process.credentials().rgid(); }
protected:
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override;
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override { return BAN::Error::from_errno(EPERM); }
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override { return BAN::Error::from_errno(EPERM); }
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override { return BAN::Error::from_errno(EPERM); }
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override { return BAN::Error::from_errno(EPERM); }
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override { return BAN::Error::from_errno(EPERM); }
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
ProcFDDirectoryInode(Process&, TmpFileSystem&, const TmpInodeInfo&);
private:
Process& m_process;
};
}

View File

@@ -51,8 +51,6 @@ namespace Kernel
: m_info(info)
{}
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan buffer) override { return recvfrom_impl(buffer, nullptr, nullptr); }
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return sendto_impl(buffer, nullptr, 0); }
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
private:

View File

@@ -28,7 +28,7 @@ namespace Kernel
// 1x singly indirect
// 1x doubly indirect
// 1x triply indirect
BAN::Array<paddr_t, 5> block;
BAN::Array<size_t, 5> block;
static constexpr size_t direct_block_count = 2;
#elif ARCH(i686)
uint32_t __padding;
@@ -36,8 +36,8 @@ namespace Kernel
// 1x singly indirect
// 1x doubly indirect
// 1x triply indirect
BAN::Array<paddr_t, 8> block;
static constexpr size_t direct_block_count = 5;
BAN::Array<size_t, 16> block;
static constexpr size_t direct_block_count = 13;
#else
#error
#endif

View File

@@ -58,7 +58,7 @@ namespace Kernel
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
virtual dev_t dev() const override { return m_rdev; }
dev_t rdev() const { return m_rdev; }
BAN::ErrorOr<BAN::RefPtr<TmpInode>> open_inode(ino_t ino);
@@ -118,16 +118,8 @@ namespace Kernel
private:
InodeLocation find_inode(ino_t ino);
paddr_t find_block(size_t index);
template<TmpFuncs::for_each_indirect_paddr_allocating_callback F>
BAN::ErrorOr<void> for_each_indirect_paddr_allocating(PageInfo page_info, F callback, size_t depth);
template<TmpFuncs::for_each_indirect_paddr_allocating_callback F>
BAN::ErrorOr<BAN::Iteration> for_each_indirect_paddr_allocating_internal(PageInfo page_info, F callback, size_t depth);
paddr_t find_indirect(PageInfo root, size_t index, size_t depth);
private:
const dev_t m_rdev;
@@ -146,14 +138,14 @@ namespace Kernel
static constexpr size_t max_data_pages =
(PAGE_SIZE / sizeof(PageInfo)) *
(PAGE_SIZE / sizeof(PageInfo)) *
(PAGE_SIZE / sizeof(PageInfo));
(PAGE_SIZE / sizeof(PageInfo) - 1);
// We store inodes in pages with double indirection.
// With 64-bit pointers we can store 512^2 pages of inodes
// which should be enough for now.
// In future this should be dynamically calculated based on maximum
// number of pages for this file system.
PageInfo m_inode_pages;
PageInfo m_inode_pages {};
static constexpr size_t first_inode = 1;
static constexpr size_t max_inodes =
(PAGE_SIZE / sizeof(PageInfo)) *

View File

@@ -47,14 +47,22 @@ namespace Kernel
protected:
TmpInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
void sync();
void free_all_blocks();
virtual BAN::ErrorOr<void> prepare_unlink() { return {}; };
void free_all_blocks();
void free_indirect_blocks(size_t block, uint32_t depth);
BAN::Optional<size_t> block_index(size_t data_block_index);
BAN::Optional<size_t> block_index_from_indirect(size_t block, size_t index, uint32_t depth);
BAN::ErrorOr<size_t> block_index_with_allocation(size_t data_block_index);
BAN::ErrorOr<size_t> block_index_from_indirect_with_allocation(size_t& block, size_t index, uint32_t depth);
protected:
TmpFileSystem& m_fs;
@@ -75,11 +83,11 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
TmpFileInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
@@ -97,11 +105,11 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); }
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); }
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); }
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
TmpSocketInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
@@ -115,14 +123,14 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<TmpSymlinkInode>> create_new(TmpFileSystem&, mode_t, uid_t, gid_t, BAN::StringView target);
~TmpSymlinkInode();
BAN::ErrorOr<void> set_link_target(BAN::StringView);
protected:
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
BAN::ErrorOr<BAN::String> link_target_impl() override;
BAN::ErrorOr<void> set_link_target_impl(BAN::StringView) override;
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
TmpSymlinkInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
@@ -148,16 +156,21 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override final;
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override final;
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override final;
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
template<TmpFuncs::for_each_valid_entry_callback F>
void for_each_valid_entry(F callback);
BAN::ErrorOr<void> unlink_inode(BAN::StringView, bool cleanup);
friend class TmpInode;
};

View File

@@ -0,0 +1,12 @@
#pragma once
#include <kernel/BootInfo.h>
#include <kernel/FS/FileSystem.h>
namespace Kernel
{
bool is_ustar_boot_module(const BootModule&);
BAN::ErrorOr<void> unpack_boot_module_into_filesystem(BAN::RefPtr<FileSystem>, const BootModule&);
}

View File

@@ -29,9 +29,6 @@ namespace Kernel
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_fs->root_inode(); }
// FIXME:
virtual dev_t dev() const override { return 0; }
BAN::ErrorOr<void> mount(const Credentials&, BAN::StringView, BAN::StringView);
BAN::ErrorOr<void> mount(const Credentials&, BAN::RefPtr<FileSystem>, BAN::StringView);
@@ -74,13 +71,13 @@ namespace Kernel
File root_file()
{
return File(root_inode(), "/"_sv);
return File { root_inode(), "/"_sv };
}
BAN::ErrorOr<File> file_from_relative_path(const File& parent, const Credentials&, BAN::StringView, int);
BAN::ErrorOr<File> file_from_absolute_path(const Credentials& credentials, BAN::StringView path, int flags)
BAN::ErrorOr<File> file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials&, BAN::StringView, int);
BAN::ErrorOr<File> file_from_absolute_path(BAN::RefPtr<Inode> root_inode, const Credentials& credentials, BAN::StringView path, int flags)
{
return file_from_relative_path(root_file(), credentials, path, flags);
return file_from_relative_path(root_inode, File { root_inode, "/"_sv }, credentials, path, flags);
}
private:

View File

@@ -129,7 +129,8 @@ namespace Kernel
}
#if ARCH(i686)
void set_tls(uintptr_t addr);
void set_fsbase(uintptr_t addr);
void set_gsbase(uintptr_t addr);
#endif
private:
@@ -150,11 +151,11 @@ namespace Kernel
private:
#if ARCH(x86_64)
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
static constexpr uint16_t m_tss_offset = 0x28;
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code (32 bit), user data, user code (64 bit), tss low, tss high
static constexpr uint16_t m_tss_offset = 0x30;
#elif ARCH(i686)
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, tls, tss
static constexpr uint16_t m_tss_offset = 0x38;
BAN::Array<SegmentDescriptor, 9> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, fsbase, gsbase, tss
static constexpr uint16_t m_tss_offset = 0x40;
#endif
TaskStateSegment m_tss;
const GDTR m_gdtr {

View File

@@ -18,10 +18,12 @@ namespace Kernel
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
constexpr uint8_t IRQ_MSI_BASE = 0x80;
constexpr uint8_t IRQ_MSI_END = 0xF0;
#if ARCH(i686)
constexpr uint8_t IRQ_SYSCALL = 0xF0;
constexpr uint8_t IRQ_YIELD = 0xF1;
constexpr uint8_t IRQ_IPI = 0xF2;
constexpr uint8_t IRQ_TIMER = 0xF3;
#endif
constexpr uint8_t IRQ_IPI = 0xF1;
constexpr uint8_t IRQ_TIMER = 0xF2;
#if ARCH(x86_64)
struct GateDescriptor
@@ -75,7 +77,7 @@ namespace Kernel
private:
IDT() = default;
void register_interrupt_handler(uint8_t index, void (*handler)());
void register_interrupt_handler(uint8_t index, void (*handler)(), uint8_t ist = 0);
void register_syscall_handler(uint8_t index, void (*handler)());
private:

View File

@@ -15,6 +15,7 @@ namespace Kernel
{
Mouse,
Keyboard,
Joystick,
};
public:
@@ -31,7 +32,7 @@ namespace Kernel
bool can_read_impl() const override { SpinLockGuard _(m_event_lock); return m_event_count > 0; }
bool can_write_impl() const override { return false; }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
private:
BAN::ErrorOr<size_t> read_non_block(BAN::ByteSpan);
@@ -64,7 +65,7 @@ namespace Kernel
public:
static BAN::ErrorOr<BAN::RefPtr<KeyboardDevice>> create(mode_t mode, uid_t uid, gid_t gid);
void notify() { m_thread_blocker.unblock(); }
void notify();
private:
KeyboardDevice(mode_t mode, uid_t uid, gid_t gid);
@@ -73,6 +74,7 @@ namespace Kernel
bool can_read_impl() const override;
bool can_write_impl() const override { return false; }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
BAN::StringView name() const final override { return m_name; }
dev_t rdev() const final override { return m_rdev; }
@@ -90,7 +92,7 @@ namespace Kernel
public:
static BAN::ErrorOr<BAN::RefPtr<MouseDevice>> create(mode_t mode, uid_t uid, gid_t gid);
void notify() { m_thread_blocker.unblock(); }
void notify();
private:
MouseDevice(mode_t mode, uid_t uid, gid_t gid);
@@ -99,6 +101,7 @@ namespace Kernel
bool can_read_impl() const override;
bool can_write_impl() const override { return false; }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
BAN::StringView name() const final override { return m_name; }
dev_t rdev() const final override { return m_rdev; }

View File

@@ -14,6 +14,15 @@ namespace Kernel::Input
class PS2Controller
{
public:
enum class DeviceType
{
None,
Unknown,
Keyboard,
Mouse,
};
public:
static BAN::ErrorOr<void> initialize(uint8_t scancode_set);
static PS2Controller& get();
@@ -24,10 +33,14 @@ namespace Kernel::Input
// Returns true, if byte is used as command, if returns false, byte is meant to device
bool handle_command_byte(PS2Device*, uint8_t);
uint8_t data_port() const { return m_data_port; }
private:
PS2Controller() = default;
BAN::ErrorOr<void> initialize_impl(uint8_t scancode_set);
BAN::ErrorOr<void> initialize_device(uint8_t, uint8_t scancode_set);
BAN::ErrorOr<DeviceType> identify_device(uint8_t);
void device_initialize_task(void*);
BAN::ErrorOr<uint8_t> read_byte();
BAN::ErrorOr<void> send_byte(uint16_t port, uint8_t byte);
@@ -59,6 +72,9 @@ namespace Kernel::Input
};
private:
uint16_t m_command_port { PS2::IOPort::COMMAND };
uint16_t m_data_port { PS2::IOPort::DATA };
BAN::RefPtr<PS2Device> m_devices[2];
Mutex m_mutex;

View File

@@ -22,6 +22,7 @@ namespace Kernel::Input
protected:
PS2Device(PS2Controller&, InputDevice::Type type);
virtual ~PS2Device();
protected:
PS2Controller& m_controller;

View File

@@ -27,7 +27,6 @@ namespace Kernel
uintptr_t r10;
uintptr_t r9;
uintptr_t r8;
uintptr_t rdi;
uintptr_t rsi;
uintptr_t rbp;
@@ -36,6 +35,18 @@ namespace Kernel
uintptr_t rcx;
uintptr_t rax;
};
struct YieldRegisters
{
uintptr_t r15;
uintptr_t r14;
uintptr_t r13;
uintptr_t r12;
uintptr_t rbp;
uintptr_t rbx;
uintptr_t ret;
uintptr_t sp;
uintptr_t ip;
};
#elif ARCH(i686)
struct InterruptRegisters
{
@@ -48,6 +59,16 @@ namespace Kernel
uintptr_t ecx;
uintptr_t eax;
};
struct YieldRegisters
{
uintptr_t ebp;
uintptr_t edi;
uintptr_t esi;
uintptr_t ebx;
uintptr_t ret;
uintptr_t sp;
uintptr_t ip;
};
#endif
}

View File

@@ -29,30 +29,4 @@ namespace Kernel
Lock& m_lock;
};
template<typename Lock>
class LockFreeGuard
{
BAN_NON_COPYABLE(LockFreeGuard);
BAN_NON_MOVABLE(LockFreeGuard);
public:
LockFreeGuard(Lock& lock)
: m_lock(lock)
, m_depth(lock.lock_depth())
{
for (uint32_t i = 0; i < m_depth; i++)
m_lock.unlock();
}
~LockFreeGuard()
{
for (uint32_t i = 0; i < m_depth; i++)
m_lock.lock();
}
private:
Lock& m_lock;
const uint32_t m_depth;
};
}

View File

@@ -9,7 +9,19 @@
namespace Kernel
{
class Mutex
class BaseMutex
{
public:
virtual void lock() = 0;
virtual bool try_lock() = 0;
virtual void unlock() = 0;
virtual pid_t locker() const = 0;
virtual bool is_locked() const = 0;
virtual uint32_t lock_depth() const = 0;
};
class Mutex : public BaseMutex
{
BAN_NON_COPYABLE(Mutex);
BAN_NON_MOVABLE(Mutex);
@@ -17,13 +29,14 @@ namespace Kernel
public:
Mutex() = default;
void lock()
void lock() override
{
const auto tid = Thread::current_tid();
if (tid == m_locker)
ASSERT(m_lock_depth > 0);
else
{
ASSERT(!tid || !Thread::current().has_spinlock());
pid_t expected = -1;
while (!m_locker.compare_exchange(expected, tid))
{
@@ -37,7 +50,7 @@ namespace Kernel
m_lock_depth++;
}
bool try_lock()
bool try_lock() override
{
const auto tid = Thread::current_tid();
if (tid == m_locker)
@@ -55,7 +68,7 @@ namespace Kernel
return true;
}
void unlock()
void unlock() override
{
const auto tid = Thread::current_tid();
ASSERT(m_locker == tid);
@@ -68,16 +81,16 @@ namespace Kernel
}
}
pid_t locker() const { return m_locker; }
bool is_locked() const { return m_locker != -1; }
uint32_t lock_depth() const { return m_lock_depth; }
pid_t locker() const override { return m_locker; }
bool is_locked() const override { return m_locker != -1; }
uint32_t lock_depth() const override { return m_lock_depth; }
private:
BAN::Atomic<pid_t> m_locker { -1 };
uint32_t m_lock_depth { 0 };
};
class PriorityMutex
class PriorityMutex : public BaseMutex
{
BAN_NON_COPYABLE(PriorityMutex);
BAN_NON_MOVABLE(PriorityMutex);
@@ -85,13 +98,15 @@ namespace Kernel
public:
PriorityMutex() = default;
void lock()
void lock() override
{
const auto tid = Thread::current_tid();
if (tid == m_locker)
ASSERT(m_lock_depth > 0);
else
{
ASSERT(!tid || !Thread::current().has_spinlock());
bool has_priority = tid ? !Thread::current().is_userspace() : true;
if (has_priority)
m_queue_length++;
@@ -108,9 +123,10 @@ namespace Kernel
m_lock_depth++;
}
bool try_lock()
bool try_lock() override
{
const auto tid = Thread::current_tid();
if (tid == m_locker)
ASSERT(m_lock_depth > 0);
else
@@ -129,7 +145,7 @@ namespace Kernel
return true;
}
void unlock()
void unlock() override
{
const auto tid = Thread::current_tid();
ASSERT(m_locker == tid);
@@ -145,9 +161,9 @@ namespace Kernel
}
}
pid_t locker() const { return m_locker; }
bool is_locked() const { return m_locker != -1; }
uint32_t lock_depth() const { return m_lock_depth; }
pid_t locker() const override { return m_locker; }
bool is_locked() const override { return m_locker != -1; }
uint32_t lock_depth() const override { return m_lock_depth; }
private:
BAN::Atomic<pid_t> m_locker { -1 };

View File

@@ -0,0 +1,97 @@
#pragma once
#include <kernel/Lock/Mutex.h>
#include <kernel/Lock/LockGuard.h>
namespace Kernel
{
class RWLock
{
BAN_NON_COPYABLE(RWLock);
BAN_NON_MOVABLE(RWLock);
public:
RWLock() = default;
void rd_lock()
{
LockGuard _(m_mutex);
while (m_writers_waiting > 0 || m_writer_active)
m_thread_blocker.block_indefinite(&m_mutex);
m_readers_active++;
}
void rd_unlock()
{
LockGuard _(m_mutex);
if (--m_readers_active == 0)
m_thread_blocker.unblock();
}
void wr_lock()
{
LockGuard _(m_mutex);
m_writers_waiting++;
while (m_readers_active > 0 || m_writer_active)
m_thread_blocker.block_indefinite(&m_mutex);
m_writers_waiting--;
m_writer_active = true;
}
void wr_unlock()
{
LockGuard _(m_mutex);
m_writer_active = false;
m_thread_blocker.unblock();
}
private:
Mutex m_mutex;
ThreadBlocker m_thread_blocker;
uint32_t m_readers_active { 0 };
uint32_t m_writers_waiting { 0 };
bool m_writer_active { false };
};
class RWLockRDGuard
{
BAN_NON_COPYABLE(RWLockRDGuard);
BAN_NON_MOVABLE(RWLockRDGuard);
public:
RWLockRDGuard(RWLock& lock)
: m_lock(lock)
{
m_lock.rd_lock();
}
~RWLockRDGuard()
{
m_lock.rd_unlock();
}
private:
RWLock& m_lock;
};
class RWLockWRGuard
{
BAN_NON_COPYABLE(RWLockWRGuard);
BAN_NON_MOVABLE(RWLockWRGuard);
public:
RWLockWRGuard(RWLock& lock)
: m_lock(lock)
{
m_lock.wr_lock();
}
~RWLockWRGuard()
{
m_lock.wr_unlock();
}
private:
RWLock& m_lock;
};
}

View File

@@ -18,42 +18,13 @@ namespace Kernel
public:
SpinLock() = default;
InterruptState lock()
{
auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
InterruptState lock();
auto id = Processor::current_id().as_u32();
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
bool try_lock_interrupts_disabled();
auto expected = PROCESSOR_NONE.as_u32();
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire))
{
Processor::pause();
expected = PROCESSOR_NONE.as_u32();
}
void unlock(InterruptState state);
return state;
}
bool try_lock_interrupts_disabled()
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
auto id = Processor::current_id().as_u32();
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
auto expected = PROCESSOR_NONE.as_u32();
return m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire);
}
void unlock(InterruptState state)
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
ASSERT(current_processor_has_lock());
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
Processor::set_interrupt_state(state);
}
uint32_t lock_depth() const { return current_processor_has_lock(); }
bool current_processor_has_lock() const
{
@@ -72,36 +43,13 @@ namespace Kernel
public:
RecursiveSpinLock() = default;
InterruptState lock()
{
auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
InterruptState lock();
auto id = Processor::current_id().as_u32();
bool try_lock_interrupts_disabled();
ProcessorID::value_type expected = PROCESSOR_NONE.as_u32();
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acq_rel))
{
if (expected == id)
break;
Processor::pause();
expected = PROCESSOR_NONE.as_u32();
}
void unlock(InterruptState state);
m_lock_depth++;
return state;
}
void unlock(InterruptState state)
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
ASSERT(current_processor_has_lock());
ASSERT(m_lock_depth > 0);
if (--m_lock_depth == 0)
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
Processor::set_interrupt_state(state);
}
uint32_t lock_depth() const { return m_lock_depth; }
bool current_processor_has_lock() const
{
@@ -113,6 +61,9 @@ namespace Kernel
uint32_t m_lock_depth { 0 };
};
template<typename Lock>
class SpinLockGuardAsMutex;
template<typename Lock>
class SpinLockGuard
{
@@ -134,6 +85,7 @@ namespace Kernel
private:
Lock& m_lock;
InterruptState m_state;
friend class SpinLockGuardAsMutex<Lock>;
};
}

View File

@@ -0,0 +1,64 @@
#pragma once
#include <kernel/Lock/SpinLock.h>
#include <kernel/Lock/Mutex.h>
namespace Kernel
{
// FIXME: These classes are HACKS to allow passing spinlock
// to unblock functions. Write a better API that either
// allows passing spinlocks or do something cleaner that
// whatever shit this is
template<typename Lock>
class SpinLockAsMutex : public BaseMutex
{
public:
SpinLockAsMutex(Lock& lock, InterruptState state)
: m_lock(lock)
, m_lock_depth(lock.lock_depth())
, m_state(state)
, m_locker(Thread::current_tid())
{
ASSERT(m_lock.current_processor_has_lock());
}
void lock() override
{
m_lock.lock();
m_lock_depth++;
}
bool try_lock() override
{
lock();
return true;
}
void unlock() override
{
m_lock.unlock(--m_lock_depth ? InterruptState::Disabled : m_state);
}
pid_t locker() const override { return is_locked() ? m_locker : -1; }
bool is_locked() const override { return m_lock_depth; }
uint32_t lock_depth() const override { return m_lock_depth; }
private:
SpinLock& m_lock;
uint32_t m_lock_depth { 0 };
InterruptState m_state;
const pid_t m_locker;
};
template<typename Lock>
class SpinLockGuardAsMutex : public SpinLockAsMutex<Lock>
{
public:
SpinLockGuardAsMutex(SpinLockGuard<Lock>& guard)
: SpinLockAsMutex<Lock>(guard.m_lock, guard.m_state)
{}
};
}

View File

@@ -0,0 +1,76 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/UniqPtr.h>
#include <BAN/Vector.h>
#include <kernel/Memory/Types.h>
namespace Kernel
{
class ByteRingBuffer
{
public:
static BAN::ErrorOr<BAN::UniqPtr<ByteRingBuffer>> create(size_t size);
~ByteRingBuffer();
void push(BAN::ConstByteSpan data)
{
ASSERT(data.size() + m_size <= m_capacity);
uint8_t* buffer_head = reinterpret_cast<uint8_t*>(m_vaddr) + (m_tail + m_size) % m_capacity;
memcpy(buffer_head, data.data(), data.size());
m_size += data.size();
}
void pop(size_t size)
{
ASSERT(size <= m_size);
m_tail = (m_tail + size) % m_capacity;
m_size -= size;
}
void pop_back(size_t size)
{
ASSERT(size <= m_size);
m_size -= size;
}
BAN::ConstByteSpan get_data() const
{
const uint8_t* base = reinterpret_cast<const uint8_t*>(m_vaddr);
return { base + m_tail, m_size };
}
uint8_t front() const
{
ASSERT(!empty());
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail];
}
uint8_t back() const
{
ASSERT(!empty());
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail + m_size];
}
bool empty() const { return m_size == 0; }
bool full() const { return m_size == m_capacity; }
size_t free() const { return m_capacity - m_size; }
size_t size() const { return m_size; }
size_t capacity() const { return m_capacity; }
private:
ByteRingBuffer(size_t capacity)
: m_capacity(capacity)
{ }
private:
size_t m_size { 0 };
size_t m_tail { 0 };
const size_t m_capacity;
vaddr_t m_vaddr { 0 };
};
}

View File

@@ -27,18 +27,19 @@ namespace Kernel
BAN_NON_MOVABLE(FileBackedRegion);
public:
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t);
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t, int status_flags);
~FileBackedRegion();
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
protected:
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
private:
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type flags, PageTable::flags_t page_flags);
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type type, PageTable::flags_t flags, int status_flags);
private:
BAN::RefPtr<Inode> m_inode;

View File

@@ -11,22 +11,23 @@ namespace Kernel
BAN_NON_MOVABLE(MemoryBackedRegion);
public:
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t);
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t, int status_flags);
~MemoryBackedRegion();
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
// Copy data from buffer into this region
// This can fail if no memory is mapped and no free memory was available
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
protected:
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
private:
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t);
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t, int status_flags);
};
}

View File

@@ -1,10 +1,10 @@
#pragma once
#include <BAN/UniqPtr.h>
#include <kernel/Lock/Mutex.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/Memory/Types.h>
#include <stddef.h>
#include <kernel/ThreadBlocker.h>
namespace Kernel
{
@@ -33,15 +33,25 @@ namespace Kernel
bool contains(vaddr_t address) const;
bool contains_fully(vaddr_t address, size_t size) const;
bool overlaps(vaddr_t address, size_t size) const;
bool is_contained_by(vaddr_t address, size_t size) const;
bool writable() const { return m_flags & PageTable::Flags::ReadWrite; }
size_t size() const { return m_size; }
vaddr_t vaddr() const { return m_vaddr; }
int status_flags() const { return m_status_flags; }
Type type() const { return m_type; }
PageTable::flags_t flags() const { return m_flags; }
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
size_t physical_page_count() const { return m_physical_page_count; }
void pin();
void unpin();
void wait_not_pinned();
BAN::ErrorOr<void> mprotect(PageTable::flags_t);
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
// Returns error if no memory was available
@@ -50,20 +60,26 @@ namespace Kernel
BAN::ErrorOr<bool> allocate_page_containing(vaddr_t address, bool wants_write);
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) = 0;
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) = 0;
protected:
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags);
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags, int status_flags);
BAN::ErrorOr<void> initialize(AddressRange);
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t address, bool wants_write) = 0;
protected:
PageTable& m_page_table;
const size_t m_size;
size_t m_size { 0 };
const Type m_type;
const PageTable::flags_t m_flags;
PageTable::flags_t m_flags;
const int m_status_flags;
vaddr_t m_vaddr { 0 };
size_t m_physical_page_count { 0 };
Mutex m_pinned_mutex;
BAN::Atomic<size_t> m_pinned_count { 0 };
ThreadBlocker m_pinned_blocker;
};
}

View File

@@ -112,7 +112,7 @@ namespace Kernel
bool is_page_free(vaddr_t) const;
bool is_range_free(vaddr_t, size_t bytes) const;
bool reserve_page(vaddr_t, bool only_free = true);
bool reserve_page(vaddr_t, bool only_free = true, bool send_smp_message = true);
bool reserve_range(vaddr_t, size_t bytes, bool only_free = true);
vaddr_t reserve_free_page(vaddr_t first_address, vaddr_t last_address = UINTPTR_MAX);
@@ -133,7 +133,7 @@ namespace Kernel
void map_kernel_memory();
void prepare_fast_page();
static void invalidate(vaddr_t, bool send_smp_message);
void invalidate(vaddr_t, bool send_smp_message);
static void map_fast_page(paddr_t);
static void unmap_fast_page();

View File

@@ -6,6 +6,8 @@
#include <kernel/Lock/SpinLock.h>
#include <kernel/Memory/MemoryRegion.h>
#include <fcntl.h>
namespace Kernel
{
@@ -55,15 +57,17 @@ namespace Kernel
public:
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
protected:
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
private:
SharedMemoryObject(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table)
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags)
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags, O_EXEC | O_RDWR)
, m_object(object)
{ }

View File

@@ -4,7 +4,7 @@
#if ARCH(x86_64)
#define KERNEL_OFFSET 0xFFFFFFFF80000000
#define USERSPACE_END 0xFFFF800000000000
#define USERSPACE_END 0x800000000000
#elif ARCH(i686)
#define KERNEL_OFFSET 0xC0000000
#define USERSPACE_END 0xC0000000
@@ -12,6 +12,7 @@
#error
#endif
#undef PAGE_SIZE
#define PAGE_SIZE ((uintptr_t)4096)
#define PAGE_SIZE_SHIFT 12
#define PAGE_ADDR_MASK (~(uintptr_t)0xFFF)

View File

@@ -15,21 +15,21 @@ namespace Kernel
public:
// Create virtual range to fixed virtual address
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr(PageTable&, vaddr_t, size_t, PageTable::flags_t flags, bool preallocate_pages);
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr(PageTable&, vaddr_t, size_t, PageTable::flags_t flags, bool preallocate_pages, bool add_guard_pages);
// Create virtual range to virtual address range
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr_range(PageTable&, vaddr_t vaddr_start, vaddr_t vaddr_end, size_t, PageTable::flags_t flags, bool preallocate_pages);
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr_range(PageTable&, vaddr_t vaddr_start, vaddr_t vaddr_end, size_t, PageTable::flags_t flags, bool preallocate_pages, bool add_guard_pages);
~VirtualRange();
BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> clone(PageTable&);
vaddr_t vaddr() const { return m_vaddr; }
size_t size() const { return m_size; }
vaddr_t vaddr() const { return m_vaddr + (m_has_guard_pages ? PAGE_SIZE : 0); }
size_t size() const { return m_size - (m_has_guard_pages ? 2 * PAGE_SIZE : 0); }
PageTable::flags_t flags() const { return m_flags; }
paddr_t paddr_of(vaddr_t vaddr) const
{
ASSERT(vaddr % PAGE_SIZE == 0);
const size_t index = (vaddr - m_vaddr) / PAGE_SIZE;
const size_t index = (vaddr - this->vaddr()) / PAGE_SIZE;
ASSERT(index < m_paddrs.size());
const paddr_t paddr = m_paddrs[index];
ASSERT(paddr);
@@ -38,15 +38,16 @@ namespace Kernel
bool contains(vaddr_t address) const { return vaddr() <= address && address < vaddr() + size(); }
BAN::ErrorOr<void> allocate_page_for_demand_paging(vaddr_t address);
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t address);
private:
VirtualRange(PageTable&, bool preallocated, vaddr_t, size_t, PageTable::flags_t);
VirtualRange(PageTable&, bool preallocated, bool has_guard_pages, vaddr_t, size_t, PageTable::flags_t);
BAN::ErrorOr<void> initialize();
private:
PageTable& m_page_table;
const bool m_preallocated;
const bool m_has_guard_pages;
const vaddr_t m_vaddr;
const size_t m_size;
const PageTable::flags_t m_flags;

Some files were not shown because too many files have changed in this diff Show More