Compare commits
3
Commits
main
..
f429e8c7bb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f429e8c7bb | ||
|
|
cba2e8cfef | ||
|
|
3ad67614aa |
@@ -98,8 +98,7 @@ namespace BAN
|
||||
|
||||
struct EntryHash
|
||||
{
|
||||
template<detail::HashMapFindable<Key, HASH, COMP> U>
|
||||
constexpr bool operator()(const U& a)
|
||||
constexpr bool operator()(const Key& a)
|
||||
{
|
||||
return HASH()(a);
|
||||
}
|
||||
@@ -111,8 +110,7 @@ namespace BAN
|
||||
|
||||
struct EntryComp
|
||||
{
|
||||
template<detail::HashMapFindable<Key, HASH, COMP> U>
|
||||
constexpr bool operator()(const Entry& a, const U& b)
|
||||
constexpr bool operator()(const Entry& a, const Key& b)
|
||||
{
|
||||
return COMP()(a.key, b);
|
||||
}
|
||||
|
||||
+36
-44
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <BAN/Limits.h>
|
||||
#include <BAN/Numbers.h>
|
||||
#include <BAN/Swap.h>
|
||||
#include <BAN/Traits.h>
|
||||
|
||||
#include <float.h>
|
||||
@@ -82,37 +81,6 @@ namespace BAN::Math
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
template<unsigned_integral T>
|
||||
requires is_same_v<T, unsigned int> || is_same_v<T, unsigned long> || is_same_v<T, unsigned long long>
|
||||
inline constexpr int clz(T x)
|
||||
{
|
||||
if constexpr (is_same_v<T, unsigned int>)
|
||||
return __builtin_clz(x);
|
||||
if constexpr (is_same_v<T, unsigned long>)
|
||||
return __builtin_clzl(x);
|
||||
return __builtin_clzll(x);
|
||||
}
|
||||
|
||||
template<unsigned_integral T> requires(sizeof(T) <= sizeof(unsigned long long))
|
||||
inline constexpr int ctz(T x)
|
||||
{
|
||||
if constexpr (sizeof(T) <= sizeof(unsigned int))
|
||||
return __builtin_ctz(x);
|
||||
if constexpr (sizeof(T) <= sizeof(unsigned long))
|
||||
return __builtin_ctzl(x);
|
||||
return __builtin_ctzll(x);
|
||||
}
|
||||
|
||||
template<unsigned_integral T> requires(sizeof(T) <= sizeof(unsigned long long))
|
||||
inline constexpr int popcount(T x)
|
||||
{
|
||||
if constexpr (sizeof(T) <= sizeof(unsigned int))
|
||||
return __builtin_popcount(x);
|
||||
if constexpr (sizeof(T) <= sizeof(unsigned long))
|
||||
return __builtin_popcountl(x);
|
||||
return __builtin_popcountll(x);
|
||||
}
|
||||
|
||||
template<integral T>
|
||||
__attribute__((always_inline))
|
||||
inline constexpr bool will_multiplication_overflow(T a, T b)
|
||||
@@ -133,7 +101,11 @@ namespace BAN::Math
|
||||
requires is_same_v<T, unsigned int> || is_same_v<T, unsigned long> || is_same_v<T, unsigned long long>
|
||||
inline constexpr T ilog2(T x)
|
||||
{
|
||||
return sizeof(T) * 8 - clz(x) - 1;
|
||||
if constexpr(is_same_v<T, unsigned int>)
|
||||
return sizeof(T) * 8 - __builtin_clz(x) - 1;
|
||||
if constexpr(is_same_v<T, unsigned long>)
|
||||
return sizeof(T) * 8 - __builtin_clzl(x) - 1;
|
||||
return sizeof(T) * 8 - __builtin_clzll(x) - 1;
|
||||
}
|
||||
|
||||
// This is ugly but my clangd does not like including
|
||||
@@ -336,6 +308,36 @@ namespace BAN::Math
|
||||
return exp2<T>(y * log2<T>(x));
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
inline constexpr T scalbn(T x, int n)
|
||||
{
|
||||
asm("fscale" : "+t"(x) : "u"(static_cast<T>(n)));
|
||||
return x;
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
inline constexpr T ldexp(T x, int y)
|
||||
{
|
||||
const bool exp_sign = y < 0;
|
||||
if (exp_sign)
|
||||
y = -y;
|
||||
|
||||
T exp = (T)1.0;
|
||||
T mult = (T)2.0;
|
||||
while (y)
|
||||
{
|
||||
if (y & 1)
|
||||
exp *= mult;
|
||||
mult *= mult;
|
||||
y >>= 1;
|
||||
}
|
||||
|
||||
if (exp_sign)
|
||||
exp = (T)1.0 / exp;
|
||||
|
||||
return x * exp;
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
inline constexpr T sqrt(T x)
|
||||
{
|
||||
@@ -468,17 +470,7 @@ namespace BAN::Math
|
||||
template<floating_point T>
|
||||
inline constexpr T hypot(T x, T y)
|
||||
{
|
||||
x = abs(x);
|
||||
y = abs(y);
|
||||
|
||||
if (x < y)
|
||||
swap(x, y);
|
||||
|
||||
if (y == (T)0.0)
|
||||
return x;
|
||||
|
||||
const T r = y / x;
|
||||
return x * sqrt<T>((T)1.0 + r * r);
|
||||
return sqrt<T>(x * x + y * y);
|
||||
}
|
||||
|
||||
#ifdef BAN_MATH_POP_OPTIONS
|
||||
|
||||
+12
-36
@@ -67,20 +67,11 @@ namespace BAN::sort
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void quick_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
while (distance(begin, end) > 1)
|
||||
{
|
||||
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||
if (distance(begin, lt) < distance(gt, end))
|
||||
{
|
||||
quick_sort(begin, lt);
|
||||
begin = gt;
|
||||
}
|
||||
else
|
||||
{
|
||||
quick_sort(gt, end);
|
||||
end = lt;
|
||||
}
|
||||
}
|
||||
if (distance(begin, end) <= 1)
|
||||
return;
|
||||
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||
quick_sort(begin, lt, comp);
|
||||
quick_sort(gt, end, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
@@ -111,28 +102,13 @@ namespace BAN::sort
|
||||
template<typename It, typename Comp>
|
||||
void intro_sort_impl(It begin, It end, size_t max_depth, Comp comp)
|
||||
{
|
||||
for (size_t i = 0; i < max_depth; i++)
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
return;
|
||||
if (len <= 16)
|
||||
return insertion_sort(begin, end, comp);
|
||||
|
||||
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||
if (distance(begin, lt) < distance(gt, end))
|
||||
{
|
||||
intro_sort_impl(begin, lt, max_depth - 1, comp);
|
||||
begin = gt;
|
||||
}
|
||||
else
|
||||
{
|
||||
intro_sort_impl(gt, end, max_depth - 1, comp);
|
||||
end = lt;
|
||||
}
|
||||
}
|
||||
|
||||
heap_sort(begin, end, comp);
|
||||
if (distance(begin, end) <= 16)
|
||||
return insertion_sort(begin, end, comp);
|
||||
if (max_depth == 0)
|
||||
return heap_sort(begin, end, comp);
|
||||
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||
intro_sort_impl(begin, lt, max_depth - 1, comp);
|
||||
intro_sort_impl(gt, end, max_depth - 1, comp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -100,22 +100,3 @@ namespace BAN
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <BAN/Formatter.h>
|
||||
|
||||
namespace BAN::Formatter
|
||||
{
|
||||
|
||||
template<typename F, typename T>
|
||||
void print_argument(F putc, const Span<T>& span, const ValueFormat& format)
|
||||
{
|
||||
putc('[');
|
||||
for (typename Span<T>::size_type i = 0; i < span.size(); i++)
|
||||
{
|
||||
if (i != 0) putc(',');
|
||||
print_argument(putc, span[i], format);
|
||||
}
|
||||
putc(']');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,12 +27,6 @@ set(BUILD_SHARED_LIBS True)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
find_program(CCACHE_PROGRAM "ccache")
|
||||
if (CCACHE_PROGRAM)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
|
||||
endif()
|
||||
|
||||
# include headers of ${library} to ${target}
|
||||
function(banan_include_headers target library)
|
||||
target_include_directories(${target} PUBLIC $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
|
||||
|
||||
@@ -9,7 +9,7 @@ This is my hobby operating system written in C++. Currently supports x86\_64 and
|
||||
|
||||
You can find a live demo [here](https://bananymous.com/banan-os)
|
||||
|
||||

|
||||
If you want to try out DOOM, you should first enter the GUI environment using the `start-gui` command. Then you can run `doom` in the GUI terminal.
|
||||
|
||||
### Features
|
||||
|
||||
@@ -18,8 +18,6 @@ You can find a live demo [here](https://bananymous.com/banan-os)
|
||||
- [x] SMP (multiprocessing)
|
||||
- [x] Linear framebuffer (VESA and GOP)
|
||||
- [x] Network stack
|
||||
- [x] USB stack
|
||||
- [x] Audio support
|
||||
- [x] ELF executable loading
|
||||
- [x] AML interpreter (partial)
|
||||
- [x] Basic graphical environment
|
||||
@@ -29,14 +27,16 @@ You can find a live demo [here](https://bananymous.com/banan-os)
|
||||
- [ ] Some nice apps
|
||||
- [x] ELF dynamic linking
|
||||
- [x] copy-on-write memory
|
||||
- [x] file mappings
|
||||
- [ ] anonymous mappings
|
||||
|
||||
#### Drivers
|
||||
- [x] NVMe disks
|
||||
- [x] ATA (IDE, SATA) disks
|
||||
- [x] E1000 and E1000E NICs
|
||||
- [x] RTL8111/8168/8211/8411 NICs
|
||||
- [x] AC97 and iHDA audio cards
|
||||
- [x] PS2 keyboard and mouse
|
||||
- [x] PS2 keyboard (all scancode sets)
|
||||
- [x] PS2 mouse
|
||||
- [x] USB
|
||||
- [x] xHCI
|
||||
- [ ] EHCI
|
||||
@@ -46,8 +46,7 @@ You can find a live demo [here](https://bananymous.com/banan-os)
|
||||
- [x] Mouse
|
||||
- [x] Mass storage
|
||||
- [x] Hubs
|
||||
- [ ] Network
|
||||
- [ ] Audio
|
||||
- [ ] ...
|
||||
- [ ] virtio devices (network, storage)
|
||||
|
||||
#### Network
|
||||
@@ -55,7 +54,7 @@ You can find a live demo [here](https://bananymous.com/banan-os)
|
||||
- [x] ICMP
|
||||
- [x] IPv4
|
||||
- [x] UDP
|
||||
- [x] TCP
|
||||
- [x] TCP (partial and buggy)
|
||||
- [x] Unix domain sockets
|
||||
- [ ] SSL
|
||||
|
||||
@@ -66,6 +65,7 @@ You can find a live demo [here](https://bananymous.com/banan-os)
|
||||
- [x] Dev
|
||||
- [x] Ram
|
||||
- [x] Proc
|
||||
- [ ] Sys
|
||||
- [ ] 9P
|
||||
|
||||
#### Bootloader support
|
||||
@@ -73,6 +73,8 @@ You can find a live demo [here](https://bananymous.com/banan-os)
|
||||
- [x] Custom BIOS bootloader
|
||||
- [ ] Custom UEFI bootloader
|
||||
|
||||

|
||||
|
||||
## Code structure
|
||||
|
||||
Each major component and library has its own subdirectory (kernel, userspace, libc, ...). Each directory contains directory *include*, which has **all** of the header files of the component. Every header is included by its absolute path.
|
||||
@@ -116,29 +118,15 @@ 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 BANAN\_INITRD is set to a value larger than 1, initrd will be gzip compressed.
|
||||
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
|
||||
```
|
||||
|
||||
To test on real hardware, I have a script to generate a compressed ISO. The ISO can be copied directly to an USB drive with for example `dd`. The file is created at build/banan-os.iso and can be generated with
|
||||
```sh
|
||||
./bos iso
|
||||
```
|
||||
|
||||
I have also created shell completion script for zsh. You can either copy the file in _script/shell-completion/zsh/\_bos_ to _/usr/share/zsh/site-functions/_ or add the _script/shell-completion/zsh_ to your fpath in _.zshrc_.
|
||||
|
||||
### Package Manager
|
||||
|
||||
banan-os uses xbps as its package manager for ports. All upstream ports are packaged into xbps packages hosted on a [repository on my server](https://packages.bananymous.com/banan-os). You can manage sysroot's xbps packages with `./bos` wrapper. You can use `xbps-install`, `xbps-remove` and `xbps-query` with repository and sysroot set to the correct values. For example to install xbps that can be used inside banan-os you can use
|
||||
```sh
|
||||
./bos xbps-install -S xbps
|
||||
```
|
||||
For xbps usage see [their documentation](https://docs.voidlinux.org/xbps/index.html).
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
As the upstream is hosted on my server https://git.bananymous.com/Bananymous/banan-os, merging contributions is not as trivial as it would be on GitHub. You can still send PRs in GitHub in which case I should be able to download the diff and apply it manually. If you want, I can also provide you an account to my git server. In this case please contact me ([email](mailto:[email protected]), [discord](https://discord.gg/ehjGySwYdK)).
|
||||
|
||||
Binary file not shown.
@@ -35,13 +35,13 @@ read_user_command_line:
|
||||
cmpb $'\n', %al
|
||||
je .read_user_command_line_done
|
||||
|
||||
movb %al, %bl
|
||||
pushw %ax
|
||||
|
||||
call isprint
|
||||
testb %al, %al
|
||||
jz .read_user_command_line_loop
|
||||
|
||||
movb %bl, %al
|
||||
popw %ax
|
||||
|
||||
# put byte to buffer
|
||||
movb %al, (%di)
|
||||
|
||||
@@ -108,11 +108,9 @@ vesa_find_video_mode:
|
||||
cmpb $0x4F, %al; jne .vesa_unsupported
|
||||
cmpb $0x00, %ah; jne .vesa_error
|
||||
|
||||
# check whether in graphics mode and linear framebuffer
|
||||
movb (vesa_mode_info_buffer + 0), %al
|
||||
andb $(0x80 | 0x10), %al
|
||||
cmpb $(0x80 | 0x10), %al
|
||||
jne .vesa_find_video_mode_next_mode
|
||||
# check whether in graphics mode
|
||||
testb $0x10, (vesa_mode_info_buffer + 0)
|
||||
jz .vesa_find_video_mode_next_mode
|
||||
|
||||
# compare mode's dimensions
|
||||
movw -2(%ebp), %ax; cmpw %ax, (vesa_mode_info_buffer + 0x12)
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
.section .stage2
|
||||
|
||||
.set mmap_entry_size, 24
|
||||
|
||||
# fills memory map data structure
|
||||
# doesn't return on error
|
||||
# NO REGISTERS SAVED
|
||||
@@ -14,7 +12,7 @@ get_memory_map:
|
||||
movl $0x0000E820, %eax
|
||||
movl $0x534D4150, %edx
|
||||
xorl %ebx, %ebx
|
||||
movl $mmap_entry_size, %ecx
|
||||
movl $20, %ecx
|
||||
movw $memory_map_entries, %di
|
||||
|
||||
clc
|
||||
@@ -26,15 +24,15 @@ get_memory_map:
|
||||
cmpl $0x534D4150, %eax
|
||||
jne .get_memory_map_error
|
||||
|
||||
# confirm that we got at least 20 bytes
|
||||
# FIXME: don't assume BIOS to always return 20 bytes
|
||||
cmpl $20, %ecx
|
||||
jl .get_memory_map_error
|
||||
jne .get_memory_map_error
|
||||
|
||||
# increment entry count
|
||||
incl (memory_map_entry_count)
|
||||
|
||||
# increment entry pointer
|
||||
addw $mmap_entry_size, %di
|
||||
addw %cx, %di
|
||||
|
||||
# BIOS can indicate end of list by 0 in ebx
|
||||
testl %ebx, %ebx
|
||||
@@ -109,7 +107,7 @@ print_memory_map:
|
||||
|
||||
call print_newline
|
||||
|
||||
addw $mmap_entry_size, %si
|
||||
addw $20, %si
|
||||
|
||||
decl %edx
|
||||
jnz .loop_memory_map
|
||||
@@ -129,8 +127,6 @@ memory_map_error_msg:
|
||||
memory_map:
|
||||
memory_map_entry_count:
|
||||
.skip 4
|
||||
memory_map_padding:
|
||||
.skip 4
|
||||
# 128 entries should be enough...
|
||||
# 100 entries should be enough...
|
||||
memory_map_entries:
|
||||
.skip mmap_entry_size * 128
|
||||
.skip 20 * 100
|
||||
|
||||
@@ -41,7 +41,6 @@ set(KERNEL_SOURCES
|
||||
kernel/FS/USTARModule.cpp
|
||||
kernel/FS/VirtualFileSystem.cpp
|
||||
kernel/GDT.cpp
|
||||
kernel/Graphics/BGA.cpp
|
||||
kernel/IDT.cpp
|
||||
kernel/Input/InputDevice.cpp
|
||||
kernel/Input/PS2/Controller.cpp
|
||||
@@ -52,8 +51,6 @@ set(KERNEL_SOURCES
|
||||
kernel/Interruptable.cpp
|
||||
kernel/InterruptController.cpp
|
||||
kernel/kernel.cpp
|
||||
kernel/Lock/Mutex.cpp
|
||||
kernel/Lock/RWLock.cpp
|
||||
kernel/Lock/SpinLock.cpp
|
||||
kernel/Memory/ByteRingBuffer.cpp
|
||||
kernel/Memory/DMARegion.cpp
|
||||
@@ -86,7 +83,6 @@ set(KERNEL_SOURCES
|
||||
kernel/Processor.cpp
|
||||
kernel/Random.cpp
|
||||
kernel/Scheduler.cpp
|
||||
kernel/SchedulerThreadNode.cpp
|
||||
kernel/SSP.cpp
|
||||
kernel/Storage/ATA/AHCI/Controller.cpp
|
||||
kernel/Storage/ATA/AHCI/Device.cpp
|
||||
|
||||
@@ -59,7 +59,7 @@ signal_trampoline:
|
||||
addl $24, %esp
|
||||
|
||||
// restore sigmask
|
||||
movl $79, %eax // SYS_SIGPROCMASK
|
||||
movl $83, %eax // SYS_SIGPROCMASK
|
||||
movl $3, %ebx // SIG_SETMASK
|
||||
leal 72(%esp), %ecx // set
|
||||
xorl %edx, %edx // oset
|
||||
|
||||
@@ -63,7 +63,7 @@ sys_fork_trampoline:
|
||||
|
||||
call read_ip
|
||||
testl %eax, %eax
|
||||
jz .Lsys_fork_trampoline_done
|
||||
jz .done
|
||||
|
||||
movl %esp, %ebx
|
||||
|
||||
@@ -73,7 +73,7 @@ sys_fork_trampoline:
|
||||
call sys_fork
|
||||
addl $16, %esp
|
||||
|
||||
.Lsys_fork_trampoline_done:
|
||||
.done:
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebx
|
||||
|
||||
@@ -28,26 +28,27 @@ safe_user_strncpy:
|
||||
testl %ecx, %ecx
|
||||
jz safe_user_strncpy_fault
|
||||
|
||||
.Lsafe_user_strncpy_loop:
|
||||
.safe_user_strncpy_loop:
|
||||
movb (%esi), %al
|
||||
movb %al, (%edi)
|
||||
testb %al, %al
|
||||
jz .Lsafe_user_strncpy_done
|
||||
jz .safe_user_strncpy_done
|
||||
|
||||
incl %edi
|
||||
incl %esi
|
||||
decl %ecx
|
||||
jnz .Lsafe_user_strncpy_loop
|
||||
jnz .safe_user_strncpy_loop
|
||||
|
||||
safe_user_strncpy_fault:
|
||||
xorl %eax, %eax
|
||||
jmp .Lsafe_user_strncpy_return
|
||||
jmp .safe_user_strncpy_return
|
||||
|
||||
.Lsafe_user_strncpy_done:
|
||||
.safe_user_strncpy_done:
|
||||
movl $1, %eax
|
||||
|
||||
.Lsafe_user_strncpy_return:
|
||||
.safe_user_strncpy_return:
|
||||
movl 4(%esp), %edi
|
||||
movl 8(%esp), %esi
|
||||
ret
|
||||
|
||||
safe_user_strncpy_end:
|
||||
|
||||
@@ -12,7 +12,7 @@ asm_yield_trampoline:
|
||||
pushl %ebp
|
||||
|
||||
pushl %esp
|
||||
call scheduler_on_yield_trampoline
|
||||
call scheduler_on_yield
|
||||
addl $4, %esp
|
||||
|
||||
popl %ebp
|
||||
|
||||
+17
-15
@@ -168,12 +168,14 @@ has_sse:
|
||||
|
||||
check_requirements:
|
||||
call has_cpuid
|
||||
jz system_halt
|
||||
jz .exit
|
||||
call has_pae
|
||||
jz system_halt
|
||||
jz .exit
|
||||
call has_sse
|
||||
jz system_halt
|
||||
jz .exit
|
||||
ret
|
||||
.exit:
|
||||
jmp system_halt
|
||||
|
||||
enable_sse:
|
||||
movl %cr0, %eax
|
||||
@@ -223,8 +225,8 @@ _start:
|
||||
|
||||
# load boot GDT
|
||||
lgdt V2P(boot_gdtr)
|
||||
ljmpl $0x08, $V2P(.Lgdt_flush)
|
||||
.Lgdt_flush:
|
||||
ljmpl $0x08, $V2P(gdt_flush)
|
||||
gdt_flush:
|
||||
# set correct segment registers
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
@@ -241,10 +243,10 @@ _start:
|
||||
movl $g_boot_stack_top, %esp
|
||||
|
||||
# jump to higher half
|
||||
leal .Lhigher_half, %ecx
|
||||
leal higher_half, %ecx
|
||||
jmp *%ecx
|
||||
|
||||
.Lhigher_half:
|
||||
higher_half:
|
||||
# call global constuctors
|
||||
call _init
|
||||
|
||||
@@ -296,18 +298,18 @@ ap_ready:
|
||||
.skip 4
|
||||
|
||||
1: cli; cld
|
||||
ljmpl $0x00, $AP_REL(.Lap_cs_clear)
|
||||
ljmpl $0x00, $AP_REL(ap_cs_clear)
|
||||
|
||||
.Lap_cs_clear:
|
||||
ap_cs_clear:
|
||||
# load ap gdt and enter protected mode
|
||||
lgdt AP_REL(ap_gdtr)
|
||||
movl %cr0, %eax
|
||||
orb $1, %al
|
||||
movl %eax, %cr0
|
||||
ljmpl $0x08, $AP_REL(.Lap_protected_mode)
|
||||
ljmpl $0x08, $AP_REL(ap_protected_mode)
|
||||
|
||||
.code32
|
||||
.Lap_protected_mode:
|
||||
ap_protected_mode:
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %ss
|
||||
@@ -321,13 +323,13 @@ ap_ready:
|
||||
|
||||
# load boot gdt and enter long mode
|
||||
lgdt V2P(boot_gdtr)
|
||||
ljmpl $0x08, $AP_REL(.Lap_flush_gdt)
|
||||
ljmpl $0x08, $AP_REL(ap_flush_gdt)
|
||||
|
||||
.Lap_flush_gdt:
|
||||
movl $.Lap_higher_half, %ecx
|
||||
ap_flush_gdt:
|
||||
movl $ap_higher_half, %ecx
|
||||
jmp *%ecx
|
||||
|
||||
.Lap_higher_half:
|
||||
ap_higher_half:
|
||||
movl AP_REL(ap_prepare_paging), %eax
|
||||
call *%eax
|
||||
|
||||
|
||||
@@ -27,10 +27,14 @@
|
||||
|
||||
isr_stub:
|
||||
intr_header 12
|
||||
movl %cr0, %eax; pushl %eax
|
||||
movl %cr2, %eax; pushl %eax
|
||||
movl %cr3, %eax; pushl %eax
|
||||
movl %cr4, %eax; pushl %eax
|
||||
|
||||
movl 32(%esp), %edi // isr number
|
||||
movl 36(%esp), %esi // error code
|
||||
leal 40(%esp), %edx // interrupt stack ptr
|
||||
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
|
||||
@@ -48,7 +52,7 @@ isr_stub:
|
||||
call cpp_isr_handler
|
||||
|
||||
movl %ebp, %esp
|
||||
addl $8, %esp
|
||||
addl $24, %esp
|
||||
|
||||
intr_footer 12
|
||||
addl $8, %esp
|
||||
|
||||
@@ -61,7 +61,7 @@ signal_trampoline:
|
||||
addq $40, %rsp
|
||||
|
||||
// restore sigmask
|
||||
movq $79, %rdi // SYS_SIGPROCMASK
|
||||
movq $83, %rdi // SYS_SIGPROCMASK
|
||||
movq $3, %rsi // SIG_SETMASK
|
||||
leaq 192(%rsp), %rdx // set
|
||||
xorq %r10, %r10 // oset
|
||||
|
||||
@@ -33,13 +33,13 @@ sys_fork_trampoline:
|
||||
|
||||
call read_ip
|
||||
testq %rax, %rax
|
||||
jz .Lsys_fork_trampoline_done
|
||||
jz .done
|
||||
|
||||
movq %rax, %rsi
|
||||
movq %rsp, %rdi
|
||||
call sys_fork
|
||||
|
||||
.Lsys_fork_trampoline_done:
|
||||
.done:
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
|
||||
+14
-14
@@ -20,28 +20,28 @@ safe_user_strncpy:
|
||||
testq %rcx, %rcx
|
||||
jz safe_user_strncpy_fault
|
||||
|
||||
.Lsafe_user_strncpy_align_loop:
|
||||
.safe_user_strncpy_align_loop:
|
||||
testb $0x7, %sil
|
||||
jz .Lsafe_user_strncpy_align_done
|
||||
jz .safe_user_strncpy_align_done
|
||||
|
||||
movb (%rsi), %al
|
||||
movb %al, (%rdi)
|
||||
testb %al, %al
|
||||
jz .Lsafe_user_strncpy_done
|
||||
jz .safe_user_strncpy_done
|
||||
|
||||
incq %rdi
|
||||
incq %rsi
|
||||
decq %rcx
|
||||
jnz .Lsafe_user_strncpy_align_loop
|
||||
jnz .safe_user_strncpy_align_loop
|
||||
jmp safe_user_strncpy_fault
|
||||
|
||||
.Lsafe_user_strncpy_align_done:
|
||||
.safe_user_strncpy_align_done:
|
||||
movq $0x0101010101010101, %r8
|
||||
movq $0x8080808080808080, %r9
|
||||
|
||||
.Lsafe_user_strncpy_qword_loop:
|
||||
.safe_user_strncpy_qword_loop:
|
||||
cmpq $8, %rcx
|
||||
jb .Lsafe_user_strncpy_qword_done
|
||||
jb .safe_user_strncpy_qword_done
|
||||
|
||||
movq (%rsi), %rax
|
||||
movq %rax, %r10
|
||||
@@ -52,36 +52,36 @@ safe_user_strncpy:
|
||||
notq %r11
|
||||
andq %r11, %r10
|
||||
andq %r9, %r10
|
||||
jnz .Lsafe_user_strncpy_byte_loop
|
||||
jnz .safe_user_strncpy_byte_loop
|
||||
|
||||
movq %rax, (%rdi)
|
||||
|
||||
addq $8, %rdi
|
||||
addq $8, %rsi
|
||||
subq $8, %rcx
|
||||
jnz .Lsafe_user_strncpy_qword_loop
|
||||
jnz .safe_user_strncpy_qword_loop
|
||||
jmp safe_user_strncpy_fault
|
||||
|
||||
.Lsafe_user_strncpy_qword_done:
|
||||
.safe_user_strncpy_qword_done:
|
||||
testq %rcx, %rcx
|
||||
jz safe_user_strncpy_fault
|
||||
|
||||
.Lsafe_user_strncpy_byte_loop:
|
||||
.safe_user_strncpy_byte_loop:
|
||||
movb (%rsi), %al
|
||||
movb %al, (%rdi)
|
||||
testb %al, %al
|
||||
jz .Lsafe_user_strncpy_done
|
||||
jz .safe_user_strncpy_done
|
||||
|
||||
incq %rdi
|
||||
incq %rsi
|
||||
decq %rcx
|
||||
jnz .Lsafe_user_strncpy_byte_loop
|
||||
jnz .safe_user_strncpy_byte_loop
|
||||
|
||||
safe_user_strncpy_fault:
|
||||
xorq %rax, %rax
|
||||
ret
|
||||
|
||||
.Lsafe_user_strncpy_done:
|
||||
.safe_user_strncpy_done:
|
||||
movb $1, %al
|
||||
ret
|
||||
safe_user_strncpy_end:
|
||||
|
||||
@@ -15,7 +15,7 @@ asm_yield_trampoline:
|
||||
pushq %r15
|
||||
|
||||
movq %rsp, %rdi
|
||||
call scheduler_on_yield_trampoline
|
||||
call scheduler_on_yield
|
||||
|
||||
popq %r15
|
||||
popq %r14
|
||||
|
||||
+16
-14
@@ -161,10 +161,12 @@ is_64_bit:
|
||||
|
||||
check_requirements:
|
||||
call has_cpuid
|
||||
jz system_halt
|
||||
jz .exit
|
||||
call is_64_bit
|
||||
jz system_halt
|
||||
jz .exit
|
||||
ret
|
||||
.exit:
|
||||
jmp system_halt
|
||||
|
||||
enable_sse:
|
||||
movl %cr0, %eax
|
||||
@@ -224,10 +226,10 @@ _start:
|
||||
|
||||
# flush gdt and jump to 64 bit
|
||||
lgdt V2P(boot_gdtr)
|
||||
ljmpl $0x08, $V2P(.Llong_mode)
|
||||
ljmpl $0x08, $V2P(long_mode)
|
||||
|
||||
.code64
|
||||
.Llong_mode:
|
||||
long_mode:
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %ss
|
||||
@@ -238,10 +240,10 @@ _start:
|
||||
addq $KERNEL_OFFSET, %rsp
|
||||
|
||||
# jump to higher half
|
||||
movabsq $.Lhigher_half, %rcx
|
||||
movabsq $higher_half, %rcx
|
||||
jmp *%rcx
|
||||
|
||||
.Lhigher_half:
|
||||
higher_half:
|
||||
# call global constuctors
|
||||
call _init
|
||||
|
||||
@@ -291,18 +293,18 @@ ap_ready:
|
||||
.skip 8
|
||||
|
||||
1: cli; cld
|
||||
ljmpl $0x00, $AP_REL(.Lap_cs_clear)
|
||||
ljmpl $0x00, $AP_REL(ap_cs_clear)
|
||||
|
||||
.Lap_cs_clear:
|
||||
ap_cs_clear:
|
||||
# load ap gdt and enter protected mode
|
||||
lgdt AP_REL(ap_gdtr)
|
||||
movl %cr0, %eax
|
||||
orb $1, %al
|
||||
movl %eax, %cr0
|
||||
ljmpl $0x08, $AP_REL(.Lap_protected_mode)
|
||||
ljmpl $0x08, $AP_REL(ap_protected_mode)
|
||||
|
||||
.code32
|
||||
.Lap_protected_mode:
|
||||
ap_protected_mode:
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %ss
|
||||
@@ -316,14 +318,14 @@ ap_ready:
|
||||
|
||||
# load boot gdt and enter long mode
|
||||
lgdt V2P(boot_gdtr)
|
||||
ljmpl $0x08, $AP_REL(.Lap_long_mode)
|
||||
ljmpl $0x08, $AP_REL(ap_long_mode)
|
||||
|
||||
.code64
|
||||
.Lap_long_mode:
|
||||
movq $.Lap_higher_half, %rax
|
||||
ap_long_mode:
|
||||
movq $ap_higher_half, %rax
|
||||
jmp *%rax
|
||||
|
||||
.Lap_higher_half:
|
||||
ap_higher_half:
|
||||
movq AP_REL(ap_prepare_paging), %rax
|
||||
call *%rax
|
||||
|
||||
|
||||
@@ -44,12 +44,17 @@
|
||||
|
||||
isr_stub:
|
||||
intr_header 24
|
||||
movq %cr0, %rax; pushq %rax
|
||||
movq %cr2, %rax; pushq %rax
|
||||
movq %cr3, %rax; pushq %rax
|
||||
movq %cr4, %rax; pushq %rax
|
||||
|
||||
movq 120(%rsp), %rdi // isr number
|
||||
movq 128(%rsp), %rsi // error code
|
||||
leaq 136(%rsp), %rdx // interrupt stack ptr
|
||||
movq %rsp, %rcx // register ptr
|
||||
movq 152(%rsp), %rdi // isr number
|
||||
movq 160(%rsp), %rsi // error code
|
||||
leaq 168(%rsp), %rdx // interrupt stack ptr
|
||||
movq %rsp, %rcx // register ptr
|
||||
call cpp_isr_handler
|
||||
addq $32, %rsp
|
||||
|
||||
intr_footer 24
|
||||
addq $16, %rsp
|
||||
|
||||
+15
-29
@@ -38,39 +38,25 @@ extern "C" void __cxa_finalize(void* f)
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" int __cxa_guard_acquire(uint64_t* g)
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
uint8_t* guard = reinterpret_cast<uint8_t*>(g);
|
||||
using __guard = uint64_t;
|
||||
|
||||
for (;;)
|
||||
extern "C" int __cxa_guard_acquire (__guard* g)
|
||||
{
|
||||
if (BAN::atomic_load(guard[0], BAN::memory_order_acquire))
|
||||
return 0;
|
||||
uint8_t* byte = reinterpret_cast<uint8_t*>(g);
|
||||
uint8_t zero = 0;
|
||||
return __atomic_compare_exchange_n(byte, &zero, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
uint8_t expected = 0;
|
||||
if (BAN::atomic_compare_exchange(guard[1], expected, 1, BAN::memory_order_acquire))
|
||||
{
|
||||
if (BAN::atomic_load(guard[0], BAN::memory_order_acquire))
|
||||
{
|
||||
BAN::atomic_store(guard[1], 0, BAN::memory_order_release);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
extern "C" void __cxa_guard_release (__guard* g)
|
||||
{
|
||||
uint8_t* byte = reinterpret_cast<uint8_t*>(g);
|
||||
__atomic_store_n(byte, 0, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
while (BAN::atomic_load(guard[1], BAN::memory_order_acquire))
|
||||
Kernel::Processor::pause();
|
||||
extern "C" void __cxa_guard_abort (__guard*)
|
||||
{
|
||||
Kernel::panic("__cxa_guard_abort");
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_release(uint64_t* g)
|
||||
{
|
||||
uint8_t* guard = reinterpret_cast<uint8_t*>(g);
|
||||
BAN::atomic_store(guard[0], 1, BAN::memory_order_release);
|
||||
BAN::atomic_store(guard[1], 0, BAN::memory_order_release);
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_abort(uint64_t*)
|
||||
{
|
||||
Kernel::panic("__cxa_guard_abort");
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <kernel/ACPI/AML/Namespace.h>
|
||||
#include <kernel/ACPI/EmbeddedController.h>
|
||||
#include <kernel/ACPI/Headers.h>
|
||||
#include <kernel/Interruptable.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
|
||||
@@ -24,7 +23,11 @@ namespace Kernel::ACPI
|
||||
|
||||
const SDTHeader* get_header(BAN::StringView signature, uint32_t index);
|
||||
|
||||
BAN::ErrorOr<void> enter_acpi_mode();
|
||||
// mode
|
||||
// 0: PIC
|
||||
// 1: APIC
|
||||
// 2: SAPIC
|
||||
BAN::ErrorOr<void> enter_acpi_mode(uint8_t mode);
|
||||
|
||||
BAN::ErrorOr<void> initialize_acpi_devices();
|
||||
|
||||
@@ -54,7 +57,6 @@ namespace Kernel::ACPI
|
||||
|
||||
BAN::ErrorOr<void> initialize_embedded_controller(const AML::Scope& embedded_controller);
|
||||
BAN::ErrorOr<void> initialize_embedded_controllers();
|
||||
void initialize_embedded_controller_gpes();
|
||||
|
||||
BAN::Optional<GAS> find_gpe_block(size_t index);
|
||||
bool enable_gpe(uint8_t gpe);
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Atomic.h>
|
||||
#include <BAN/Optional.h>
|
||||
#include <BAN/UniqPtr.h>
|
||||
|
||||
#include <kernel/ACPI/AML/Scope.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
#include <kernel/Thread.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
@@ -14,7 +13,7 @@ namespace Kernel::ACPI
|
||||
class EmbeddedController
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<EmbeddedController>> create(AML::Scope&& scope, uint16_t command_port, uint16_t data_port);
|
||||
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);
|
||||
@@ -22,21 +21,21 @@ namespace Kernel::ACPI
|
||||
|
||||
const AML::Scope& scope() const { return m_scope; }
|
||||
|
||||
static void handle_gpe_trampoline(void*);
|
||||
|
||||
private:
|
||||
EmbeddedController(AML::Scope&& scope, uint16_t command_port, uint16_t data_port)
|
||||
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 mask, bool set);
|
||||
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);
|
||||
@@ -57,6 +56,7 @@ namespace Kernel::ACPI
|
||||
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;
|
||||
|
||||
@@ -8,7 +8,6 @@ namespace Kernel::API
|
||||
enum SharedPageFeature : uint32_t
|
||||
{
|
||||
SPF_GETTIME = 1 << 0,
|
||||
SPF_RDTSCP = 1 << 1,
|
||||
};
|
||||
|
||||
struct SharedPage
|
||||
@@ -19,8 +18,9 @@ namespace Kernel::API
|
||||
|
||||
struct
|
||||
{
|
||||
uint64_t realtime_s;
|
||||
uint32_t realtime_ns;
|
||||
uint8_t shift;
|
||||
uint64_t mult;
|
||||
uint64_t realtime_seconds;
|
||||
} gettime_shared;
|
||||
|
||||
struct
|
||||
@@ -28,8 +28,6 @@ namespace Kernel::API
|
||||
struct
|
||||
{
|
||||
uint32_t seq;
|
||||
uint32_t mult;
|
||||
int8_t shift;
|
||||
uint64_t last_ns;
|
||||
uint64_t last_tsc;
|
||||
} gettime_local;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/InterruptNumbers.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
|
||||
@@ -13,10 +12,10 @@ namespace Kernel
|
||||
{
|
||||
public:
|
||||
virtual void eoi(uint8_t) override;
|
||||
virtual void enable_irq(uint8_t, bool level_triggered) override;
|
||||
virtual void enable_irq(uint8_t) override;
|
||||
virtual bool is_in_service(uint8_t) override;
|
||||
|
||||
virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq, bool shared) override;
|
||||
virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq) override;
|
||||
virtual BAN::Optional<uint8_t> get_free_irq() override;
|
||||
|
||||
virtual void initialize_multiprocessor() override;
|
||||
@@ -24,10 +23,9 @@ namespace Kernel
|
||||
virtual void broadcast_ipi() override;
|
||||
virtual void enable() override;
|
||||
|
||||
BAN::ErrorOr<uint8_t> reserve_gsi(uint32_t gsi, bool shared = false);
|
||||
BAN::ErrorOr<uint8_t> reserve_gsi(uint32_t gsi);
|
||||
|
||||
void initialize_timer();
|
||||
void set_timer_dealine(uint64_t ns);
|
||||
|
||||
private:
|
||||
uint32_t read_from_local_apic(ptrdiff_t);
|
||||
@@ -72,8 +70,7 @@ namespace Kernel
|
||||
Kernel::vaddr_t m_local_apic_vaddr = 0;
|
||||
BAN::Vector<IOAPIC> m_io_apics;
|
||||
uint8_t m_irq_overrides[0x100] {};
|
||||
uint8_t m_used_gsis[m_irq_count / 8] {};
|
||||
uint8_t m_excl_gsis[m_irq_count / 8] {};
|
||||
uint8_t m_reserved_gsis[m_irq_count / 8] {};
|
||||
uint64_t m_lapic_timer_frequency_hz { 0 };
|
||||
};
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long request, void* arg) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int cmd, void* arg) override;
|
||||
|
||||
protected:
|
||||
ThreadBlocker m_sample_data_blocker;
|
||||
|
||||
@@ -67,7 +67,6 @@ namespace Kernel
|
||||
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 };
|
||||
size_t m_amplifier_idx { SIZE_MAX };
|
||||
|
||||
uint8_t m_stream_id { 0xFF };
|
||||
uint8_t m_stream_index { 0xFF };
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Optional.h>
|
||||
#include <BAN/Vector.h>
|
||||
|
||||
namespace Kernel::HDAudio
|
||||
@@ -65,7 +64,6 @@ namespace Kernel::HDAudio
|
||||
};
|
||||
|
||||
BAN::Optional<Amplifier> output_amplifier;
|
||||
BAN::Optional<Amplifier> input_amplifier;
|
||||
|
||||
BAN::Vector<uint16_t> connections;
|
||||
};
|
||||
|
||||
@@ -21,17 +21,13 @@ struct BananBootloaderMemoryMapEntry
|
||||
uint64_t address;
|
||||
uint64_t length;
|
||||
uint32_t type;
|
||||
uint32_t unused;
|
||||
};
|
||||
static_assert(sizeof(BananBootloaderMemoryMapEntry) == 24);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct BananBootloaderMemoryMapInfo
|
||||
{
|
||||
uint32_t entry_count;
|
||||
uint32_t padding;
|
||||
struct BananBootloaderMemoryMapEntry entries[];
|
||||
};
|
||||
static_assert(sizeof(BananBootloaderMemoryMapInfo) == 8);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct BananBootloaderInfo
|
||||
{
|
||||
@@ -39,5 +35,4 @@ struct BananBootloaderInfo
|
||||
uint32_t framebuffer_addr;
|
||||
uint32_t memory_map_addr;
|
||||
uint32_t kernel_paddr;
|
||||
};
|
||||
static_assert(sizeof(BananBootloaderInfo) == 16);
|
||||
} __attribute__((packed));
|
||||
|
||||
@@ -82,8 +82,5 @@ namespace CPUID
|
||||
bool has_pat();
|
||||
bool has_1gib_pages();
|
||||
bool has_invariant_tsc();
|
||||
bool has_rdtscp();
|
||||
uint64_t get_tsc_frequency();
|
||||
bool has_kvm_pvclock();
|
||||
|
||||
}
|
||||
|
||||
@@ -6,22 +6,15 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class BGAController;
|
||||
|
||||
class FramebufferDevice : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create(paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp);
|
||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create(BAN::RefPtr<BGAController>);
|
||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create_from_boot_framebuffer();
|
||||
static BAN::RefPtr<FramebufferDevice> boot_framebuffer();
|
||||
~FramebufferDevice();
|
||||
|
||||
uint32_t width() const { return m_width; }
|
||||
uint32_t height() const { return m_height; }
|
||||
uint8_t bpp() const { return m_bpp; }
|
||||
|
||||
BAN::ErrorOr<void> set_bga_controller(BAN::RefPtr<BGAController>);
|
||||
|
||||
uint32_t get_pixel(uint32_t x, uint32_t y) const;
|
||||
void set_pixel(uint32_t x, uint32_t y, uint32_t rgb);
|
||||
@@ -43,7 +36,7 @@ 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;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long request, void* arg) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int cmd, void* arg) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
@@ -57,16 +50,14 @@ namespace Kernel
|
||||
private:
|
||||
const BAN::String m_name;
|
||||
|
||||
vaddr_t m_video_memory_vaddr { 0 };
|
||||
paddr_t m_video_memory_paddr { 0 };
|
||||
|
||||
uint32_t m_width { 0 };
|
||||
uint32_t m_height { 0 };
|
||||
uint32_t m_pitch { 0 };
|
||||
uint8_t m_bpp { 0 };
|
||||
vaddr_t m_video_memory_vaddr { 0 };
|
||||
const paddr_t m_video_memory_paddr;
|
||||
const uint32_t m_width;
|
||||
const uint32_t m_height;
|
||||
const uint32_t m_pitch;
|
||||
const uint8_t m_bpp;
|
||||
|
||||
BAN::UniqPtr<VirtualRange> m_video_buffer;
|
||||
BAN::RefPtr<BGAController> m_bga_controller;
|
||||
|
||||
friend class FramebufferMemoryRegion;
|
||||
};
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace Kernel::ELF
|
||||
size_t size;
|
||||
};
|
||||
|
||||
bool open_execfd;
|
||||
vaddr_t entry_point;
|
||||
BAN::Optional<vaddr_t> interp_base;
|
||||
BAN::Optional<TLS> master_tls;
|
||||
BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <BAN/HashMap.h>
|
||||
#include <kernel/FS/Inode.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
|
||||
#include <sys/epoll.h>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/Device/Device.h>
|
||||
#include <kernel/FS/TmpFS/FileSystem.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
@@ -8,8 +9,6 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class Device;
|
||||
|
||||
class DevFileSystem final : public TmpFileSystem
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <kernel/FS/Inode.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -23,16 +22,16 @@ namespace Kernel
|
||||
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
|
||||
bool can_read_impl() const override;
|
||||
bool can_write_impl() const override;
|
||||
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:
|
||||
const bool m_is_semaphore;
|
||||
uint64_t m_value;
|
||||
BAN::Atomic<uint64_t> m_value;
|
||||
|
||||
mutable Mutex m_mutex;
|
||||
Mutex m_mutex;
|
||||
ThreadBlocker m_thread_blocker;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
#include <BAN/HashMap.h>
|
||||
#include <kernel/Device/Device.h>
|
||||
#include <kernel/FS/Ext2/Inode.h>
|
||||
#include <kernel/FS/FileSystem.h>
|
||||
#include <kernel/Memory/VirtualRange.h>
|
||||
#include <kernel/FS/Ext2/Inode.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -29,7 +28,7 @@ namespace Kernel
|
||||
BAN_NON_COPYABLE(BlockBufferWrapper);
|
||||
|
||||
public:
|
||||
BlockBufferWrapper(BAN::ByteSpan buffer, void (*callback)(void*, const uint8_t*), void* argument)
|
||||
BlockBufferWrapper(BAN::Span<uint8_t> buffer, void (*callback)(void*, const uint8_t*), void* argument)
|
||||
: m_buffer(buffer)
|
||||
, m_callback(callback)
|
||||
, m_argument(argument)
|
||||
@@ -61,13 +60,13 @@ namespace Kernel
|
||||
const uint8_t* data() const { return m_buffer.data(); }
|
||||
|
||||
BAN::ByteSpan span() { return m_buffer; }
|
||||
BAN::ConstByteSpan span() const { return m_buffer; }
|
||||
BAN::ConstByteSpan span() const { return m_buffer.as_const(); }
|
||||
|
||||
uint8_t& operator[](size_t index) { return m_buffer[index]; }
|
||||
uint8_t operator[](size_t index) const { return m_buffer[index]; }
|
||||
|
||||
private:
|
||||
BAN::ByteSpan m_buffer;
|
||||
BAN::Span<uint8_t> m_buffer;
|
||||
void (*m_callback)(void*, const uint8_t*);
|
||||
void* m_argument;
|
||||
};
|
||||
@@ -100,8 +99,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
|
||||
BAN::ErrorOr<void> release_block(uint32_t block);
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> open_inode(ino_t);
|
||||
void remove_from_cache(ino_t);
|
||||
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>>& inode_cache() { return m_inode_cache; }
|
||||
|
||||
const Ext2::Superblock& superblock() const { return m_superblock; }
|
||||
|
||||
@@ -129,7 +127,7 @@ namespace Kernel
|
||||
private:
|
||||
struct BlockBuffer
|
||||
{
|
||||
BAN::ByteSpan buffer;
|
||||
BAN::Vector<uint8_t> buffer;
|
||||
bool used { false };
|
||||
};
|
||||
|
||||
@@ -145,7 +143,6 @@ namespace Kernel
|
||||
|
||||
Mutex m_buffer_mutex;
|
||||
ThreadBlocker m_buffer_blocker;
|
||||
BAN::UniqPtr<VirtualRange> m_buffer_data;
|
||||
BAN::Array<BlockBuffer, max_threads * max_buffers_per_thread> m_buffers;
|
||||
BAN::Array<ThreadInfo, max_threads> m_thread_infos;
|
||||
};
|
||||
@@ -158,7 +155,6 @@ namespace Kernel
|
||||
BAN::RefPtr<Inode> m_root_inode;
|
||||
BAN::Vector<uint32_t> m_superblock_backups;
|
||||
|
||||
Mutex m_inode_cache_lock;
|
||||
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>> m_inode_cache;
|
||||
|
||||
BlockBufferManager m_buffer_manager;
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_no_lock(BAN::StringView);
|
||||
|
||||
/* needs write end of the lock when allocate is true*/
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block_no_lock(uint32_t block, uint32_t index, uint32_t depth, bool allocate);
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate);
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate);
|
||||
|
||||
/* needs write end of the lock */
|
||||
@@ -71,13 +71,7 @@ namespace Kernel
|
||||
private:
|
||||
Ext2Inode(Ext2FS& fs, Ext2::Inode inode, uint32_t ino);
|
||||
|
||||
BAN::Optional<uint32_t> block_cache_find(uint32_t block, uint32_t index) const;
|
||||
void block_cache_remove(uint32_t block, uint32_t index);
|
||||
void block_cache_add(uint32_t block, uint32_t index, uint32_t target);
|
||||
|
||||
BAN::RefPtr<Inode> dir_cache_find(BAN::StringView) const;
|
||||
void dir_cache_remove(BAN::StringView);
|
||||
void dir_cache_add(BAN::StringView, BAN::RefPtr<Inode>);
|
||||
static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t);
|
||||
|
||||
private:
|
||||
struct ScopedSync
|
||||
@@ -113,27 +107,6 @@ namespace Kernel
|
||||
const uint32_t m_og_faddr;
|
||||
const Ext2::Osd2 m_og_osd2;
|
||||
|
||||
struct BlockCacheEntry
|
||||
{
|
||||
mutable uint32_t freq;
|
||||
uint32_t block;
|
||||
uint32_t index;
|
||||
uint32_t target;
|
||||
};
|
||||
mutable SpinLock m_block_cache_lock;
|
||||
BAN::Array<BlockCacheEntry, 8> m_block_cache;
|
||||
|
||||
struct DirCacheEntry
|
||||
{
|
||||
mutable size_t freq { 0 };
|
||||
BAN::RefPtr<Inode> inode;
|
||||
size_t name_len { 0 };
|
||||
char name[256];
|
||||
};
|
||||
static constexpr size_t dir_cache_size = 32;
|
||||
mutable RWLock m_dir_cache_lock;
|
||||
BAN::Vector<DirCacheEntry> m_dir_cache;
|
||||
|
||||
friend class Ext2FS;
|
||||
friend class BAN::RefPtr<Ext2Inode>;
|
||||
};
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <kernel/FS/FAT/Definitions.h>
|
||||
#include <kernel/FS/FAT/Inode.h>
|
||||
#include <kernel/FS/FileSystem.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Device/Device.h>
|
||||
#include <kernel/FS/Inode.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class BlockDevice;
|
||||
|
||||
class FileSystem : public BAN::RefCounted<FileSystem>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -83,7 +83,6 @@ namespace Kernel
|
||||
public:
|
||||
virtual ~Inode() {}
|
||||
|
||||
static bool can_access(uid_t uid, gid_t gid, mode_t mode, const Credentials& credentials, int);
|
||||
bool can_access(const Credentials&, int) const;
|
||||
|
||||
bool operator==(const Inode& other) const { return dev() == other.dev() && ino() == other.ino(); }
|
||||
@@ -151,7 +150,7 @@ namespace Kernel
|
||||
bool has_error() const { return has_error_impl(); }
|
||||
bool has_hungup() const { return has_hungup_impl(); }
|
||||
|
||||
BAN::ErrorOr<long> ioctl(unsigned long request, void* arg);
|
||||
BAN::ErrorOr<long> ioctl(int request, void* arg);
|
||||
|
||||
BAN::ErrorOr<void> add_epoll(class Epoll*);
|
||||
void del_epoll(class Epoll*);
|
||||
@@ -200,7 +199,7 @@ namespace Kernel
|
||||
virtual bool has_error_impl() const = 0;
|
||||
virtual bool has_hungup_impl() const = 0;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
protected:
|
||||
// TODO: this is supposed to be const I guess?
|
||||
|
||||
@@ -2,20 +2,17 @@
|
||||
|
||||
#include <kernel/FS/TmpFS/FileSystem.h>
|
||||
#include <kernel/FS/TmpFS/Inode.h>
|
||||
#include <kernel/Process.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class Process;
|
||||
|
||||
class ProcFileSystem final : public TmpFileSystem
|
||||
{
|
||||
public:
|
||||
static void initialize();
|
||||
static ProcFileSystem& get();
|
||||
|
||||
void post_scheduler_initialize();
|
||||
|
||||
BAN::ErrorOr<void> on_process_create(Process&);
|
||||
void on_process_delete(Process&);
|
||||
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
|
||||
#include <kernel/FS/TmpFS/FileSystem.h>
|
||||
#include <kernel/FS/TmpFS/Inode.h>
|
||||
#include <kernel/Process.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class Process;
|
||||
|
||||
class ProcPidInode final : public TmpDirectoryInode
|
||||
{
|
||||
// FIXME: dynamically update ruid/rgid.
|
||||
@@ -77,7 +76,7 @@ namespace Kernel
|
||||
class ProcROInode final : public TmpInode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create_new(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem&, void*, mode_t, uid_t, gid_t);
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create_new(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, mode_t, uid_t, gid_t);
|
||||
~ProcROInode() = default;
|
||||
|
||||
protected:
|
||||
@@ -93,11 +92,10 @@ namespace Kernel
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcROInode(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem&, void*, const TmpInodeInfo&);
|
||||
ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&);
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<size_t> (*m_callback)(off_t, BAN::ByteSpan, void*);
|
||||
void* m_argument;
|
||||
size_t (*m_callback)(off_t, BAN::ByteSpan);
|
||||
};
|
||||
|
||||
class ProcSymlinkInode final : public TmpInode
|
||||
|
||||
@@ -92,9 +92,8 @@ namespace Kernel
|
||||
MountPoint* mount_from_root_inode(BAN::RefPtr<Inode>);
|
||||
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
BAN::RefPtr<FileSystem> m_root_fs;
|
||||
|
||||
Mutex m_mount_point_lock;
|
||||
BAN::Vector<MountPoint> m_mount_points;
|
||||
|
||||
friend class BAN::RefPtr<VirtualFileSystem>;
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/RefPtr.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/PCI.h>
|
||||
|
||||
#include <sys/framebuffer.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class BGAController : public BAN::RefCounted<BGAController>
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<BGAController>> create(PCI::Device&);
|
||||
|
||||
fb_fix_info get_fb_fix_info() const;
|
||||
fb_var_info get_fb_var_info() const;
|
||||
BAN::ErrorOr<void> set_fb_var_info(const fb_var_info&);
|
||||
|
||||
private:
|
||||
BGAController(PCI::Device&);
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
void write_reg(uint16_t reg, uint16_t value);
|
||||
uint16_t read_reg(uint16_t reg);
|
||||
|
||||
private:
|
||||
mutable RecursiveSpinLock m_lock;
|
||||
PCI::Device& m_pci_device;
|
||||
BAN::UniqPtr<PCI::BarRegion> m_lfb_bar;
|
||||
|
||||
fb_fix_info m_fix_info {};
|
||||
fb_var_info m_var_info {};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -10,6 +10,21 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
// IDT entries
|
||||
// 0x00->0x1F (32): ISR
|
||||
// 0x20->0x7F (96): PIC/IOAPIC
|
||||
// 0x80->0xEF (112): MSI
|
||||
// 0xF0->0xFE (15): internal
|
||||
|
||||
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; // hard coded in kernel/API/Syscall.h
|
||||
#endif
|
||||
constexpr uint8_t IRQ_IPI = 0xF1;
|
||||
constexpr uint8_t IRQ_TIMER = 0xF2;
|
||||
|
||||
#if ARCH(x86_64)
|
||||
struct GateDescriptor
|
||||
{
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace Kernel::Input
|
||||
uint8_t m_byte_index { 0 };
|
||||
bool m_basic { false };
|
||||
|
||||
bool m_scancode_set_uncertain { false };
|
||||
uint8_t m_scancode_set { 0xFF };
|
||||
uint16_t m_modifiers { 0 };
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Kernel
|
||||
virtual ~InterruptController() {}
|
||||
|
||||
virtual void eoi(uint8_t) = 0;
|
||||
virtual void enable_irq(uint8_t, bool level_triggered = false) = 0;
|
||||
virtual void enable_irq(uint8_t) = 0;
|
||||
virtual bool is_in_service(uint8_t) = 0;
|
||||
|
||||
static void initialize(bool force_pic);
|
||||
@@ -26,7 +26,7 @@ namespace Kernel
|
||||
virtual void broadcast_ipi() = 0;
|
||||
virtual void enable() = 0;
|
||||
|
||||
virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq, bool shared = false) = 0;
|
||||
virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq) = 0;
|
||||
virtual BAN::Optional<uint8_t> get_free_irq() = 0;
|
||||
|
||||
bool is_using_apic() const { return m_using_apic; }
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Arch.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
// IDT entries
|
||||
// 0x00->0x1F (32): ISR
|
||||
// 0x20->0x7F (96): PIC/IOAPIC
|
||||
// 0x80->0xEF (112): MSI
|
||||
// 0xF0->0xFE (15): internal
|
||||
|
||||
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; // hard coded in kernel/API/Syscall.h
|
||||
#endif
|
||||
constexpr uint8_t IRQ_IPI = 0xF1;
|
||||
constexpr uint8_t IRQ_TIMER = 0xF2;
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#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> requires requires (Lock& lock) { lock.lock(); lock.unlock(InterruptState::Disabled); lock.current_processor_has_lock(); }
|
||||
class BlockableSpinLock : public BaseMutex
|
||||
{
|
||||
public:
|
||||
BlockableSpinLock(Lock& lock)
|
||||
: m_lock(lock)
|
||||
{
|
||||
ASSERT(m_lock.current_processor_has_lock());
|
||||
}
|
||||
|
||||
void lock() override
|
||||
{
|
||||
m_lock.lock();
|
||||
}
|
||||
|
||||
void unlock() override
|
||||
{
|
||||
m_lock.unlock(InterruptState::Disabled);
|
||||
}
|
||||
|
||||
uint32_t lock_depth() const override { return m_lock.lock_depth(); }
|
||||
bool is_locked_by_current_thread() const override { return m_lock.current_processor_has_lock(); }
|
||||
|
||||
private:
|
||||
Lock& m_lock;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <BAN/Atomic.h>
|
||||
#include <BAN/NoCopyMove.h>
|
||||
#include <kernel/Thread.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -12,10 +13,12 @@ namespace Kernel
|
||||
{
|
||||
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;
|
||||
virtual bool is_locked_by_current_thread() const = 0;
|
||||
};
|
||||
|
||||
class Mutex final : public BaseMutex
|
||||
@@ -26,14 +29,63 @@ namespace Kernel
|
||||
public:
|
||||
Mutex() = default;
|
||||
|
||||
bool try_lock();
|
||||
void lock() override;
|
||||
void unlock() override;
|
||||
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))
|
||||
{
|
||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Enabled);
|
||||
Processor::yield();
|
||||
expected = -1;
|
||||
}
|
||||
ASSERT(m_lock_depth == 0);
|
||||
if (tid)
|
||||
Thread::current().add_mutex();
|
||||
}
|
||||
m_lock_depth++;
|
||||
}
|
||||
|
||||
pid_t locker() const { return m_locker; }
|
||||
bool is_locked() const { return m_locker != -1; }
|
||||
bool try_lock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
if (tid == m_locker)
|
||||
ASSERT(m_lock_depth > 0);
|
||||
else
|
||||
{
|
||||
pid_t expected = -1;
|
||||
if (!m_locker.compare_exchange(expected, tid))
|
||||
return false;
|
||||
ASSERT(m_lock_depth == 0);
|
||||
if (tid)
|
||||
Thread::current().add_mutex();
|
||||
}
|
||||
m_lock_depth++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void unlock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
ASSERT(m_locker == tid);
|
||||
ASSERT(m_lock_depth > 0);
|
||||
if (--m_lock_depth == 0)
|
||||
{
|
||||
m_locker = -1;
|
||||
if (tid)
|
||||
Thread::current().remove_mutex();
|
||||
}
|
||||
}
|
||||
|
||||
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; }
|
||||
bool is_locked_by_current_thread() const override;
|
||||
bool is_locked_by_current_thread() const { return m_locker == Thread::current_tid(); }
|
||||
|
||||
private:
|
||||
BAN::Atomic<pid_t> m_locker { -1 };
|
||||
@@ -48,14 +100,74 @@ namespace Kernel
|
||||
public:
|
||||
PriorityMutex() = default;
|
||||
|
||||
bool try_lock();
|
||||
void lock() override;
|
||||
void unlock() override;
|
||||
void lock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
|
||||
pid_t locker() const { return m_locker; }
|
||||
bool is_locked() const { return m_locker != -1; }
|
||||
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++;
|
||||
pid_t expected = -1;
|
||||
while (!(has_priority || m_queue_length == 0) || !m_locker.compare_exchange(expected, tid))
|
||||
{
|
||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Enabled);
|
||||
Processor::yield();
|
||||
expected = -1;
|
||||
}
|
||||
ASSERT(m_lock_depth == 0);
|
||||
if (tid)
|
||||
Thread::current().add_mutex();
|
||||
}
|
||||
m_lock_depth++;
|
||||
}
|
||||
|
||||
bool try_lock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
|
||||
if (tid == m_locker)
|
||||
ASSERT(m_lock_depth > 0);
|
||||
else
|
||||
{
|
||||
bool has_priority = tid ? !Thread::current().is_userspace() : true;
|
||||
pid_t expected = -1;
|
||||
if (!(has_priority || m_queue_length == 0) || !m_locker.compare_exchange(expected, tid))
|
||||
return false;
|
||||
if (has_priority)
|
||||
m_queue_length++;
|
||||
ASSERT(m_lock_depth == 0);
|
||||
if (tid)
|
||||
Thread::current().add_mutex();
|
||||
}
|
||||
m_lock_depth++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void unlock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
ASSERT(m_locker == tid);
|
||||
ASSERT(m_lock_depth > 0);
|
||||
if (--m_lock_depth == 0)
|
||||
{
|
||||
bool has_priority = tid ? !Thread::current().is_userspace() : true;
|
||||
if (has_priority)
|
||||
m_queue_length--;
|
||||
m_locker = -1;
|
||||
if (tid)
|
||||
Thread::current().remove_mutex();
|
||||
}
|
||||
}
|
||||
|
||||
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; }
|
||||
bool is_locked_by_current_thread() const override;
|
||||
bool is_locked_by_current_thread() const { return m_locker == Thread::current_tid(); }
|
||||
|
||||
private:
|
||||
BAN::Atomic<pid_t> m_locker { -1 };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -13,13 +13,51 @@ namespace Kernel
|
||||
public:
|
||||
RWLock() = default;
|
||||
|
||||
void rd_lock();
|
||||
void rd_unlock();
|
||||
void wr_lock();
|
||||
void wr_unlock();
|
||||
void rd_lock()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
while (m_writers_waiting > 0 || m_writer != -1)
|
||||
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()
|
||||
{
|
||||
if (m_writer == Thread::current_tid())
|
||||
{
|
||||
m_writer_depth++;
|
||||
return;
|
||||
}
|
||||
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
m_writers_waiting++;
|
||||
while (m_readers_active > 0 || m_writer != -1)
|
||||
m_thread_blocker.block_indefinite(&m_mutex);
|
||||
m_writers_waiting--;
|
||||
|
||||
m_writer = Thread::current_tid();
|
||||
m_writer_depth = 1;
|
||||
}
|
||||
|
||||
void wr_unlock()
|
||||
{
|
||||
if (--m_writer_depth != 0)
|
||||
return;
|
||||
LockGuard _(m_mutex);
|
||||
m_writer = -1;
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
|
||||
private:
|
||||
SpinLock m_lock;
|
||||
Mutex m_mutex;
|
||||
ThreadBlocker m_thread_blocker;
|
||||
uint32_t m_readers_active { 0 };
|
||||
uint32_t m_writers_waiting { 0 };
|
||||
|
||||
@@ -61,6 +61,9 @@ namespace Kernel
|
||||
uint32_t m_lock_depth { 0 };
|
||||
};
|
||||
|
||||
template<typename Lock>
|
||||
class SpinLockGuardAsMutex;
|
||||
|
||||
template<typename Lock>
|
||||
class SpinLockGuard
|
||||
{
|
||||
@@ -82,6 +85,7 @@ namespace Kernel
|
||||
private:
|
||||
Lock& m_lock;
|
||||
InterruptState m_state;
|
||||
friend class SpinLockGuardAsMutex<Lock>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
Lock& 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)
|
||||
{}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/Memory/MemoryRegion.h>
|
||||
|
||||
namespace Kernel
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/HashMap.h>
|
||||
#include <BAN/RefPtr.h>
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/Memory/MemoryRegion.h>
|
||||
|
||||
#include <sys/shm.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class SharedMemoryObject;
|
||||
|
||||
class SharedMemoryObjectManager
|
||||
{
|
||||
public:
|
||||
using Key = size_t;
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<void> initialize();
|
||||
static SharedMemoryObjectManager& get();
|
||||
|
||||
BAN::ErrorOr<int> shmget(key_t key, size_t size, int shmflg);
|
||||
BAN::ErrorOr<void> shmctl(int shmid, int cmd, struct shmid_ds* user_buf);
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> shmat(int shmid, const void* shmaddr, int shmflg);
|
||||
BAN::ErrorOr<Key> create_object(size_t size, PageTable::flags_t);
|
||||
BAN::ErrorOr<void> delete_object(Key);
|
||||
BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> map_object(Key, PageTable&, AddressRange);
|
||||
|
||||
private:
|
||||
SharedMemoryObjectManager() {}
|
||||
@@ -29,31 +32,49 @@ namespace Kernel
|
||||
private:
|
||||
struct Object : public BAN::RefCounted<Object>
|
||||
{
|
||||
Object(key_t key, int id, shmid_ds info)
|
||||
: key(key)
|
||||
, id(id)
|
||||
, info(info)
|
||||
{ }
|
||||
~Object();
|
||||
|
||||
bool can_current_process_access(int flags) const;
|
||||
|
||||
const key_t key;
|
||||
const int id;
|
||||
shmid_ds info;
|
||||
|
||||
Mutex mutex;
|
||||
Key key;
|
||||
size_t size;
|
||||
PageTable::flags_t flags;
|
||||
BAN::Vector<paddr_t> paddrs;
|
||||
bool marked_for_deletion { false };
|
||||
SpinLock spin_lock;
|
||||
};
|
||||
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
BAN::HashMap<key_t, int> m_ids;
|
||||
BAN::HashMap<int, BAN::RefPtr<Object>> m_objects;
|
||||
BAN::HashMap<Key, BAN::RefPtr<Object>> m_objects;
|
||||
|
||||
friend class SharedMemoryObject;
|
||||
friend class BAN::UniqPtr<SharedMemoryObjectManager>;
|
||||
};
|
||||
|
||||
class SharedMemoryObject : public MemoryRegion
|
||||
{
|
||||
BAN_NON_COPYABLE(SharedMemoryObject);
|
||||
BAN_NON_MOVABLE(SharedMemoryObject);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
|
||||
|
||||
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:
|
||||
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, O_EXEC | O_RDWR)
|
||||
, m_object(object)
|
||||
{ }
|
||||
|
||||
private:
|
||||
BAN::RefPtr<SharedMemoryObjectManager::Object> m_object;
|
||||
|
||||
friend class BAN::UniqPtr<SharedMemoryObject>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <BAN/HashMap.h>
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
#include <kernel/Thread.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace Kernel
|
||||
REG_TDLEN = 0x3808,
|
||||
REG_TDH = 0x3810,
|
||||
REG_TDT = 0x3818,
|
||||
REG_RXCSUM = 0x5000,
|
||||
REG_MTA = 0x5200,
|
||||
};
|
||||
|
||||
@@ -168,15 +167,6 @@ namespace Kernel
|
||||
RCTL_BSIZE_16384 = (0b01 << 16) | RCTL_BSEX,
|
||||
};
|
||||
|
||||
enum E1000_RXCSUM : uint32_t
|
||||
{
|
||||
RXSUM_IPOFLD = 1 << 8,
|
||||
RXSUM_TUOFLD = 1 << 9,
|
||||
RXSUM_CRCOFLD = 1 << 11,
|
||||
RXSUM_IPPCE = 1 << 12,
|
||||
RXSUM_PCSD = 1 << 13,
|
||||
};
|
||||
|
||||
enum E1000_CMD : uint8_t
|
||||
{
|
||||
CMD_EOP = 1 << 0,
|
||||
@@ -188,26 +178,6 @@ namespace Kernel
|
||||
CMD_IDE = 1 << 7,
|
||||
};
|
||||
|
||||
enum E1000_RX_STS : uint8_t
|
||||
{
|
||||
RX_STS_IPCS = 1 << 6,
|
||||
RX_STS_TCPCS = 1 << 5,
|
||||
RX_STS_UDPCS = 1 << 5,
|
||||
RX_STS_EOP = 1 << 1,
|
||||
RX_STS_DD = 1 << 0,
|
||||
};
|
||||
|
||||
enum E1000_RX_ERR : uint8_t
|
||||
{
|
||||
RX_ERR_RXE = 1 << 7,
|
||||
RX_ERR_IPE = 1 << 6,
|
||||
RX_ERR_TCPE = 1 << 5,
|
||||
RX_ERR_CXE = 1 << 4,
|
||||
RX_ERR_SEQ = 1 << 2,
|
||||
RX_ERR_SE = 1 << 1,
|
||||
RX_ERR_CE = 1 << 0,
|
||||
};
|
||||
|
||||
struct e1000_rx_desc
|
||||
{
|
||||
uint64_t addr;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Kernel
|
||||
uint32_t read32(uint16_t reg);
|
||||
void write32(uint16_t reg, uint32_t value);
|
||||
|
||||
BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) override;
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
||||
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
@@ -74,8 +74,8 @@ namespace Kernel
|
||||
BAN::UniqPtr<DMARegion> m_rx_descriptor_region;
|
||||
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
||||
|
||||
BAN::Atomic<uint32_t> m_tx_head { 0 };
|
||||
BAN::Atomic<uint32_t> m_tx_commit { 0 };
|
||||
BAN::Atomic<uint32_t> m_tx_head1 { 0 };
|
||||
BAN::Atomic<uint32_t> m_tx_head2 { 0 };
|
||||
|
||||
SpinLock m_rx_lock;
|
||||
ThreadBlocker m_rx_blocker;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
#include <kernel/Networking/NetworkLayer.h>
|
||||
#include <kernel/Networking/NetworkSocket.h>
|
||||
#include <kernel/Thread.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -40,14 +41,14 @@ namespace Kernel
|
||||
|
||||
ARPTable& arp_table() { return *m_arp_table; }
|
||||
|
||||
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan, uint32_t validated_cksums);
|
||||
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
|
||||
|
||||
virtual void unbind_socket(uint16_t port) override;
|
||||
virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) override;
|
||||
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) override;
|
||||
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) override;
|
||||
|
||||
virtual BAN::ErrorOr<void> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||
|
||||
virtual Socket::Domain domain() const override { return Socket::Domain::INET ;}
|
||||
virtual size_t header_size() const override { return sizeof(IPv4Header); }
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
#include <kernel/Memory/VirtualRange.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -28,7 +27,7 @@ namespace Kernel
|
||||
{}
|
||||
~LoopbackInterface();
|
||||
|
||||
BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) override;
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
||||
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
@@ -47,7 +46,7 @@ namespace Kernel
|
||||
};
|
||||
|
||||
private:
|
||||
SpinLock m_buffer_lock;
|
||||
Mutex m_buffer_lock;
|
||||
BAN::UniqPtr<VirtualRange> m_buffer;
|
||||
|
||||
uint32_t m_buffer_tail { 0 };
|
||||
|
||||
@@ -23,13 +23,6 @@ namespace Kernel
|
||||
ARP = 0x0806,
|
||||
};
|
||||
|
||||
enum NetworkChecksum : uint32_t
|
||||
{
|
||||
CKSUM_IPV4 = 1 << 0,
|
||||
CKSUM_TCP = 1 << 1,
|
||||
CKSUM_UDP = 1 << 2,
|
||||
};
|
||||
|
||||
class NetworkInterface : public CharacterDevice
|
||||
{
|
||||
BAN_NON_COPYABLE(NetworkInterface);
|
||||
@@ -66,33 +59,11 @@ namespace Kernel
|
||||
|
||||
virtual BAN::StringView name() const override { return m_name; }
|
||||
|
||||
BAN::ErrorOr<void> send_with_ethernet_header(BAN::MACAddress dst_mac, EtherType ether_type, BAN::ConstByteSpan buffer)
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan payload)
|
||||
{
|
||||
BAN::ConstByteSpan buffer_array[1] { buffer };
|
||||
return send_with_ethernet_header(dst_mac, ether_type, buffer_array);
|
||||
return send_bytes(destination, protocol, { &payload, 1 });
|
||||
}
|
||||
|
||||
template<size_t SIZE>
|
||||
BAN::ErrorOr<void> send_with_ethernet_header(BAN::MACAddress dst_mac, EtherType ether_type, const BAN::ConstByteSpan (&buffer_array)[SIZE])
|
||||
{
|
||||
const auto ethernet_header = EthernetHeader {
|
||||
.dst_mac = dst_mac,
|
||||
.src_mac = get_mac_address(),
|
||||
.ether_type = ether_type,
|
||||
};
|
||||
|
||||
BAN::ConstByteSpan new_buffer_array[SIZE + 1];
|
||||
new_buffer_array[0] = BAN::ConstByteSpan::from(ethernet_header);
|
||||
for (size_t i = 0; i < SIZE; i++)
|
||||
new_buffer_array[i + 1] = buffer_array[i];
|
||||
|
||||
return send_raw_bytes({ new_buffer_array, SIZE + 1 });
|
||||
}
|
||||
|
||||
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) = 0;
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0;
|
||||
|
||||
private:
|
||||
const Type m_type;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) = 0;
|
||||
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) = 0;
|
||||
|
||||
virtual BAN::ErrorOr<void> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0;
|
||||
virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0;
|
||||
|
||||
virtual Socket::Domain domain() const = 0;
|
||||
virtual size_t header_size() const = 0;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<BAN::RefPtr<Socket>> create_socket(Socket::Domain, Socket::Type, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> connect_sockets(Socket::Domain, BAN::RefPtr<Socket>, BAN::RefPtr<Socket>);
|
||||
|
||||
void on_receive(NetworkInterface&, BAN::ConstByteSpan, uint32_t validated_cksums);
|
||||
void on_receive(NetworkInterface&, BAN::ConstByteSpan);
|
||||
|
||||
private:
|
||||
NetworkManager() {}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Kernel
|
||||
virtual void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) = 0;
|
||||
virtual NetworkProtocol protocol() const = 0;
|
||||
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len, uint32_t validated_cksums) = 0;
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0;
|
||||
|
||||
bool is_bound() const { return m_address_len >= static_cast<socklen_t>(sizeof(sa_family_t)) && m_address.ss_family != AF_UNSPEC; }
|
||||
in_port_t bound_port() const
|
||||
@@ -54,7 +54,7 @@ namespace Kernel
|
||||
protected:
|
||||
NetworkSocket(NetworkLayer&, const Socket::Info&);
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(unsigned long request, void* arg) override;
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int request, void* arg) override;
|
||||
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override = 0;
|
||||
|
||||
|
||||
@@ -7,25 +7,25 @@ namespace Kernel
|
||||
|
||||
enum RTL8169_IO_REGS : uint16_t
|
||||
{
|
||||
RTL8169_IO_IDR0 = 0x00,
|
||||
RTL8169_IO_IDR1 = 0x01,
|
||||
RTL8169_IO_IDR2 = 0x02,
|
||||
RTL8169_IO_IDR3 = 0x03,
|
||||
RTL8169_IO_IDR4 = 0x04,
|
||||
RTL8169_IO_IDR5 = 0x05,
|
||||
RTL8169_IO_IDR0 = 0x00,
|
||||
RTL8169_IO_IDR1 = 0x01,
|
||||
RTL8169_IO_IDR2 = 0x02,
|
||||
RTL8169_IO_IDR3 = 0x03,
|
||||
RTL8169_IO_IDR4 = 0x04,
|
||||
RTL8169_IO_IDR5 = 0x05,
|
||||
|
||||
RTL8169_IO_TNPDS = 0x20,
|
||||
RTL8169_IO_CR = 0x37,
|
||||
RTL8169_IO_TPPoll = 0x38,
|
||||
RTL8169_IO_IMR = 0x3C,
|
||||
RTL8169_IO_ISR = 0x3E,
|
||||
RTL8169_IO_TCR = 0x40,
|
||||
RTL8169_IO_RCR = 0x44,
|
||||
RTL8169_IO_PHYSts = 0x6C,
|
||||
RTL8169_IO_RMS = 0xDA,
|
||||
RTL8169_IO_CPlusCR = 0xE0,
|
||||
RTL8169_IO_RDSAR = 0xE4,
|
||||
RTL8169_IO_MTPS = 0xEC,
|
||||
RTL8169_IO_TNPDS = 0x20,
|
||||
RTL8169_IO_CR = 0x37,
|
||||
RTL8169_IO_TPPoll = 0x38,
|
||||
RTL8169_IO_IMR = 0x3C,
|
||||
RTL8169_IO_ISR = 0x3E,
|
||||
RTL8169_IO_TCR = 0x40,
|
||||
RTL8169_IO_RCR = 0x44,
|
||||
RTL8169_IO_9346CR = 0x50,
|
||||
RTL8169_IO_PHYSts = 0x6C,
|
||||
RTL8169_IO_RMS = 0xDA,
|
||||
RTL8169_IO_RDSAR = 0xE4,
|
||||
RTL8169_IO_MTPS = 0xEC,
|
||||
};
|
||||
|
||||
enum RTL8169_CR : uint8_t
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Kernel
|
||||
virtual bool link_up() override { return m_link_up; }
|
||||
virtual int link_speed() override;
|
||||
|
||||
virtual size_t payload_mtu() const override { return 0x1FF8 - sizeof(EthernetHeader); }
|
||||
virtual size_t payload_mtu() const override { return 7436 - sizeof(EthernetHeader); }
|
||||
|
||||
virtual void handle_irq() override;
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) override;
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan>) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
@@ -64,17 +64,14 @@ namespace Kernel
|
||||
BAN::UniqPtr<DMARegion> m_rx_descriptor_region;
|
||||
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
||||
|
||||
BAN::Atomic<bool> m_rx_thread_should_die { false };
|
||||
BAN::Atomic<bool> m_rx_thread_is_dead { true };
|
||||
SpinLock m_lock;
|
||||
|
||||
uint32_t m_rx_head { 0 };
|
||||
SpinLock m_rx_lock;
|
||||
ThreadBlocker m_rx_blocker;
|
||||
bool m_thread_should_die { false };
|
||||
BAN::Atomic<bool> m_thread_is_dead { true };
|
||||
ThreadBlocker m_thread_blocker;
|
||||
|
||||
BAN::Atomic<uint32_t> m_tx_head { 0 };
|
||||
BAN::Atomic<uint32_t> m_tx_commit { 0 };
|
||||
SpinLock m_tx_lock;
|
||||
ThreadBlocker m_tx_blocker;
|
||||
uint32_t m_rx_current { 0 };
|
||||
size_t m_tx_current { 0 };
|
||||
|
||||
BAN::MACAddress m_mac_address {};
|
||||
BAN::Atomic<bool> m_link_up { false };
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <kernel/Memory/ByteRingBuffer.h>
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
#include <kernel/Networking/NetworkSocket.h>
|
||||
#include <kernel/Thread.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
|
||||
namespace Kernel
|
||||
@@ -65,9 +66,9 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len, uint32_t validated_cksums) override;
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||
|
||||
bool can_read_impl() const override;
|
||||
bool can_write_impl() const override;
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Kernel
|
||||
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override;
|
||||
|
||||
protected:
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len, uint32_t validated_cksums) override;
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||
|
||||
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||
BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
|
||||
@@ -41,7 +41,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
bool can_read_impl() const override { return !m_packets.empty(); }
|
||||
bool can_write_impl() const override { return true; }
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <kernel/FS/Socket.h>
|
||||
#include <kernel/FS/TmpFS/Inode.h>
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/Memory/VirtualRange.h>
|
||||
#include <kernel/OpenFileDescriptorSet.h>
|
||||
|
||||
namespace Kernel
|
||||
@@ -31,7 +30,6 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace Kernel
|
||||
BAN::ErrorOr<int> dup2(int, int);
|
||||
|
||||
BAN::ErrorOr<int> fcntl(int fd, int cmd, uintptr_t extra);
|
||||
BAN::ErrorOr<long> ioctl(int fd, unsigned long request, void* arg);
|
||||
|
||||
BAN::ErrorOr<off_t> seek(int fd, off_t offset, int whence);
|
||||
BAN::ErrorOr<off_t> tell(int) const;
|
||||
@@ -59,8 +58,6 @@ namespace Kernel
|
||||
BAN::ErrorOr<size_t> recvmsg(int socket, msghdr& message, int flags);
|
||||
BAN::ErrorOr<size_t> sendmsg(int socket, const msghdr& message, int flags);
|
||||
|
||||
int get_max_open_fd() const;
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
|
||||
BAN::ErrorOr<BAN::String> path_of(int) const;
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> inode_of(int);
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/ACPI/AML/Node.h>
|
||||
#include <kernel/InterruptNumbers.h>
|
||||
#include <kernel/Interruptable.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
#include <kernel/Storage/StorageController.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -180,7 +179,7 @@ namespace Kernel::PCI
|
||||
private:
|
||||
struct PCIeInfo
|
||||
{
|
||||
paddr_t bus_paddr[256] {};
|
||||
paddr_t bus_paddr[256];
|
||||
};
|
||||
|
||||
PCIManager() = default;
|
||||
|
||||
@@ -10,10 +10,10 @@ namespace Kernel
|
||||
{
|
||||
public:
|
||||
virtual void eoi(uint8_t) override;
|
||||
virtual void enable_irq(uint8_t, bool level_triggered) override;
|
||||
virtual void enable_irq(uint8_t) override;
|
||||
virtual bool is_in_service(uint8_t) override;
|
||||
|
||||
virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq, bool shared) override;
|
||||
virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq) override;
|
||||
virtual BAN::Optional<uint8_t> get_free_irq() override;
|
||||
|
||||
virtual void initialize_multiprocessor() override;
|
||||
@@ -29,8 +29,7 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
SpinLock m_lock;
|
||||
uint16_t m_used_irqs { 1u << 2 };
|
||||
uint16_t m_excl_irqs { 1u << 2 };
|
||||
uint16_t m_reserved_irqs { 1u << 2 };
|
||||
|
||||
friend class InterruptController;
|
||||
};
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <poll.h>
|
||||
#include <sys/banan-os.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -27,6 +26,8 @@
|
||||
#include <sys/time.h>
|
||||
#include <termios.h>
|
||||
|
||||
struct epoll_event;
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
@@ -43,10 +44,10 @@ namespace Kernel
|
||||
~Process();
|
||||
void cleanup_function(Thread*);
|
||||
|
||||
BAN::ErrorOr<vaddr_t> setup_initial_process_stack(MemoryBackedRegion&, BAN::Span<BAN::String> argv, BAN::Span<BAN::String> envp, BAN::Span<LibELF::AuxiliaryVector> auxv);
|
||||
|
||||
void register_to_scheduler();
|
||||
void exit(int status, int signal);
|
||||
|
||||
void add_thread(Thread*);
|
||||
// returns true if thread was the last one
|
||||
bool on_thread_exit(Thread&);
|
||||
|
||||
@@ -67,6 +68,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<long> sys_exec(const char* path, const char* const* argv, const char* const* envp);
|
||||
|
||||
BAN::ErrorOr<long> sys_wait(pid_t pid, int* stat_loc, int options);
|
||||
BAN::ErrorOr<long> sys_sleep(int seconds);
|
||||
BAN::ErrorOr<long> sys_nanosleep(const timespec* rqtp, timespec* rmtp);
|
||||
BAN::ErrorOr<long> sys_setitimer(int which, const itimerval* value, itimerval* ovalue);
|
||||
|
||||
@@ -135,7 +137,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<long> sys_recvmsg(int socket, msghdr* message, int flags);
|
||||
BAN::ErrorOr<long> sys_sendmsg(int socket, const msghdr* message, int flags);
|
||||
|
||||
BAN::ErrorOr<long> sys_ioctl(int fildes, unsigned long request, void* arg);
|
||||
BAN::ErrorOr<long> sys_ioctl(int fildes, int request, void* arg);
|
||||
|
||||
BAN::ErrorOr<long> sys_pselect(sys_pselect_t* arguments);
|
||||
BAN::ErrorOr<long> sys_ppoll(pollfd* fds, nfds_t nfds, const timespec* tmp_p, const sigset_t* sigmask);
|
||||
@@ -178,10 +180,9 @@ namespace Kernel
|
||||
BAN::ErrorOr<long> sys_mprotect(void* addr, size_t len, int prot);
|
||||
BAN::ErrorOr<long> sys_msync(void* addr, size_t len, int flags);
|
||||
|
||||
BAN::ErrorOr<long> sys_shmget(key_t key, size_t size, int shmflg);
|
||||
BAN::ErrorOr<long> sys_shmctl(int shmid, int cmd, struct shmid_ds* buf);
|
||||
BAN::ErrorOr<long> sys_shmat(int shmid, const void* shmaddr, int shmflg);
|
||||
BAN::ErrorOr<long> sys_shmdt(const void* shmaddr);
|
||||
BAN::ErrorOr<long> sys_smo_create(size_t len, int prot);
|
||||
BAN::ErrorOr<long> sys_smo_delete(SharedMemoryObjectManager::Key);
|
||||
BAN::ErrorOr<long> sys_smo_map(SharedMemoryObjectManager::Key);
|
||||
|
||||
BAN::ErrorOr<long> sys_ttyname(int fildes, char* name, size_t namesize);
|
||||
BAN::ErrorOr<long> sys_posix_openpt(int flags);
|
||||
@@ -209,12 +210,12 @@ namespace Kernel
|
||||
BAN::ErrorOr<long> sys_set_gsbase(void*);
|
||||
BAN::ErrorOr<long> sys_get_gsbase();
|
||||
|
||||
BAN::ErrorOr<long> sys_thread_create(void (*entry)(void*), void* arg, void* stack_base, size_t stack_size);
|
||||
BAN::ErrorOr<long> sys_thread_exit(void* value);
|
||||
BAN::ErrorOr<long> sys_thread_join(pid_t tid, void** value);
|
||||
BAN::ErrorOr<long> sys_thread_getid();
|
||||
BAN::ErrorOr<long> sys_thread_kill(pid_t tid, int signal);
|
||||
BAN::ErrorOr<long> sys_thread_detach(pid_t tid);
|
||||
BAN::ErrorOr<long> sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg);
|
||||
BAN::ErrorOr<long> sys_pthread_exit(void* value);
|
||||
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, void** value);
|
||||
BAN::ErrorOr<long> sys_pthread_self();
|
||||
BAN::ErrorOr<long> sys_pthread_kill(pthread_t thread, int signal);
|
||||
BAN::ErrorOr<long> sys_pthread_detach(pthread_t thread);
|
||||
|
||||
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*);
|
||||
|
||||
@@ -228,12 +229,11 @@ namespace Kernel
|
||||
|
||||
vaddr_t shared_page_vaddr() const { return m_shared_page_vaddr; }
|
||||
|
||||
PageTable& page_table() { return *m_page_table; }
|
||||
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
|
||||
|
||||
size_t proc_meminfo(off_t offset, BAN::ByteSpan) const;
|
||||
size_t proc_cmdline(off_t offset, BAN::ByteSpan) const;
|
||||
size_t proc_environ(off_t offset, BAN::ByteSpan) const;
|
||||
size_t proc_cputime(off_t offset, BAN::ByteSpan) const;
|
||||
BAN::ErrorOr<BAN::String> proc_cwd() const;
|
||||
BAN::ErrorOr<BAN::String> proc_exe() const;
|
||||
|
||||
@@ -255,8 +255,6 @@ namespace Kernel
|
||||
const VirtualFileSystem::File& working_directory() const { return m_working_directory; }
|
||||
const VirtualFileSystem::File& root_file() const { return m_root_file; }
|
||||
|
||||
BAN::ErrorOr<AddressRange> find_free_address_range(size_t size);
|
||||
|
||||
private:
|
||||
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
|
||||
static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0);
|
||||
@@ -282,11 +280,13 @@ namespace Kernel
|
||||
// You must hold reader end of m_mapped_region_lock when calling this.
|
||||
size_t find_mapped_region(vaddr_t) const;
|
||||
|
||||
BAN::ErrorOr<AddressRange> find_free_address_range(size_t size);
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> find_file(int fd, const char* path, int flags) const;
|
||||
BAN::ErrorOr<FileParent> find_parent_file(int fd, const char* path, int flags) const;
|
||||
BAN::ErrorOr<VirtualFileSystem::File> find_relative_parent(int fd, const char* path) const;
|
||||
|
||||
BAN::ErrorOr<void> validate_and_pin_pointer_access(const void*, size_t, bool needs_write, BAN::Vector<MemoryRegion*>&);
|
||||
BAN::ErrorOr<MemoryRegion*> validate_and_pin_pointer_access(const void*, size_t, bool needs_write);
|
||||
|
||||
uint64_t signal_pending_mask() const
|
||||
{
|
||||
@@ -364,13 +364,13 @@ namespace Kernel
|
||||
|
||||
BAN::Vector<Thread*> m_threads;
|
||||
|
||||
struct exited_thread_info_t
|
||||
struct pthread_info_t
|
||||
{
|
||||
pid_t tid;
|
||||
pthread_t thread;
|
||||
void* value;
|
||||
};
|
||||
BAN::Vector<exited_thread_info_t> m_exited_threads;
|
||||
ThreadBlocker m_thread_exit_blocker;
|
||||
BAN::Vector<pthread_info_t> m_exited_pthreads;
|
||||
ThreadBlocker m_pthread_exit_blocker;
|
||||
|
||||
uint64_t m_alarm_interval_ns { 0 };
|
||||
uint64_t m_alarm_wake_time_ns { 0 };
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Array.h>
|
||||
#include <BAN/Atomic.h>
|
||||
#include <BAN/NoCopyMove.h>
|
||||
#include <BAN/ForwardList.h>
|
||||
#include <BAN/Math.h>
|
||||
|
||||
#include <kernel/API/SharedPage.h>
|
||||
#include <kernel/Arch.h>
|
||||
#include <kernel/GDT.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <kernel/InterruptStack.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
#include <kernel/ProcessorID.h>
|
||||
#include <kernel/Scheduler.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -19,11 +22,6 @@ namespace Kernel
|
||||
Enabled,
|
||||
};
|
||||
|
||||
class GDT;
|
||||
class IDT;
|
||||
class Scheduler;
|
||||
class Thread;
|
||||
|
||||
#if ARCH(x86_64) || ARCH(i686)
|
||||
class Processor
|
||||
{
|
||||
@@ -53,18 +51,12 @@ namespace Kernel
|
||||
union
|
||||
{
|
||||
TLBEntry flush_tlb;
|
||||
Thread* new_thread;
|
||||
Thread* unblock_thread;
|
||||
SchedulerQueue::Node* new_thread;
|
||||
SchedulerQueue::Node* unblock_thread;
|
||||
bool dummy;
|
||||
};
|
||||
};
|
||||
|
||||
struct LoadStats
|
||||
{
|
||||
uint64_t ns_idle;
|
||||
uint64_t ns_total;
|
||||
};
|
||||
|
||||
public:
|
||||
static Processor& create(ProcessorID id);
|
||||
static Processor& initialize();
|
||||
@@ -80,6 +72,9 @@ namespace Kernel
|
||||
static void set_smp_enabled() { s_is_smp_enabled = true; }
|
||||
static void wait_until_processors_ready();
|
||||
|
||||
static void toggle_should_print_cpu_load() { s_should_print_cpu_load = !s_should_print_cpu_load; }
|
||||
static bool get_should_print_cpu_load() { return s_should_print_cpu_load; }
|
||||
|
||||
static ProcessorID bsp_id() { return s_bsp_id; }
|
||||
static bool current_is_bsp() { return current_id() == bsp_id(); }
|
||||
|
||||
@@ -106,17 +101,10 @@ namespace Kernel
|
||||
static void pause()
|
||||
{
|
||||
__builtin_ia32_pause();
|
||||
if (is_smp_enabled() && !smp_messages_disabled())
|
||||
if (is_smp_enabled())
|
||||
handle_smp_messages();
|
||||
}
|
||||
|
||||
static bool smp_messages_disabled() { return read_gs_sized<bool>(offsetof(Processor, m_smp_messages_disabled)); }
|
||||
static void set_disable_smp_messages(bool disabled)
|
||||
{
|
||||
ASSERT(smp_messages_disabled() != disabled);
|
||||
write_gs_sized<bool>(offsetof(Processor, m_smp_messages_disabled), disabled);
|
||||
}
|
||||
|
||||
vaddr_t stack_top_vaddr() const { return m_stack_vaddr + s_stack_size; }
|
||||
paddr_t stack_top_paddr() const { return m_stack_paddr + s_stack_size; }
|
||||
|
||||
@@ -128,12 +116,10 @@ namespace Kernel
|
||||
static void* get_current_page_table() { return read_gs_sized<void*>(offsetof(Processor, m_current_page_table)); }
|
||||
static void set_current_page_table(void* page_table) { write_gs_sized<void*>(offsetof(Processor, m_current_page_table), page_table); }
|
||||
|
||||
static LoadStats get_load_stats(size_t index);
|
||||
|
||||
static void yield();
|
||||
static Scheduler& scheduler() { return *read_gs_sized<Scheduler*>(offsetof(Processor, m_scheduler)); }
|
||||
|
||||
static void initialize_tsc(uint64_t realtime_seconds);
|
||||
static void initialize_tsc(uint8_t shift, uint64_t mult, uint64_t realtime_seconds);
|
||||
static void update_tsc();
|
||||
static uint64_t ns_since_boot_tsc();
|
||||
|
||||
@@ -181,23 +167,17 @@ namespace Kernel
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T read_gs_sized(uintptr_t offset) requires(sizeof(T) <= sizeof(uintptr_t) && BAN::Math::is_power_of_two(sizeof(T)))
|
||||
static T read_gs_sized(uintptr_t offset) requires(sizeof(T) <= 8 && BAN::Math::is_power_of_two(sizeof(T)))
|
||||
{
|
||||
T value;
|
||||
if constexpr (sizeof(T) == 1 && ARCH(i686))
|
||||
asm volatile("mov %%gs:%a[offset], %[value]" : [value]"=q"(value) : [offset]"ir"(offset) : "memory");
|
||||
else
|
||||
asm volatile("mov %%gs:%a[offset], %[value]" : [value]"=r"(value) : [offset]"ir"(offset) : "memory");
|
||||
asm volatile("mov %%gs:%a[offset], %[value]" : [value]"=r"(value) : [offset]"ir"(offset));
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void write_gs_sized(uintptr_t offset, T value) requires(sizeof(T) <= sizeof(uintptr_t) && BAN::Math::is_power_of_two(sizeof(T)))
|
||||
static void write_gs_sized(uintptr_t offset, T value) requires(sizeof(T) <= 8 && BAN::Math::is_power_of_two(sizeof(T)))
|
||||
{
|
||||
if constexpr (sizeof(T) == 1 && ARCH(i686))
|
||||
asm volatile("mov %[value], %%gs:%a[offset]" :: [value]"q"(value), [offset]"ir"(offset) : "memory");
|
||||
else
|
||||
asm volatile("mov %[value], %%gs:%a[offset]" :: [value]"r"(value), [offset]"ir"(offset) : "memory");
|
||||
asm volatile("mov %[value], %%gs:%a[offset]" :: [value]"r"(value), [offset]"ir"(offset) : "memory");
|
||||
}
|
||||
|
||||
void lock_tlb_lock();
|
||||
@@ -207,14 +187,13 @@ namespace Kernel
|
||||
static ProcessorID s_bsp_id;
|
||||
static BAN::Atomic<uint8_t> s_processor_count;
|
||||
static BAN::Atomic<bool> s_is_smp_enabled;
|
||||
static BAN::Atomic<bool> s_should_print_cpu_load;
|
||||
static paddr_t s_shared_page_paddr;
|
||||
static vaddr_t s_shared_page_vaddr;
|
||||
|
||||
ProcessorID m_id { 0 };
|
||||
uint8_t m_index { 0 };
|
||||
|
||||
bool m_smp_messages_disabled { false };
|
||||
|
||||
vaddr_t m_thread_syscall_stack;
|
||||
|
||||
Thread* m_sse_thread { nullptr };
|
||||
@@ -228,9 +207,10 @@ namespace Kernel
|
||||
|
||||
Scheduler* m_scheduler { nullptr };
|
||||
|
||||
BAN::Atomic<bool> m_load_stat_lock;
|
||||
uint64_t m_load_start_ns { 0 };
|
||||
LoadStats m_load_stats {};
|
||||
uint64_t m_start_ns { 0 };
|
||||
uint64_t m_idle_ns { 0 };
|
||||
uint64_t m_last_update_ns { 0 };
|
||||
uint64_t m_next_update_ns { 0 };
|
||||
|
||||
BAN::Atomic<SMPMessage*> m_smp_pending { nullptr };
|
||||
BAN::Atomic<SMPMessage*> m_smp_free { nullptr };
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <BAN/NoCopyMove.h>
|
||||
#include <kernel/InterruptStack.h>
|
||||
#include <kernel/ProcessorID.h>
|
||||
#include <kernel/SchedulerThreadNode.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -15,6 +14,29 @@ namespace Kernel
|
||||
class BaseMutex;
|
||||
class Thread;
|
||||
class ThreadBlocker;
|
||||
struct SchedulerQueueNode;
|
||||
|
||||
class SchedulerQueue
|
||||
{
|
||||
public:
|
||||
using Node = SchedulerQueueNode;
|
||||
|
||||
public:
|
||||
void add_thread_to_back(Node*);
|
||||
void add_thread_with_wake_time(Node*);
|
||||
template<typename F>
|
||||
Node* remove_with_condition(F callback);
|
||||
void remove_node(Node*);
|
||||
Node* front();
|
||||
Node* pop_front();
|
||||
|
||||
bool empty() const { return m_head == nullptr; }
|
||||
|
||||
private:
|
||||
Node* m_head { nullptr };
|
||||
Node* m_tail { nullptr };
|
||||
};
|
||||
|
||||
class Scheduler
|
||||
{
|
||||
BAN_NON_COPYABLE(Scheduler);
|
||||
@@ -23,12 +45,12 @@ namespace Kernel
|
||||
public:
|
||||
struct NewThreadRequest
|
||||
{
|
||||
SchedulerThreadNode* node;
|
||||
SchedulerQueue::Node* node;
|
||||
};
|
||||
|
||||
struct UnblockRequest
|
||||
{
|
||||
SchedulerThreadNode* node;
|
||||
SchedulerQueue::Node* node;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -36,13 +58,13 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
void reschedule(YieldRegisters*);
|
||||
void reschedule_if_needed();
|
||||
void reschedule_if_idle();
|
||||
|
||||
void on_timer_interrupt();
|
||||
void on_yield(YieldRegisters*);
|
||||
void timer_interrupt();
|
||||
|
||||
static void bind_thread_to_processor(Thread*, ProcessorID);
|
||||
void add_thread(Thread*);
|
||||
static BAN::ErrorOr<void> bind_thread_to_processor(Thread*, ProcessorID);
|
||||
// if thread is already bound, this will never fail
|
||||
BAN::ErrorOr<void> add_thread(Thread*);
|
||||
|
||||
void block_current_thread(ThreadBlocker* thread_blocker, uint64_t wake_time_ns, BaseMutex* mutex);
|
||||
void unblock_thread(Thread*);
|
||||
@@ -56,21 +78,23 @@ namespace Kernel
|
||||
private:
|
||||
Scheduler() = default;
|
||||
|
||||
void add_current_to_most_loaded(void* target_list);
|
||||
void update_most_loaded_node_list(SchedulerThreadNode*, void* target_list);
|
||||
void remove_node_from_most_loaded(SchedulerThreadNode*);
|
||||
void add_current_to_most_loaded(SchedulerQueue* target_queue);
|
||||
void update_most_loaded_node_queue(SchedulerQueue::Node*, SchedulerQueue* target_queue);
|
||||
void remove_node_from_most_loaded(SchedulerQueue::Node*);
|
||||
|
||||
void update_wake_up_deadline();
|
||||
void wake_up_sleeping_threads();
|
||||
|
||||
void do_load_balancing();
|
||||
|
||||
class ProcessorID find_least_loaded_processor() const;
|
||||
|
||||
void add_thread(SchedulerQueue::Node*);
|
||||
void unblock_thread(SchedulerQueue::Node*);
|
||||
|
||||
private:
|
||||
SchedulerQueue m_run_list;
|
||||
SchedulerHeap m_block_list;
|
||||
SchedulerThreadNode* m_current { nullptr };
|
||||
SchedulerQueue m_run_queue;
|
||||
SchedulerQueue m_block_queue;
|
||||
SchedulerQueue::Node* m_current { nullptr };
|
||||
|
||||
uint32_t m_thread_count { 0 };
|
||||
|
||||
@@ -82,8 +106,8 @@ namespace Kernel
|
||||
|
||||
struct ThreadInfo
|
||||
{
|
||||
void* list { nullptr };
|
||||
SchedulerThreadNode* node { nullptr };
|
||||
SchedulerQueue* queue { nullptr };
|
||||
SchedulerQueue::Node* node { nullptr };
|
||||
};
|
||||
BAN::Array<ThreadInfo, 10> m_most_loaded_threads;
|
||||
|
||||
@@ -92,8 +116,6 @@ namespace Kernel
|
||||
|
||||
bool m_should_calculate_max_load_threads { true };
|
||||
|
||||
bool m_has_pending_reschedule { false };
|
||||
|
||||
Thread* m_idle_thread { nullptr };
|
||||
|
||||
friend class ThreadBlocker;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/ProcessorID.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class Thread;
|
||||
class ThreadBlocker;
|
||||
|
||||
struct SchedulerQueueNode
|
||||
{
|
||||
SchedulerQueueNode(Thread* thread)
|
||||
: thread(thread)
|
||||
{}
|
||||
|
||||
Thread* const thread;
|
||||
|
||||
SchedulerQueueNode* next { nullptr };
|
||||
SchedulerQueueNode* prev { nullptr };
|
||||
|
||||
uint64_t wake_time_ns { static_cast<uint64_t>(-1) };
|
||||
|
||||
BAN::Atomic<ThreadBlocker*> blocker { nullptr };
|
||||
SchedulerQueueNode* block_chain_prev { nullptr };
|
||||
SchedulerQueueNode* block_chain_next { nullptr };
|
||||
|
||||
ProcessorID processor_id { PROCESSOR_NONE };
|
||||
bool blocked { false };
|
||||
|
||||
uint64_t last_start_ns { 0 };
|
||||
uint64_t time_used_ns { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Atomic.h>
|
||||
#include <BAN/NoCopyMove.h>
|
||||
#include <kernel/ProcessorID.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class Thread;
|
||||
class ThreadBlocker;
|
||||
|
||||
struct SchedulerThreadNode
|
||||
{
|
||||
SchedulerThreadNode(Thread* thread)
|
||||
: thread(thread)
|
||||
, heap({ nullptr, nullptr, nullptr })
|
||||
{}
|
||||
|
||||
Thread* const thread;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
SchedulerThreadNode* next;
|
||||
SchedulerThreadNode* prev;
|
||||
} queue;
|
||||
struct
|
||||
{
|
||||
SchedulerThreadNode* parent;
|
||||
SchedulerThreadNode* lchild;
|
||||
SchedulerThreadNode* rchild;
|
||||
} heap;
|
||||
};
|
||||
|
||||
uint64_t wake_time_ns { static_cast<uint64_t>(-1) };
|
||||
|
||||
BAN::Atomic<ThreadBlocker*> blocker { nullptr };
|
||||
SchedulerThreadNode* block_chain_prev { nullptr };
|
||||
SchedulerThreadNode* block_chain_next { nullptr };
|
||||
|
||||
ProcessorID processor_id { PROCESSOR_NONE };
|
||||
bool blocked { false };
|
||||
|
||||
uint64_t last_start_ns { 0 };
|
||||
uint64_t time_used_ns { 0 };
|
||||
};
|
||||
|
||||
class SchedulerQueue
|
||||
{
|
||||
BAN_NON_COPYABLE(SchedulerQueue);
|
||||
BAN_NON_MOVABLE(SchedulerQueue);
|
||||
public:
|
||||
SchedulerQueue() = default;
|
||||
|
||||
SchedulerThreadNode* front();
|
||||
SchedulerThreadNode* pop_front();
|
||||
|
||||
void push(SchedulerThreadNode*);
|
||||
void pop(SchedulerThreadNode*);
|
||||
|
||||
void walk(void (*)(const SchedulerThreadNode*, void*), void*) const;
|
||||
bool empty() const { return m_head == nullptr; }
|
||||
|
||||
private:
|
||||
SchedulerThreadNode* m_head { nullptr };
|
||||
SchedulerThreadNode* m_tail { nullptr };
|
||||
};
|
||||
|
||||
class SchedulerHeap
|
||||
{
|
||||
BAN_NON_COPYABLE(SchedulerHeap);
|
||||
BAN_NON_MOVABLE(SchedulerHeap);
|
||||
public:
|
||||
SchedulerHeap() = default;
|
||||
|
||||
SchedulerThreadNode* front();
|
||||
SchedulerThreadNode* pop_front();
|
||||
|
||||
void push(SchedulerThreadNode*);
|
||||
void pop(SchedulerThreadNode*);
|
||||
|
||||
void walk(void (*)(const SchedulerThreadNode*, void*), void*) const;
|
||||
bool empty() const { return m_root == nullptr; }
|
||||
|
||||
private:
|
||||
void walk_impl(void (*)(const SchedulerThreadNode*, void*), void*, const SchedulerThreadNode*) const;
|
||||
void swap_nodes(SchedulerThreadNode*, SchedulerThreadNode*);
|
||||
|
||||
private:
|
||||
SchedulerThreadNode* m_root { nullptr };
|
||||
SchedulerThreadNode* m_last { nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
@@ -10,19 +10,16 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class AHCIController final : public BAN::RefCounted<AHCIController>, public Interruptable
|
||||
class AHCIController final : public StorageController, public Interruptable
|
||||
{
|
||||
BAN_NON_COPYABLE(AHCIController);
|
||||
BAN_NON_MOVABLE(AHCIController);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<AHCIController>> create(PCI::Device&);
|
||||
|
||||
~AHCIController();
|
||||
|
||||
virtual void handle_irq() override;
|
||||
|
||||
bool supports_64bit() const { return m_supports_64bit; }
|
||||
uint32_t command_slot_count() const { return m_command_slot_count; }
|
||||
|
||||
private:
|
||||
@@ -30,7 +27,6 @@ namespace Kernel
|
||||
: m_pci_device(pci_device)
|
||||
{ }
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
BAN::Optional<AHCIPortType> check_port_type(volatile HBAPortMemorySpace&);
|
||||
|
||||
private:
|
||||
@@ -39,8 +35,9 @@ namespace Kernel
|
||||
|
||||
BAN::Array<AHCIDevice*, 32> m_devices;
|
||||
|
||||
bool m_supports_64bit { false };
|
||||
uint32_t m_command_slot_count { 0 };
|
||||
|
||||
friend class ATAController;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
static constexpr uint32_t s_hba_prdt_count { 8 };
|
||||
|
||||
struct FISRegisterH2D
|
||||
{
|
||||
uint8_t fis_type; // FIS_TYPE_REGISTER_H2D
|
||||
@@ -59,8 +61,7 @@ namespace Kernel
|
||||
uint8_t control;
|
||||
|
||||
uint8_t __reserved1[4];
|
||||
};
|
||||
static_assert(sizeof(FISRegisterH2D) == 20);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct FISRegisterD2H
|
||||
{
|
||||
@@ -89,8 +90,7 @@ namespace Kernel
|
||||
uint8_t __reserved3[2];
|
||||
|
||||
uint8_t __reserved4[4];
|
||||
};
|
||||
static_assert(sizeof(FISRegisterD2H) == 20);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct FISDataBI
|
||||
{
|
||||
@@ -102,8 +102,7 @@ namespace Kernel
|
||||
uint8_t __reserved1[2];
|
||||
|
||||
uint32_t data[0]; // Payload (1 - 2048 dwords)
|
||||
};
|
||||
static_assert(sizeof(FISDataBI) == 4);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct SetDeviceBitsD2H
|
||||
{
|
||||
@@ -118,8 +117,7 @@ namespace Kernel
|
||||
uint8_t error;
|
||||
|
||||
uint32_t __reserved1;
|
||||
};
|
||||
static_assert(sizeof(SetDeviceBitsD2H) == 8);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct PIOSetupD2H
|
||||
{
|
||||
@@ -151,8 +149,7 @@ namespace Kernel
|
||||
|
||||
uint16_t tc; // Transfer count
|
||||
uint8_t __reserved4[2];
|
||||
};
|
||||
static_assert(sizeof(PIOSetupD2H) == 20);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct DMASetupBI
|
||||
{
|
||||
@@ -166,8 +163,8 @@ namespace Kernel
|
||||
|
||||
uint8_t __reserved1[2];
|
||||
|
||||
uint32_t dma_buffer_id_lo; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory.
|
||||
uint32_t dma_buffer_id_hi; // SATA Spec says host specific and not in Spec. Trying AHCI spec might work.
|
||||
uint64_t dma_buffer_id; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory.
|
||||
// SATA Spec says host specific and not in Spec. Trying AHCI spec might work.
|
||||
|
||||
uint32_t __reserved2;
|
||||
|
||||
@@ -176,8 +173,7 @@ namespace Kernel
|
||||
uint32_t dma_transfer_count; // Number of bytes to transfer. Bit 0 must be 0
|
||||
|
||||
uint32_t __reserved3;
|
||||
};
|
||||
static_assert(sizeof(DMASetupBI) == 28);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct HBAPortMemorySpace
|
||||
{
|
||||
@@ -200,8 +196,7 @@ namespace Kernel
|
||||
uint32_t fbs; // FIS-based switch control
|
||||
uint32_t __reserved1[11];
|
||||
uint32_t vendor[4];
|
||||
};
|
||||
static_assert(sizeof(HBAPortMemorySpace) == 128);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct HBAGeneralMemorySpace
|
||||
{
|
||||
@@ -222,8 +217,7 @@ namespace Kernel
|
||||
uint8_t vendor[0x100-0xA0];
|
||||
|
||||
HBAPortMemorySpace ports[0]; // 1 - 32 ports
|
||||
};
|
||||
static_assert(sizeof(HBAGeneralMemorySpace) == 256);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ReceivedFIS
|
||||
{
|
||||
@@ -241,8 +235,7 @@ namespace Kernel
|
||||
uint8_t ufis[64];
|
||||
|
||||
uint8_t __reserved[0x100-0xA0];
|
||||
};
|
||||
static_assert(sizeof(ReceivedFIS) == 256);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct HBACommandHeader
|
||||
{
|
||||
@@ -259,14 +252,13 @@ namespace Kernel
|
||||
|
||||
uint16_t prdtl; // Physical region descriptor table length in entries
|
||||
|
||||
uint32_t prdbc; // Physical region descriptor byte count transferred
|
||||
volatile uint32_t prdbc; // Physical region descriptor byte count transferred
|
||||
|
||||
uint32_t ctba; // Command table descriptor base address
|
||||
uint32_t ctbau; // Command table descriptor base address upper 32 bits
|
||||
|
||||
uint32_t __reserved1[4];
|
||||
};
|
||||
static_assert(sizeof(HBACommandHeader) == 32);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct HBAPRDTEntry
|
||||
{
|
||||
@@ -277,17 +269,15 @@ namespace Kernel
|
||||
uint32_t dbc : 22; // Byte count, 4M max
|
||||
uint32_t __reserved1 : 9;
|
||||
uint32_t i : 1; // Interrupt on completion
|
||||
};
|
||||
static_assert(sizeof(HBAPRDTEntry) == 16);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct HBACommandTable
|
||||
{
|
||||
uint8_t cfis[64];
|
||||
uint8_t acmd[16];
|
||||
uint8_t __reserved[48];
|
||||
HBAPRDTEntry prdt_entry[0];
|
||||
};
|
||||
static_assert(sizeof(HBACommandTable) == 128);
|
||||
HBAPRDTEntry prdt_entry[s_hba_prdt_count];
|
||||
} __attribute__((packed));
|
||||
|
||||
enum class AHCIPortType
|
||||
{
|
||||
|
||||
@@ -20,39 +20,30 @@ namespace Kernel
|
||||
, m_port(port)
|
||||
{ }
|
||||
BAN::ErrorOr<void> initialize();
|
||||
BAN::ErrorOr<void> allocate_buffers();
|
||||
BAN::ErrorOr<void> rebase();
|
||||
BAN::ErrorOr<void> read_identify_data();
|
||||
|
||||
paddr_t read_paddr(volatile uint32_t& lo, volatile uint32_t& hi) const;
|
||||
void write_paddr(volatile uint32_t& lo, volatile uint32_t& hi, paddr_t paddr);
|
||||
|
||||
bool can_use_buffer_directly(BAN::ConstByteSpan buffer) const;
|
||||
|
||||
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan) override;
|
||||
BAN::ErrorOr<size_t> send_command_sync(uint64_t lba, BAN::ConstByteSpan buffer, Command command);
|
||||
BAN::ErrorOr<void> send_command_and_block(uint64_t lba, uint64_t sector_count, Command command);
|
||||
|
||||
BAN::ErrorOr<void> send_command_and_wait(uint32_t slot);
|
||||
BAN::ErrorOr<uint32_t> find_free_command_slot();
|
||||
BAN::Optional<uint32_t> find_free_command_slot();
|
||||
|
||||
void handle_irq();
|
||||
|
||||
private:
|
||||
static constexpr uint32_t m_max_hba_prdt_count { 64 };
|
||||
BAN::ErrorOr<void> block_until_command_completed(uint32_t command_slot);
|
||||
|
||||
BAN::Atomic<uint32_t> m_prev_is { 0 };
|
||||
uint32_t m_free_slots { 0 };
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
|
||||
BAN::RefPtr<AHCIController> m_controller;
|
||||
volatile HBAPortMemorySpace* const m_port;
|
||||
|
||||
BAN::UniqPtr<DMARegion> m_dma_region;
|
||||
|
||||
Mutex m_temp_buffer_mutex;
|
||||
BAN::UniqPtr<DMARegion> m_temp_buffer;
|
||||
|
||||
SpinLock m_command_lock;
|
||||
ThreadBlocker m_command_blocker;
|
||||
// Intermediate read/write buffer
|
||||
// TODO: can we read straight to user buffer?
|
||||
BAN::UniqPtr<DMARegion> m_data_dma_region;
|
||||
|
||||
friend class AHCIController;
|
||||
};
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace Kernel
|
||||
|
||||
// Non-owning pointers
|
||||
BAN::Vector<ATADevice*> m_devices;
|
||||
|
||||
friend class ATAController;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,22 +2,23 @@
|
||||
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <kernel/PCI.h>
|
||||
#include <kernel/Storage/StorageController.h>
|
||||
#include <kernel/Storage/ATA/ATABus.h>
|
||||
#include <kernel/Storage/ATA/ATADevice.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class ATAController : public BAN::RefCounted<ATAController>
|
||||
class ATAController : public StorageController
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ATAController>> create(PCI::Device&);
|
||||
static BAN::ErrorOr<BAN::RefPtr<StorageController>> create(PCI::Device&);
|
||||
virtual BAN::ErrorOr<void> initialize() override;
|
||||
|
||||
private:
|
||||
ATAController(PCI::Device& pci_device)
|
||||
: m_pci_device(pci_device)
|
||||
{ }
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
private:
|
||||
PCI::Device& m_pci_device;
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class NVMeController final : public CharacterDevice
|
||||
class NVMeController final : public StorageController, public CharacterDevice
|
||||
{
|
||||
BAN_NON_COPYABLE(NVMeController);
|
||||
BAN_NON_MOVABLE(NVMeController);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<NVMeController>> create(PCI::Device&);
|
||||
static BAN::ErrorOr<BAN::RefPtr<StorageController>> create(PCI::Device&);
|
||||
|
||||
NVMeQueue& io_queue() { return *m_io_queue; }
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
NVMeController(PCI::Device& pci_device);
|
||||
BAN::ErrorOr<void> initialize();
|
||||
virtual BAN::ErrorOr<void> initialize() override;
|
||||
|
||||
BAN::ErrorOr<void> identify_controller();
|
||||
BAN::ErrorOr<void> identify_namespaces();
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/RefPtr.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class StorageController : public BAN::RefCounted<StorageController>
|
||||
{
|
||||
public:
|
||||
virtual ~StorageController() {}
|
||||
virtual BAN::ErrorOr<void> initialize() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/WeakPtr.h>
|
||||
#include <kernel/Memory/VirtualRange.h>
|
||||
#include <kernel/Terminal/TTY.h>
|
||||
|
||||
namespace Kernel
|
||||
@@ -33,7 +32,7 @@ namespace Kernel
|
||||
|
||||
void on_close(int) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
private:
|
||||
PseudoTerminalMaster(BAN::UniqPtr<VirtualRange>, mode_t, uid_t, gid_t);
|
||||
|
||||
@@ -53,8 +53,6 @@ namespace Kernel
|
||||
|
||||
virtual bool master_has_closed() const { return false; }
|
||||
|
||||
virtual bool is_vtty() const { return false; }
|
||||
|
||||
protected:
|
||||
TTY(termios termios, mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
@@ -70,7 +68,7 @@ namespace Kernel
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
private:
|
||||
bool putchar(uint8_t ch);
|
||||
@@ -102,9 +100,9 @@ namespace Kernel
|
||||
termios m_termios;
|
||||
|
||||
protected:
|
||||
Mutex m_input_mutex;
|
||||
Mutex m_mutex;
|
||||
|
||||
RecursiveSpinLock m_write_lock;
|
||||
Mutex m_write_lock;
|
||||
ThreadBlocker m_write_blocker;
|
||||
};
|
||||
|
||||
|
||||
@@ -21,9 +21,6 @@ namespace Kernel
|
||||
|
||||
void clear() override;
|
||||
|
||||
bool is_vtty() const override { return true; }
|
||||
BAN::ErrorOr<void> set_terminal_driver(BAN::RefPtr<TerminalDriver>);
|
||||
|
||||
protected:
|
||||
BAN::StringView name() const override { return m_name; }
|
||||
bool putchar_impl(uint8_t ch) override;
|
||||
@@ -99,6 +96,8 @@ namespace Kernel
|
||||
uint32_t m_last_cursor_row { static_cast<uint32_t>(-1) };
|
||||
uint32_t m_last_cursor_column { static_cast<uint32_t>(-1) };
|
||||
|
||||
const Palette& m_palette;
|
||||
|
||||
TerminalDriver::Color m_foreground;
|
||||
TerminalDriver::Color m_background;
|
||||
bool m_colors_inverted { false };
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
#include <BAN/RefPtr.h>
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <kernel/InterruptStack.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Memory/VirtualRange.h>
|
||||
#include <kernel/SchedulerThreadNode.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
|
||||
#include <LibELF/AuxiliaryVector.h>
|
||||
|
||||
@@ -19,7 +18,6 @@ namespace Kernel
|
||||
|
||||
class MemoryBackedRegion;
|
||||
class Process;
|
||||
class ThreadBlocker;
|
||||
|
||||
class Thread
|
||||
{
|
||||
@@ -43,20 +41,22 @@ namespace Kernel
|
||||
// TODO: userspace stack size is hard limited, maybe make this dynamic?
|
||||
#if ARCH(x86_64)
|
||||
static constexpr size_t userspace_stack_size { 32 << 20 };
|
||||
static constexpr vaddr_t userspace_stack_base { 0x0000700000000000 };
|
||||
#elif ARCH(i686)
|
||||
static constexpr size_t userspace_stack_size { 4 << 20 };
|
||||
static constexpr vaddr_t userspace_stack_base { 0xB0000000 };
|
||||
#endif
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*);
|
||||
static BAN::ErrorOr<Thread*> create_userspace(Process*, PageTable&, vaddr_t userspace_stack_vaddr, size_t userspace_stack_size, vaddr_t entry_point, vaddr_t stack_pointer);
|
||||
static BAN::ErrorOr<Thread*> create_userspace(Process*, PageTable&);
|
||||
~Thread();
|
||||
|
||||
BAN::ErrorOr<Thread*> pthread_create(entry_t, void*);
|
||||
|
||||
BAN::ErrorOr<Thread*> clone(Process*, uintptr_t sp, uintptr_t ip);
|
||||
void setup_process_cleanup();
|
||||
|
||||
BAN::ErrorOr<void> initialize_userspace(vaddr_t entry, BAN::Span<BAN::String> argv, BAN::Span<BAN::String> envp, BAN::Span<LibELF::AuxiliaryVector> auxv);
|
||||
|
||||
// Returns true, if thread is going to trigger signal
|
||||
bool is_interrupted_by_signal(bool skip_stop_and_cont = false) const;
|
||||
|
||||
@@ -77,21 +77,15 @@ namespace Kernel
|
||||
|
||||
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout
|
||||
// if mutex is not nullptr, it will be atomically freed before blocking and automatically locked on wake
|
||||
BAN::ErrorOr<void> sleep_or_eintr_for_ns(uint64_t timeout_ns);
|
||||
BAN::ErrorOr<void> sleep_or_eintr_until_ns(uint64_t waketime_ns);
|
||||
BAN::ErrorOr<void> sleep_or_eintr_ns(uint64_t ns);
|
||||
BAN::ErrorOr<void> block_or_eintr_indefinite(ThreadBlocker& thread_blocker, BaseMutex* mutex);
|
||||
BAN::ErrorOr<void> block_or_eintr_or_timeout_ns(ThreadBlocker& thread_blocker, uint64_t timeout_ns, bool etimedout, BaseMutex* mutex);
|
||||
BAN::ErrorOr<void> block_or_eintr_or_waketime_ns(ThreadBlocker& thread_blocker, uint64_t wake_time_ns, bool etimedout, BaseMutex* mutex);
|
||||
|
||||
BAN::ErrorOr<void> sleep_or_eintr_for_ms(uint64_t timeout_ms)
|
||||
BAN::ErrorOr<void> sleep_or_eintr_ms(uint64_t ms)
|
||||
{
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(timeout_ms, 1'000'000));
|
||||
return sleep_or_eintr_for_ns(timeout_ms * 1'000'000);
|
||||
}
|
||||
BAN::ErrorOr<void> sleep_or_eintr_until_ms(uint64_t waketime_ms)
|
||||
{
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(waketime_ms, 1'000'000));
|
||||
return sleep_or_eintr_until_ns(waketime_ms * 1'000'000);
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(ms, 1'000'000));
|
||||
return sleep_or_eintr_ns(ms * 1'000'000);
|
||||
}
|
||||
BAN::ErrorOr<void> block_or_eintr_or_timeout_ms(ThreadBlocker& thread_blocker, uint64_t timeout_ms, bool etimedout, BaseMutex* mutex)
|
||||
{
|
||||
@@ -112,6 +106,8 @@ namespace Kernel
|
||||
vaddr_t kernel_stack_top() const { return m_kernel_stack->vaddr() + m_kernel_stack->size(); }
|
||||
VirtualRange& kernel_stack() { return *m_kernel_stack; }
|
||||
|
||||
MemoryBackedRegion& userspace_stack() { ASSERT(is_userspace() && m_userspace_stack); return *m_userspace_stack; }
|
||||
|
||||
static Thread& current();
|
||||
static pid_t current_tid();
|
||||
|
||||
@@ -126,14 +122,10 @@ namespace Kernel
|
||||
|
||||
bool is_userspace() const { return m_is_userspace; }
|
||||
|
||||
uint64_t cpu_time_total_ns() const;
|
||||
void cpu_time_ns(uint64_t& user_ns, uint64_t& system_ns) const;
|
||||
uint64_t cpu_time_ns() const;
|
||||
void set_cpu_time_start();
|
||||
void set_cpu_time_stop();
|
||||
|
||||
void set_is_in_syscall(bool is_in_syscall);
|
||||
bool is_in_syscall() const { return m_is_in_syscall; }
|
||||
|
||||
void update_processor_index_address();
|
||||
|
||||
void set_fsbase(vaddr_t base) { m_fsbase = base; }
|
||||
@@ -159,6 +151,8 @@ namespace Kernel
|
||||
private:
|
||||
Thread(pid_t tid, Process*);
|
||||
|
||||
void setup_exec(vaddr_t ip, vaddr_t sp);
|
||||
|
||||
static void on_exit_trampoline(Thread*);
|
||||
void on_exit();
|
||||
|
||||
@@ -180,6 +174,7 @@ namespace Kernel
|
||||
BAN::UniqPtr<PageTable> m_keep_alive_page_table;
|
||||
|
||||
BAN::UniqPtr<VirtualRange> m_kernel_stack;
|
||||
MemoryBackedRegion* m_userspace_stack { nullptr };
|
||||
const pid_t m_tid { 0 };
|
||||
State m_state { State::NotStarted };
|
||||
Process* m_process { nullptr };
|
||||
@@ -187,13 +182,10 @@ namespace Kernel
|
||||
BAN::Atomic<bool> m_is_detached { false };
|
||||
bool m_delete_process { false };
|
||||
|
||||
vaddr_t m_userspace_stack_vaddr { 0 };
|
||||
size_t m_userspace_stack_size { 0 };
|
||||
|
||||
vaddr_t m_fsbase { 0 };
|
||||
vaddr_t m_gsbase { 0 };
|
||||
|
||||
SchedulerThreadNode m_scheduler_node;
|
||||
SchedulerQueue::Node* m_scheduler_node { nullptr };
|
||||
|
||||
YieldRegisters m_yield_registers { };
|
||||
|
||||
@@ -206,10 +198,8 @@ namespace Kernel
|
||||
static_assert(_SIGMAX < 64);
|
||||
|
||||
mutable SpinLock m_cpu_time_lock;
|
||||
uint64_t m_cpu_time_user_ns { 0 };
|
||||
uint64_t m_cpu_time_system_ns { 0 };
|
||||
uint64_t m_cpu_time_ns { 0 };
|
||||
uint64_t m_cpu_time_start_ns { UINT64_MAX };
|
||||
BAN::Atomic<bool> m_is_in_syscall { false };
|
||||
|
||||
BAN::Atomic<uint32_t> m_spinlock_count { 0 };
|
||||
BAN::Atomic<uint32_t> m_mutex_count { 0 };
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Math.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/Scheduler.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class SchedulerThreadNode;
|
||||
|
||||
class ThreadBlocker
|
||||
{
|
||||
public:
|
||||
@@ -29,11 +27,11 @@ namespace Kernel
|
||||
}
|
||||
|
||||
private:
|
||||
void add_thread_to_block_queue(SchedulerThreadNode*);
|
||||
void remove_thread_from_block_queue(SchedulerThreadNode*);
|
||||
void add_thread_to_block_queue(SchedulerQueue::Node*);
|
||||
void remove_thread_from_block_queue(SchedulerQueue::Node*);
|
||||
|
||||
private:
|
||||
SchedulerThreadNode* m_block_chain { nullptr };
|
||||
SchedulerQueue::Node* m_block_chain { nullptr };
|
||||
SpinLock m_lock;
|
||||
|
||||
friend class Scheduler;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Kernel
|
||||
class HPET final : public Timer, public Interruptable
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<HPET>> create();
|
||||
static BAN::ErrorOr<BAN::UniqPtr<HPET>> create(bool force_pic);
|
||||
~HPET();
|
||||
|
||||
virtual uint64_t ms_since_boot() const override;
|
||||
@@ -26,7 +26,7 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
HPET() = default;
|
||||
BAN::ErrorOr<void> initialize();
|
||||
BAN::ErrorOr<void> initialize(bool force_pic);
|
||||
|
||||
volatile HPETRegisters& registers();
|
||||
const volatile HPETRegisters& registers() const;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/Memory/DMARegion.h>
|
||||
#include <kernel/Timer/RTC.h>
|
||||
|
||||
#include <time.h>
|
||||
@@ -32,14 +31,7 @@ namespace Kernel
|
||||
class SystemTimer : public Timer
|
||||
{
|
||||
public:
|
||||
struct TSCInfo
|
||||
{
|
||||
int8_t shift;
|
||||
uint32_t mult;
|
||||
};
|
||||
|
||||
public:
|
||||
static void initialize();
|
||||
static void initialize(bool force_pic);
|
||||
static SystemTimer& get();
|
||||
static bool is_initialized();
|
||||
|
||||
@@ -52,60 +44,29 @@ namespace Kernel
|
||||
virtual bool pre_scheduler_sleep_needs_lock() const override;
|
||||
virtual void pre_scheduler_sleep_ns(uint64_t) override;
|
||||
|
||||
void sleep_for_ns(uint64_t timeout_ns) const;
|
||||
void sleep_until_ns(uint64_t waketime_ns) const;
|
||||
|
||||
void sleep_for_ms(uint64_t timeout_ms) const
|
||||
{
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(timeout_ms, 1'000'000));
|
||||
return sleep_for_ns(timeout_ms * 1'000'000);
|
||||
}
|
||||
void sleep_until_ms(uint64_t waketime_ms) const
|
||||
{
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(waketime_ms, 1'000'000));
|
||||
return sleep_until_ns(waketime_ms * 1'000'000);
|
||||
}
|
||||
void sleep_ms(uint64_t ms) const { ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(ms, 1'000'000)); return sleep_ns(ms * 1'000'000); }
|
||||
void sleep_ns(uint64_t ns) const;
|
||||
|
||||
void dont_invoke_scheduler() { m_timer->m_should_invoke_scheduler = false; }
|
||||
|
||||
void update_tsc();
|
||||
TSCInfo tsc_info() const;
|
||||
|
||||
uint64_t ns_since_boot_no_tsc() const { return m_timer->ns_since_boot(); }
|
||||
void update_tsc() const;
|
||||
uint64_t ns_since_boot_no_tsc() const;
|
||||
|
||||
timespec real_time() const;
|
||||
|
||||
private:
|
||||
SystemTimer() = default;
|
||||
|
||||
void initialize_timers();
|
||||
void initialize_timers(bool force_pic);
|
||||
|
||||
void initialize_invariant_tsc();
|
||||
void initialize_pvclock();
|
||||
uint64_t get_tsc_frequency() const;
|
||||
|
||||
private:
|
||||
enum class TSCType
|
||||
{
|
||||
None,
|
||||
Invariant,
|
||||
PVClock,
|
||||
};
|
||||
|
||||
uint64_t m_boot_time { 0 };
|
||||
BAN::UniqPtr<RTC> m_rtc;
|
||||
BAN::UniqPtr<Timer> m_timer;
|
||||
|
||||
TSCType m_tsc_type = TSCType::None;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int8_t shift;
|
||||
uint32_t mult;
|
||||
} invariant;
|
||||
} m_tsc_info;
|
||||
|
||||
BAN::UniqPtr<DMARegion> m_tsc_page;
|
||||
uint64_t m_tsc_update_ns { 0 };
|
||||
bool m_has_invariant_tsc { false };
|
||||
mutable uint32_t m_timer_ticks { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace Kernel
|
||||
Hub = 0x09,
|
||||
BillboardDeviceClass = 0x11,
|
||||
DiagnosticDevice = 0xDC,
|
||||
WirelessController = 0xE0,
|
||||
Miscellaneous = 0xEF,
|
||||
VendorSpecific = 0xFF,
|
||||
};
|
||||
|
||||
@@ -23,8 +23,6 @@ namespace Kernel
|
||||
|
||||
virtual void handle_stall(uint8_t endpoint_id) = 0;
|
||||
virtual void handle_input_data(size_t byte_count, uint8_t endpoint_id) = 0;
|
||||
|
||||
virtual bool is_hid_driver() const { return false; }
|
||||
};
|
||||
|
||||
class USBDevice
|
||||
@@ -64,12 +62,6 @@ namespace Kernel
|
||||
uint8_t tt_think_time;
|
||||
};
|
||||
|
||||
struct HIDInfo
|
||||
{
|
||||
BAN::Atomic<uint32_t> led_mask { 0 };
|
||||
BAN::Vector<USBClassDriver*> led_controls;
|
||||
};
|
||||
|
||||
public:
|
||||
USBDevice(USBController& controller, USB::SpeedClass speed_class, uint8_t depth)
|
||||
: m_controller(controller)
|
||||
@@ -100,8 +92,6 @@ namespace Kernel
|
||||
void register_hub_to_init() { m_controller.register_hub_to_init(m_depth + 1); };
|
||||
void mark_hub_init_done() { m_controller.mark_hub_init_done(m_depth + 1); };
|
||||
|
||||
void update_led_mask(uint32_t led_mask);
|
||||
|
||||
protected:
|
||||
void handle_stall(uint8_t endpoint_id);
|
||||
void handle_input_data(size_t byte_count, uint8_t endpoint_id);
|
||||
@@ -122,7 +112,6 @@ namespace Kernel
|
||||
BAN::UniqPtr<DMARegion> m_dma_buffer;
|
||||
|
||||
BAN::Vector<BAN::UniqPtr<USBClassDriver>> m_class_drivers;
|
||||
HIDInfo m_hid_info;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -74,7 +74,6 @@ namespace Kernel
|
||||
struct DeviceReport
|
||||
{
|
||||
BAN::Vector<USBHID::Report> inputs;
|
||||
BAN::Vector<USBHID::Report> outputs;
|
||||
BAN::RefPtr<USBHIDDevice> device;
|
||||
};
|
||||
|
||||
@@ -82,43 +81,27 @@ namespace Kernel
|
||||
void handle_stall(uint8_t endpoint_id) override;
|
||||
void handle_input_data(size_t byte_count, uint8_t endpoint_id) override;
|
||||
|
||||
bool is_hid_driver() const override { return true; }
|
||||
|
||||
USBDevice& device() { return m_device; }
|
||||
const USBDevice::InterfaceDescriptor& interface() const { return m_interface; }
|
||||
|
||||
bool has_led_control() const { return !m_led_controls.empty(); }
|
||||
void set_leds(uint32_t led_mask);
|
||||
|
||||
private:
|
||||
USBHIDDriver(USBDevice&, const USBDevice::InterfaceDescriptor&);
|
||||
~USBHIDDriver();
|
||||
|
||||
BAN::ErrorOr<void> initialize() override;
|
||||
|
||||
BAN::ErrorOr<void> initializes_device_reports(const BAN::Vector<USBHID::Collection>&);
|
||||
|
||||
private:
|
||||
struct LEDControl
|
||||
{
|
||||
DeviceReport* report;
|
||||
uint32_t report_id;
|
||||
uint32_t report_bits;
|
||||
};
|
||||
BAN::ErrorOr<BAN::Vector<DeviceReport>> initializes_device_reports(const BAN::Vector<USBHID::Collection>&);
|
||||
|
||||
private:
|
||||
USBDevice& m_device;
|
||||
USBDevice::InterfaceDescriptor m_interface;
|
||||
|
||||
bool m_uses_report_id { false };
|
||||
BAN::Vector<DeviceReport> m_device_reports;
|
||||
BAN::Vector<DeviceReport> m_device_inputs;
|
||||
|
||||
uint8_t m_data_endpoint_id = 0;
|
||||
BAN::UniqPtr<DMARegion> m_data_buffer;
|
||||
|
||||
BAN::Vector<LEDControl> m_led_controls;
|
||||
BAN::UniqPtr<DMARegion> m_led_region;
|
||||
|
||||
friend class BAN::UniqPtr<USBHIDDriver>;
|
||||
};
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
bool can_read_impl() const override { return true; }
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long request, void* arg) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int request, void* arg) override;
|
||||
|
||||
private:
|
||||
USBJoystick(USBHIDDriver&);
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace Kernel
|
||||
BAN_NON_MOVABLE(USBKeyboard);
|
||||
|
||||
public:
|
||||
BAN::ErrorOr<void> initialize() override;
|
||||
|
||||
void start_report() override;
|
||||
void stop_report() override;
|
||||
|
||||
@@ -21,9 +23,12 @@ namespace Kernel
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
USBKeyboard(USBHIDDriver& driver);
|
||||
USBKeyboard(USBHIDDriver& driver, BAN::Vector<USBHID::Report>&& outputs);
|
||||
~USBKeyboard() = default;
|
||||
|
||||
void set_leds(uint16_t mask);
|
||||
void set_leds(uint8_t report_id, uint16_t mask);
|
||||
|
||||
private:
|
||||
USBHIDDriver& m_driver;
|
||||
|
||||
@@ -33,7 +38,11 @@ namespace Kernel
|
||||
BAN::Array<bool, 0x100> m_keyboard_state { false };
|
||||
BAN::Array<bool, 0x100> m_keyboard_state_temp { false };
|
||||
uint16_t m_toggle_mask { 0 };
|
||||
|
||||
uint16_t m_led_mask { 0 };
|
||||
BAN::UniqPtr<DMARegion> m_led_region;
|
||||
|
||||
BAN::Vector<USBHID::Report> m_outputs;
|
||||
|
||||
BAN::Optional<uint8_t> m_repeat_scancode;
|
||||
uint8_t m_repeat_modifier { 0 };
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Process.h>
|
||||
#include <kernel/USB/Device.h>
|
||||
|
||||
namespace Kernel
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user