Compare commits

..
1 Commits
Author SHA1 Message Date
Bananymous 54763a952c BuildSystem: Fix keymap in base sysroot 2026-07-07 13:38:15 +03:00
218 changed files with 2192 additions and 5065 deletions
+36 -44
View File
@@ -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
-6
View File
@@ -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)
Binary file not shown.
+2 -2
View File
@@ -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)
+3 -5
View File
@@ -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)
+7 -11
View File
@@ -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
-3
View File
@@ -51,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
@@ -85,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
+1 -1
View File
@@ -59,7 +59,7 @@ signal_trampoline:
addl $24, %esp
// restore sigmask
movl $79, %eax // SYS_SIGPROCMASK
movl $78, %eax // SYS_SIGPROCMASK
movl $3, %ebx // SIG_SETMASK
leal 72(%esp), %ecx // set
xorl %edx, %edx // oset
+2 -2
View File
@@ -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
+7 -6
View File
@@ -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:
+17 -15
View File
@@ -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
+1 -1
View File
@@ -61,7 +61,7 @@ signal_trampoline:
addq $40, %rsp
// restore sigmask
movq $79, %rdi // SYS_SIGPROCMASK
movq $78, %rdi // SYS_SIGPROCMASK
movq $3, %rsi // SIG_SETMASK
leaq 192(%rsp), %rdx // set
xorq %r10, %r10 // oset
+2 -2
View File
@@ -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
View File
@@ -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:
+16 -14
View File
@@ -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
+15 -29
View File
@@ -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");
}
+5 -2
View File
@@ -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();
@@ -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
{
+4 -6
View File
@@ -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,7 +23,7 @@ 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);
@@ -72,8 +71,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 };
};
@@ -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;
};
+3 -8
View File
@@ -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));
-1
View File
@@ -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 -2
View File
@@ -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:
+4 -5
View File
@@ -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;
};
+5 -7
View File
@@ -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;
};
@@ -129,7 +128,7 @@ namespace Kernel
private:
struct BlockBuffer
{
BAN::ByteSpan buffer;
BAN::Vector<uint8_t> buffer;
bool used { false };
};
@@ -145,7 +144,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;
};
@@ -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 -2
View File
@@ -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:
-1
View File
@@ -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(); }
+1 -2
View File
@@ -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 ProcFileSystem final : public TmpFileSystem
{
public:
+1 -2
View File
@@ -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.
+15
View File
@@ -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 };
+2 -2
View File
@@ -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; }
-23
View File
@@ -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;
};
}
+125 -13
View File
@@ -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 };
+49 -5
View File
@@ -1,7 +1,7 @@
#pragma once
#include <kernel/Lock/SpinLock.h>
#include <kernel/ThreadBlocker.h>
#include <kernel/Lock/SpinLockAsMutex.h>
namespace Kernel
{
@@ -13,10 +13,54 @@ namespace Kernel
public:
RWLock() = default;
void rd_lock();
void rd_unlock();
void wr_lock();
void wr_unlock();
void rd_lock()
{
SpinLockGuard _(m_lock);
while (m_writers_waiting > 0 || m_writer != -1)
{
SpinLockGuardAsMutex smutex(_);
m_thread_blocker.block_indefinite(&smutex);
}
m_readers_active++;
}
void rd_unlock()
{
SpinLockGuard _(m_lock);
if (--m_readers_active == 0)
m_thread_blocker.unblock();
}
void wr_lock()
{
if (m_writer == Thread::current_tid())
{
m_writer_depth++;
return;
}
SpinLockGuard _(m_lock);
m_writers_waiting++;
while (m_readers_active > 0 || m_writer != -1)
{
SpinLockGuardAsMutex smutex(_);
m_thread_blocker.block_indefinite(&smutex);
}
m_writers_waiting--;
m_writer = Thread::current_tid();
m_writer_depth = 1;
}
void wr_unlock()
{
if (--m_writer_depth != 0)
return;
SpinLockGuard _(m_lock);
m_writer = -1;
m_thread_blocker.unblock();
}
private:
SpinLock m_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
{
@@ -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
{
@@ -1,7 +1,6 @@
#pragma once
#include <kernel/Networking/NetworkInterface.h>
#include <kernel/Memory/VirtualRange.h>
namespace Kernel
{
@@ -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
@@ -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
@@ -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;
-2
View File
@@ -3,8 +3,6 @@
#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 <sys/types.h>
+3 -4
View File
@@ -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;
};
+7 -7
View File
@@ -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
{
@@ -178,10 +179,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);
@@ -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,6 +280,8 @@ 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;
+12 -30
View File
@@ -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,12 +22,6 @@ namespace Kernel
Enabled,
};
class GDT;
class IDT;
class Scheduler;
class SchedulerThreadNode;
class Thread;
#if ARCH(x86_64) || ARCH(i686)
class Processor
{
@@ -54,8 +51,8 @@ namespace Kernel
union
{
TLBEntry flush_tlb;
SchedulerThreadNode* new_thread;
SchedulerThreadNode* unblock_thread;
SchedulerQueue::Node* new_thread;
SchedulerQueue::Node* unblock_thread;
bool dummy;
};
};
@@ -107,17 +104,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; }
@@ -182,23 +172,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();
@@ -214,8 +198,6 @@ namespace Kernel
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 };
+36 -16
View File
@@ -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*);
bool add_thread_with_wake_time(Node*); // return true if node was inserted as the first element
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,7 +58,7 @@ 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*);
@@ -57,9 +79,9 @@ 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();
@@ -68,13 +90,13 @@ namespace Kernel
class ProcessorID find_least_loaded_processor() const;
void add_thread(SchedulerThreadNode*);
void unblock_thread(SchedulerThreadNode*);
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 };
@@ -86,8 +108,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;
@@ -96,8 +118,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 };
};
}
@@ -22,7 +22,6 @@ namespace Kernel
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:
@@ -39,8 +38,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;
};
@@ -1,7 +1,6 @@
#pragma once
#include <BAN/WeakPtr.h>
#include <kernel/Memory/VirtualRange.h>
#include <kernel/Terminal/TTY.h>
namespace Kernel
@@ -96,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 };
+4 -11
View File
@@ -5,8 +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/ThreadBlocker.h>
#include <LibELF/AuxiliaryVector.h>
@@ -18,7 +18,6 @@ namespace Kernel
class MemoryBackedRegion;
class Process;
class ThreadBlocker;
class Thread
{
@@ -125,14 +124,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; }
@@ -192,7 +187,7 @@ namespace Kernel
vaddr_t m_fsbase { 0 };
vaddr_t m_gsbase { 0 };
SchedulerThreadNode* m_scheduler_node { nullptr };
SchedulerQueue::Node* m_scheduler_node { nullptr };
YieldRegisters m_yield_registers { };
@@ -205,10 +200,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 };
+4 -6
View File
@@ -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;
-11
View File
@@ -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;
};
}
+2 -19
View File
@@ -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>;
};
+10 -1
View File
@@ -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
@@ -373,33 +373,6 @@ namespace Kernel::XHCI
uint32_t slot_id : 8;
} configure_endpoint_command;
struct
{
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
uint32_t cycle_bit : 1;
uint32_t : 8;
uint32_t tsp : 1;
uint32_t trb_type : 6;
uint32_t endpoint_id : 5;
uint32_t : 3;
uint32_t slot_id : 8;
} reset_endpoint_command;
struct
{
uint64_t new_tr_deque_pointer : 64;
uint32_t : 16;
uint32_t stream_id : 16;
uint32_t cycle_bit : 1;
uint32_t : 9;
uint32_t trb_type : 6;
uint32_t endpoint_id : 5;
uint32_t : 3;
uint32_t slot_id : 8;
} set_tr_deque_pointer_command;
struct
{
uint64_t ring_segment_ponter : 64;
+15 -18
View File
@@ -6,9 +6,9 @@
#include <kernel/BootInfo.h>
#include <kernel/InterruptController.h>
#include <kernel/IO.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/Process.h>
#include <kernel/Scheduler.h>
#include <kernel/Timer/Timer.h>
#define RSPD_SIZE 20
@@ -790,7 +790,7 @@ acpi_release_global_lock:
auto [gpe_path, gpe_obj] = TRY(m_namespace->find_named_object(embedded_controller, TRY(AML::NameString::from_string("_GPE"_sv)), true));
if (gpe_obj == nullptr)
{
dwarnln("EC {} does not have _GPE", embedded_controller);
dwarnln("EC {} does have _GPE", embedded_controller);
break;
}
@@ -807,7 +807,7 @@ acpi_release_global_lock:
auto [crs_path, crs_obj] = TRY(m_namespace->find_named_object(embedded_controller, TRY(AML::NameString::from_string("_CRS"_sv)), true));
if (crs_obj == nullptr)
{
dwarnln("EC {} does not have _CRS", embedded_controller);
dwarnln("EC {} does have _CRS", embedded_controller);
return BAN::Error::from_errno(ENOENT);
}
@@ -935,7 +935,7 @@ acpi_release_global_lock:
return false;
}
BAN::ErrorOr<void> ACPI::enter_acpi_mode()
BAN::ErrorOr<void> ACPI::enter_acpi_mode(uint8_t mode)
{
ASSERT(!m_namespace);
@@ -1014,7 +1014,7 @@ acpi_release_global_lock:
AML::Reference arg_ref;
arg_ref.node.type = AML::Node::Type::Integer;
arg_ref.node.as.integer.value = InterruptController::get().is_using_apic() ? 1 : 0;
arg_ref.node.as.integer.value = mode;
arg_ref.ref_count = 2;
BAN::Array<AML::Reference*, 7> arguments(nullptr);
@@ -1022,7 +1022,7 @@ acpi_release_global_lock:
TRY(AML::method_call(pic_path, pic_node, BAN::move(arguments)));
}
dprintln("Evaluated \\_PIC({})", InterruptController::get().is_using_apic() ? 1 : 0);
dprintln("Evaluated \\_PIC({})", mode);
uint8_t irq = fadt().sci_int;
if (auto ret = InterruptController::get().reserve_irq(irq); ret.is_error())
@@ -1098,17 +1098,14 @@ acpi_release_global_lock:
dprintln("Initialized ACPI interrupts");
if (InterruptController::get().is_using_apic())
if (auto interrupt_link_devices_or_error = m_namespace->find_device_with_eisa_id("PNP0C0F"_sv); !interrupt_link_devices_or_error.is_error())
{
if (auto interrupt_link_devices_or_error = m_namespace->find_device_with_eisa_id("PNP0C0F"_sv); !interrupt_link_devices_or_error.is_error())
{
uint64_t routed_irq_mask = 0;
auto interrupt_link_devices = interrupt_link_devices_or_error.release_value();
for (const auto& device : interrupt_link_devices)
if (auto ret = route_interrupt_link_device(device, routed_irq_mask); ret.is_error())
dwarnln("failed to route interrupt link device: {}", ret.error());
dprintln("Routed interrupt link devices");
}
uint64_t routed_irq_mask = 0;
auto interrupt_link_devices = interrupt_link_devices_or_error.release_value();
for (const auto& device : interrupt_link_devices)
if (auto ret = route_interrupt_link_device(device, routed_irq_mask); ret.is_error())
dwarnln("failed to route interrupt link device: {}", ret.error());
dprintln("Routed interrupt link devices");
}
return {};
@@ -1199,8 +1196,6 @@ acpi_release_global_lock:
continue;
handle_event:
IO::outw(sts_port, pending);
if (pending & PM1_EVN_PWRBTN)
{
dprintln("Power button pressed");
@@ -1211,6 +1206,8 @@ handle_event:
{
dwarnln("Unhandled ACPI fixed event {H}", pending);
}
IO::outw(sts_port, pending);
}
}
+28 -36
View File
@@ -1,6 +1,5 @@
#include <kernel/ACPI/BatterySystem.h>
#include <kernel/Device/Device.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/DevFS//FileSystem.h>
#include <kernel/Timer/Timer.h>
namespace Kernel::ACPI
@@ -36,11 +35,34 @@ namespace Kernel::ACPI
if (offset < 0)
return BAN::Error::from_errno(EINVAL);
auto target_str = TRY(BAN::String::formatted("{}", TRY(get_value())));
if (SystemTimer::get().ms_since_boot() > m_last_read_ms + 1000)
{
auto [method_path, method_ref] = TRY(m_acpi_namespace.find_named_object(m_battery_path, m_method_name));
if (method_ref == nullptr)
return BAN::Error::from_errno(EFAULT);
auto result = TRY(AML::method_call(method_path, method_ref->node, BAN::Array<AML::Reference*, 7>{}));
if (result.type != AML::Node::Type::Package || result.as.package->num_elements < m_result_index)
return BAN::Error::from_errno(EFAULT);
auto& target_elem = result.as.package->elements[m_result_index];
if (!target_elem.resolved || !target_elem.value.node)
return BAN::Error::from_errno(EFAULT);
auto target_conv = AML::convert_node(TRY(target_elem.value.node->copy()), AML::ConvInteger, sizeof(uint64_t));
if (target_conv.is_error())
return BAN::Error::from_errno(EFAULT);
m_last_read_ms = SystemTimer::get().ms_since_boot();
m_last_value = target_conv.value().as.integer.value;
}
auto target_str = TRY(BAN::String::formatted("{}", m_last_value.load()));
if (static_cast<size_t>(offset) >= target_str.size())
return 0;
const size_t ncopy = BAN::Math::min<size_t>(buffer.size(), target_str.size() - offset);
const size_t ncopy = BAN::Math::min(buffer.size(), target_str.size() - offset);
memcpy(buffer.data(), target_str.data() + offset, ncopy);
return ncopy;
}
@@ -62,44 +84,14 @@ namespace Kernel::ACPI
, m_result_index(index)
{ }
BAN::ErrorOr<uint64_t> get_value()
{
LockGuard _(m_mutex);
if (SystemTimer::get().ms_since_boot() < m_last_read_ms + 1000)
return m_last_value;
auto [method_path, method_ref] = TRY(m_acpi_namespace.find_named_object(m_battery_path, m_method_name));
if (method_ref == nullptr)
return BAN::Error::from_errno(EFAULT);
auto result = TRY(AML::method_call(method_path, method_ref->node, BAN::Array<AML::Reference*, 7>{}));
if (result.type != AML::Node::Type::Package || result.as.package->num_elements < m_result_index)
return BAN::Error::from_errno(EFAULT);
auto& target_elem = result.as.package->elements[m_result_index];
if (!target_elem.resolved || !target_elem.value.node)
return BAN::Error::from_errno(EFAULT);
auto target_conv = AML::convert_node(TRY(target_elem.value.node->copy()), AML::ConvInteger, sizeof(uint64_t));
if (target_conv.is_error())
return BAN::Error::from_errno(EFAULT);
m_last_read_ms = SystemTimer::get().ms_since_boot();
m_last_value = target_conv.value().as.integer.value;
return m_last_value;
}
private:
AML::Namespace& m_acpi_namespace;
AML::Scope m_battery_path;
AML::NameString m_method_name;
size_t m_result_index;
Mutex m_mutex;
uint64_t m_last_read_ms = 0;
uint64_t m_last_value = 0;
BAN::Atomic<uint64_t> m_last_read_ms = 0;
BAN::Atomic<uint64_t> m_last_value = 0;
};
BAN::ErrorOr<void> BatterySystem::initialize(AML::Namespace& acpi_namespace)
@@ -4,8 +4,6 @@
#include <kernel/ACPI/EmbeddedController.h>
#include <kernel/IO.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Scheduler.h>
#include <kernel/Thread.h>
#include <kernel/Timer/Timer.h>
namespace Kernel::ACPI
+29 -38
View File
@@ -351,17 +351,17 @@ namespace Kernel
// give processor upto 100 * 100 us + 200 us to boot
PageTable::with_fast_page(ap_init_paddr, [&] {
for (int i = 0; i < 100; i++, udelay(100))
if (BAN::atomic_load(PageTable::fast_page_as<ap_init_info_t>(8).ready))
if (__atomic_load_n(&PageTable::fast_page_as<ap_init_info_t>(8).ready, __ATOMIC_SEQ_CST))
break;
});
initialized_aps++;
}
BAN::atomic_store(g_ap_startup_done[0], 1);
__atomic_store_n(&g_ap_startup_done[0], 1, __ATOMIC_SEQ_CST);
const size_t timeout_ms = SystemTimer::get().ms_since_boot() + 500;
while (BAN::atomic_load(g_ap_running_count[0]) < initialized_aps)
while (__atomic_load_n(&g_ap_running_count[0], __ATOMIC_SEQ_CST) < initialized_aps)
{
if (SystemTimer::get().ms_since_boot() >= timeout_ms)
Kernel::panic("Could not start all APs ({}/{} started)", g_ap_running_count[0], initialized_aps);
@@ -487,12 +487,17 @@ namespace Kernel
write_to_local_apic(LAPIC_EIO_REG, 0);
}
void APIC::enable_irq(uint8_t irq, bool level_triggered)
void APIC::enable_irq(uint8_t irq)
{
SpinLockGuard _(m_lock);
const uint32_t gsi = m_irq_overrides[irq];
ASSERT(m_used_gsis[gsi / 8] & (1 << (gsi % 8)));
{
int byte = gsi / 8;
int bit = gsi % 8;
ASSERT(m_reserved_gsis[byte] & (1 << bit));
}
IOAPIC* ioapic = nullptr;
for (IOAPIC& io : m_io_apics)
@@ -510,30 +515,27 @@ namespace Kernel
RedirectionEntry redir;
redir.lo_dword = ioapic->read(IOAPIC_REDIRS + pin * 2);
redir.hi_dword = ioapic->read(IOAPIC_REDIRS + pin * 2 + 1);
ASSERT(redir.mask); // TODO: handle overlapping interrupts
redir.vector = IRQ_VECTOR_BASE + irq;
redir.delivery_mode = 0; // fixed
redir.pin_polarity = 0; // active high
redir.trigger_mode = level_triggered;
redir.mask = 0;
redir.destination_mode = 0; // physical
// FIXME: distribute IRQs more evenly?
redir.destination = Kernel::Processor::bsp_id().as_u32();
ioapic->write(IOAPIC_REDIRS + pin * 2, redir.lo_dword);
ioapic->write(IOAPIC_REDIRS + pin * 2 + 1, redir.hi_dword);
ioapic->write(IOAPIC_REDIRS + pin * 2, redir.lo_dword);
ioapic->write(IOAPIC_REDIRS + pin * 2 + 1, redir.hi_dword);
}
bool APIC::is_in_service(uint8_t irq)
{
const uint32_t dword = (irq + IRQ_VECTOR_BASE) / 32;
const uint32_t bit = (irq + IRQ_VECTOR_BASE) % 32;
uint32_t dword = (irq + IRQ_VECTOR_BASE) / 32;
uint32_t bit = (irq + IRQ_VECTOR_BASE) % 32;
const uint32_t isr = read_from_local_apic(LAPIC_IS_REG + dword * 0x10);
uint32_t isr = read_from_local_apic(LAPIC_IS_REG + dword * 0x10);
return isr & (1 << bit);
}
BAN::ErrorOr<void> APIC::reserve_irq(uint8_t irq, bool shared)
BAN::ErrorOr<void> APIC::reserve_irq(uint8_t irq)
{
SpinLockGuard _(m_lock);
@@ -555,26 +557,20 @@ namespace Kernel
return BAN::Error::from_errno(EINVAL);
}
const uint8_t byte = gsi / 8;
const uint8_t mask = 1 << (gsi % 8);
if (!shared && (m_excl_gsis[byte] & mask))
int byte = gsi / 8;
int bit = gsi % 8;
if (m_reserved_gsis[byte] & (1 << bit))
{
dwarnln("GSI {} is already reserved as exclusive", gsi);
return BAN::Error::from_errno(EINVAL);
dwarnln("GSI {} is already reserved (IRQ {})", gsi, irq);
return BAN::Error::from_errno(EFAULT);
}
m_used_gsis[byte] |= mask;
if (!shared)
m_excl_gsis[byte] |= mask;
m_reserved_gsis[byte] |= 1 << bit;
return {};
}
// FIXME: rewrite gsi and vector reserving
// this is a hack to allow direct GSI reservation
BAN::ErrorOr<uint8_t> APIC::reserve_gsi(uint32_t gsi, bool shared)
BAN::ErrorOr<uint8_t> APIC::reserve_gsi(uint32_t gsi)
{
size_t irq = 0;
for (; irq < 0x100; irq++)
@@ -587,7 +583,7 @@ namespace Kernel
return BAN::Error::from_errno(ENOTSUP);
}
TRY(reserve_irq(irq, shared));
TRY(reserve_irq(irq));
return irq;
}
@@ -595,7 +591,6 @@ namespace Kernel
BAN::Optional<uint8_t> APIC::get_free_irq()
{
SpinLockGuard _(m_lock);
for (uint8_t irq = 0; irq < m_irq_count; irq++)
{
const uint8_t gsi = m_irq_overrides[irq];
@@ -613,17 +608,13 @@ namespace Kernel
if (!ioapic)
continue;
const uint8_t byte = gsi / 8;
const uint8_t mask = 1 << (gsi % 8);
if (m_used_gsis[byte] & mask)
const uint8_t byte = gsi / 8;
const uint8_t bit = gsi % 8;
if (m_reserved_gsis[byte] & (1 << bit))
continue;
m_used_gsis[byte] |= mask;
m_excl_gsis[byte] |= mask;
m_reserved_gsis[byte] |= 1 << bit;
return irq;
}
return {};
}
+6 -19
View File
@@ -182,22 +182,13 @@ namespace Kernel
m_bdl_region = TRY(DMARegion::create(bdl_size + buffer_size * m_used_bdl_entries));
memset(reinterpret_cast<void*>(m_bdl_region->vaddr()), 0x00, m_bdl_region->size());
if (m_bdl_region->paddr() + m_bdl_region->size() > BAN::numeric_limits<uint32_t>::max())
{
dwarnln("Could not allocate 32 bit dma buffer");
return BAN::Error::from_errno(EFAULT);
}
auto* bdl_entries = reinterpret_cast<AC97::BufferDescriptorListEntry*>(m_bdl_region->vaddr());
for (size_t i = 0; i < m_bdl_entries; i++)
{
bdl_entries[i] = {
.address = static_cast<uint32_t>(m_bdl_region->paddr() + bdl_size + (i % m_used_bdl_entries) * buffer_size),
.samples = 0,
.flags = 1 << 15,
};
auto& entry = reinterpret_cast<AC97::BufferDescriptorListEntry*>(m_bdl_region->vaddr())[i];
entry.address = m_bdl_region->paddr() + bdl_size + (i % m_used_bdl_entries) * buffer_size;
entry.samples = 0;
entry.flags = 0;
}
bdl_entries[m_bdl_entries - 1].flags |= 1 << 14;
m_bus_master->write32(BusMasterRegister::PO_BDBAR, m_bdl_region->paddr());
@@ -224,12 +215,7 @@ namespace Kernel
BAN::ErrorOr<void> AC97AudioController::set_volume_mdB(int32_t mdB)
{
m_volume_info.mdB = BAN::Math::clamp(mdB, m_volume_info.min_mdB, m_volume_info.max_mdB);
const uint32_t volume_data = get_volume_data();
m_mixer->write16(AudioMixerRegister::MasterVolume, volume_data);
m_volume_info.mdB = -(volume_data & 0xFF) * m_volume_info.step_mdB;
m_mixer->write16(AudioMixerRegister::MasterVolume, get_volume_data());
return {};
}
@@ -259,6 +245,7 @@ namespace Kernel
auto& entry = reinterpret_cast<AC97::BufferDescriptorListEntry*>(m_bdl_region->vaddr())[m_bdl_head];
entry.samples = sample_frames * get_channels();
entry.flags = (1 << 15);
memcpy(
reinterpret_cast<void*>(m_bdl_region->paddr_to_vaddr(entry.address)),
m_sample_data->get_data().data(),
+3 -4
View File
@@ -3,8 +3,7 @@
#include <kernel/Audio/HDAudio/Controller.h>
#include <kernel/Device/DeviceNumbers.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Thread.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <sys/ioctl.h>
#include <sys/sysmacros.h>
@@ -66,8 +65,8 @@ namespace Kernel
while (m_sample_data->full())
{
BlockableSpinLock block(m_spinlock);
TRY(Thread::current().block_or_eintr_indefinite(m_sample_data_blocker, &block));
SpinLockGuardAsMutex smutex(lock_guard);
TRY(Thread::current().block_or_eintr_indefinite(m_sample_data_blocker, &smutex));
}
const size_t to_copy = BAN::Math::min(buffer.size(), m_sample_data->free());
@@ -139,27 +139,31 @@ namespace Kernel
BAN::ErrorOr<void> HDAudioFunctionGroup::set_volume_mdB(int32_t mdB)
{
if (m_amplifier_idx == SIZE_MAX)
return BAN::Error::from_errno(ENOTSUP);
mdB = BAN::Math::clamp(mdB, m_volume_info.min_mdB, m_volume_info.max_mdB);
const auto* node = m_output_paths[m_output_path_index][m_amplifier_idx];
const auto& path = m_output_paths[m_output_path_index];
for (size_t i = 0; i < path.size(); i++)
{
if (!path[i]->output_amplifier.has_value())
continue;
const int32_t step_round = (mdB >= 0)
? +m_volume_info.step_mdB / 2
: -m_volume_info.step_mdB / 2;
const uint32_t step = (mdB + step_round) / m_volume_info.step_mdB + node->output_amplifier->offset;
const uint32_t volume = 0b1'0'1'1'0000'0'0000000 | step;
const int32_t step_round = (mdB >= 0)
? +m_volume_info.step_mdB / 2
: -m_volume_info.step_mdB / 2;
const uint32_t step = (mdB + step_round) / m_volume_info.step_mdB + path[i]->output_amplifier->offset;
const uint32_t volume = 0b1'0'1'1'0000'0'0000000 | step;
TRY(m_controller->send_command({
.data = static_cast<uint8_t>(volume & 0xFF),
.command = static_cast<uint16_t>(0x300 | (volume >> 8)),
.node_index = node->id,
.codec_address = m_cid,
}));
TRY(m_controller->send_command({
.data = static_cast<uint8_t>(volume & 0xFF),
.command = static_cast<uint16_t>(0x300 | (volume >> 8)),
.node_index = path[i]->id,
.codec_address = m_cid,
}));
m_volume_info.mdB = (mdB + step_round) / m_volume_info.step_mdB * m_volume_info.step_mdB;
break;
}
m_volume_info.mdB = mdB;
return {};
}
@@ -327,8 +331,8 @@ namespace Kernel
uint16_t HDAudioFunctionGroup::get_format_data() const
{
// TODO: don't hardcode this
// format: PCM, 48 kHz, 16 bit
return 0b0'0'000'000'0'001'0000 | (get_channels() - 1);
// format: PCM, 48 kHz, 16 bit, 2 channels
return 0b0'0'000'000'0'001'0001;
}
BAN::ErrorOr<void> HDAudioFunctionGroup::enable_output_path(uint8_t index)
@@ -342,7 +346,6 @@ namespace Kernel
{
using HDAudio::AFGWidget;
case AFGWidget::Type::OutputConverter:
case AFGWidget::Type::Mixer:
case AFGWidget::Type::PinComplex:
break;
default:
@@ -364,7 +367,7 @@ namespace Kernel
}));
// set connection index
if (i + 1 < path.size() && path[i]->connections.size() > 1 && path[i]->type != HDAudio::AFGWidget::Type::Mixer)
if (i + 1 < path.size() && path[i]->connections.size() > 1)
{
uint8_t index = 0;
for (; index < path[i]->connections.size(); index++)
@@ -404,13 +407,6 @@ namespace Kernel
.node_index = path[i]->id,
.codec_address = m_cid,
}));
// set channel count
TRY(m_controller->send_command({
.data = static_cast<uint8_t>(get_channels() - 1),
.command = 0x72D,
.node_index = path[i]->id,
.codec_address = m_cid,
}));
// set format
TRY(m_controller->send_command({
.data = static_cast<uint8_t>(format & 0xFF),
@@ -420,25 +416,6 @@ namespace Kernel
}));
break;
case AFGWidget::Type::Mixer:
if (path[i]->input_amplifier.has_value())
{
for (size_t idx = 0; idx < path[i]->connections.size(); idx++)
{
const uint8_t step = (path[i]->connections[idx] == path[i + 1]->id)
? path[i]->input_amplifier->offset
: 0b1'0000000;
const uint32_t volume = 0b0'1'1'1'0000'0'0000000 | (idx << 8) | step;
TRY(m_controller->send_command({
.data = static_cast<uint8_t>(volume & 0xFF),
.command = static_cast<uint16_t>(0x300 | (volume >> 8)),
.node_index = path[i]->id,
.codec_address = m_cid,
}));
}
}
break;
case AFGWidget::Type::PinComplex:
// enable output and H-Phn
TRY(m_controller->send_command({
@@ -461,25 +438,15 @@ namespace Kernel
}
}
int32_t max_steps { 0 };
m_amplifier_idx = SIZE_MAX;
// update volume info to this path
m_volume_info.min_mdB = 0;
m_volume_info.max_mdB = 0;
m_volume_info.step_mdB = 0;
for (size_t i = 0; i < path.size(); i++)
{
if (!path[i]->output_amplifier.has_value())
continue;
if (auto steps = path[i]->output_amplifier->num_steps; steps > max_steps)
{
max_steps = steps;
m_amplifier_idx = i;
}
}
if (m_amplifier_idx == SIZE_MAX)
m_volume_info = {};
else
{
const auto& amp = path[m_amplifier_idx]->output_amplifier.value();
const auto& amp = path[i]->output_amplifier.value();
const int32_t step_mdB = (amp.step_size + 1) * 250;
m_volume_info.step_mdB = step_mdB;
@@ -496,11 +463,16 @@ namespace Kernel
TRY(m_controller->send_command({
.data = static_cast<uint8_t>(volume & 0xFF),
.command = static_cast<uint16_t>(0x300 | (volume >> 8)),
.node_index = path[m_amplifier_idx]->id,
.node_index = path[i]->id,
.codec_address = m_cid,
}));
break;
}
if (m_volume_info.min_mdB == 0 && m_volume_info.max_mdB == 0)
m_volume_info.mdB = 0;
return {};
}
@@ -524,7 +496,6 @@ namespace Kernel
using HDAudio::AFGWidget;
case AFGWidget::Type::OutputConverter:
case AFGWidget::Type::Mixer:
break;
case AFGWidget::Type::PinComplex:
@@ -664,8 +635,11 @@ namespace Kernel
m_bdl_tail = (m_bdl_tail + 1) % m_bdl_entry_count;
if (m_bdl_tail == m_bdl_head)
{
bar.write8(base + Regs::SDCTL, bar.read8(base + Regs::SDCTL) & 0xFD);
m_stream_running = false;
if (auto ret = reset_stream(); ret.is_error())
{
dwarnln("failed to reset HDA stream: {}", ret.error());
return;
}
}
queue_bdl_data();
+3 -17
View File
@@ -1,8 +1,8 @@
#include <kernel/Audio/HDAudio/AudioFunctionGroup.h>
#include <kernel/Audio/HDAudio/Controller.h>
#include <kernel/Audio/HDAudio/Registers.h>
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/MMIO.h>
#include <kernel/Timer/Timer.h>
@@ -333,20 +333,6 @@ namespace Kernel
};
}
if (const uint32_t in_amp_cap = send_command_or_zero(0xF00, 0x0D))
{
const uint8_t offset = (in_amp_cap >> 0) & 0x7F;
const uint8_t num_steps = (in_amp_cap >> 8) & 0x7F;
const uint8_t step_size = (in_amp_cap >> 16) & 0x7F;
const bool mute = (in_amp_cap >> 31);
result.input_amplifier = HDAudio::AFGWidget::Amplifier {
.offset = offset,
.num_steps = num_steps,
.step_size = step_size,
.mute = mute,
};
}
const uint8_t connection_info = send_command_or_zero(0xF00, 0x0E);
const uint8_t conn_width = (connection_info & 0x80) ? 2 : 1;
const uint8_t conn_count = connection_info & 0x3F;
@@ -383,8 +369,8 @@ namespace Kernel
{
if (SystemTimer::get().ms_since_boot() > waketime_ms)
return BAN::Error::from_errno(ETIMEDOUT);
BlockableSpinLock block(m_rb_lock);
m_rb_blocker.block_with_timeout_ms(10, &block);
SpinLockGuardAsMutex smutex(sguard);
m_rb_blocker.block_with_timeout_ms(10, &smutex);
}
const size_t offset = 2 * m_rirb.index * sizeof(uint32_t);
+1 -14
View File
@@ -14,8 +14,6 @@
#include <kernel/Lock/SpinLock.h>
#include <kernel/UserCopy.h>
#if ARCH(x86_64)
using namespace LibELF;
using namespace Kernel;
@@ -206,7 +204,7 @@ BAN::ErrorOr<size_t> Banos::load_driver_from_image(const char* u_image) {
// NOTE: should be more than plenty ;)
extern char g_drv_builtin_begin[];
extern char g_drv_builtin_end[];
void Banos::initialize_initial_drivers() {
void Banos::initialize_initial_drivers(void) {
import_symbols(g_banos_export, g_banos_export_end - g_banos_export);
char* head = g_drv_builtin_begin;
while(head < g_drv_builtin_end) {
@@ -215,14 +213,3 @@ void Banos::initialize_initial_drivers() {
head += drv->driver_size;
}
}
#else
void Banos::initialize_initial_drivers()
{
}
BAN::ErrorOr<size_t> Banos::load_driver_from_image(const char* u_image)
{
(void)u_image;
return BAN::Error::from_errno(ENOTSUP);
}
#endif
+3 -4
View File
@@ -1,7 +1,6 @@
#include <kernel/Epoll.h>
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Thread.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Timer/Timer.h>
namespace Kernel
@@ -223,8 +222,8 @@ namespace Kernel
if (!m_ready_events.empty())
continue;
BlockableSpinLock block(m_ready_lock);
TRY(Thread::current().block_or_eintr_or_waketime_ns(m_thread_blocker, waketime_ns, false, &block));
SpinLockGuardAsMutex smutex(guard);
TRY(Thread::current().block_or_eintr_or_waketime_ns(m_thread_blocker, waketime_ns, false, &smutex));
}
return event_count;
+3 -3
View File
@@ -7,8 +7,8 @@
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/TmpFS/Inode.h>
#include <kernel/Input/InputDevice.h>
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Process.h>
#include <kernel/Scheduler.h>
#include <kernel/Storage/StorageDevice.h>
@@ -77,8 +77,8 @@ namespace Kernel
bool expected = true;
if (!devfs->m_should_drop_disk_cache.compare_exchange(expected, false))
{
BlockableSpinLock block(devfs->m_disk_cache_lock);
devfs->m_disk_cache_thread_blocker.block_indefinite(&block);
SpinLockGuardAsMutex smutex(guard);
devfs->m_disk_cache_thread_blocker.block_indefinite(&smutex);
continue;
}
}
+1 -14
View File
@@ -1,6 +1,5 @@
#include <kernel/FS/EventFD.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Thread.h>
#include <sys/epoll.h>
@@ -44,7 +43,7 @@ namespace Kernel
while (m_value == 0)
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
const uint64_t read_value = m_is_semaphore ? 1 : m_value;
const uint64_t read_value = m_is_semaphore ? 1 : m_value.load();
m_value -= read_value;
buffer.as<uint64_t>() = read_value;
@@ -80,16 +79,4 @@ namespace Kernel
return sizeof(uint64_t);
}
bool EventFD::can_read_impl() const
{
LockGuard _(m_mutex);
return m_value > 0;
}
bool EventFD::can_write_impl() const
{
LockGuard _(m_mutex);
return m_value < UINT64_MAX - 1;
}
}
+4 -17
View File
@@ -2,7 +2,6 @@
#include <BAN/Sort.h>
#include <kernel/FS/Ext2/FileSystem.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Thread.h>
#define EXT2_DEBUG_PRINT 0
#define EXT2_VERIFY_INODE 0
@@ -625,7 +624,7 @@ namespace Kernel
continue;
buffer.used = true;
return Ext2FS::BlockBufferWrapper {
buffer.buffer,
buffer.buffer.span(),
[](void* self, const uint8_t* buffer) { static_cast<BlockBufferManager*>(self)->destroy_callback(buffer); },
this
};
@@ -636,23 +635,11 @@ namespace Kernel
BAN::ErrorOr<void> Ext2FS::BlockBufferManager::initialize(size_t block_size)
{
m_buffer_data = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(),
{ KERNEL_OFFSET, BAN::numeric_limits<vaddr_t>::max() },
block_size * m_buffers.size(),
PageTable::ReadWrite | PageTable::Present,
false
));
auto buffer_data_span = BAN::ByteSpan { reinterpret_cast<uint8_t*>(m_buffer_data->vaddr()), m_buffer_data->size() };
for (size_t i = 0; i < m_buffers.size(); i++)
for (auto& buffer : m_buffers)
{
m_buffers[i] = {
.buffer = buffer_data_span.slice(i * block_size, block_size),
.used = false,
};
TRY(buffer.buffer.resize(block_size));
buffer.used = false;
}
return {};
}
+19 -17
View File
@@ -1,4 +1,3 @@
#include <kernel/Device/Device.h>
#include <kernel/FS/FAT/FileSystem.h>
#include <kernel/Lock/LockGuard.h>
@@ -124,6 +123,18 @@ namespace Kernel
{
LockGuard _(m_mutex);
uint32_t block_count = 0;
{
uint32_t cluster = entry.first_cluster_lo;
if (m_type == Type::FAT32)
cluster |= static_cast<uint32_t>(entry.first_cluster_hi) << 16;
while (cluster >= 2 && cluster < cluster_count())
{
block_count++;
cluster = TRY(get_next_cluster(cluster));
}
}
uint32_t entry_cluster;
switch (m_type)
{
@@ -132,34 +143,25 @@ namespace Kernel
if (parent == m_root_inode)
entry_cluster = 1;
else
{
entry_cluster = parent->entry().first_cluster_lo;
for (uint32_t i = 0; i < cluster_index; i++)
entry_cluster = TRY(get_next_cluster(entry_cluster));
}
break;
case Type::FAT32:
if (parent == m_root_inode)
entry_cluster = m_bpb.ext_32.root_cluster;
else
entry_cluster = (static_cast<uint32_t>(parent->entry().first_cluster_hi) << 16) | parent->entry().first_cluster_lo;
for (uint32_t i = 0; i < cluster_index; i++)
entry_cluster = TRY(get_next_cluster(entry_cluster));
break;
default:
ASSERT_NOT_REACHED();
}
uint32_t block_count = 0;
for (uint32_t i = 0; i < cluster_index; i++)
{
block_count++;
entry_cluster = TRY(get_next_cluster(entry_cluster));
}
const uint32_t dirent_per_cluster = m_bpb.bytes_per_sector * m_bpb.sectors_per_cluster / sizeof(FAT::DirectoryEntry);
ASSERT(BAN::Math::is_power_of_two(dirent_per_cluster));
ASSERT(entry_index < dirent_per_cluster);
const uint32_t ino_cluster_shift = BAN::Math::ctz(dirent_per_cluster);
const ino_t ino = (static_cast<ino_t>(entry_cluster) << ino_cluster_shift) | entry_index;
if (ino >> ino_cluster_shift != entry_cluster)
dwarnln("FAT ino mapping not unique");
const ino_t ino = (static_cast<ino_t>(entry_cluster) << 32) | entry_index;
auto it = m_inode_cache.find(ino);
if (it != m_inode_cache.end())
{
-1
View File
@@ -1,6 +1,5 @@
#include <BAN/Time.h>
#include <kernel/Device/Device.h>
#include <kernel/FS/FAT/FileSystem.h>
#include <kernel/FS/FAT/Inode.h>
+11 -16
View File
@@ -11,18 +11,18 @@
namespace Kernel
{
bool Inode::can_access(uid_t uid, gid_t gid, mode_t mode, const Credentials& credentials, int flags)
bool Inode::can_access(const Credentials& credentials, int flags) const
{
if (credentials.is_superuser())
return true;
if (flags & O_RDONLY)
{
if (mode & S_IROTH)
if (mode().mode & S_IROTH)
{ }
else if ((mode & S_IRUSR) && credentials.euid() == uid)
else if ((mode().mode & S_IRUSR) && credentials.euid() == uid())
{ }
else if ((mode & S_IRGRP) && credentials.has_egid(gid))
else if ((mode().mode & S_IRGRP) && credentials.has_egid(gid()))
{ }
else
{
@@ -32,11 +32,11 @@ namespace Kernel
if (flags & O_WRONLY)
{
if (mode & S_IWOTH)
if (mode().mode & S_IWOTH)
{ }
else if ((mode & S_IWUSR) && credentials.euid() == uid)
else if ((mode().mode & S_IWUSR) && credentials.euid() == uid())
{ }
else if ((mode & S_IWGRP) && credentials.has_egid(gid))
else if ((mode().mode & S_IWGRP) && credentials.has_egid(gid()))
{ }
else
{
@@ -44,13 +44,13 @@ namespace Kernel
}
}
if ((flags & O_EXEC) || (Mode { mode }.ifdir() && (flags & O_SEARCH)))
if ((flags & O_EXEC) || (mode().ifdir() && (flags & O_SEARCH)))
{
if (mode & S_IXOTH)
if (mode().mode & S_IXOTH)
{ }
else if ((mode & S_IXUSR) && credentials.euid() == uid)
else if ((mode().mode & S_IXUSR) && credentials.euid() == uid())
{ }
else if ((mode & S_IXGRP) && credentials.has_egid(gid))
else if ((mode().mode & S_IXGRP) && credentials.has_egid(gid()))
{ }
else
{
@@ -61,11 +61,6 @@ namespace Kernel
return true;
}
bool Inode::can_access(const Credentials& credentials, int flags) const
{
return can_access(uid(), gid(), mode().mode, credentials, flags);
}
BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name)
{
if (!mode().ifdir())
-1
View File
@@ -1,7 +1,6 @@
#include <kernel/BootInfo.h>
#include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/ProcFS/Inode.h>
#include <kernel/Process.h>
namespace Kernel
{
-1
View File
@@ -1,5 +1,4 @@
#include <kernel/FS/ProcFS/Inode.h>
#include <kernel/Process.h>
#include <ctype.h>
+8 -17
View File
@@ -1,9 +1,7 @@
#include <BAN/Array.h>
#include <BAN/Errors.h>
#include <kernel/GDT.h>
#include <kernel/IDT.h>
#include <kernel/InterruptController.h>
#include <kernel/InterruptNumbers.h>
#include <kernel/InterruptStack.h>
#include <kernel/Memory/kmalloc.h>
#include <kernel/Panic.h>
@@ -415,14 +413,10 @@ namespace Kernel
extern "C" void cpp_ipi_handler()
{
if (!InterruptController::get().is_in_service(IRQ_IPI - IRQ_VECTOR_BASE))
return;
Processor::handle_ipi();
ASSERT(InterruptController::get().is_in_service(IRQ_IPI - IRQ_VECTOR_BASE));
InterruptController::get().eoi(IRQ_IPI - IRQ_VECTOR_BASE);
Processor::scheduler().reschedule_if_needed();
Processor::handle_ipi();
Processor::scheduler().reschedule_if_idle();
}
extern "C" void cpp_timer_handler()
@@ -435,17 +429,13 @@ namespace Kernel
asm volatile("cli; 1: hlt; jmp 1b");
}
if (!InterruptController::get().is_in_service(IRQ_TIMER - IRQ_VECTOR_BASE))
return;
ASSERT(InterruptController::get().is_in_service(IRQ_TIMER - IRQ_VECTOR_BASE));
InterruptController::get().eoi(IRQ_TIMER - IRQ_VECTOR_BASE);
if (Processor::current_is_bsp())
Process::update_alarm_queue();
Processor::scheduler().on_timer_interrupt();
InterruptController::get().eoi(IRQ_TIMER - IRQ_VECTOR_BASE);
Processor::scheduler().reschedule_if_needed();
}
extern "C" void cpp_irq_handler(uint32_t irq)
@@ -463,14 +453,15 @@ namespace Kernel
if (!InterruptController::get().is_in_service(irq))
return;
InterruptController::get().eoi(irq);
if (auto* handler = s_interruptables[irq])
handler->handle_irq();
else
dprintln("no handler for irq 0x{2H}", irq);
InterruptController::get().eoi(irq);
Processor::scheduler().reschedule_if_idle();
Processor::scheduler().reschedule_if_needed();
ASSERT(Thread::current().state() != Thread::State::Terminated);
}
extern "C" void cpp_check_signal()
+9 -11
View File
@@ -3,10 +3,8 @@
#include <kernel/Device/DeviceNumbers.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Input/InputDevice.h>
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Scheduler.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Terminal/TTY.h>
#include <kernel/Thread.h>
#include <LibInput/Joystick.h>
#include <LibInput/KeyEvent.h>
@@ -247,8 +245,8 @@ namespace Kernel
while (m_event_count == 0)
{
// FIXME: should m_mutex be unlocked?
BlockableSpinLock block(m_event_lock);
TRY(Thread::current().block_or_eintr_indefinite(m_event_thread_blocker, &block));
SpinLockGuardAsMutex smutex(guard);
TRY(Thread::current().block_or_eintr_indefinite(m_event_thread_blocker, &smutex));
}
memcpy(buffer.data(), &m_event_buffer[m_event_tail * m_event_size], m_event_size);
@@ -291,8 +289,8 @@ namespace Kernel
if (s_tty_keyboard_events.empty())
{
BlockableSpinLock block(s_tty_keyboard_event_lock);
s_tty_keyboard_event_blocker.block_indefinite(&block);
SpinLockGuardAsMutex smutex(guard);
s_tty_keyboard_event_blocker.block_indefinite(&smutex);
continue;
}
@@ -352,8 +350,8 @@ namespace Kernel
return bytes;
}
BlockableSpinLock block(s_keyboard_lock);
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &block));
SpinLockGuardAsMutex smutex(keyboard_guard);
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &smutex));
}
}
@@ -409,8 +407,8 @@ namespace Kernel
return bytes;
}
BlockableSpinLock block(s_mouse_lock);
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &block));
SpinLockGuardAsMutex smutex(mouse_guard);
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &smutex));
}
}
+29 -29
View File
@@ -8,8 +8,6 @@
#include <kernel/Input/PS2/Keyboard.h>
#include <kernel/Input/PS2/Mouse.h>
#include <kernel/IO.h>
#include <kernel/Scheduler.h>
#include <kernel/Thread.h>
#include <kernel/Timer/Timer.h>
namespace Kernel::Input
@@ -347,7 +345,7 @@ namespace Kernel::Input
result.command_port = data->as.fixed_io_port.range_base;
break;
case ACPI::ResourceData::Type::IRQ:
if (BAN::Math::popcount(data->as.irq.irq_mask) != 1)
if (__builtin_popcount(data->as.irq.irq_mask) != 1)
break;
for (int i = 0; i < 16; i++)
if (data->as.irq.irq_mask & (1 << i))
@@ -388,11 +386,14 @@ namespace Kernel::Input
}
dprintln("Found {} PS/2 devices from ACPI namespace", acpi_devices.size());
if (acpi_devices.empty())
return {};
if (acpi_devices.size() > 2)
{
dwarnln("TODO: over 2 PS/2 devices");
MUST(acpi_devices.resize(2));
while (acpi_devices.size() > 2)
acpi_devices.pop_back();
}
if (acpi_devices.size() == 2)
@@ -418,43 +419,42 @@ namespace Kernel::Input
}
}
if (!acpi_devices.empty())
{
BAN::Optional<uint16_t> command_port;
command_port = acpi_devices[0].command_port;
if (!command_port.has_value() && acpi_devices.size() >= 2)
command_port = acpi_devices[1].command_port;
if (command_port.has_value())
m_command_port = command_port.value();
BAN::Optional<uint16_t> command_port;
command_port = acpi_devices[0].command_port;
if (!command_port.has_value() && acpi_devices.size() >= 2)
command_port = acpi_devices[1].command_port;
if (command_port.has_value())
m_command_port = command_port.value();
BAN::Optional<uint16_t> data_port;
data_port = acpi_devices[0].data_port;
if (!data_port.has_value() && acpi_devices.size() >= 2)
data_port = acpi_devices[1].data_port;
if (data_port.has_value())
m_data_port = data_port.value();
}
BAN::Optional<uint16_t> data_port;
data_port = acpi_devices[0].data_port;
if (!data_port.has_value() && acpi_devices.size() >= 2)
data_port = acpi_devices[1].data_port;
if (data_port.has_value())
m_data_port = data_port.value();
for (size_t i = 0; i < acpi_devices.size(); i++)
devices[0] = {
.type = acpi_devices[0].type,
.interrupt = acpi_devices[0].irq.value_or(PS2::INTERRUPT_FIRST_PORT)
};
if (acpi_devices.size() > 1)
{
devices[i] = {
.type = acpi_devices[i].type,
.interrupt = acpi_devices[i].irq.value_or(i == 0 ? PS2::IRQ::DEVICE0 : PS2::IRQ::DEVICE1),
devices[1] = {
.type = acpi_devices[1].type,
.interrupt = acpi_devices[1].irq.value_or(PS2::INTERRUPT_SECOND_PORT)
};
}
}
if (devices[0].type != DeviceType::None)
;
else if (scancode_set || has_legacy_8042())
else if (has_legacy_8042())
{
devices[0] = {
.type = DeviceType::Unknown,
.interrupt = PS2::IRQ::DEVICE0,
.interrupt = PS2::INTERRUPT_FIRST_PORT,
};
devices[1] = {
.type = DeviceType::Unknown,
.interrupt = PS2::IRQ::DEVICE1,
.interrupt = PS2::INTERRUPT_SECOND_PORT,
};
}
else
+2 -15
View File
@@ -53,9 +53,8 @@ namespace Kernel::Input
if (command_data[0] == Command::CONFIG_SCANCODE_SET && m_scancode_set >= 0xFE)
{
dwarnln("Could not detect scancode set, assuming 1");
m_scancode_set_uncertain = true;
m_scancode_set = 1;
dwarnln("Could not detect scancode set, assuming 2");
m_scancode_set = 2;
m_keymap.initialize(m_scancode_set);
append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING, 0);
}
@@ -90,7 +89,6 @@ namespace Kernel::Input
else
{
dwarnln("Could not detect scancode set, assuming 1");
m_scancode_set_uncertain = true;
m_scancode_set = 1;
}
m_keymap.initialize(m_scancode_set);
@@ -105,17 +103,6 @@ namespace Kernel::Input
return;
}
// If we could not detect scancode set, we assume it to be 1
// If we get byte 0xF0 which is indicates release in scancode set 2
// and nothing in scancode set 1, switch to scancode set 2
if (m_scancode_set_uncertain && byte == 0xF0)
{
dprintln("Switching to scancode set 2");
m_scancode_set_uncertain = false;
m_scancode_set = 2;
m_keymap.initialize(m_scancode_set);
}
m_byte_buffer[m_byte_index++] = byte;
if (byte == 0xE0)
return;
-134
View File
@@ -1,134 +0,0 @@
#include <kernel/Lock/Mutex.h>
#include <kernel/Thread.h>
namespace Kernel
{
bool Mutex::try_lock()
{
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 Mutex::lock()
{
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++;
}
void Mutex::unlock()
{
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();
}
}
bool Mutex::is_locked_by_current_thread() const
{
return m_locker == Thread::current_tid();
}
bool PriorityMutex::try_lock()
{
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 PriorityMutex::lock()
{
const auto tid = Thread::current_tid();
if (tid == m_locker)
ASSERT(m_lock_depth > 0);
else
{
ASSERT(!tid || !Thread::current().has_spinlock());
bool has_priority = tid ? !Thread::current().is_userspace() : true;
if (has_priority)
m_queue_length++;
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++;
}
void PriorityMutex::unlock()
{
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();
}
}
bool PriorityMutex::is_locked_by_current_thread() const
{
return m_locker == Thread::current_tid();
}
}
-58
View File
@@ -1,58 +0,0 @@
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Lock/RWLock.h>
#include <kernel/Thread.h>
namespace Kernel
{
void RWLock::rd_lock()
{
SpinLockGuard _(m_lock);
while (m_writers_waiting > 0 || m_writer != -1)
{
BlockableSpinLock block(m_lock);
m_thread_blocker.block_indefinite(&block);
}
m_readers_active++;
}
void RWLock::rd_unlock()
{
SpinLockGuard _(m_lock);
if (--m_readers_active == 0)
m_thread_blocker.unblock();
}
void RWLock::wr_lock()
{
if (m_writer == Thread::current_tid())
{
m_writer_depth++;
return;
}
SpinLockGuard _(m_lock);
m_writers_waiting++;
while (m_readers_active > 0 || m_writer != -1)
{
BlockableSpinLock block(m_lock);
m_thread_blocker.block_indefinite(&block);
}
m_writers_waiting--;
m_writer = Thread::current_tid();
m_writer_depth = 1;
}
void RWLock::wr_unlock()
{
if (--m_writer_depth != 0)
return;
SpinLockGuard _(m_lock);
m_writer = -1;
m_thread_blocker.unblock();
}
}
+1 -1
View File
@@ -115,7 +115,7 @@ namespace Kernel
return {};
const vaddr_t first_page = BAN::Math::max(m_vaddr, address) & PAGE_ADDR_MASK;
const vaddr_t last_page = BAN::Math::div_round_up<vaddr_t>(BAN::Math::min(m_vaddr + m_size, address + size), PAGE_SIZE) * PAGE_SIZE;
const vaddr_t last_page = BAN::Math::div_round_up(BAN::Math::min(m_vaddr + m_size, address + size), PAGE_SIZE) * PAGE_SIZE;
RWLockRDGuard _(m_shared_data->rw_lock);
for (vaddr_t page_addr = first_page; page_addr < last_page; page_addr += PAGE_SIZE)
+2 -1
View File
@@ -43,10 +43,11 @@ namespace Kernel
PageTable::with_per_cpu_fast_page(current_paddr, [&page_matched_bit](void* addr) {
for (size_t j = 0; j < PAGE_SIZE / sizeof(size_t); j++)
{
static_assert(sizeof(size_t) == sizeof(long));
auto& current = static_cast<size_t*>(addr)[j];
if (current == BAN::numeric_limits<size_t>::max())
continue;
const int ctz = BAN::Math::ctz(~current);
const int ctz = __builtin_ctzl(~current);
current |= static_cast<size_t>(1) << ctz;
page_matched_bit = j * sizeof(size_t) * 8 + ctz;
return;
+47 -201
View File
@@ -1,44 +1,13 @@
#include <kernel/Lock/LockGuard.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/SharedMemoryObject.h>
#include <kernel/Process.h>
#include <kernel/Random.h>
#include <kernel/Timer/Timer.h>
#include <kernel/UserCopy.h>
#include <fcntl.h>
namespace Kernel
{
static BAN::UniqPtr<SharedMemoryObjectManager> s_instance;
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, int status_flags);
~SharedMemoryObject();
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>, PageTable& page_table, int status_flags);
private:
BAN::RefPtr<SharedMemoryObjectManager::Object> m_object;
friend class BAN::UniqPtr<SharedMemoryObject>;
};
BAN::ErrorOr<void> SharedMemoryObjectManager::initialize()
{
ASSERT(!s_instance);
@@ -59,193 +28,70 @@ namespace Kernel
Heap::get().release_page(paddr);
}
BAN::ErrorOr<int> SharedMemoryObjectManager::shmget(key_t key, size_t size, int shmflg)
BAN::ErrorOr<SharedMemoryObjectManager::Key> SharedMemoryObjectManager::create_object(size_t size, PageTable::flags_t flags)
{
ASSERT(size % PAGE_SIZE == 0);
auto object = TRY(BAN::RefPtr<Object>::create());
object->size = size;
object->flags = flags;
TRY(object->paddrs.resize(size / PAGE_SIZE, 0));
LockGuard _(m_mutex);
// NOTE: don't set the top bit so cast to signed is not negative
auto generate_key = []() { return Random::get<Key>() & (~(Key)0 >> 1); };
Key key = generate_key();
while (m_objects.contains(key))
key = generate_key();
object->key = key;
TRY(m_objects.insert(key, object));
return key;
}
BAN::ErrorOr<void> SharedMemoryObjectManager::delete_object(Key key)
{
LockGuard _(m_mutex);
if (key != IPC_PRIVATE)
{
if (auto it = m_ids.find(key); it != m_ids.end())
{
if (shmflg & IPC_EXCL)
return BAN::Error::from_errno(EEXIST);
const auto& object = m_objects[it->value];
if (object->info.shm_segsz < size)
return BAN::Error::from_errno(EINVAL);
const int flags =
(shmflg & S_IRUSR ? O_RDONLY : 0) |
(shmflg & S_IWUSR ? O_WRONLY : 0);
if (!object->can_current_process_access(flags))
return BAN::Error::from_errno(EACCES);
return it->value;
}
if (!(shmflg & IPC_CREAT))
return BAN::Error::from_errno(ENOENT);
}
const auto& process = Process::current();
const uid_t uid = process.credentials().euid();
const gid_t gid = process.credentials().egid();
const pid_t pid = process.pid();
const mode_t mode = shmflg & 0777;
const int shmid = ({
int id;
do {
id = Random::get<unsigned>() & BAN::numeric_limits<int>::max();
} while (m_ids.contains(shmid));
id;
});
auto object = TRY(BAN::RefPtr<Object>::create(key, shmid, shmid_ds {
.shm_perm = {
.uid = uid,
.gid = gid,
.cuid = uid,
.cgid = uid,
.mode = mode,
},
.shm_segsz = size,
.shm_lpid = 0,
.shm_cpid = pid,
.shm_nattch = 0,
.shm_atime = 0,
.shm_dtime = 0,
.shm_ctime = SystemTimer::get().real_time().tv_sec,
}));
TRY(object->paddrs.resize(BAN::Math::div_round_up<size_t>(size, PAGE_SIZE), 0));
if (key != IPC_PRIVATE)
TRY(m_ids.insert(key, shmid));
if (auto ret = m_objects.insert(shmid, object); ret.is_error())
{
if (key != IPC_PRIVATE)
m_ids.remove(key);
return ret.release_error();
}
return shmid;
}
BAN::ErrorOr<void> SharedMemoryObjectManager::shmctl(int shmid, int cmd, struct shmid_ds* user_buf)
{
LockGuard _0(m_mutex);
auto it = m_objects.find(shmid);
if (it == m_objects.end())
return BAN::Error::from_errno(EINVAL);
LockGuard _1(it->value->mutex);
switch (cmd)
{
case IPC_RMID:
if (!it->value->can_current_process_access(O_WRONLY))
return BAN::Error::from_errno(EACCES);
if (it->key != IPC_PRIVATE)
m_ids.remove(it->key);
if (it->value->info.shm_nattch == 0)
m_objects.remove(it);
else
it->value->marked_for_deletion = true;
break;
case IPC_STAT:
TRY(write_to_user(user_buf, &it->value->info, sizeof(shmid_ds)));
break;
case IPC_SET:
{
if (!it->value->can_current_process_access(O_WRONLY))
return BAN::Error::from_errno(EACCES);
shmid_ds buf;
TRY(read_from_user(user_buf, &buf, sizeof(shmid_ds)));
it->value->info.shm_perm.uid = buf.shm_perm.uid;
it->value->info.shm_perm.gid = buf.shm_perm.gid;
it->value->info.shm_perm.mode = buf.shm_perm.mode & 0777;
break;
}
default:
return BAN::Error::from_errno(EINVAL);
}
return {};
}
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> SharedMemoryObjectManager::shmat(int shmid, const void* shmaddr, int shmflg)
{
LockGuard _(m_mutex);
auto it = m_objects.find(shmid);
auto it = m_objects.find(key);
if (it == m_objects.end())
return BAN::Error::from_errno(ENOENT);
const int status_flags = (shmflg & SHM_RDONLY) ? O_RDONLY : O_RDWR;
if (!it->value->can_current_process_access(status_flags))
return BAN::Error::from_errno(EACCES);
const AddressRange address_range = (shmaddr == nullptr)
? AddressRange { .start = 0x400000, .end = USERSPACE_END }
: TRY(Process::current().find_free_address_range(it->value->info.shm_segsz));
auto region = TRY(SharedMemoryObject::create(it->value, Process::current().page_table(), address_range, status_flags));
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
m_objects.remove(it);
return {};
}
bool SharedMemoryObjectManager::Object::can_current_process_access(int flags) const
BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> SharedMemoryObjectManager::map_object(Key key, PageTable& page_table, AddressRange address_range)
{
const auto& creds = Process::current().credentials();
if (Inode::can_access(info.shm_perm.uid, info.shm_perm.gid, info.shm_perm.mode, creds, flags))
return true;
if (Inode::can_access(info.shm_perm.cuid, info.shm_perm.cgid, info.shm_perm.mode, creds, flags))
return true;
return false;
LockGuard _(m_mutex);
auto it = m_objects.find(key);
if (it == m_objects.end())
return BAN::Error::from_errno(ENOENT);
return TRY(SharedMemoryObject::create(it->value, page_table, address_range));
}
BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> SharedMemoryObject::create(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table, AddressRange address_range, int status_flags)
BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> SharedMemoryObject::create(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table, AddressRange address_range)
{
auto shared_memory_object = TRY(BAN::UniqPtr<SharedMemoryObject>::create(object, page_table, status_flags));
TRY(shared_memory_object->initialize(address_range));
return shared_memory_object;
}
SharedMemoryObject::SharedMemoryObject(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table, int status_flags)
: MemoryRegion(
page_table,
object->info.shm_segsz,
MemoryRegion::Type::SHARED,
PageTable::UserSupervisor | ((status_flags & O_WRONLY) ? PageTable::ReadWrite : 0) | PageTable::Present,
status_flags
), m_object(object)
{
LockGuard _(m_object->mutex);
m_object->info.shm_nattch++;
m_object->info.shm_atime = SystemTimer::get().real_time().tv_sec;
m_object->info.shm_lpid = Process::current().pid();
}
SharedMemoryObject::~SharedMemoryObject()
{
LockGuard _(m_object->mutex);
if (--m_object->info.shm_nattch == 0 && m_object->marked_for_deletion)
SharedMemoryObjectManager::get().m_objects.remove(m_object->id);
m_object->info.shm_dtime = SystemTimer::get().real_time().tv_sec;
m_object->info.shm_lpid = Process::current().pid();
auto smo = TRY(BAN::UniqPtr<SharedMemoryObject>::create(object, page_table));
TRY(smo->initialize(address_range));
return BAN::move(smo);
}
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> SharedMemoryObject::clone(PageTable& new_page_table)
{
auto region = TRY(SharedMemoryObject::create(m_object, new_page_table, { .start = vaddr(), .end = vaddr() + size() }, m_status_flags));
auto region = TRY(SharedMemoryObject::create(m_object, new_page_table, { .start = vaddr(), .end = vaddr() + size() }));
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
}
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> SharedMemoryObject::split(size_t)
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> SharedMemoryObject::split(size_t offset)
{
derrorln("SharedMemoryObjects are not splittable");
return BAN::Error::from_errno(EINVAL);
(void)offset;
dwarnln("TODO: SharedMemoryObject::split");
return BAN::Error::from_errno(ENOTSUP);
}
BAN::ErrorOr<bool> SharedMemoryObject::allocate_page_containing_impl(vaddr_t address, bool wants_write)
@@ -253,11 +99,12 @@ namespace Kernel
ASSERT(contains(address));
(void)wants_write;
const vaddr_t vaddr = address & PAGE_ADDR_MASK;
// Check if address is already mapped
vaddr_t vaddr = address & PAGE_ADDR_MASK;
if (m_page_table.physical_address_of(vaddr) != 0)
return false;
LockGuard _(m_object->mutex);
SpinLockGuard _(m_object->spin_lock);
paddr_t paddr = m_object->paddrs[(vaddr - m_vaddr) / PAGE_SIZE];
if (paddr == 0)
@@ -270,7 +117,6 @@ namespace Kernel
});
m_object->paddrs[(vaddr - m_vaddr) / PAGE_SIZE] = paddr;
}
m_page_table.map_page_at(paddr, vaddr, m_flags);
return true;
+4 -2
View File
@@ -125,6 +125,8 @@ struct BitmapAllocator
// NOTE: We could optimize other bitmap functions than this
// but this one is the bottle neck so it doesn't matter
static_assert(sizeof(unsigned long long) == sizeof(uint64_t));
if (index >= total_chunks)
return index;
@@ -132,7 +134,7 @@ struct BitmapAllocator
{
const uint64_t qword = *reinterpret_cast<const uint64_t*>(base + (index - rem) / 8) >> rem;
if (qword != (1ull << (64 - rem)) - 1)
return index + BAN::Math::ctz(~qword);
return index + __builtin_ctzll(~qword);
index += 64 - rem;
}
@@ -140,7 +142,7 @@ struct BitmapAllocator
{
const uint64_t qword = *reinterpret_cast<const uint64_t*>(base + index / 8);
if (qword != UINT64_MAX)
return index + BAN::Math::ctz(~qword);
return index + __builtin_ctzll(~qword);
index += 64;
}
+1
View File
@@ -1,3 +1,4 @@
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Networking/ARPTable.h>
#include <kernel/Scheduler.h>
#include <kernel/Timer/Timer.h>
+3 -5
View File
@@ -1,13 +1,11 @@
#include <kernel/IDT.h>
#include <kernel/InterruptController.h>
#include <kernel/IO.h>
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/MMIO.h>
#include <kernel/Networking/E1000/E1000.h>
#include <kernel/Networking/NetworkManager.h>
#include <kernel/Scheduler.h>
#include <kernel/Thread.h>
namespace Kernel
{
@@ -382,8 +380,8 @@ namespace Kernel
if (rx_current != rx_tail)
write32(REG_RDT0, rx_tail);
BlockableSpinLock block(m_rx_lock);
m_rx_blocker.block_indefinite(&block);
SpinLockGuardAsMutex smutex(guard);
m_rx_blocker.block_indefinite(&smutex);
}
m_thread_is_dead = true;
+1 -1
View File
@@ -1,6 +1,6 @@
#include <kernel/Lock/SpinLock.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Networking/ICMP.h>
#include <kernel/Networking/IPv4Layer.h>
#include <kernel/Networking/NetworkManager.h>
+5 -7
View File
@@ -1,8 +1,6 @@
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Networking/Loopback.h>
#include <kernel/Networking/NetworkManager.h>
#include <kernel/Scheduler.h>
#include <kernel/Thread.h>
namespace Kernel
{
@@ -74,8 +72,8 @@ namespace Kernel
descriptor.state = 1;
return descriptor;
}
BlockableSpinLock block(m_buffer_lock);
m_thread_blocker.block_indefinite(&block);
SpinLockGuardAsMutex smutex(guard);
m_thread_blocker.block_indefinite(&smutex);
}
}();
@@ -120,8 +118,8 @@ namespace Kernel
m_thread_blocker.unblock();
}
BlockableSpinLock block(m_buffer_lock);
m_thread_blocker.block_indefinite(&block);
SpinLockGuardAsMutex smutex(guard);
m_thread_blocker.block_indefinite(&smutex);
}
m_thread_is_dead = true;
+5 -7
View File
@@ -1,9 +1,7 @@
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Networking/NetworkManager.h>
#include <kernel/Networking/RTL8169/Definitions.h>
#include <kernel/Networking/RTL8169/RTL8169.h>
#include <kernel/Scheduler.h>
#include <kernel/Thread.h>
#include <kernel/Timer/Timer.h>
namespace Kernel
@@ -220,8 +218,8 @@ namespace Kernel
SpinLockGuard guard(m_tx_lock);
while (descriptor.command & RTL8169_DESC_CMD_OWN)
{
BlockableSpinLock block(m_tx_lock);
m_tx_blocker.block_indefinite(&block);
SpinLockGuardAsMutex smutex(guard);
m_tx_blocker.block_indefinite(&smutex);
}
}
@@ -310,8 +308,8 @@ namespace Kernel
m_rx_head = (m_rx_head + 1) % m_rx_descriptor_count;
}
BlockableSpinLock block(m_rx_lock);
m_rx_blocker.block_indefinite(&block);
SpinLockGuardAsMutex smutex(rx_lock_guard);
m_rx_blocker.block_indefinite(&smutex);
}
m_rx_thread_is_dead = true;
-1
View File
@@ -3,7 +3,6 @@
#include <kernel/Networking/TCPSocket.h>
#include <kernel/Process.h>
#include <kernel/Random.h>
#include <kernel/Scheduler.h>
#include <kernel/Timer/Timer.h>
#include <fcntl.h>

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