Compare commits
3 Commits
main
...
f429e8c7bb
| Author | SHA1 | Date | |
|---|---|---|---|
| f429e8c7bb | |||
| cba2e8cfef | |||
| 3ad67614aa |
@@ -98,8 +98,7 @@ namespace BAN
|
||||
|
||||
struct EntryHash
|
||||
{
|
||||
template<detail::HashMapFindable<Key, HASH, COMP> U>
|
||||
constexpr bool operator()(const U& a)
|
||||
constexpr bool operator()(const Key& a)
|
||||
{
|
||||
return HASH()(a);
|
||||
}
|
||||
@@ -111,8 +110,7 @@ namespace BAN
|
||||
|
||||
struct EntryComp
|
||||
{
|
||||
template<detail::HashMapFindable<Key, HASH, COMP> U>
|
||||
constexpr bool operator()(const Entry& a, const U& b)
|
||||
constexpr bool operator()(const Entry& a, const Key& b)
|
||||
{
|
||||
return COMP()(a.key, b);
|
||||
}
|
||||
|
||||
@@ -67,20 +67,11 @@ namespace BAN::sort
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void quick_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
while (distance(begin, end) > 1)
|
||||
{
|
||||
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||
if (distance(begin, lt) < distance(gt, end))
|
||||
{
|
||||
quick_sort(begin, lt);
|
||||
begin = gt;
|
||||
}
|
||||
else
|
||||
{
|
||||
quick_sort(gt, end);
|
||||
end = lt;
|
||||
}
|
||||
}
|
||||
if (distance(begin, end) <= 1)
|
||||
return;
|
||||
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||
quick_sort(begin, lt, comp);
|
||||
quick_sort(gt, end, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
@@ -111,28 +102,13 @@ namespace BAN::sort
|
||||
template<typename It, typename Comp>
|
||||
void intro_sort_impl(It begin, It end, size_t max_depth, Comp comp)
|
||||
{
|
||||
for (size_t i = 0; i < max_depth; i++)
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
return;
|
||||
if (len <= 16)
|
||||
return insertion_sort(begin, end, comp);
|
||||
|
||||
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||
if (distance(begin, lt) < distance(gt, end))
|
||||
{
|
||||
intro_sort_impl(begin, lt, max_depth - 1, comp);
|
||||
begin = gt;
|
||||
}
|
||||
else
|
||||
{
|
||||
intro_sort_impl(gt, end, max_depth - 1, comp);
|
||||
end = lt;
|
||||
}
|
||||
}
|
||||
|
||||
heap_sort(begin, end, comp);
|
||||
if (distance(begin, end) <= 16)
|
||||
return insertion_sort(begin, end, comp);
|
||||
if (max_depth == 0)
|
||||
return heap_sort(begin, end, comp);
|
||||
const auto [lt, gt] = detail::partition(begin, end, comp);
|
||||
intro_sort_impl(begin, lt, max_depth - 1, comp);
|
||||
intro_sort_impl(gt, end, max_depth - 1, comp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -100,22 +100,3 @@ namespace BAN
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <BAN/Formatter.h>
|
||||
|
||||
namespace BAN::Formatter
|
||||
{
|
||||
|
||||
template<typename F, typename T>
|
||||
void print_argument(F putc, const Span<T>& span, const ValueFormat& format)
|
||||
{
|
||||
putc('[');
|
||||
for (typename Span<T>::size_type i = 0; i < span.size(); i++)
|
||||
{
|
||||
if (i != 0) putc(',');
|
||||
print_argument(putc, span[i], format);
|
||||
}
|
||||
putc(']');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ To change the bootloader you can set environment variable BANAN\_BOOTLOADER; sup
|
||||
|
||||
To run with UEFI set environment variable BANAN\_UEFI\_BOOT=1. You will also have to set OVMF\_PATH to the correct OVMF (default */usr/share/ovmf/x64/OVMF.fd*).
|
||||
|
||||
To build an image with no physical root filesystem, but an initrd set environment variable BANAN\_INITRD=1. This can be used when testing on hardware with unsupported USB controller. If BANAN\_INITRD is set to a value larger than 1, initrd will be gzip compressed.
|
||||
To build an image with no physical root filesystem, but an initrd set environment variable BANAN\_INITRD=1. This can be used when testing on hardware with unsupported USB controller.
|
||||
|
||||
If you have corrupted your disk image or want to create new one, you can either manually delete *build/banan-os.img* and build system will automatically create you a new one or you can run the following command.
|
||||
```sh
|
||||
|
||||
Binary file not shown.
@@ -59,7 +59,7 @@ signal_trampoline:
|
||||
addl $24, %esp
|
||||
|
||||
// restore sigmask
|
||||
movl $78, %eax // SYS_SIGPROCMASK
|
||||
movl $83, %eax // SYS_SIGPROCMASK
|
||||
movl $3, %ebx // SIG_SETMASK
|
||||
leal 72(%esp), %ecx // set
|
||||
xorl %edx, %edx // oset
|
||||
|
||||
@@ -12,7 +12,7 @@ asm_yield_trampoline:
|
||||
pushl %ebp
|
||||
|
||||
pushl %esp
|
||||
call scheduler_on_yield_trampoline
|
||||
call scheduler_on_yield
|
||||
addl $4, %esp
|
||||
|
||||
popl %ebp
|
||||
|
||||
@@ -27,10 +27,14 @@
|
||||
|
||||
isr_stub:
|
||||
intr_header 12
|
||||
movl %cr0, %eax; pushl %eax
|
||||
movl %cr2, %eax; pushl %eax
|
||||
movl %cr3, %eax; pushl %eax
|
||||
movl %cr4, %eax; pushl %eax
|
||||
|
||||
movl 32(%esp), %edi // isr number
|
||||
movl 36(%esp), %esi // error code
|
||||
leal 40(%esp), %edx // interrupt stack ptr
|
||||
movl 48(%esp), %edi // isr number
|
||||
movl 52(%esp), %esi // error code
|
||||
leal 56(%esp), %edx // interrupt stack ptr
|
||||
movl %esp, %ecx // register ptr
|
||||
|
||||
# stack frame for stack trace
|
||||
@@ -48,7 +52,7 @@ isr_stub:
|
||||
call cpp_isr_handler
|
||||
|
||||
movl %ebp, %esp
|
||||
addl $8, %esp
|
||||
addl $24, %esp
|
||||
|
||||
intr_footer 12
|
||||
addl $8, %esp
|
||||
|
||||
@@ -61,7 +61,7 @@ signal_trampoline:
|
||||
addq $40, %rsp
|
||||
|
||||
// restore sigmask
|
||||
movq $78, %rdi // SYS_SIGPROCMASK
|
||||
movq $83, %rdi // SYS_SIGPROCMASK
|
||||
movq $3, %rsi // SIG_SETMASK
|
||||
leaq 192(%rsp), %rdx // set
|
||||
xorq %r10, %r10 // oset
|
||||
|
||||
@@ -15,7 +15,7 @@ asm_yield_trampoline:
|
||||
pushq %r15
|
||||
|
||||
movq %rsp, %rdi
|
||||
call scheduler_on_yield_trampoline
|
||||
call scheduler_on_yield
|
||||
|
||||
popq %r15
|
||||
popq %r14
|
||||
|
||||
@@ -44,12 +44,17 @@
|
||||
|
||||
isr_stub:
|
||||
intr_header 24
|
||||
movq %cr0, %rax; pushq %rax
|
||||
movq %cr2, %rax; pushq %rax
|
||||
movq %cr3, %rax; pushq %rax
|
||||
movq %cr4, %rax; pushq %rax
|
||||
|
||||
movq 120(%rsp), %rdi // isr number
|
||||
movq 128(%rsp), %rsi // error code
|
||||
leaq 136(%rsp), %rdx // interrupt stack ptr
|
||||
movq %rsp, %rcx // register ptr
|
||||
movq 152(%rsp), %rdi // isr number
|
||||
movq 160(%rsp), %rsi // error code
|
||||
leaq 168(%rsp), %rdx // interrupt stack ptr
|
||||
movq %rsp, %rcx // register ptr
|
||||
call cpp_isr_handler
|
||||
addq $32, %rsp
|
||||
|
||||
intr_footer 24
|
||||
addq $16, %rsp
|
||||
|
||||
@@ -8,7 +8,6 @@ namespace Kernel::API
|
||||
enum SharedPageFeature : uint32_t
|
||||
{
|
||||
SPF_GETTIME = 1 << 0,
|
||||
SPF_RDTSCP = 1 << 1,
|
||||
};
|
||||
|
||||
struct SharedPage
|
||||
@@ -19,8 +18,9 @@ namespace Kernel::API
|
||||
|
||||
struct
|
||||
{
|
||||
uint64_t realtime_s;
|
||||
uint32_t realtime_ns;
|
||||
uint8_t shift;
|
||||
uint64_t mult;
|
||||
uint64_t realtime_seconds;
|
||||
} gettime_shared;
|
||||
|
||||
struct
|
||||
@@ -28,8 +28,6 @@ namespace Kernel::API
|
||||
struct
|
||||
{
|
||||
uint32_t seq;
|
||||
uint32_t mult;
|
||||
int8_t shift;
|
||||
uint64_t last_ns;
|
||||
uint64_t last_tsc;
|
||||
} gettime_local;
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace Kernel
|
||||
BAN::ErrorOr<uint8_t> reserve_gsi(uint32_t gsi);
|
||||
|
||||
void initialize_timer();
|
||||
void set_timer_dealine(uint64_t ns);
|
||||
|
||||
private:
|
||||
uint32_t read_from_local_apic(ptrdiff_t);
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long request, void* arg) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int cmd, void* arg) override;
|
||||
|
||||
protected:
|
||||
ThreadBlocker m_sample_data_blocker;
|
||||
|
||||
@@ -82,8 +82,5 @@ namespace CPUID
|
||||
bool has_pat();
|
||||
bool has_1gib_pages();
|
||||
bool has_invariant_tsc();
|
||||
bool has_rdtscp();
|
||||
uint64_t get_tsc_frequency();
|
||||
bool has_kvm_pvclock();
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long request, void* arg) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int cmd, void* arg) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace Kernel::ELF
|
||||
size_t size;
|
||||
};
|
||||
|
||||
bool open_execfd;
|
||||
vaddr_t entry_point;
|
||||
BAN::Optional<vaddr_t> interp_base;
|
||||
BAN::Optional<TLS> master_tls;
|
||||
BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions;
|
||||
};
|
||||
|
||||
@@ -99,8 +99,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
|
||||
BAN::ErrorOr<void> release_block(uint32_t block);
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> open_inode(ino_t);
|
||||
void remove_from_cache(ino_t);
|
||||
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>>& inode_cache() { return m_inode_cache; }
|
||||
|
||||
const Ext2::Superblock& superblock() const { return m_superblock; }
|
||||
|
||||
@@ -156,7 +155,6 @@ namespace Kernel
|
||||
BAN::RefPtr<Inode> m_root_inode;
|
||||
BAN::Vector<uint32_t> m_superblock_backups;
|
||||
|
||||
Mutex m_inode_cache_lock;
|
||||
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>> m_inode_cache;
|
||||
|
||||
BlockBufferManager m_buffer_manager;
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_no_lock(BAN::StringView);
|
||||
|
||||
/* needs write end of the lock when allocate is true*/
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block_no_lock(uint32_t block, uint32_t index, uint32_t depth, bool allocate);
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate);
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate);
|
||||
|
||||
/* needs write end of the lock */
|
||||
@@ -71,13 +71,7 @@ namespace Kernel
|
||||
private:
|
||||
Ext2Inode(Ext2FS& fs, Ext2::Inode inode, uint32_t ino);
|
||||
|
||||
BAN::Optional<uint32_t> block_cache_find(uint32_t block, uint32_t index) const;
|
||||
void block_cache_remove(uint32_t block, uint32_t index);
|
||||
void block_cache_add(uint32_t block, uint32_t index, uint32_t target);
|
||||
|
||||
BAN::RefPtr<Inode> dir_cache_find(BAN::StringView) const;
|
||||
void dir_cache_remove(BAN::StringView);
|
||||
void dir_cache_add(BAN::StringView, BAN::RefPtr<Inode>);
|
||||
static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t);
|
||||
|
||||
private:
|
||||
struct ScopedSync
|
||||
@@ -113,27 +107,6 @@ namespace Kernel
|
||||
const uint32_t m_og_faddr;
|
||||
const Ext2::Osd2 m_og_osd2;
|
||||
|
||||
struct BlockCacheEntry
|
||||
{
|
||||
mutable uint32_t freq;
|
||||
uint32_t block;
|
||||
uint32_t index;
|
||||
uint32_t target;
|
||||
};
|
||||
mutable SpinLock m_block_cache_lock;
|
||||
BAN::Array<BlockCacheEntry, 8> m_block_cache;
|
||||
|
||||
struct DirCacheEntry
|
||||
{
|
||||
mutable size_t freq { 0 };
|
||||
BAN::RefPtr<Inode> inode;
|
||||
size_t name_len { 0 };
|
||||
char name[256];
|
||||
};
|
||||
static constexpr size_t dir_cache_size = 32;
|
||||
mutable RWLock m_dir_cache_lock;
|
||||
BAN::Vector<DirCacheEntry> m_dir_cache;
|
||||
|
||||
friend class Ext2FS;
|
||||
friend class BAN::RefPtr<Ext2Inode>;
|
||||
};
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Kernel
|
||||
bool has_error() const { return has_error_impl(); }
|
||||
bool has_hungup() const { return has_hungup_impl(); }
|
||||
|
||||
BAN::ErrorOr<long> ioctl(unsigned long request, void* arg);
|
||||
BAN::ErrorOr<long> ioctl(int request, void* arg);
|
||||
|
||||
BAN::ErrorOr<void> add_epoll(class Epoll*);
|
||||
void del_epoll(class Epoll*);
|
||||
@@ -199,7 +199,7 @@ namespace Kernel
|
||||
virtual bool has_error_impl() const = 0;
|
||||
virtual bool has_hungup_impl() const = 0;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
protected:
|
||||
// TODO: this is supposed to be const I guess?
|
||||
|
||||
@@ -13,8 +13,6 @@ namespace Kernel
|
||||
static void initialize();
|
||||
static ProcFileSystem& get();
|
||||
|
||||
void post_scheduler_initialize();
|
||||
|
||||
BAN::ErrorOr<void> on_process_create(Process&);
|
||||
void on_process_delete(Process&);
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Kernel
|
||||
class ProcROInode final : public TmpInode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create_new(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem&, void*, mode_t, uid_t, gid_t);
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create_new(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, mode_t, uid_t, gid_t);
|
||||
~ProcROInode() = default;
|
||||
|
||||
protected:
|
||||
@@ -92,11 +92,10 @@ namespace Kernel
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcROInode(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem&, void*, const TmpInodeInfo&);
|
||||
ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&);
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<size_t> (*m_callback)(off_t, BAN::ByteSpan, void*);
|
||||
void* m_argument;
|
||||
size_t (*m_callback)(off_t, BAN::ByteSpan);
|
||||
};
|
||||
|
||||
class ProcSymlinkInode final : public TmpInode
|
||||
|
||||
@@ -92,9 +92,8 @@ namespace Kernel
|
||||
MountPoint* mount_from_root_inode(BAN::RefPtr<Inode>);
|
||||
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
BAN::RefPtr<FileSystem> m_root_fs;
|
||||
|
||||
Mutex m_mount_point_lock;
|
||||
BAN::Vector<MountPoint> m_mount_points;
|
||||
|
||||
friend class BAN::RefPtr<VirtualFileSystem>;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/Lock/SpinLockAsMutex.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -15,18 +15,15 @@ namespace Kernel
|
||||
|
||||
void rd_lock()
|
||||
{
|
||||
SpinLockGuard _(m_lock);
|
||||
LockGuard _(m_mutex);
|
||||
while (m_writers_waiting > 0 || m_writer != -1)
|
||||
{
|
||||
SpinLockGuardAsMutex smutex(_);
|
||||
m_thread_blocker.block_indefinite(&smutex);
|
||||
}
|
||||
m_thread_blocker.block_indefinite(&m_mutex);
|
||||
m_readers_active++;
|
||||
}
|
||||
|
||||
void rd_unlock()
|
||||
{
|
||||
SpinLockGuard _(m_lock);
|
||||
LockGuard _(m_mutex);
|
||||
if (--m_readers_active == 0)
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
@@ -39,14 +36,11 @@ namespace Kernel
|
||||
return;
|
||||
}
|
||||
|
||||
SpinLockGuard _(m_lock);
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
m_writers_waiting++;
|
||||
while (m_readers_active > 0 || m_writer != -1)
|
||||
{
|
||||
SpinLockGuardAsMutex smutex(_);
|
||||
m_thread_blocker.block_indefinite(&smutex);
|
||||
}
|
||||
m_thread_blocker.block_indefinite(&m_mutex);
|
||||
m_writers_waiting--;
|
||||
|
||||
m_writer = Thread::current_tid();
|
||||
@@ -57,13 +51,13 @@ namespace Kernel
|
||||
{
|
||||
if (--m_writer_depth != 0)
|
||||
return;
|
||||
SpinLockGuard _(m_lock);
|
||||
LockGuard _(m_mutex);
|
||||
m_writer = -1;
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
|
||||
private:
|
||||
SpinLock m_lock;
|
||||
Mutex m_mutex;
|
||||
ThreadBlocker m_thread_blocker;
|
||||
uint32_t m_readers_active { 0 };
|
||||
uint32_t m_writers_waiting { 0 };
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace Kernel
|
||||
REG_TDLEN = 0x3808,
|
||||
REG_TDH = 0x3810,
|
||||
REG_TDT = 0x3818,
|
||||
REG_RXCSUM = 0x5000,
|
||||
REG_MTA = 0x5200,
|
||||
};
|
||||
|
||||
@@ -168,15 +167,6 @@ namespace Kernel
|
||||
RCTL_BSIZE_16384 = (0b01 << 16) | RCTL_BSEX,
|
||||
};
|
||||
|
||||
enum E1000_RXCSUM : uint32_t
|
||||
{
|
||||
RXSUM_IPOFLD = 1 << 8,
|
||||
RXSUM_TUOFLD = 1 << 9,
|
||||
RXSUM_CRCOFLD = 1 << 11,
|
||||
RXSUM_IPPCE = 1 << 12,
|
||||
RXSUM_PCSD = 1 << 13,
|
||||
};
|
||||
|
||||
enum E1000_CMD : uint8_t
|
||||
{
|
||||
CMD_EOP = 1 << 0,
|
||||
@@ -188,26 +178,6 @@ namespace Kernel
|
||||
CMD_IDE = 1 << 7,
|
||||
};
|
||||
|
||||
enum E1000_RX_STS : uint8_t
|
||||
{
|
||||
RX_STS_IPCS = 1 << 6,
|
||||
RX_STS_TCPCS = 1 << 5,
|
||||
RX_STS_UDPCS = 1 << 5,
|
||||
RX_STS_EOP = 1 << 1,
|
||||
RX_STS_DD = 1 << 0,
|
||||
};
|
||||
|
||||
enum E1000_RX_ERR : uint8_t
|
||||
{
|
||||
RX_ERR_RXE = 1 << 7,
|
||||
RX_ERR_IPE = 1 << 6,
|
||||
RX_ERR_TCPE = 1 << 5,
|
||||
RX_ERR_CXE = 1 << 4,
|
||||
RX_ERR_SEQ = 1 << 2,
|
||||
RX_ERR_SE = 1 << 1,
|
||||
RX_ERR_CE = 1 << 0,
|
||||
};
|
||||
|
||||
struct e1000_rx_desc
|
||||
{
|
||||
uint64_t addr;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Kernel
|
||||
uint32_t read32(uint16_t reg);
|
||||
void write32(uint16_t reg, uint32_t value);
|
||||
|
||||
BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) override;
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
||||
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
@@ -74,8 +74,8 @@ namespace Kernel
|
||||
BAN::UniqPtr<DMARegion> m_rx_descriptor_region;
|
||||
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
||||
|
||||
BAN::Atomic<uint32_t> m_tx_head { 0 };
|
||||
BAN::Atomic<uint32_t> m_tx_commit { 0 };
|
||||
BAN::Atomic<uint32_t> m_tx_head1 { 0 };
|
||||
BAN::Atomic<uint32_t> m_tx_head2 { 0 };
|
||||
|
||||
SpinLock m_rx_lock;
|
||||
ThreadBlocker m_rx_blocker;
|
||||
|
||||
@@ -41,14 +41,14 @@ namespace Kernel
|
||||
|
||||
ARPTable& arp_table() { return *m_arp_table; }
|
||||
|
||||
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan, uint32_t validated_cksums);
|
||||
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
|
||||
|
||||
virtual void unbind_socket(uint16_t port) override;
|
||||
virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) override;
|
||||
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) override;
|
||||
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) override;
|
||||
|
||||
virtual BAN::ErrorOr<void> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||
|
||||
virtual Socket::Domain domain() const override { return Socket::Domain::INET ;}
|
||||
virtual size_t header_size() const override { return sizeof(IPv4Header); }
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Kernel
|
||||
{}
|
||||
~LoopbackInterface();
|
||||
|
||||
BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) override;
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
||||
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
@@ -46,7 +46,7 @@ namespace Kernel
|
||||
};
|
||||
|
||||
private:
|
||||
SpinLock m_buffer_lock;
|
||||
Mutex m_buffer_lock;
|
||||
BAN::UniqPtr<VirtualRange> m_buffer;
|
||||
|
||||
uint32_t m_buffer_tail { 0 };
|
||||
|
||||
@@ -23,13 +23,6 @@ namespace Kernel
|
||||
ARP = 0x0806,
|
||||
};
|
||||
|
||||
enum NetworkChecksum : uint32_t
|
||||
{
|
||||
CKSUM_IPV4 = 1 << 0,
|
||||
CKSUM_TCP = 1 << 1,
|
||||
CKSUM_UDP = 1 << 2,
|
||||
};
|
||||
|
||||
class NetworkInterface : public CharacterDevice
|
||||
{
|
||||
BAN_NON_COPYABLE(NetworkInterface);
|
||||
@@ -66,33 +59,11 @@ namespace Kernel
|
||||
|
||||
virtual BAN::StringView name() const override { return m_name; }
|
||||
|
||||
BAN::ErrorOr<void> send_with_ethernet_header(BAN::MACAddress dst_mac, EtherType ether_type, BAN::ConstByteSpan buffer)
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan payload)
|
||||
{
|
||||
BAN::ConstByteSpan buffer_array[1] { buffer };
|
||||
return send_with_ethernet_header(dst_mac, ether_type, buffer_array);
|
||||
return send_bytes(destination, protocol, { &payload, 1 });
|
||||
}
|
||||
|
||||
template<size_t SIZE>
|
||||
BAN::ErrorOr<void> send_with_ethernet_header(BAN::MACAddress dst_mac, EtherType ether_type, const BAN::ConstByteSpan (&buffer_array)[SIZE])
|
||||
{
|
||||
const auto ethernet_header = EthernetHeader {
|
||||
.dst_mac = dst_mac,
|
||||
.src_mac = get_mac_address(),
|
||||
.ether_type = ether_type,
|
||||
};
|
||||
|
||||
BAN::ConstByteSpan new_buffer_array[SIZE + 1];
|
||||
new_buffer_array[0] = BAN::ConstByteSpan::from(ethernet_header);
|
||||
for (size_t i = 0; i < SIZE; i++)
|
||||
new_buffer_array[i + 1] = buffer_array[i];
|
||||
|
||||
return send_raw_bytes({ new_buffer_array, SIZE + 1 });
|
||||
}
|
||||
|
||||
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) = 0;
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0;
|
||||
|
||||
private:
|
||||
const Type m_type;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) = 0;
|
||||
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) = 0;
|
||||
|
||||
virtual BAN::ErrorOr<void> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0;
|
||||
virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0;
|
||||
|
||||
virtual Socket::Domain domain() const = 0;
|
||||
virtual size_t header_size() const = 0;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<BAN::RefPtr<Socket>> create_socket(Socket::Domain, Socket::Type, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> connect_sockets(Socket::Domain, BAN::RefPtr<Socket>, BAN::RefPtr<Socket>);
|
||||
|
||||
void on_receive(NetworkInterface&, BAN::ConstByteSpan, uint32_t validated_cksums);
|
||||
void on_receive(NetworkInterface&, BAN::ConstByteSpan);
|
||||
|
||||
private:
|
||||
NetworkManager() {}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Kernel
|
||||
virtual void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) = 0;
|
||||
virtual NetworkProtocol protocol() const = 0;
|
||||
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len, uint32_t validated_cksums) = 0;
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0;
|
||||
|
||||
bool is_bound() const { return m_address_len >= static_cast<socklen_t>(sizeof(sa_family_t)) && m_address.ss_family != AF_UNSPEC; }
|
||||
in_port_t bound_port() const
|
||||
@@ -54,7 +54,7 @@ namespace Kernel
|
||||
protected:
|
||||
NetworkSocket(NetworkLayer&, const Socket::Info&);
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(unsigned long request, void* arg) override;
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int request, void* arg) override;
|
||||
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override = 0;
|
||||
|
||||
|
||||
@@ -7,25 +7,25 @@ namespace Kernel
|
||||
|
||||
enum RTL8169_IO_REGS : uint16_t
|
||||
{
|
||||
RTL8169_IO_IDR0 = 0x00,
|
||||
RTL8169_IO_IDR1 = 0x01,
|
||||
RTL8169_IO_IDR2 = 0x02,
|
||||
RTL8169_IO_IDR3 = 0x03,
|
||||
RTL8169_IO_IDR4 = 0x04,
|
||||
RTL8169_IO_IDR5 = 0x05,
|
||||
RTL8169_IO_IDR0 = 0x00,
|
||||
RTL8169_IO_IDR1 = 0x01,
|
||||
RTL8169_IO_IDR2 = 0x02,
|
||||
RTL8169_IO_IDR3 = 0x03,
|
||||
RTL8169_IO_IDR4 = 0x04,
|
||||
RTL8169_IO_IDR5 = 0x05,
|
||||
|
||||
RTL8169_IO_TNPDS = 0x20,
|
||||
RTL8169_IO_CR = 0x37,
|
||||
RTL8169_IO_TPPoll = 0x38,
|
||||
RTL8169_IO_IMR = 0x3C,
|
||||
RTL8169_IO_ISR = 0x3E,
|
||||
RTL8169_IO_TCR = 0x40,
|
||||
RTL8169_IO_RCR = 0x44,
|
||||
RTL8169_IO_PHYSts = 0x6C,
|
||||
RTL8169_IO_RMS = 0xDA,
|
||||
RTL8169_IO_CPlusCR = 0xE0,
|
||||
RTL8169_IO_RDSAR = 0xE4,
|
||||
RTL8169_IO_MTPS = 0xEC,
|
||||
RTL8169_IO_TNPDS = 0x20,
|
||||
RTL8169_IO_CR = 0x37,
|
||||
RTL8169_IO_TPPoll = 0x38,
|
||||
RTL8169_IO_IMR = 0x3C,
|
||||
RTL8169_IO_ISR = 0x3E,
|
||||
RTL8169_IO_TCR = 0x40,
|
||||
RTL8169_IO_RCR = 0x44,
|
||||
RTL8169_IO_9346CR = 0x50,
|
||||
RTL8169_IO_PHYSts = 0x6C,
|
||||
RTL8169_IO_RMS = 0xDA,
|
||||
RTL8169_IO_RDSAR = 0xE4,
|
||||
RTL8169_IO_MTPS = 0xEC,
|
||||
};
|
||||
|
||||
enum RTL8169_CR : uint8_t
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Kernel
|
||||
virtual bool link_up() override { return m_link_up; }
|
||||
virtual int link_speed() override;
|
||||
|
||||
virtual size_t payload_mtu() const override { return 0x1FF8 - sizeof(EthernetHeader); }
|
||||
virtual size_t payload_mtu() const override { return 7436 - sizeof(EthernetHeader); }
|
||||
|
||||
virtual void handle_irq() override;
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) override;
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan>) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
@@ -64,17 +64,14 @@ namespace Kernel
|
||||
BAN::UniqPtr<DMARegion> m_rx_descriptor_region;
|
||||
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
||||
|
||||
BAN::Atomic<bool> m_rx_thread_should_die { false };
|
||||
BAN::Atomic<bool> m_rx_thread_is_dead { true };
|
||||
SpinLock m_lock;
|
||||
|
||||
uint32_t m_rx_head { 0 };
|
||||
SpinLock m_rx_lock;
|
||||
ThreadBlocker m_rx_blocker;
|
||||
bool m_thread_should_die { false };
|
||||
BAN::Atomic<bool> m_thread_is_dead { true };
|
||||
ThreadBlocker m_thread_blocker;
|
||||
|
||||
BAN::Atomic<uint32_t> m_tx_head { 0 };
|
||||
BAN::Atomic<uint32_t> m_tx_commit { 0 };
|
||||
SpinLock m_tx_lock;
|
||||
ThreadBlocker m_tx_blocker;
|
||||
uint32_t m_rx_current { 0 };
|
||||
size_t m_tx_current { 0 };
|
||||
|
||||
BAN::MACAddress m_mac_address {};
|
||||
BAN::Atomic<bool> m_link_up { false };
|
||||
|
||||
@@ -66,9 +66,9 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len, uint32_t validated_cksums) override;
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||
|
||||
bool can_read_impl() const override;
|
||||
bool can_write_impl() const override;
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Kernel
|
||||
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override;
|
||||
|
||||
protected:
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len, uint32_t validated_cksums) override;
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||
|
||||
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||
BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
|
||||
@@ -41,7 +41,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
bool can_read_impl() const override { return !m_packets.empty(); }
|
||||
bool can_write_impl() const override { return true; }
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
|
||||
@@ -58,8 +58,6 @@ namespace Kernel
|
||||
BAN::ErrorOr<size_t> recvmsg(int socket, msghdr& message, int flags);
|
||||
BAN::ErrorOr<size_t> sendmsg(int socket, const msghdr& message, int flags);
|
||||
|
||||
int get_max_open_fd() const;
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
|
||||
BAN::ErrorOr<BAN::String> path_of(int) const;
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> inode_of(int);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/ACPI/AML/Node.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
#include <kernel/Storage/StorageController.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -178,7 +179,7 @@ namespace Kernel::PCI
|
||||
private:
|
||||
struct PCIeInfo
|
||||
{
|
||||
paddr_t bus_paddr[256] {};
|
||||
paddr_t bus_paddr[256];
|
||||
};
|
||||
|
||||
PCIManager() = default;
|
||||
|
||||
@@ -44,10 +44,10 @@ namespace Kernel
|
||||
~Process();
|
||||
void cleanup_function(Thread*);
|
||||
|
||||
BAN::ErrorOr<vaddr_t> setup_initial_process_stack(MemoryBackedRegion&, BAN::Span<BAN::String> argv, BAN::Span<BAN::String> envp, BAN::Span<LibELF::AuxiliaryVector> auxv);
|
||||
|
||||
void register_to_scheduler();
|
||||
void exit(int status, int signal);
|
||||
|
||||
void add_thread(Thread*);
|
||||
// returns true if thread was the last one
|
||||
bool on_thread_exit(Thread&);
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<long> sys_exec(const char* path, const char* const* argv, const char* const* envp);
|
||||
|
||||
BAN::ErrorOr<long> sys_wait(pid_t pid, int* stat_loc, int options);
|
||||
BAN::ErrorOr<long> sys_sleep(int seconds);
|
||||
BAN::ErrorOr<long> sys_nanosleep(const timespec* rqtp, timespec* rmtp);
|
||||
BAN::ErrorOr<long> sys_setitimer(int which, const itimerval* value, itimerval* ovalue);
|
||||
|
||||
@@ -136,7 +137,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<long> sys_recvmsg(int socket, msghdr* message, int flags);
|
||||
BAN::ErrorOr<long> sys_sendmsg(int socket, const msghdr* message, int flags);
|
||||
|
||||
BAN::ErrorOr<long> sys_ioctl(int fildes, unsigned long request, void* arg);
|
||||
BAN::ErrorOr<long> sys_ioctl(int fildes, int request, void* arg);
|
||||
|
||||
BAN::ErrorOr<long> sys_pselect(sys_pselect_t* arguments);
|
||||
BAN::ErrorOr<long> sys_ppoll(pollfd* fds, nfds_t nfds, const timespec* tmp_p, const sigset_t* sigmask);
|
||||
@@ -209,12 +210,12 @@ namespace Kernel
|
||||
BAN::ErrorOr<long> sys_set_gsbase(void*);
|
||||
BAN::ErrorOr<long> sys_get_gsbase();
|
||||
|
||||
BAN::ErrorOr<long> sys_thread_create(void (*entry)(void*), void* arg, void* stack_base, size_t stack_size);
|
||||
BAN::ErrorOr<long> sys_thread_exit(void* value);
|
||||
BAN::ErrorOr<long> sys_thread_join(pid_t tid, void** value);
|
||||
BAN::ErrorOr<long> sys_thread_getid();
|
||||
BAN::ErrorOr<long> sys_thread_kill(pid_t tid, int signal);
|
||||
BAN::ErrorOr<long> sys_thread_detach(pid_t tid);
|
||||
BAN::ErrorOr<long> sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg);
|
||||
BAN::ErrorOr<long> sys_pthread_exit(void* value);
|
||||
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, void** value);
|
||||
BAN::ErrorOr<long> sys_pthread_self();
|
||||
BAN::ErrorOr<long> sys_pthread_kill(pthread_t thread, int signal);
|
||||
BAN::ErrorOr<long> sys_pthread_detach(pthread_t thread);
|
||||
|
||||
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*);
|
||||
|
||||
@@ -228,12 +229,11 @@ namespace Kernel
|
||||
|
||||
vaddr_t shared_page_vaddr() const { return m_shared_page_vaddr; }
|
||||
|
||||
PageTable& page_table() { return *m_page_table; }
|
||||
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
|
||||
|
||||
size_t proc_meminfo(off_t offset, BAN::ByteSpan) const;
|
||||
size_t proc_cmdline(off_t offset, BAN::ByteSpan) const;
|
||||
size_t proc_environ(off_t offset, BAN::ByteSpan) const;
|
||||
size_t proc_cputime(off_t offset, BAN::ByteSpan) const;
|
||||
BAN::ErrorOr<BAN::String> proc_cwd() const;
|
||||
BAN::ErrorOr<BAN::String> proc_exe() const;
|
||||
|
||||
@@ -364,13 +364,13 @@ namespace Kernel
|
||||
|
||||
BAN::Vector<Thread*> m_threads;
|
||||
|
||||
struct exited_thread_info_t
|
||||
struct pthread_info_t
|
||||
{
|
||||
pid_t tid;
|
||||
pthread_t thread;
|
||||
void* value;
|
||||
};
|
||||
BAN::Vector<exited_thread_info_t> m_exited_threads;
|
||||
ThreadBlocker m_thread_exit_blocker;
|
||||
BAN::Vector<pthread_info_t> m_exited_pthreads;
|
||||
ThreadBlocker m_pthread_exit_blocker;
|
||||
|
||||
uint64_t m_alarm_interval_ns { 0 };
|
||||
uint64_t m_alarm_wake_time_ns { 0 };
|
||||
|
||||
@@ -57,12 +57,6 @@ namespace Kernel
|
||||
};
|
||||
};
|
||||
|
||||
struct LoadStats
|
||||
{
|
||||
uint64_t ns_idle;
|
||||
uint64_t ns_total;
|
||||
};
|
||||
|
||||
public:
|
||||
static Processor& create(ProcessorID id);
|
||||
static Processor& initialize();
|
||||
@@ -78,6 +72,9 @@ namespace Kernel
|
||||
static void set_smp_enabled() { s_is_smp_enabled = true; }
|
||||
static void wait_until_processors_ready();
|
||||
|
||||
static void toggle_should_print_cpu_load() { s_should_print_cpu_load = !s_should_print_cpu_load; }
|
||||
static bool get_should_print_cpu_load() { return s_should_print_cpu_load; }
|
||||
|
||||
static ProcessorID bsp_id() { return s_bsp_id; }
|
||||
static bool current_is_bsp() { return current_id() == bsp_id(); }
|
||||
|
||||
@@ -119,12 +116,10 @@ namespace Kernel
|
||||
static void* get_current_page_table() { return read_gs_sized<void*>(offsetof(Processor, m_current_page_table)); }
|
||||
static void set_current_page_table(void* page_table) { write_gs_sized<void*>(offsetof(Processor, m_current_page_table), page_table); }
|
||||
|
||||
static LoadStats get_load_stats(size_t index);
|
||||
|
||||
static void yield();
|
||||
static Scheduler& scheduler() { return *read_gs_sized<Scheduler*>(offsetof(Processor, m_scheduler)); }
|
||||
|
||||
static void initialize_tsc(uint64_t realtime_seconds);
|
||||
static void initialize_tsc(uint8_t shift, uint64_t mult, uint64_t realtime_seconds);
|
||||
static void update_tsc();
|
||||
static uint64_t ns_since_boot_tsc();
|
||||
|
||||
@@ -192,6 +187,7 @@ namespace Kernel
|
||||
static ProcessorID s_bsp_id;
|
||||
static BAN::Atomic<uint8_t> s_processor_count;
|
||||
static BAN::Atomic<bool> s_is_smp_enabled;
|
||||
static BAN::Atomic<bool> s_should_print_cpu_load;
|
||||
static paddr_t s_shared_page_paddr;
|
||||
static vaddr_t s_shared_page_vaddr;
|
||||
|
||||
@@ -211,9 +207,10 @@ namespace Kernel
|
||||
|
||||
Scheduler* m_scheduler { nullptr };
|
||||
|
||||
BAN::Atomic<bool> m_load_stat_lock;
|
||||
uint64_t m_load_start_ns { 0 };
|
||||
LoadStats m_load_stats {};
|
||||
uint64_t m_start_ns { 0 };
|
||||
uint64_t m_idle_ns { 0 };
|
||||
uint64_t m_last_update_ns { 0 };
|
||||
uint64_t m_next_update_ns { 0 };
|
||||
|
||||
BAN::Atomic<SMPMessage*> m_smp_pending { nullptr };
|
||||
BAN::Atomic<SMPMessage*> m_smp_free { nullptr };
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Kernel
|
||||
|
||||
public:
|
||||
void add_thread_to_back(Node*);
|
||||
bool add_thread_with_wake_time(Node*); // return true if node was inserted as the first element
|
||||
void add_thread_with_wake_time(Node*);
|
||||
template<typename F>
|
||||
Node* remove_with_condition(F callback);
|
||||
void remove_node(Node*);
|
||||
@@ -60,8 +60,7 @@ namespace Kernel
|
||||
void reschedule(YieldRegisters*);
|
||||
void reschedule_if_idle();
|
||||
|
||||
void on_timer_interrupt();
|
||||
void on_yield(YieldRegisters*);
|
||||
void timer_interrupt();
|
||||
|
||||
static BAN::ErrorOr<void> bind_thread_to_processor(Thread*, ProcessorID);
|
||||
// if thread is already bound, this will never fail
|
||||
@@ -83,7 +82,6 @@ namespace Kernel
|
||||
void update_most_loaded_node_queue(SchedulerQueue::Node*, SchedulerQueue* target_queue);
|
||||
void remove_node_from_most_loaded(SchedulerQueue::Node*);
|
||||
|
||||
void update_wake_up_deadline();
|
||||
void wake_up_sleeping_threads();
|
||||
|
||||
void do_load_balancing();
|
||||
|
||||
@@ -10,14 +10,12 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class AHCIController final : public BAN::RefCounted<AHCIController>, public Interruptable
|
||||
class AHCIController final : public StorageController, public Interruptable
|
||||
{
|
||||
BAN_NON_COPYABLE(AHCIController);
|
||||
BAN_NON_MOVABLE(AHCIController);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<AHCIController>> create(PCI::Device&);
|
||||
|
||||
~AHCIController();
|
||||
|
||||
virtual void handle_irq() override;
|
||||
@@ -29,7 +27,6 @@ namespace Kernel
|
||||
: m_pci_device(pci_device)
|
||||
{ }
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
BAN::Optional<AHCIPortType> check_port_type(volatile HBAPortMemorySpace&);
|
||||
|
||||
private:
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace Kernel
|
||||
|
||||
// Non-owning pointers
|
||||
BAN::Vector<ATADevice*> m_devices;
|
||||
|
||||
friend class ATAController;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,22 +2,23 @@
|
||||
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <kernel/PCI.h>
|
||||
#include <kernel/Storage/StorageController.h>
|
||||
#include <kernel/Storage/ATA/ATABus.h>
|
||||
#include <kernel/Storage/ATA/ATADevice.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class ATAController : public BAN::RefCounted<ATAController>
|
||||
class ATAController : public StorageController
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ATAController>> create(PCI::Device&);
|
||||
static BAN::ErrorOr<BAN::RefPtr<StorageController>> create(PCI::Device&);
|
||||
virtual BAN::ErrorOr<void> initialize() override;
|
||||
|
||||
private:
|
||||
ATAController(PCI::Device& pci_device)
|
||||
: m_pci_device(pci_device)
|
||||
{ }
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
private:
|
||||
PCI::Device& m_pci_device;
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class NVMeController final : public CharacterDevice
|
||||
class NVMeController final : public StorageController, public CharacterDevice
|
||||
{
|
||||
BAN_NON_COPYABLE(NVMeController);
|
||||
BAN_NON_MOVABLE(NVMeController);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<NVMeController>> create(PCI::Device&);
|
||||
static BAN::ErrorOr<BAN::RefPtr<StorageController>> create(PCI::Device&);
|
||||
|
||||
NVMeQueue& io_queue() { return *m_io_queue; }
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
NVMeController(PCI::Device& pci_device);
|
||||
BAN::ErrorOr<void> initialize();
|
||||
virtual BAN::ErrorOr<void> initialize() override;
|
||||
|
||||
BAN::ErrorOr<void> identify_controller();
|
||||
BAN::ErrorOr<void> identify_namespaces();
|
||||
|
||||
15
kernel/include/kernel/Storage/StorageController.h
Normal file
15
kernel/include/kernel/Storage/StorageController.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/RefPtr.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class StorageController : public BAN::RefCounted<StorageController>
|
||||
{
|
||||
public:
|
||||
virtual ~StorageController() {}
|
||||
virtual BAN::ErrorOr<void> initialize() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace Kernel
|
||||
|
||||
void on_close(int) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
private:
|
||||
PseudoTerminalMaster(BAN::UniqPtr<VirtualRange>, mode_t, uid_t, gid_t);
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Kernel
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(unsigned long, void*) override;
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
private:
|
||||
bool putchar(uint8_t ch);
|
||||
|
||||
@@ -41,20 +41,22 @@ namespace Kernel
|
||||
// TODO: userspace stack size is hard limited, maybe make this dynamic?
|
||||
#if ARCH(x86_64)
|
||||
static constexpr size_t userspace_stack_size { 32 << 20 };
|
||||
static constexpr vaddr_t userspace_stack_base { 0x0000700000000000 };
|
||||
#elif ARCH(i686)
|
||||
static constexpr size_t userspace_stack_size { 4 << 20 };
|
||||
static constexpr vaddr_t userspace_stack_base { 0xB0000000 };
|
||||
#endif
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*);
|
||||
static BAN::ErrorOr<Thread*> create_userspace(Process*, PageTable&, vaddr_t userspace_stack_vaddr, size_t userspace_stack_size, vaddr_t entry_point, vaddr_t stack_pointer);
|
||||
static BAN::ErrorOr<Thread*> create_userspace(Process*, PageTable&);
|
||||
~Thread();
|
||||
|
||||
BAN::ErrorOr<Thread*> pthread_create(entry_t, void*);
|
||||
|
||||
BAN::ErrorOr<Thread*> clone(Process*, uintptr_t sp, uintptr_t ip);
|
||||
void setup_process_cleanup();
|
||||
|
||||
BAN::ErrorOr<void> initialize_userspace(vaddr_t entry, BAN::Span<BAN::String> argv, BAN::Span<BAN::String> envp, BAN::Span<LibELF::AuxiliaryVector> auxv);
|
||||
|
||||
// Returns true, if thread is going to trigger signal
|
||||
bool is_interrupted_by_signal(bool skip_stop_and_cont = false) const;
|
||||
|
||||
@@ -75,21 +77,15 @@ namespace Kernel
|
||||
|
||||
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout
|
||||
// if mutex is not nullptr, it will be atomically freed before blocking and automatically locked on wake
|
||||
BAN::ErrorOr<void> sleep_or_eintr_for_ns(uint64_t timeout_ns);
|
||||
BAN::ErrorOr<void> sleep_or_eintr_until_ns(uint64_t waketime_ns);
|
||||
BAN::ErrorOr<void> sleep_or_eintr_ns(uint64_t ns);
|
||||
BAN::ErrorOr<void> block_or_eintr_indefinite(ThreadBlocker& thread_blocker, BaseMutex* mutex);
|
||||
BAN::ErrorOr<void> block_or_eintr_or_timeout_ns(ThreadBlocker& thread_blocker, uint64_t timeout_ns, bool etimedout, BaseMutex* mutex);
|
||||
BAN::ErrorOr<void> block_or_eintr_or_waketime_ns(ThreadBlocker& thread_blocker, uint64_t wake_time_ns, bool etimedout, BaseMutex* mutex);
|
||||
|
||||
BAN::ErrorOr<void> sleep_or_eintr_for_ms(uint64_t timeout_ms)
|
||||
BAN::ErrorOr<void> sleep_or_eintr_ms(uint64_t ms)
|
||||
{
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(timeout_ms, 1'000'000));
|
||||
return sleep_or_eintr_for_ns(timeout_ms * 1'000'000);
|
||||
}
|
||||
BAN::ErrorOr<void> sleep_or_eintr_until_ms(uint64_t waketime_ms)
|
||||
{
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(waketime_ms, 1'000'000));
|
||||
return sleep_or_eintr_until_ns(waketime_ms * 1'000'000);
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(ms, 1'000'000));
|
||||
return sleep_or_eintr_ns(ms * 1'000'000);
|
||||
}
|
||||
BAN::ErrorOr<void> block_or_eintr_or_timeout_ms(ThreadBlocker& thread_blocker, uint64_t timeout_ms, bool etimedout, BaseMutex* mutex)
|
||||
{
|
||||
@@ -110,6 +106,8 @@ namespace Kernel
|
||||
vaddr_t kernel_stack_top() const { return m_kernel_stack->vaddr() + m_kernel_stack->size(); }
|
||||
VirtualRange& kernel_stack() { return *m_kernel_stack; }
|
||||
|
||||
MemoryBackedRegion& userspace_stack() { ASSERT(is_userspace() && m_userspace_stack); return *m_userspace_stack; }
|
||||
|
||||
static Thread& current();
|
||||
static pid_t current_tid();
|
||||
|
||||
@@ -153,6 +151,8 @@ namespace Kernel
|
||||
private:
|
||||
Thread(pid_t tid, Process*);
|
||||
|
||||
void setup_exec(vaddr_t ip, vaddr_t sp);
|
||||
|
||||
static void on_exit_trampoline(Thread*);
|
||||
void on_exit();
|
||||
|
||||
@@ -174,6 +174,7 @@ namespace Kernel
|
||||
BAN::UniqPtr<PageTable> m_keep_alive_page_table;
|
||||
|
||||
BAN::UniqPtr<VirtualRange> m_kernel_stack;
|
||||
MemoryBackedRegion* m_userspace_stack { nullptr };
|
||||
const pid_t m_tid { 0 };
|
||||
State m_state { State::NotStarted };
|
||||
Process* m_process { nullptr };
|
||||
@@ -181,9 +182,6 @@ namespace Kernel
|
||||
BAN::Atomic<bool> m_is_detached { false };
|
||||
bool m_delete_process { false };
|
||||
|
||||
vaddr_t m_userspace_stack_vaddr { 0 };
|
||||
size_t m_userspace_stack_size { 0 };
|
||||
|
||||
vaddr_t m_fsbase { 0 };
|
||||
vaddr_t m_gsbase { 0 };
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Kernel
|
||||
class HPET final : public Timer, public Interruptable
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<HPET>> create();
|
||||
static BAN::ErrorOr<BAN::UniqPtr<HPET>> create(bool force_pic);
|
||||
~HPET();
|
||||
|
||||
virtual uint64_t ms_since_boot() const override;
|
||||
@@ -26,7 +26,7 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
HPET() = default;
|
||||
BAN::ErrorOr<void> initialize();
|
||||
BAN::ErrorOr<void> initialize(bool force_pic);
|
||||
|
||||
volatile HPETRegisters& registers();
|
||||
const volatile HPETRegisters& registers() const;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/Memory/DMARegion.h>
|
||||
#include <kernel/Timer/RTC.h>
|
||||
|
||||
#include <time.h>
|
||||
@@ -32,14 +31,7 @@ namespace Kernel
|
||||
class SystemTimer : public Timer
|
||||
{
|
||||
public:
|
||||
struct TSCInfo
|
||||
{
|
||||
int8_t shift;
|
||||
uint32_t mult;
|
||||
};
|
||||
|
||||
public:
|
||||
static void initialize();
|
||||
static void initialize(bool force_pic);
|
||||
static SystemTimer& get();
|
||||
static bool is_initialized();
|
||||
|
||||
@@ -52,60 +44,29 @@ namespace Kernel
|
||||
virtual bool pre_scheduler_sleep_needs_lock() const override;
|
||||
virtual void pre_scheduler_sleep_ns(uint64_t) override;
|
||||
|
||||
void sleep_for_ns(uint64_t timeout_ns) const;
|
||||
void sleep_until_ns(uint64_t waketime_ns) const;
|
||||
|
||||
void sleep_for_ms(uint64_t timeout_ms) const
|
||||
{
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(timeout_ms, 1'000'000));
|
||||
return sleep_for_ns(timeout_ms * 1'000'000);
|
||||
}
|
||||
void sleep_until_ms(uint64_t waketime_ms) const
|
||||
{
|
||||
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(waketime_ms, 1'000'000));
|
||||
return sleep_until_ns(waketime_ms * 1'000'000);
|
||||
}
|
||||
void sleep_ms(uint64_t ms) const { ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(ms, 1'000'000)); return sleep_ns(ms * 1'000'000); }
|
||||
void sleep_ns(uint64_t ns) const;
|
||||
|
||||
void dont_invoke_scheduler() { m_timer->m_should_invoke_scheduler = false; }
|
||||
|
||||
void update_tsc();
|
||||
TSCInfo tsc_info() const;
|
||||
|
||||
uint64_t ns_since_boot_no_tsc() const { return m_timer->ns_since_boot(); }
|
||||
void update_tsc() const;
|
||||
uint64_t ns_since_boot_no_tsc() const;
|
||||
|
||||
timespec real_time() const;
|
||||
|
||||
private:
|
||||
SystemTimer() = default;
|
||||
|
||||
void initialize_timers();
|
||||
void initialize_timers(bool force_pic);
|
||||
|
||||
void initialize_invariant_tsc();
|
||||
void initialize_pvclock();
|
||||
uint64_t get_tsc_frequency() const;
|
||||
|
||||
private:
|
||||
enum class TSCType
|
||||
{
|
||||
None,
|
||||
Invariant,
|
||||
PVClock,
|
||||
};
|
||||
|
||||
uint64_t m_boot_time { 0 };
|
||||
BAN::UniqPtr<RTC> m_rtc;
|
||||
BAN::UniqPtr<Timer> m_timer;
|
||||
|
||||
TSCType m_tsc_type = TSCType::None;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int8_t shift;
|
||||
uint32_t mult;
|
||||
} invariant;
|
||||
} m_tsc_info;
|
||||
|
||||
BAN::UniqPtr<DMARegion> m_tsc_page;
|
||||
uint64_t m_tsc_update_ns { 0 };
|
||||
bool m_has_invariant_tsc { false };
|
||||
mutable uint32_t m_timer_ticks { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
bool can_read_impl() const override { return true; }
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(unsigned long request, void* arg) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int request, void* arg) override;
|
||||
|
||||
private:
|
||||
USBJoystick(USBHIDDriver&);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Kernel
|
||||
const uint64_t m_block_count;
|
||||
const uint32_t m_block_size;
|
||||
|
||||
char m_name[4];
|
||||
const char m_name[4];
|
||||
|
||||
friend class BAN::RefPtr<USBSCSIDevice>;
|
||||
};
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Errors.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
namespace Kernel {
|
||||
BAN::ErrorOr<void> read_from_user(const void* user_addr, void* out, size_t size);
|
||||
BAN::ErrorOr<void> read_string_from_user(const char* user_addr, char* out, size_t max_size);
|
||||
BAN::ErrorOr<void> write_to_user(void* user_addr, const void* in, size_t size);
|
||||
|
||||
};
|
||||
|
||||
@@ -952,7 +952,7 @@ acpi_release_global_lock:
|
||||
{
|
||||
if (IO::inw(fadt().pm1a_cnt_blk) & PM1_CNT_SCI_EN)
|
||||
break;
|
||||
SystemTimer::get().sleep_for_ms(10);
|
||||
SystemTimer::get().sleep_ms(10);
|
||||
}
|
||||
|
||||
if (!(IO::inw(fadt().pm1a_cnt_blk) & PM1_CNT_SCI_EN))
|
||||
|
||||
@@ -2146,9 +2146,9 @@ namespace Kernel::ACPI::AML
|
||||
|
||||
auto milliseconds = TRY(convert_node(TRY(parse_node(context)), ConvInteger, sizeof(uint64_t)));
|
||||
|
||||
const uint64_t waketime_ms = SystemTimer::get().ms_since_boot() + milliseconds.as.integer.value;
|
||||
while (SystemTimer::get().ms_since_boot() < waketime_ms)
|
||||
SystemTimer::get().sleep_until_ms(waketime_ms);
|
||||
const uint64_t wakeup_ms = SystemTimer::get().ms_since_boot() + milliseconds.as.integer.value;
|
||||
for (uint64_t curr_ms = SystemTimer::get().ms_since_boot(); curr_ms < wakeup_ms; curr_ms = SystemTimer::get().ms_since_boot())
|
||||
SystemTimer::get().sleep_ms(wakeup_ms - curr_ms);
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -2392,7 +2392,7 @@ namespace Kernel::ACPI::AML
|
||||
result.type = Node::Type::Integer;
|
||||
result.as.integer.value = BAN::numeric_limits<uint64_t>::max();
|
||||
|
||||
const uint64_t waketime_ms = (timeout_ms >= 0xFFFF)
|
||||
const uint64_t wake_time_ms = (timeout_ms >= 0xFFFF)
|
||||
? BAN::numeric_limits<uint64_t>::max()
|
||||
: SystemTimer::get().ms_since_boot() + timeout_ms;
|
||||
|
||||
@@ -2401,9 +2401,9 @@ namespace Kernel::ACPI::AML
|
||||
{
|
||||
if (sync_object->node.as.mutex->mutex.try_lock())
|
||||
break;
|
||||
if (SystemTimer::get().ms_since_boot() >= waketime_ms)
|
||||
if (SystemTimer::get().ms_since_boot() >= wake_time_ms)
|
||||
return result;
|
||||
Processor::yield();
|
||||
SystemTimer::get().sleep_ms(1);
|
||||
}
|
||||
|
||||
if (sync_object->node.as.mutex->global_lock)
|
||||
|
||||
@@ -437,27 +437,8 @@ namespace Kernel
|
||||
|
||||
dprintln("CPU {}: lapic timer frequency: {} Hz", Kernel::Processor::current_id(), m_lapic_timer_frequency_hz);
|
||||
|
||||
write_to_local_apic(LAPIC_TIMER_LVT, TimerModeOneShot | IRQ_TIMER);
|
||||
write_to_local_apic(LAPIC_TIMER_INITIAL_REG, 0);
|
||||
}
|
||||
|
||||
void APIC::set_timer_dealine(uint64_t target_ns)
|
||||
{
|
||||
// TODO: don't hardcode divide by 2
|
||||
const uint64_t effective_freq = m_lapic_timer_frequency_hz / 2;
|
||||
|
||||
const uint64_t delta_ns = [&]() -> uint64_t {
|
||||
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||
if (current_ns >= target_ns)
|
||||
return 1;
|
||||
const uint64_t delta_ns = target_ns - current_ns;
|
||||
if (BAN::Math::will_multiplication_overflow(delta_ns, effective_freq))
|
||||
return BAN::numeric_limits<uint64_t>::max() / effective_freq;
|
||||
return delta_ns;
|
||||
}();
|
||||
|
||||
const uint64_t ticks = BAN::Math::div_round_up<uint64_t>(delta_ns * effective_freq, 1'000'000'000);
|
||||
write_to_local_apic(LAPIC_TIMER_INITIAL_REG, BAN::Math::min<uint64_t>(ticks, BAN::numeric_limits<uint32_t>::max()));
|
||||
write_to_local_apic(LAPIC_TIMER_LVT, TimerModePeriodic | IRQ_TIMER);
|
||||
write_to_local_apic(LAPIC_TIMER_INITIAL_REG, m_lapic_timer_frequency_hz / 2 / 100);
|
||||
}
|
||||
|
||||
uint32_t APIC::read_from_local_apic(ptrdiff_t offset)
|
||||
|
||||
@@ -77,9 +77,9 @@ namespace Kernel
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> AudioController::ioctl_impl(unsigned long request, void* arg)
|
||||
BAN::ErrorOr<long> AudioController::ioctl_impl(int cmd, void* arg)
|
||||
{
|
||||
switch (request)
|
||||
switch (cmd)
|
||||
{
|
||||
case SND_GET_CHANNELS:
|
||||
*static_cast<uint32_t*>(arg) = get_channels();
|
||||
@@ -92,7 +92,7 @@ namespace Kernel
|
||||
{
|
||||
SpinLockGuard _(m_spinlock);
|
||||
*static_cast<uint32_t*>(arg) = m_sample_data->size();
|
||||
if (request == SND_RESET_BUFFER)
|
||||
if (cmd == SND_RESET_BUFFER)
|
||||
m_sample_data->pop(m_sample_data->size());
|
||||
return 0;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ namespace Kernel
|
||||
return 0;
|
||||
}
|
||||
|
||||
return CharacterDevice::ioctl_impl(request, arg);
|
||||
return CharacterDevice::ioctl_impl(cmd, arg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -448,7 +448,7 @@ namespace Kernel
|
||||
continue;
|
||||
const auto& amp = path[i]->output_amplifier.value();
|
||||
|
||||
const int32_t step_mdB = (amp.step_size + 1) * 250;
|
||||
const int32_t step_mdB = amp.step_size * 250;
|
||||
m_volume_info.step_mdB = step_mdB;
|
||||
m_volume_info.min_mdB = -amp.offset * step_mdB;
|
||||
m_volume_info.max_mdB = (amp.num_steps - amp.offset) * step_mdB;
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace Kernel
|
||||
// 4.3 The software must wait at least 521 us (25 frames) after reading CRST as a 1
|
||||
// before assuming that codecs have all made status change requests and have been
|
||||
// registered by the controller
|
||||
SystemTimer::get().sleep_for_ns(521'000);
|
||||
SystemTimer::get().sleep_ms(1);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -85,38 +85,6 @@ namespace CPUID
|
||||
return buffer[3] & (1 << 8);
|
||||
}
|
||||
|
||||
bool has_rdtscp()
|
||||
{
|
||||
uint32_t buffer[4] {};
|
||||
get_cpuid(0x80000000, buffer);
|
||||
if (buffer[0] < 0x80000001)
|
||||
return false;
|
||||
get_cpuid(0x80000001, buffer);
|
||||
return buffer[3] & (1 << 27);
|
||||
}
|
||||
|
||||
uint64_t get_tsc_frequency()
|
||||
{
|
||||
uint32_t buffer[4];
|
||||
get_cpuid(0x00, buffer);
|
||||
if (buffer[0] < 0x15)
|
||||
return 0;
|
||||
get_cpuid(0x15, buffer);
|
||||
if (buffer[0] == 0 || buffer[1] == 0 || buffer[2] == 0)
|
||||
return 0;
|
||||
return static_cast<uint64_t>(buffer[2]) * buffer[1] / buffer[0];
|
||||
}
|
||||
|
||||
bool has_kvm_pvclock()
|
||||
{
|
||||
uint32_t buffer[4] {};
|
||||
get_cpuid(0x40000000, buffer);
|
||||
if (buffer[1] != 0x4B4D564B || buffer[2] != 0x564B4D56 || buffer[3] != 0x4D)
|
||||
return false;
|
||||
get_cpuid(0x40000001, buffer);
|
||||
return buffer[0] & (1 << 3);
|
||||
}
|
||||
|
||||
const char* feature_string_ecx(uint32_t feat)
|
||||
{
|
||||
switch (feat)
|
||||
|
||||
@@ -135,9 +135,9 @@ namespace Kernel
|
||||
return bytes_to_copy;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> FramebufferDevice::ioctl_impl(unsigned long request, void* arg)
|
||||
BAN::ErrorOr<long> FramebufferDevice::ioctl_impl(int cmd, void* arg)
|
||||
{
|
||||
switch (request)
|
||||
switch (cmd)
|
||||
{
|
||||
case FB_MSYNC_RECTANGLE:
|
||||
{
|
||||
@@ -152,7 +152,7 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
return CharacterDevice::ioctl_impl(request, arg);
|
||||
return CharacterDevice::ioctl(cmd, arg);
|
||||
}
|
||||
|
||||
uint32_t FramebufferDevice::get_pixel(uint32_t x, uint32_t y) const
|
||||
@@ -356,7 +356,51 @@ namespace Kernel
|
||||
|
||||
void do_msync(uint32_t first_pixel, uint32_t pixel_count)
|
||||
{
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
if (!Processor::get_should_print_cpu_load())
|
||||
return m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
|
||||
const uint32_t fb_width = m_framebuffer->width();
|
||||
|
||||
// If we are here (in FramebufferMemoryRegion), our terminal driver is FramebufferTerminalDriver
|
||||
ASSERT(g_terminal_driver->has_font());
|
||||
const auto& font = g_terminal_driver->font();
|
||||
|
||||
const uint32_t x = first_pixel % fb_width;
|
||||
const uint32_t y = first_pixel / fb_width;
|
||||
|
||||
const uint32_t load_w = 16 * font.width();
|
||||
const uint32_t load_h = Processor::count() * font.height();
|
||||
|
||||
if (y >= load_h || x + pixel_count <= fb_width - load_w)
|
||||
return m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
|
||||
if (x >= fb_width - load_w && x + pixel_count <= fb_width)
|
||||
return;
|
||||
|
||||
if (x < fb_width - load_w)
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, fb_width - load_w - x);
|
||||
|
||||
if (x + pixel_count > fb_width)
|
||||
{
|
||||
const uint32_t past_last_pixel = first_pixel + pixel_count;
|
||||
|
||||
first_pixel = (y + 1) * fb_width;
|
||||
pixel_count = past_last_pixel - first_pixel;
|
||||
|
||||
const uint32_t cpu_load_end = load_h * fb_width;
|
||||
|
||||
while (pixel_count && first_pixel < cpu_load_end)
|
||||
{
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, BAN::Math::min(pixel_count, fb_width - load_w));
|
||||
|
||||
const uint32_t advance = BAN::Math::min(pixel_count, fb_width);
|
||||
pixel_count -= advance;
|
||||
first_pixel += advance;
|
||||
}
|
||||
|
||||
if (pixel_count)
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace Kernel::ELF
|
||||
{
|
||||
@@ -290,9 +291,7 @@ namespace Kernel::ELF
|
||||
TRY(memory_regions.emplace_back(BAN::move(region)));
|
||||
}
|
||||
|
||||
if (!interpreter.empty())
|
||||
result.interp_base = load_base_vaddr;
|
||||
|
||||
result.open_execfd = !interpreter.empty();
|
||||
result.entry_point = load_base_vaddr + file_header.e_entry;
|
||||
result.regions = BAN::move(memory_regions);
|
||||
return BAN::move(result);
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace Kernel
|
||||
[](void* _devfs)
|
||||
{
|
||||
auto* devfs = static_cast<DevFileSystem*>(_devfs);
|
||||
uint64_t next_update_ms = SystemTimer::get().ms_since_boot();
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
@@ -58,8 +57,7 @@ namespace Kernel
|
||||
for (auto& device : devfs->m_devices)
|
||||
device->update();
|
||||
}
|
||||
SystemTimer::get().sleep_until_ms(next_update_ms);
|
||||
next_update_ms += 10;
|
||||
SystemTimer::get().sleep_ms(10);
|
||||
}
|
||||
}, s_instance
|
||||
));
|
||||
|
||||
@@ -167,36 +167,10 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> Ext2FS::initialize_root_inode()
|
||||
{
|
||||
m_root_inode = TRY(open_inode(Ext2::Enum::ROOT_INO));
|
||||
m_root_inode = TRY(Ext2Inode::create(*this, Ext2::Enum::ROOT_INO));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> Ext2FS::open_inode(ino_t ino)
|
||||
{
|
||||
LockGuard _(m_inode_cache_lock);
|
||||
|
||||
auto it = m_inode_cache.find(ino);
|
||||
if (it != m_inode_cache.end())
|
||||
return it->value;
|
||||
|
||||
auto inode_location = TRY(locate_inode(ino));
|
||||
|
||||
auto block_buffer = TRY(get_block_buffer());
|
||||
TRY(read_block(inode_location.block, block_buffer));
|
||||
|
||||
auto& inode = block_buffer.span().slice(inode_location.offset).as<Ext2::Inode>();
|
||||
|
||||
auto result = TRY(BAN::RefPtr<Ext2Inode>::create(*this, inode, ino));
|
||||
TRY(m_inode_cache.insert(ino, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void Ext2FS::remove_from_cache(ino_t ino)
|
||||
{
|
||||
LockGuard _(m_inode_cache_lock);
|
||||
m_inode_cache.remove(ino);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<uint32_t> Ext2FS::create_inode(const Ext2::Inode& ext2_inode)
|
||||
{
|
||||
auto bgd_buffer = TRY(m_buffer_manager.get_buffer());
|
||||
|
||||
@@ -42,6 +42,24 @@ namespace Kernel
|
||||
return (m_ino - 1) / m_fs.superblock().blocks_per_group;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> Ext2Inode::create(Ext2FS& fs, uint32_t inode_ino)
|
||||
{
|
||||
auto it = fs.inode_cache().find(inode_ino);
|
||||
if (it != fs.inode_cache().end())
|
||||
return it->value;
|
||||
|
||||
auto inode_location = TRY(fs.locate_inode(inode_ino));
|
||||
|
||||
auto block_buffer = TRY(fs.get_block_buffer());
|
||||
TRY(fs.read_block(inode_location.block, block_buffer));
|
||||
|
||||
auto& inode = block_buffer.span().slice(inode_location.offset).as<Ext2::Inode>();
|
||||
|
||||
auto result = TRY(BAN::RefPtr<Ext2Inode>::create(fs, inode, inode_ino));
|
||||
TRY(fs.inode_cache().insert(inode_ino, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Ext2Inode::~Ext2Inode()
|
||||
{
|
||||
if (m_nlink > 0)
|
||||
@@ -71,53 +89,57 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block_no_lock(uint32_t block, uint32_t index, uint32_t depth, bool allocate)
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate)
|
||||
{
|
||||
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
|
||||
|
||||
ASSERT(block != 0);
|
||||
if (block == 0 && !allocate)
|
||||
return BAN::Optional<uint32_t>();
|
||||
|
||||
if (depth == 0)
|
||||
return BAN::Optional<uint32_t>(block);
|
||||
|
||||
uint32_t local_index = index;
|
||||
for (uint32_t i = 1; i < depth; i++)
|
||||
local_index /= indices_per_fs_block;
|
||||
local_index %= indices_per_fs_block;
|
||||
|
||||
uint32_t next_block = 0;
|
||||
|
||||
if (auto cached = block_cache_find(block, local_index); cached.has_value())
|
||||
next_block = cached.value();
|
||||
|
||||
if (next_block == 0)
|
||||
{
|
||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||
TRY(m_fs.read_block(block, block_buffer));
|
||||
auto block_span = block_buffer.span().as_span<uint32_t>();
|
||||
|
||||
next_block = block_span[local_index];
|
||||
|
||||
if (next_block == 0)
|
||||
if (block == 0)
|
||||
{
|
||||
if (!allocate)
|
||||
return BAN::Optional<uint32_t>();
|
||||
|
||||
auto zero_buffer = TRY(m_fs.get_block_buffer());
|
||||
memset(zero_buffer.data(), 0, zero_buffer.size());
|
||||
|
||||
next_block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
TRY(m_fs.write_block(next_block, zero_buffer));
|
||||
block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
m_blocks++;
|
||||
|
||||
block_span[local_index] = next_block;
|
||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||
memset(block_buffer.data(), 0x00, block_buffer.size());
|
||||
TRY(m_fs.write_block(block, block_buffer));
|
||||
}
|
||||
|
||||
block_cache_add(block, local_index, next_block);
|
||||
return BAN::Optional<uint32_t>(block);
|
||||
}
|
||||
|
||||
return block_from_indirect_block_no_lock(next_block, index, depth - 1, allocate);
|
||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||
|
||||
bool needs_write = false;
|
||||
|
||||
if (block != 0)
|
||||
TRY(m_fs.read_block(block, block_buffer));
|
||||
else
|
||||
{
|
||||
block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
m_blocks++;
|
||||
|
||||
memset(block_buffer.data(), 0, block_buffer.size());
|
||||
|
||||
needs_write = true;
|
||||
}
|
||||
|
||||
uint32_t divisor = 1;
|
||||
for (uint32_t i = 1; i < depth; i++)
|
||||
divisor *= indices_per_fs_block;
|
||||
|
||||
uint32_t& new_block = block_buffer.span().as_span<uint32_t>()[(index / divisor) % indices_per_fs_block];
|
||||
const auto old_block = new_block;
|
||||
|
||||
const auto result = TRY(block_from_indirect_block_no_lock(new_block, index, depth - 1, allocate));
|
||||
|
||||
if (needs_write || old_block != new_block)
|
||||
TRY(m_fs.write_block(block, block_buffer));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate)
|
||||
@@ -144,29 +166,16 @@ namespace Kernel
|
||||
}
|
||||
data_block_index -= 12;
|
||||
|
||||
uint32_t depth_block_count = indices_per_block;
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
if (data_block_index < depth_block_count)
|
||||
{
|
||||
auto& block = m_ext2_blocks.block[12 + i];
|
||||
if (block == 0)
|
||||
{
|
||||
if (!allocate)
|
||||
return BAN::Optional<uint32_t>();
|
||||
if (data_block_index < indices_per_block)
|
||||
return block_from_indirect_block_no_lock(m_ext2_blocks.block[12], data_block_index, 1, allocate);
|
||||
data_block_index -= indices_per_block;
|
||||
|
||||
auto zero_buffer = TRY(m_fs.get_block_buffer());
|
||||
memset(zero_buffer.data(), 0, zero_buffer.size());
|
||||
if (data_block_index < indices_per_block * indices_per_block)
|
||||
return block_from_indirect_block_no_lock(m_ext2_blocks.block[13], data_block_index, 2, allocate);
|
||||
data_block_index -= indices_per_block * indices_per_block;
|
||||
|
||||
block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
TRY(m_fs.write_block(block, zero_buffer));
|
||||
m_blocks++;
|
||||
}
|
||||
return block_from_indirect_block_no_lock(block, data_block_index, i + 1, allocate);
|
||||
}
|
||||
data_block_index -= depth_block_count;
|
||||
depth_block_count *= indices_per_block;
|
||||
}
|
||||
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
|
||||
return block_from_indirect_block_no_lock(m_ext2_blocks.block[14], data_block_index, 3, allocate);
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
@@ -533,7 +542,7 @@ done:
|
||||
|
||||
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
|
||||
|
||||
auto inode_or_error = m_fs.open_inode(new_ino);
|
||||
auto inode_or_error = Ext2Inode::create(m_fs, new_ino);
|
||||
if (inode_or_error.is_error())
|
||||
{
|
||||
TRY(m_fs.delete_inode(new_ino));
|
||||
@@ -559,7 +568,7 @@ done:
|
||||
|
||||
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
|
||||
|
||||
auto inode_or_error = m_fs.open_inode(new_ino);
|
||||
auto inode_or_error = Ext2Inode::create(m_fs, new_ino);
|
||||
if (inode_or_error.is_error())
|
||||
{
|
||||
TRY(m_fs.delete_inode(new_ino));
|
||||
@@ -805,7 +814,7 @@ needs_new_block:
|
||||
}
|
||||
else if (entry_name == ".."_sv)
|
||||
{
|
||||
auto parent = TRY(m_fs.open_inode(entry.inode));
|
||||
auto parent = TRY(Ext2Inode::create(m_fs, entry.inode));
|
||||
parent->m_nlink--;
|
||||
TRY(parent->sync_inode_no_lock());
|
||||
}
|
||||
@@ -851,7 +860,7 @@ needs_new_block:
|
||||
auto& entry = block_buffer.span().slice(offset).as<Ext2::LinkedDirectoryEntry>();
|
||||
if (entry.inode && name == BAN::StringView(entry.name, entry.name_len))
|
||||
{
|
||||
auto inode = TRY(m_fs.open_inode(entry.inode));
|
||||
auto inode = TRY(Ext2Inode::create(m_fs, entry.inode));
|
||||
if (cleanup_directory && inode->mode().ifdir())
|
||||
{
|
||||
if (!TRY(inode->is_directory_empty_no_lock()))
|
||||
@@ -869,7 +878,11 @@ needs_new_block:
|
||||
// NOTE: If this was the last link to inode we must
|
||||
// remove it from inode cache to trigger cleanup
|
||||
if (inode->nlink() == 0)
|
||||
m_fs.remove_from_cache(inode->ino());
|
||||
{
|
||||
auto& cache = m_fs.inode_cache();
|
||||
if (cache.contains(inode->ino()))
|
||||
cache.remove(inode->ino());
|
||||
}
|
||||
|
||||
// FIXME: This should expand the last inode if exists
|
||||
entry.inode = 0;
|
||||
@@ -879,8 +892,6 @@ needs_new_block:
|
||||
}
|
||||
}
|
||||
|
||||
dir_cache_remove(name);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -917,8 +928,6 @@ needs_new_block:
|
||||
auto inode_location = TRY(m_fs.locate_inode(ino()));
|
||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||
|
||||
// FIXME: race condition when syncing multiple inodes :)
|
||||
|
||||
TRY(m_fs.read_block(inode_location.block, block_buffer));
|
||||
if (memcmp(block_buffer.data() + inode_location.offset, &inode, sizeof(Ext2::Inode)))
|
||||
{
|
||||
@@ -939,9 +948,6 @@ needs_new_block:
|
||||
{
|
||||
ASSERT(mode().ifdir());
|
||||
|
||||
if (auto cached = dir_cache_find(file_name))
|
||||
return cached;
|
||||
|
||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||
|
||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||
@@ -957,129 +963,11 @@ needs_new_block:
|
||||
auto& entry = entry_span.as<const Ext2::LinkedDirectoryEntry>();
|
||||
BAN::StringView entry_name(entry.name, entry.name_len);
|
||||
if (entry.inode && entry_name == file_name)
|
||||
{
|
||||
auto inode = BAN::RefPtr<Inode>(TRY(m_fs.open_inode(entry.inode)));
|
||||
dir_cache_add(file_name, inode);
|
||||
return inode;
|
||||
}
|
||||
return BAN::RefPtr<Inode>(TRY(Ext2Inode::create(m_fs, entry.inode)));
|
||||
entry_span = entry_span.slice(entry.rec_len);
|
||||
}
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
}
|
||||
|
||||
BAN::Optional<uint32_t> Ext2Inode::block_cache_find(uint32_t block, uint32_t index) const
|
||||
{
|
||||
SpinLockGuard _(m_block_cache_lock);
|
||||
for (const auto& cache : m_block_cache)
|
||||
{
|
||||
if (cache.block != block || cache.index != index)
|
||||
continue;
|
||||
cache.freq++;
|
||||
return cache.target;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Ext2Inode::block_cache_remove(uint32_t block, uint32_t index)
|
||||
{
|
||||
SpinLockGuard _(m_block_cache_lock);
|
||||
for (auto& cache : m_block_cache)
|
||||
{
|
||||
if (cache.block != block || cache.index != index)
|
||||
continue;
|
||||
cache = {};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Ext2Inode::block_cache_add(uint32_t block, uint32_t index, uint32_t target)
|
||||
{
|
||||
SpinLockGuard _(m_block_cache_lock);
|
||||
|
||||
size_t min_freq = BAN::numeric_limits<size_t>::max();
|
||||
size_t min_index = 0;
|
||||
for (size_t i = 0; i < m_block_cache.size(); i++)
|
||||
{
|
||||
const auto& cache = m_block_cache[i];
|
||||
if (cache.block == block && cache.index == index)
|
||||
{
|
||||
ASSERT(cache.target == target);
|
||||
cache.freq++;
|
||||
return;
|
||||
}
|
||||
if (cache.freq < min_freq)
|
||||
{
|
||||
min_freq = cache.freq;
|
||||
min_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
m_block_cache[min_index] = {
|
||||
.freq = 1,
|
||||
.block = block,
|
||||
.index = index,
|
||||
.target = target,
|
||||
};
|
||||
}
|
||||
|
||||
BAN::RefPtr<Inode> Ext2Inode::dir_cache_find(BAN::StringView name) const
|
||||
{
|
||||
RWLockRDGuard _(m_dir_cache_lock);
|
||||
for (const auto& cache : m_dir_cache)
|
||||
{
|
||||
if (!cache.inode || name != BAN::StringView(cache.name, cache.name_len))
|
||||
continue;
|
||||
BAN::atomic_add_fetch(cache.freq, 1);
|
||||
return cache.inode;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Ext2Inode::dir_cache_remove(BAN::StringView name)
|
||||
{
|
||||
RWLockWRGuard _(m_dir_cache_lock);
|
||||
for (auto& cache : m_dir_cache)
|
||||
{
|
||||
if (!cache.inode || name != BAN::StringView(cache.name, cache.name_len))
|
||||
continue;
|
||||
cache.freq = 0;
|
||||
cache.inode = {};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Ext2Inode::dir_cache_add(BAN::StringView name, BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
RWLockWRGuard _(m_dir_cache_lock);
|
||||
|
||||
if (m_dir_cache.empty() && m_dir_cache.resize(dir_cache_size).is_error())
|
||||
return;
|
||||
|
||||
size_t min_freq = BAN::numeric_limits<size_t>::max();
|
||||
size_t min_index = 0;
|
||||
for (size_t i = 0; i < m_dir_cache.size(); i++)
|
||||
{
|
||||
const auto& cache = m_dir_cache[i];
|
||||
if (cache.inode && name == BAN::StringView(cache.name, cache.name_len))
|
||||
{
|
||||
ASSERT(cache.inode == inode);
|
||||
cache.freq++;
|
||||
return;
|
||||
}
|
||||
if (cache.freq < min_freq)
|
||||
{
|
||||
min_freq = cache.freq;
|
||||
min_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
auto& cache = m_dir_cache[min_index];
|
||||
cache.freq = 1;
|
||||
cache.inode = inode;
|
||||
cache.name_len = name.size();
|
||||
memcpy(cache.name, name.data(), name.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Inode::ioctl(unsigned long request, void* arg)
|
||||
BAN::ErrorOr<long> Inode::ioctl(int request, void* arg)
|
||||
{
|
||||
auto ret = ioctl_impl(request, arg);
|
||||
if (!ret.is_error() || ret.error().get_error_code() != ENOTSUP)
|
||||
|
||||
@@ -16,23 +16,22 @@ namespace Kernel
|
||||
MUST(s_instance->TmpFileSystem::initialize(0555, 0, 0));
|
||||
|
||||
auto meminfo_inode = MUST(ProcROInode::create_new(
|
||||
[](off_t offset, BAN::ByteSpan buffer, void*) -> BAN::ErrorOr<size_t>
|
||||
[](off_t offset, BAN::ByteSpan buffer) -> size_t
|
||||
{
|
||||
ASSERT(offset >= 0);
|
||||
if ((size_t)offset >= sizeof(full_meminfo_t))
|
||||
return 0;
|
||||
|
||||
const full_meminfo_t meminfo {
|
||||
.page_size = PAGE_SIZE,
|
||||
.free_pages = Heap::get().free_pages(),
|
||||
.used_pages = Heap::get().used_pages(),
|
||||
};
|
||||
full_meminfo_t meminfo;
|
||||
meminfo.page_size = PAGE_SIZE;
|
||||
meminfo.free_pages = Heap::get().free_pages();
|
||||
meminfo.used_pages = Heap::get().used_pages();
|
||||
|
||||
size_t bytes = BAN::Math::min<size_t>(sizeof(full_meminfo_t) - offset, buffer.size());
|
||||
memcpy(buffer.data(), (uint8_t*)&meminfo + offset, bytes);
|
||||
return bytes;
|
||||
},
|
||||
*s_instance, nullptr, 0444, 0, 0
|
||||
*s_instance, 0444, 0, 0
|
||||
));
|
||||
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*meminfo_inode, "meminfo"_sv));
|
||||
|
||||
@@ -49,35 +48,6 @@ namespace Kernel
|
||||
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*self_inode, "self"_sv));
|
||||
}
|
||||
|
||||
void ProcFileSystem::post_scheduler_initialize()
|
||||
{
|
||||
MUST(s_instance->root_inode()->create_directory("cpu"_sv, Inode::Mode::IFDIR | 0555, 0, 0));
|
||||
auto cpu_directory = MUST(s_instance->root_inode()->find_inode("cpu"_sv));
|
||||
|
||||
for (size_t i = 0; i < Processor::count(); i++)
|
||||
{
|
||||
auto cpu_inode = MUST(ProcROInode::create_new(
|
||||
[](off_t offset, BAN::ByteSpan buffer, void* index_ptr) -> BAN::ErrorOr<size_t>
|
||||
{
|
||||
ASSERT(offset >= 0);
|
||||
|
||||
const size_t index = reinterpret_cast<uintptr_t>(index_ptr);
|
||||
const auto load_stats = Processor::get_load_stats(index);
|
||||
|
||||
auto string = TRY(BAN::String::formatted("{} {}", load_stats.ns_idle, load_stats.ns_total));
|
||||
if (static_cast<size_t>(offset) >= string.size())
|
||||
return 0;
|
||||
|
||||
const size_t bytes = BAN::Math::min<size_t>(string.size() - offset, buffer.size());
|
||||
memcpy(buffer.data(), string.data() + offset, bytes);
|
||||
return bytes;
|
||||
},
|
||||
*s_instance, reinterpret_cast<void*>(i), 0444, 0, 0
|
||||
));
|
||||
MUST(cpu_directory->link_inode(MUST(BAN::String::formatted("{}", i)), cpu_inode));
|
||||
}
|
||||
}
|
||||
|
||||
ProcFileSystem& ProcFileSystem::get()
|
||||
{
|
||||
ASSERT(s_instance);
|
||||
|
||||
@@ -16,13 +16,12 @@ namespace Kernel
|
||||
|
||||
TRY(inode->link_inode(*inode, "."_sv));
|
||||
TRY(inode->link_inode(static_cast<TmpInode&>(*fs.root_inode()), ".."_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_meminfo, fs, 0444)), "meminfo"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_meminfo, fs, 0400)), "meminfo"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_cmdline, fs, 0444)), "cmdline"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_environ, fs, 0400)), "environ"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_cputime, fs, 0444)), "cputime"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcSymlinkProcessInode::create_new(process, &Process::proc_cwd, fs, 0777)), "cwd"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcSymlinkProcessInode::create_new(process, &Process::proc_exe, fs, 0777)), "exe"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcFDDirectoryInode::create_new(process, fs, 0500)), "fd"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcFDDirectoryInode::create_new(process, fs, 0777)), "fd"_sv));
|
||||
|
||||
return inode;
|
||||
}
|
||||
@@ -39,7 +38,6 @@ namespace Kernel
|
||||
(void)TmpDirectoryInode::unlink_impl("meminfo"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("cmdline"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("environ"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("cputime"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("cwd"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("exe"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("fd"_sv);
|
||||
@@ -97,20 +95,19 @@ namespace Kernel
|
||||
return (m_process.*m_callback)();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcROInode>> ProcROInode::create_new(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem& fs, void* argument, mode_t mode, uid_t uid, gid_t gid)
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcROInode>> ProcROInode::create_new(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||
{
|
||||
auto inode_info = create_inode_info(Mode::IFREG | mode, uid, gid);
|
||||
|
||||
auto* inode_ptr = new ProcROInode(callback, fs, argument, inode_info);
|
||||
auto* inode_ptr = new ProcROInode(callback, fs, inode_info);
|
||||
if (inode_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
return BAN::RefPtr<ProcROInode>::adopt(inode_ptr);
|
||||
}
|
||||
|
||||
ProcROInode::ProcROInode(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem& fs, void* argument, const TmpInodeInfo& inode_info)
|
||||
ProcROInode::ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem& fs, const TmpInodeInfo& inode_info)
|
||||
: TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info)
|
||||
, m_callback(callback)
|
||||
, m_argument(argument)
|
||||
{
|
||||
m_mode |= Inode::Mode::IFREG;
|
||||
}
|
||||
@@ -119,7 +116,7 @@ namespace Kernel
|
||||
{
|
||||
if (offset < 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
return TRY(m_callback(offset, buffer, m_argument));
|
||||
return m_callback(offset, buffer);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> ProcSymlinkInode::create_new(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace Kernel
|
||||
if (i == 4)
|
||||
dwarnln("Could not find specified root device, waiting for it to get loaded...");
|
||||
|
||||
SystemTimer::get().sleep_for_ms(sleep_ms);
|
||||
SystemTimer::get().sleep_ms(sleep_ms);
|
||||
}
|
||||
|
||||
derrorln("Could not find root device '{}' after {} ms", root_path, timeout_ms);
|
||||
@@ -210,14 +210,14 @@ namespace Kernel
|
||||
if (!file.inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
|
||||
LockGuard _(m_mount_point_lock);
|
||||
LockGuard _(m_mutex);
|
||||
TRY(m_mount_points.emplace_back(file_system, BAN::move(file)));
|
||||
return {};
|
||||
}
|
||||
|
||||
VirtualFileSystem::MountPoint* VirtualFileSystem::mount_from_host_inode(BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
LockGuard _(m_mount_point_lock);
|
||||
LockGuard _(m_mutex);
|
||||
for (MountPoint& mount : m_mount_points)
|
||||
if (*mount.host.inode == *inode)
|
||||
return &mount;
|
||||
@@ -226,52 +226,53 @@ namespace Kernel
|
||||
|
||||
VirtualFileSystem::MountPoint* VirtualFileSystem::mount_from_root_inode(BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
LockGuard _(m_mount_point_lock);
|
||||
LockGuard _(m_mutex);
|
||||
for (MountPoint& mount : m_mount_points)
|
||||
if (*mount.target->root_inode() == *inode)
|
||||
return &mount;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstack-usage="
|
||||
BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials& credentials, BAN::StringView path, int flags)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
auto inode = parent.inode;
|
||||
ASSERT(inode);
|
||||
|
||||
char canonical_buf[PATH_MAX];
|
||||
size_t canonical_len = parent.canonical_path.size();
|
||||
if (!parent.canonical_path.empty() && parent.canonical_path.back() == '/')
|
||||
canonical_len--;
|
||||
memcpy(canonical_buf, parent.canonical_path.data(), canonical_len);
|
||||
ASSERT(canonical_len == 0 || canonical_buf[canonical_len - 1] != '/');
|
||||
BAN::String canonical_path;
|
||||
TRY(canonical_path.append(parent.canonical_path));
|
||||
if (!canonical_path.empty() && canonical_path.back() == '/')
|
||||
canonical_path.pop_back();
|
||||
ASSERT(canonical_path.empty() || canonical_path.back() != '/');
|
||||
|
||||
char path_storage[PATH_MAX];
|
||||
BAN::Vector<BAN::String> path_parts;
|
||||
|
||||
const auto append_string_view_in_reverse =
|
||||
[&path_parts](BAN::StringView path) -> BAN::ErrorOr<void>
|
||||
{
|
||||
auto split_path = TRY(path.split('/'));
|
||||
TRY(path_parts.reserve(path_parts.size() + split_path.size()));
|
||||
for (size_t i = split_path.size(); i > 0; i--)
|
||||
{
|
||||
TRY(path_parts.emplace_back());
|
||||
TRY(path_parts.back().append(split_path[i - 1]));
|
||||
}
|
||||
return {};
|
||||
};
|
||||
TRY(append_string_view_in_reverse(path));
|
||||
|
||||
size_t link_depth = 0;
|
||||
for (;;)
|
||||
|
||||
while (!path_parts.empty())
|
||||
{
|
||||
const auto path_part = [&path] {
|
||||
size_t off = 0;
|
||||
while (off < path.size() && path[off] == '/')
|
||||
off++;
|
||||
BAN::String path_part = BAN::move(path_parts.back());
|
||||
path_parts.pop_back();
|
||||
|
||||
size_t len = 0;
|
||||
while (off + len < path.size() && path[off + len] != '/')
|
||||
len++;
|
||||
|
||||
const auto result = path.substring(off, len);
|
||||
path = path.substring(off + len);
|
||||
return result;
|
||||
}();
|
||||
|
||||
if (path_part.empty())
|
||||
break;
|
||||
if (path_part == "."_sv)
|
||||
if (path_part.empty() || path_part == "."_sv)
|
||||
continue;
|
||||
|
||||
auto orig_inode = inode;
|
||||
auto orig = inode;
|
||||
|
||||
// resolve file name
|
||||
{
|
||||
@@ -288,26 +289,26 @@ namespace Kernel
|
||||
|
||||
if (path_part == ".."_sv)
|
||||
{
|
||||
while (canonical_len && canonical_buf[canonical_len - 1] != '/')
|
||||
canonical_len--;
|
||||
if (canonical_len)
|
||||
canonical_len--;
|
||||
if (!canonical_path.empty())
|
||||
{
|
||||
ASSERT(canonical_path.front() == '/');
|
||||
while (canonical_path.back() != '/')
|
||||
canonical_path.pop_back();
|
||||
canonical_path.pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (auto* mount_point = mount_from_host_inode(inode))
|
||||
inode = mount_point->target->root_inode();
|
||||
if (canonical_len + 1 + path_part.size() > sizeof(canonical_buf))
|
||||
return BAN::Error::from_errno(ENAMETOOLONG);
|
||||
canonical_buf[canonical_len++] = '/';
|
||||
memcpy(canonical_buf + canonical_len, path_part.data(), path_part.size());
|
||||
canonical_len += path_part.size();
|
||||
TRY(canonical_path.push_back('/'));
|
||||
TRY(canonical_path.append(path_part));
|
||||
}
|
||||
}
|
||||
|
||||
if (!inode->mode().iflnk())
|
||||
continue;
|
||||
if ((flags & O_NOFOLLOW) && !path.find([](char ch) { return ch != '/'; }).has_value())
|
||||
if ((flags & O_NOFOLLOW) && path_parts.empty())
|
||||
continue;
|
||||
|
||||
// resolve symbolic links
|
||||
@@ -319,26 +320,21 @@ namespace Kernel
|
||||
if (link_target.front() == '/')
|
||||
{
|
||||
inode = root_inode;
|
||||
canonical_len = 0;
|
||||
canonical_path.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
inode = orig_inode;
|
||||
inode = orig;
|
||||
|
||||
while (canonical_len && canonical_buf[canonical_len - 1] != '/')
|
||||
canonical_len--;
|
||||
if (canonical_len)
|
||||
canonical_len--;
|
||||
while (canonical_path.back() != '/')
|
||||
canonical_path.pop_back();
|
||||
canonical_path.pop_back();
|
||||
}
|
||||
|
||||
if (link_target.size() + path.size() > sizeof(path_storage))
|
||||
return BAN::Error::from_errno(ENAMETOOLONG);
|
||||
memcpy(path_storage, link_target.data(), link_target.size());
|
||||
memcpy(path_storage + link_target.size(), path.data(), path.size());
|
||||
path = BAN::StringView(path_storage, link_target.size() + path.size());
|
||||
TRY(append_string_view_in_reverse(link_target.sv()));
|
||||
|
||||
link_depth++;
|
||||
if (link_depth > SYMLOOP_MAX)
|
||||
if (link_depth > 100)
|
||||
return BAN::Error::from_errno(ELOOP);
|
||||
}
|
||||
}
|
||||
@@ -346,14 +342,17 @@ namespace Kernel
|
||||
if (!inode->can_access(credentials, flags))
|
||||
return BAN::Error::from_errno(EACCES);
|
||||
|
||||
if (canonical_len == 0)
|
||||
canonical_buf[canonical_len++] = '/';
|
||||
if (canonical_path.empty())
|
||||
TRY(canonical_path.push_back('/'));
|
||||
|
||||
BAN::String canonical_path;
|
||||
TRY(canonical_path.append(BAN::StringView(canonical_buf, canonical_len)));
|
||||
File file;
|
||||
file.inode = inode;
|
||||
file.canonical_path = BAN::move(canonical_path);
|
||||
|
||||
return File(BAN::move(inode), BAN::move(canonical_path));
|
||||
if (file.canonical_path.empty())
|
||||
TRY(file.canonical_path.push_back('/'));
|
||||
|
||||
return file;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,11 @@ namespace Kernel
|
||||
#if ARCH(x86_64)
|
||||
struct Registers
|
||||
{
|
||||
uint64_t cr4;
|
||||
uint64_t cr3;
|
||||
uint64_t cr2;
|
||||
uint64_t cr0;
|
||||
|
||||
uint64_t r15;
|
||||
uint64_t r14;
|
||||
uint64_t r13;
|
||||
@@ -44,6 +49,11 @@ namespace Kernel
|
||||
#elif ARCH(i686)
|
||||
struct Registers
|
||||
{
|
||||
uint32_t cr4;
|
||||
uint32_t cr3;
|
||||
uint32_t cr2;
|
||||
uint32_t cr0;
|
||||
|
||||
uint32_t edi;
|
||||
uint32_t esi;
|
||||
uint32_t ebp;
|
||||
@@ -216,11 +226,8 @@ namespace Kernel
|
||||
return;
|
||||
}
|
||||
|
||||
uintptr_t cr2;
|
||||
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
|
||||
Processor::set_interrupt_state(InterruptState::Enabled);
|
||||
auto result = Process::current().allocate_page_for_demand_paging(cr2, page_fault_error.write, page_fault_error.instruction);
|
||||
auto result = Process::current().allocate_page_for_demand_paging(regs->cr2, page_fault_error.write, page_fault_error.instruction);
|
||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||
|
||||
if (result.is_error())
|
||||
@@ -249,18 +256,6 @@ namespace Kernel
|
||||
|
||||
break;
|
||||
}
|
||||
case ISR::GeneralProtectionFault:
|
||||
{
|
||||
const uint8_t* ip = reinterpret_cast<const uint8_t*>(interrupt_stack->ip);
|
||||
for (const auto& safe_user : s_safe_user_page_faults)
|
||||
{
|
||||
if (ip < safe_user.ip_start || ip >= safe_user.ip_end)
|
||||
continue;
|
||||
interrupt_stack->ip = reinterpret_cast<vaddr_t>(safe_user.ip_fault);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ISR::DeviceNotAvailable:
|
||||
{
|
||||
if (pid == 0 || !Thread::current().is_userspace())
|
||||
@@ -279,15 +274,6 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t cr0, cr2, cr3, cr4;
|
||||
asm volatile(
|
||||
"mov %%cr0, %0;"
|
||||
"mov %%cr2, %1;"
|
||||
"mov %%cr3, %2;"
|
||||
"mov %%cr4, %3;"
|
||||
: "=r"(cr0), "=r"(cr2), "=r"(cr3), "=r"(cr4)
|
||||
);
|
||||
|
||||
Debug::s_debug_lock.lock();
|
||||
|
||||
if (PageTable::current().get_page_flags(interrupt_stack->ip & PAGE_ADDR_MASK) & PageTable::Flags::Present)
|
||||
@@ -325,7 +311,7 @@ namespace Kernel
|
||||
regs->r8, regs->r9, regs->r10, regs->r11,
|
||||
regs->r12, regs->r13, regs->r14, regs->r15,
|
||||
interrupt_stack->ip, interrupt_stack->flags,
|
||||
cr0, cr2, cr3, cr4
|
||||
regs->cr0, regs->cr2, regs->cr3, regs->cr4
|
||||
);
|
||||
#elif ARCH(i686)
|
||||
dwarnln(
|
||||
@@ -339,7 +325,7 @@ namespace Kernel
|
||||
regs->eax, regs->ebx, regs->ecx, regs->edx,
|
||||
interrupt_stack->sp, regs->ebp, regs->edi, regs->esi,
|
||||
interrupt_stack->ip, interrupt_stack->flags,
|
||||
cr0, cr2, cr3, cr4
|
||||
regs->cr0, regs->cr2, regs->cr3, regs->cr4
|
||||
);
|
||||
#endif
|
||||
if (isr == ISR::PageFault)
|
||||
@@ -387,11 +373,11 @@ namespace Kernel
|
||||
break;
|
||||
case ISR::PageFault:
|
||||
signal_info.si_signo = SIGSEGV;
|
||||
if (PageTable::current().get_page_flags(cr2 & PAGE_ADDR_MASK) & PageTable::Flags::Present)
|
||||
if (PageTable::current().get_page_flags(regs->cr2 & PAGE_ADDR_MASK) & PageTable::Flags::Present)
|
||||
signal_info.si_code = SEGV_ACCERR;
|
||||
else
|
||||
signal_info.si_code = SEGV_MAPERR;
|
||||
signal_info.si_addr = reinterpret_cast<void*>(cr2);
|
||||
signal_info.si_addr = reinterpret_cast<void*>(regs->cr2);
|
||||
break;
|
||||
default:
|
||||
dwarnln("Unhandled exception");
|
||||
@@ -435,7 +421,7 @@ namespace Kernel
|
||||
if (Processor::current_is_bsp())
|
||||
Process::update_alarm_queue();
|
||||
|
||||
Processor::scheduler().on_timer_interrupt();
|
||||
Processor::scheduler().timer_interrupt();
|
||||
}
|
||||
|
||||
extern "C" void cpp_irq_handler(uint32_t irq)
|
||||
|
||||
@@ -197,6 +197,9 @@ namespace Kernel
|
||||
}
|
||||
else switch (key_event.keycode)
|
||||
{
|
||||
case LibInput::keycode_function(1):
|
||||
Processor::toggle_should_print_cpu_load();
|
||||
break;
|
||||
case LibInput::keycode_function(11):
|
||||
DevFileSystem::get().initiate_disk_cache_drop();
|
||||
break;
|
||||
|
||||
@@ -151,18 +151,16 @@ namespace Kernel::Input
|
||||
uint16_t toggle_mask = 0;
|
||||
switch (dummy_event.key)
|
||||
{
|
||||
case Key::LeftShift: modifier_mask = KeyModifier::LShift; break;
|
||||
case Key::RightShift: modifier_mask = KeyModifier::RShift; break;
|
||||
case Key::LeftCtrl: modifier_mask = KeyModifier::LCtrl; break;
|
||||
case Key::RightCtrl: modifier_mask = KeyModifier::RCtrl; break;
|
||||
case Key::LeftAlt: modifier_mask = KeyModifier::LAlt; break;
|
||||
case Key::RightAlt: modifier_mask = KeyModifier::RAlt; break;
|
||||
case Key::LeftSuper: modifier_mask = KeyModifier::LSuper; break;
|
||||
case Key::RightSuper: modifier_mask = KeyModifier::RSuper; break;
|
||||
case Key::LeftShift: modifier_mask = KeyModifier::LShift; break;
|
||||
case Key::RightShift: modifier_mask = KeyModifier::RShift; break;
|
||||
case Key::LeftCtrl: modifier_mask = KeyModifier::LCtrl; break;
|
||||
case Key::RightCtrl: modifier_mask = KeyModifier::RCtrl; break;
|
||||
case Key::LeftAlt: modifier_mask = KeyModifier::LAlt; break;
|
||||
case Key::RightAlt: modifier_mask = KeyModifier::RAlt; break;
|
||||
|
||||
case Key::ScrollLock: toggle_mask = KeyModifier::ScrollLock; break;
|
||||
case Key::NumLock: toggle_mask = KeyModifier::NumLock; break;
|
||||
case Key::CapsLock: toggle_mask = KeyModifier::CapsLock; break;
|
||||
case Key::ScrollLock: toggle_mask = KeyModifier::ScrollLock; break;
|
||||
case Key::NumLock: toggle_mask = KeyModifier::NumLock; break;
|
||||
case Key::CapsLock: toggle_mask = KeyModifier::CapsLock; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
@@ -95,9 +95,7 @@ namespace Kernel::Input
|
||||
m_scancode_to_keycode_normal[0x38] = keycode_normal(4, 2);
|
||||
m_scancode_to_keycode_normal[0x39] = keycode_normal(4, 3);
|
||||
m_scancode_to_keycode_extended[0x38] = keycode_normal(4, 4);
|
||||
m_scancode_to_keycode_extended[0x5C] = keycode_normal(4, 5);
|
||||
m_scancode_to_keycode_extended[0x5D] = keycode_normal(4, 6);
|
||||
m_scancode_to_keycode_extended[0x1D] = keycode_normal(4, 7);
|
||||
m_scancode_to_keycode_extended[0x1D] = keycode_normal(4, 5);
|
||||
|
||||
m_scancode_to_keycode_normal[0x45] = keycode_numpad(0, 0);
|
||||
m_scancode_to_keycode_extended[0x35] = keycode_numpad(0, 1);
|
||||
@@ -210,9 +208,7 @@ namespace Kernel::Input
|
||||
m_scancode_to_keycode_normal[0x11] = keycode_normal(4, 2);
|
||||
m_scancode_to_keycode_normal[0x29] = keycode_normal(4, 3);
|
||||
m_scancode_to_keycode_extended[0x11] = keycode_normal(4, 4);
|
||||
m_scancode_to_keycode_extended[0x27] = keycode_normal(4, 5);
|
||||
m_scancode_to_keycode_extended[0x2F] = keycode_normal(4, 6);
|
||||
m_scancode_to_keycode_extended[0x14] = keycode_normal(4, 7);
|
||||
m_scancode_to_keycode_extended[0x14] = keycode_normal(4, 5);
|
||||
|
||||
m_scancode_to_keycode_normal[0x77] = keycode_numpad(0, 0);
|
||||
m_scancode_to_keycode_extended[0x4A] = keycode_numpad(0, 1);
|
||||
@@ -325,9 +321,7 @@ namespace Kernel::Input
|
||||
m_scancode_to_keycode_normal[0x19] = keycode_normal(4, 2);
|
||||
m_scancode_to_keycode_normal[0x29] = keycode_normal(4, 3);
|
||||
m_scancode_to_keycode_normal[0x39] = keycode_normal(4, 4);
|
||||
m_scancode_to_keycode_normal[0x8C] = keycode_normal(4, 5);
|
||||
m_scancode_to_keycode_normal[0x8D] = keycode_normal(4, 6);
|
||||
m_scancode_to_keycode_normal[0x58] = keycode_normal(4, 7);
|
||||
m_scancode_to_keycode_normal[0x58] = keycode_normal(4, 5);
|
||||
|
||||
m_scancode_to_keycode_normal[0x76] = keycode_numpad(0, 0);
|
||||
m_scancode_to_keycode_normal[0x4A] = keycode_numpad(0, 1);
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Kernel
|
||||
|
||||
void SharedFileData::sync_no_lock(size_t page_index)
|
||||
{
|
||||
if (pages[page_index] == 0 || BAN::atomic_load(writers[page_index]) > 0)
|
||||
if (pages[page_index] == 0 || BAN::atomic_load(writers[page_index]) == 0)
|
||||
return;
|
||||
|
||||
uint8_t page_buffer[PAGE_SIZE];
|
||||
@@ -108,9 +108,8 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> FileBackedRegion::msync(vaddr_t address, size_t size, int flags)
|
||||
{
|
||||
// TODO: maybe do something with the flags :)
|
||||
(void)flags;
|
||||
|
||||
if (flags != MS_SYNC)
|
||||
dprintln("async file backed mmap msync");
|
||||
if (m_type != Type::SHARED)
|
||||
return {};
|
||||
|
||||
|
||||
@@ -112,8 +112,8 @@ namespace Kernel
|
||||
paddr = Heap::get().take_free_page();
|
||||
if (paddr == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
PageTable::with_per_cpu_fast_page(paddr, [&](void* addr) {
|
||||
memset(addr, 0x00, PAGE_SIZE);
|
||||
PageTable::with_fast_page(paddr, [&] {
|
||||
memset(PageTable::fast_page_as_ptr(), 0x00, PAGE_SIZE);
|
||||
});
|
||||
m_object->paddrs[(vaddr - m_vaddr) / PAGE_SIZE] = paddr;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace Kernel
|
||||
Reply = 2,
|
||||
};
|
||||
|
||||
static constexpr BAN::IPv4Address s_broadcast_ipv4 { 0xFFFFFFFF };
|
||||
static constexpr BAN::MACAddress s_broadcast_mac {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
|
||||
static constexpr BAN::IPv4Address s_broadcast_ipv4 { 0xFFFFFFFF };
|
||||
static constexpr BAN::MACAddress s_broadcast_mac {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<ARPTable>> ARPTable::create()
|
||||
{
|
||||
@@ -50,19 +50,18 @@ namespace Kernel
|
||||
return it->value;
|
||||
}
|
||||
|
||||
const auto arp_request = ARPPacket {
|
||||
.htype = 0x0001,
|
||||
.ptype = EtherType::IPv4,
|
||||
.hlen = 0x06,
|
||||
.plen = 0x04,
|
||||
.oper = ARPOperation::Request,
|
||||
.sha = interface.get_mac_address(),
|
||||
.spa = interface.get_ipv4_address(),
|
||||
.tha = {{ 0, 0, 0, 0, 0, 0 }},
|
||||
.tpa = ipv4_address,
|
||||
};
|
||||
ARPPacket arp_request;
|
||||
arp_request.htype = 0x0001;
|
||||
arp_request.ptype = EtherType::IPv4;
|
||||
arp_request.hlen = 0x06;
|
||||
arp_request.plen = 0x04;
|
||||
arp_request.oper = ARPOperation::Request;
|
||||
arp_request.sha = interface.get_mac_address();
|
||||
arp_request.spa = interface.get_ipv4_address();
|
||||
arp_request.tha = {{ 0, 0, 0, 0, 0, 0 }};
|
||||
arp_request.tpa = ipv4_address;
|
||||
|
||||
TRY(interface.send_with_ethernet_header(s_broadcast_mac, EtherType::ARP, BAN::ConstByteSpan::from(arp_request)));
|
||||
TRY(interface.send_bytes(s_broadcast_mac, EtherType::ARP, BAN::ConstByteSpan::from(arp_request)));
|
||||
|
||||
uint64_t timeout = SystemTimer::get().ms_since_boot() + 1'000;
|
||||
while (SystemTimer::get().ms_since_boot() < timeout)
|
||||
@@ -101,7 +100,7 @@ namespace Kernel
|
||||
{
|
||||
if (packet.tpa == interface.get_ipv4_address())
|
||||
{
|
||||
const auto arp_reply = ARPPacket {
|
||||
const ARPPacket arp_reply {
|
||||
.htype = 0x0001,
|
||||
.ptype = EtherType::IPv4,
|
||||
.hlen = 0x06,
|
||||
@@ -112,7 +111,7 @@ namespace Kernel
|
||||
.tha = packet.sha,
|
||||
.tpa = packet.spa,
|
||||
};
|
||||
TRY(interface.send_with_ethernet_header(packet.sha, EtherType::ARP, BAN::ConstByteSpan::from(arp_reply)));
|
||||
TRY(interface.send_bytes(packet.sha, EtherType::ARP, BAN::ConstByteSpan::from(arp_reply)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -202,8 +202,6 @@ namespace Kernel
|
||||
rctrl |= RCTL_BSIZE_8192;
|
||||
write32(REG_RCTL, rctrl);
|
||||
|
||||
write32(REG_RXCSUM, RXSUM_IPOFLD | RXSUM_TUOFLD);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -281,13 +279,9 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> E1000::send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers)
|
||||
BAN::ErrorOr<void> E1000::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload)
|
||||
{
|
||||
const auto interrupt_state = Processor::get_interrupt_state();
|
||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||
|
||||
const uint32_t tx_current_nowrap = m_tx_head.fetch_add(1);
|
||||
const uint32_t tx_current = tx_current_nowrap % E1000_TX_DESCRIPTOR_COUNT;
|
||||
const uint32_t tx_current = m_tx_head1.fetch_add(1) % E1000_TX_DESCRIPTOR_COUNT;
|
||||
|
||||
auto& descriptor = reinterpret_cast<volatile e1000_tx_desc*>(m_tx_descriptor_region->vaddr())[tx_current];
|
||||
while (descriptor.status == 0)
|
||||
@@ -295,10 +289,15 @@ namespace Kernel
|
||||
|
||||
auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + E1000_TX_BUFFER_SIZE * tx_current);
|
||||
|
||||
size_t packet_size = 0;
|
||||
for (const auto& buffer : buffers)
|
||||
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(tx_buffer);
|
||||
ethernet_header.dst_mac = destination;
|
||||
ethernet_header.src_mac = get_mac_address();
|
||||
ethernet_header.ether_type = protocol;
|
||||
|
||||
size_t packet_size = sizeof(EthernetHeader);
|
||||
for (const auto& buffer : payload)
|
||||
{
|
||||
ASSERT(packet_size + buffer.size() <= E1000_TX_BUFFER_SIZE);
|
||||
ASSERT(packet_size + buffer.size() < E1000_TX_BUFFER_SIZE);
|
||||
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
|
||||
packet_size += buffer.size();
|
||||
}
|
||||
@@ -307,12 +306,8 @@ namespace Kernel
|
||||
descriptor.status = 0;
|
||||
descriptor.cmd = CMD_EOP | CMD_IFCS | CMD_RS;
|
||||
|
||||
while (tx_current_nowrap != m_tx_commit.load())
|
||||
Processor::pause();
|
||||
write32(REG_TDT, (tx_current + 1) % E1000_TX_DESCRIPTOR_COUNT);
|
||||
m_tx_commit.add_fetch(1);
|
||||
|
||||
Processor::set_interrupt_state(interrupt_state);
|
||||
if (tx_current == m_tx_head2.fetch_add(1) % E1000_TX_DESCRIPTOR_COUNT)
|
||||
write32(REG_TDT, (tx_current + 1) % E1000_TX_DESCRIPTOR_COUNT);
|
||||
|
||||
dprintln_if(DEBUG_E1000, "sent {} bytes", packet_size);
|
||||
|
||||
@@ -321,66 +316,35 @@ namespace Kernel
|
||||
|
||||
void E1000::receive_thread()
|
||||
{
|
||||
SpinLockGuard guard(m_rx_lock);
|
||||
|
||||
uint32_t rx_current = 0;
|
||||
SpinLockGuard _(m_rx_lock);
|
||||
|
||||
while (!m_thread_should_die)
|
||||
{
|
||||
uint32_t rx_tail = rx_current;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const uint32_t rx_current = (read32(REG_RDT0) + 1) % E1000_RX_DESCRIPTOR_COUNT;
|
||||
|
||||
auto& descriptor = reinterpret_cast<volatile e1000_rx_desc*>(m_rx_descriptor_region->vaddr())[rx_current];
|
||||
|
||||
const auto status = descriptor.status;
|
||||
if (!(status & RX_STS_DD))
|
||||
if (!(descriptor.status & 1))
|
||||
break;
|
||||
ASSERT(descriptor.length <= E1000_RX_BUFFER_SIZE);
|
||||
|
||||
const auto errors = descriptor.errors;
|
||||
if (!(status & RX_STS_EOP))
|
||||
dwarnln("multi descriptor packet??");
|
||||
else if (errors & (RX_ERR_CE | RX_ERR_SE | RX_ERR_RXE))
|
||||
dwarnln("descriptor error {2h}", errors);
|
||||
else if ((status & RX_STS_IPCS) && (errors & RX_ERR_IPE))
|
||||
dwarnln("IPv4 checksum error");
|
||||
else if ((status & RX_STS_TCPCS) && (errors & RX_ERR_TCPE))
|
||||
dwarnln("TCP checkum error");
|
||||
else if ((status & RX_STS_UDPCS) && (errors & RX_ERR_TCPE))
|
||||
dwarnln("UDP checksum error");
|
||||
else
|
||||
{
|
||||
m_rx_lock.unlock(InterruptState::Enabled);
|
||||
dprintln_if(DEBUG_E1000, "got {} bytes", (uint16_t)descriptor.length);
|
||||
|
||||
const uint32_t packet_length = descriptor.length;
|
||||
ASSERT(packet_length <= E1000_RX_BUFFER_SIZE);
|
||||
m_rx_lock.unlock(InterruptState::Enabled);
|
||||
|
||||
dprintln_if(DEBUG_E1000, "got {} bytes", packet_length);
|
||||
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
|
||||
reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + rx_current * E1000_RX_BUFFER_SIZE),
|
||||
descriptor.length
|
||||
});
|
||||
|
||||
uint32_t validated_cksums = 0;
|
||||
if ((status & RX_STS_IPCS) && !(errors & RX_ERR_IPE))
|
||||
validated_cksums |= CKSUM_IPV4;
|
||||
if ((status & RX_STS_TCPCS) && !(errors & RX_ERR_TCPE))
|
||||
validated_cksums |= CKSUM_TCP;
|
||||
if ((status & RX_STS_UDPCS) && !(errors & RX_ERR_TCPE))
|
||||
validated_cksums |= CKSUM_UDP;
|
||||
|
||||
const uint8_t* packet_data = reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + rx_current * E1000_RX_BUFFER_SIZE);
|
||||
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan { packet_data, packet_length }, validated_cksums);
|
||||
|
||||
m_rx_lock.lock();
|
||||
}
|
||||
m_rx_lock.lock();
|
||||
|
||||
descriptor.status = 0;
|
||||
|
||||
rx_tail = rx_current;
|
||||
rx_current = (rx_current + 1) % E1000_RX_DESCRIPTOR_COUNT;
|
||||
write32(REG_RDT0, rx_current);
|
||||
}
|
||||
|
||||
if (rx_current != rx_tail)
|
||||
write32(REG_RDT0, rx_tail);
|
||||
|
||||
SpinLockGuardAsMutex smutex(guard);
|
||||
SpinLockAsMutex smutex(m_rx_lock, InterruptState::Enabled);
|
||||
m_rx_blocker.block_indefinite(&smutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan payload, const sockaddr* address, socklen_t address_len)
|
||||
BAN::ErrorOr<size_t> IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan payload, const sockaddr* address, socklen_t address_len)
|
||||
{
|
||||
if (address->sa_family != AF_INET)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
@@ -224,21 +224,23 @@ namespace Kernel
|
||||
};
|
||||
|
||||
uint8_t protocol_header_buffer[32];
|
||||
ASSERT(socket.protocol_header_size() < sizeof(protocol_header_buffer));
|
||||
|
||||
auto protocol_header = BAN::ByteSpan::from(protocol_header_buffer).slice(0, socket.protocol_header_size());
|
||||
socket.get_protocol_header(protocol_header, payload, dst_port, pseudo_header);
|
||||
|
||||
const BAN::ConstByteSpan buffers[] {
|
||||
BAN::ConstByteSpan buffers[] {
|
||||
BAN::ConstByteSpan::from(ipv4_header),
|
||||
protocol_header,
|
||||
payload,
|
||||
};
|
||||
|
||||
TRY(interface->send_with_ethernet_header(dst_mac, EtherType::IPv4, buffers));
|
||||
TRY(interface->send_bytes(dst_mac, EtherType::IPv4, { buffers, sizeof(buffers) / sizeof(*buffers) }));
|
||||
|
||||
return {};
|
||||
return payload.size();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan packet, uint32_t validated_cksums)
|
||||
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan packet)
|
||||
{
|
||||
if (packet.size() < sizeof(IPv4Header))
|
||||
{
|
||||
@@ -247,7 +249,7 @@ namespace Kernel
|
||||
}
|
||||
|
||||
auto& ipv4_header = packet.as<const IPv4Header>();
|
||||
if (!(validated_cksums & CKSUM_IPV4) && calculate_internet_checksum(BAN::ConstByteSpan::from(ipv4_header)) != 0)
|
||||
if (calculate_internet_checksum(BAN::ConstByteSpan::from(ipv4_header)) != 0)
|
||||
{
|
||||
dwarnln_if(DEBUG_IPV4, "IPv4 packet checksum failed");
|
||||
return {};
|
||||
@@ -282,33 +284,34 @@ namespace Kernel
|
||||
{
|
||||
case ICMPType::EchoRequest:
|
||||
{
|
||||
const auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(interface, src_ipv4));
|
||||
auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(interface, src_ipv4));
|
||||
|
||||
const auto send_ipv4_header = get_ipv4_header(
|
||||
auto send_ipv4_header = get_ipv4_header(
|
||||
ipv4_data.size(),
|
||||
interface.get_ipv4_address(),
|
||||
src_ipv4,
|
||||
NetworkProtocol::ICMP
|
||||
);
|
||||
|
||||
auto send_icmp_header = ICMPHeader {
|
||||
ICMPHeader send_icmp_header {
|
||||
.type = ICMPType::EchoReply,
|
||||
.code = icmp_header.code,
|
||||
.checksum = 0,
|
||||
.rest = icmp_header.rest,
|
||||
};
|
||||
|
||||
auto send_payload = ipv4_data.slice(sizeof(ICMPHeader));
|
||||
|
||||
const BAN::ConstByteSpan send_buffers[] {
|
||||
BAN::ConstByteSpan::from(send_ipv4_header),
|
||||
BAN::ConstByteSpan::from(send_icmp_header),
|
||||
ipv4_data.slice(sizeof(ICMPHeader))
|
||||
send_payload
|
||||
};
|
||||
auto send_buffers_span = BAN::Span { send_buffers, sizeof(send_buffers) / sizeof(*send_buffers) };
|
||||
|
||||
send_icmp_header.checksum = calculate_internet_checksum({
|
||||
send_buffers + 1, sizeof(send_buffers) / sizeof(*send_buffers) - 1
|
||||
});
|
||||
send_icmp_header.checksum = calculate_internet_checksum(send_buffers_span.slice(1));
|
||||
|
||||
TRY(interface.send_with_ethernet_header(dst_mac, EtherType::IPv4, send_buffers));
|
||||
TRY(interface.send_bytes(dst_mac, EtherType::IPv4, send_buffers_span));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -386,7 +389,7 @@ namespace Kernel
|
||||
sender.sin_family = AF_INET;
|
||||
sender.sin_port = BAN::host_to_network_endian(src_port);
|
||||
sender.sin_addr.s_addr = src_ipv4.raw;
|
||||
bound_socket->receive_packet(ipv4_data, reinterpret_cast<const sockaddr*>(&sender), sizeof(sender), validated_cksums);
|
||||
bound_socket->receive_packet(ipv4_data, reinterpret_cast<const sockaddr*>(&sender), sizeof(sender));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <kernel/Lock/SpinLockAsMutex.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Networking/Loopback.h>
|
||||
#include <kernel/Networking/NetworkManager.h>
|
||||
|
||||
@@ -54,15 +54,12 @@ namespace Kernel
|
||||
Processor::yield();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> LoopbackInterface::send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers)
|
||||
BAN::ErrorOr<void> LoopbackInterface::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload)
|
||||
{
|
||||
const auto interrupt_state = Processor::get_interrupt_state();
|
||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||
|
||||
auto& descriptor =
|
||||
[&]() -> Descriptor&
|
||||
{
|
||||
SpinLockGuard guard(m_buffer_lock);
|
||||
LockGuard _(m_buffer_lock);
|
||||
for (;;)
|
||||
{
|
||||
auto& descriptor = m_descriptors[m_buffer_head];
|
||||
@@ -72,31 +69,34 @@ namespace Kernel
|
||||
descriptor.state = 1;
|
||||
return descriptor;
|
||||
}
|
||||
SpinLockGuardAsMutex smutex(guard);
|
||||
m_thread_blocker.block_indefinite(&smutex);
|
||||
m_thread_blocker.block_indefinite(&m_buffer_lock);
|
||||
}
|
||||
}();
|
||||
|
||||
size_t packet_size = 0;
|
||||
for (const auto& buffer : buffers)
|
||||
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(descriptor.addr);
|
||||
ethernet_header.dst_mac = destination;
|
||||
ethernet_header.src_mac = get_mac_address();
|
||||
ethernet_header.ether_type = protocol;
|
||||
|
||||
size_t packet_size = sizeof(EthernetHeader);
|
||||
for (const auto& buffer : payload)
|
||||
{
|
||||
ASSERT(packet_size + buffer.size() <= buffer_size);
|
||||
memcpy(descriptor.addr + packet_size, buffer.data(), buffer.size());
|
||||
packet_size += buffer.size();
|
||||
}
|
||||
|
||||
m_buffer_lock.lock();
|
||||
LockGuard _(m_buffer_lock);
|
||||
descriptor.size = packet_size;
|
||||
descriptor.state = 2;
|
||||
m_thread_blocker.unblock();
|
||||
m_buffer_lock.unlock(interrupt_state);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void LoopbackInterface::receive_thread()
|
||||
{
|
||||
SpinLockGuard guard(m_buffer_lock);
|
||||
LockGuard _(m_buffer_lock);
|
||||
|
||||
while (!m_thread_should_die)
|
||||
{
|
||||
@@ -107,9 +107,12 @@ namespace Kernel
|
||||
break;
|
||||
m_buffer_tail = (m_buffer_tail + 1) % buffer_count;
|
||||
|
||||
m_buffer_lock.unlock(InterruptState::Enabled);
|
||||
m_buffer_lock.unlock();
|
||||
|
||||
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan { descriptor.addr, descriptor.size }, 0);
|
||||
NetworkManager::get().on_receive(*this, {
|
||||
descriptor.addr,
|
||||
descriptor.size,
|
||||
});
|
||||
|
||||
m_buffer_lock.lock();
|
||||
|
||||
@@ -118,8 +121,7 @@ namespace Kernel
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
|
||||
SpinLockGuardAsMutex smutex(guard);
|
||||
m_thread_blocker.block_indefinite(&smutex);
|
||||
m_thread_blocker.block_indefinite(&m_buffer_lock);
|
||||
}
|
||||
|
||||
m_thread_is_dead = true;
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -27,7 +25,7 @@ namespace Kernel
|
||||
}
|
||||
|
||||
NetworkInterface::NetworkInterface(Type type)
|
||||
: CharacterDevice(0664, 0, 0)
|
||||
: CharacterDevice(0400, 0, 0)
|
||||
, m_type(type)
|
||||
{
|
||||
m_rdev = get_rdev(type);
|
||||
@@ -45,95 +43,4 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> NetworkInterface::ioctl_impl(unsigned long request, void* arg)
|
||||
{
|
||||
if (arg == nullptr)
|
||||
{
|
||||
dprintln("No argument provided");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
auto* ifreq = reinterpret_cast<struct ifreq*>(arg);
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case SIOCGIFADDR:
|
||||
{
|
||||
auto& ifru_addr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
|
||||
ifru_addr.sin_family = AF_INET;
|
||||
ifru_addr.sin_addr.s_addr = get_ipv4_address().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFADDR:
|
||||
{
|
||||
auto& ifru_addr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
|
||||
if (ifru_addr.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr });
|
||||
dprintln("IPv4 address set to {}", get_ipv4_address());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFNETMASK:
|
||||
{
|
||||
auto& ifru_netmask = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
|
||||
ifru_netmask.sin_family = AF_INET;
|
||||
ifru_netmask.sin_addr.s_addr = get_netmask().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFNETMASK:
|
||||
{
|
||||
auto& ifru_netmask = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
|
||||
if (ifru_netmask.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr });
|
||||
dprintln("Netmask set to {}", get_netmask());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFGWADDR:
|
||||
{
|
||||
auto& ifru_gwaddr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
|
||||
ifru_gwaddr.sin_family = AF_INET;
|
||||
ifru_gwaddr.sin_addr.s_addr = get_gateway().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFGWADDR:
|
||||
{
|
||||
auto& ifru_gwaddr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
|
||||
if (ifru_gwaddr.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr });
|
||||
dprintln("Gateway set to {}", get_gateway());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFHWADDR:
|
||||
{
|
||||
auto mac_address = get_mac_address();
|
||||
ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET;
|
||||
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFNAME:
|
||||
{
|
||||
auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name;
|
||||
ASSERT(name().size() < sizeof(ifrn_name));
|
||||
memcpy(ifrn_name, name().data(), name().size());
|
||||
ifrn_name[name().size()] = '\0';
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFFLAGS:
|
||||
{
|
||||
int flags = 0;
|
||||
if (link_up())
|
||||
flags |= IFF_UP | IFF_RUNNING;
|
||||
if (m_type == Type::Loopback)
|
||||
flags |= IFF_LOOPBACK;
|
||||
ifreq->ifr_ifru.ifru_flags = flags;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return CharacterDevice::ioctl_impl(request, arg);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
void NetworkManager::on_receive(NetworkInterface& interface, BAN::ConstByteSpan packet, uint32_t validated_cksums)
|
||||
void NetworkManager::on_receive(NetworkInterface& interface, BAN::ConstByteSpan packet)
|
||||
{
|
||||
if (packet.size() < sizeof(EthernetHeader))
|
||||
return;
|
||||
@@ -163,7 +163,7 @@ namespace Kernel
|
||||
dwarnln("ARP: {}", ret.error());
|
||||
break;
|
||||
case EtherType::IPv4:
|
||||
if (auto ret = m_ipv4_layer->handle_ipv4_packet(interface, packet_data, validated_cksums); ret.is_error())
|
||||
if (auto ret = m_ipv4_layer->handle_ipv4_packet(interface, packet_data); ret.is_error())
|
||||
dwarnln("IPv4; {}", ret.error());
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -108,22 +108,85 @@ namespace Kernel
|
||||
m_address_len = addr_len;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> NetworkSocket::ioctl_impl(unsigned long request, void* arg)
|
||||
BAN::ErrorOr<long> NetworkSocket::ioctl_impl(int request, void* arg)
|
||||
{
|
||||
if (!arg)
|
||||
{
|
||||
dprintln("No argument provided");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
auto interface = TRY(this->interface(nullptr, 0));
|
||||
auto* ifreq = reinterpret_cast<struct ifreq*>(arg);
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case SIOCGIFADDR:
|
||||
{
|
||||
auto& ifru_addr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
|
||||
ifru_addr.sin_family = AF_INET;
|
||||
ifru_addr.sin_addr.s_addr = interface->get_ipv4_address().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFADDR:
|
||||
{
|
||||
auto& ifru_addr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
|
||||
if (ifru_addr.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
interface->set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr });
|
||||
dprintln("IPv4 address set to {}", interface->get_ipv4_address());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFNETMASK:
|
||||
{
|
||||
auto& ifru_netmask = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
|
||||
ifru_netmask.sin_family = AF_INET;
|
||||
ifru_netmask.sin_addr.s_addr = interface->get_netmask().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFNETMASK:
|
||||
{
|
||||
auto& ifru_netmask = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
|
||||
if (ifru_netmask.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
interface->set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr });
|
||||
dprintln("Netmask set to {}", interface->get_netmask());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFGWADDR:
|
||||
{
|
||||
auto& ifru_gwaddr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
|
||||
ifru_gwaddr.sin_family = AF_INET;
|
||||
ifru_gwaddr.sin_addr.s_addr = interface->get_gateway().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFGWADDR:
|
||||
{
|
||||
auto& ifru_gwaddr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
|
||||
if (ifru_gwaddr.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
interface->set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr });
|
||||
dprintln("Gateway set to {}", interface->get_gateway());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFHWADDR:
|
||||
{
|
||||
auto mac_address = interface->get_mac_address();
|
||||
ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET;
|
||||
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFNAME:
|
||||
return TRY(interface(nullptr, 0))->ioctl(request, arg);
|
||||
{
|
||||
auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name;
|
||||
ASSERT(interface->name().size() < sizeof(ifrn_name));
|
||||
memcpy(ifrn_name, interface->name().data(), interface->name().size());
|
||||
ifrn_name[interface->name().size()] = '\0';
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
return Socket::ioctl_impl(request, arg);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> NetworkSocket::getsockname_impl(sockaddr* address, socklen_t* address_len)
|
||||
|
||||
@@ -47,29 +47,30 @@ namespace Kernel
|
||||
|
||||
TRY(reset());
|
||||
|
||||
// disable rx, tx, checksum offload
|
||||
m_io_bar_region->write16(RTL8169_IO_CPlusCR, 0x0000);
|
||||
m_io_bar_region->write8 (RTL8169_IO_CR, 0x00);
|
||||
|
||||
dprintln(" reset done");
|
||||
|
||||
for (size_t i = 0; i < 6; i++)
|
||||
m_mac_address.address[i] = m_io_bar_region->read8(RTL8169_IO_IDR0 + i);
|
||||
dprintln(" MAC {}", m_mac_address);
|
||||
|
||||
// unlock config registers
|
||||
m_io_bar_region->write8(RTL8169_IO_9346CR, RTL8169_9346CR_MODE_CONFIG);
|
||||
|
||||
TRY(initialize_rx());
|
||||
TRY(initialize_tx());
|
||||
m_io_bar_region->write8(RTL8169_IO_CR, RTL8169_CR_RE | RTL8169_CR_TE);
|
||||
dprintln(" descriptors initialized");
|
||||
|
||||
m_link_up = m_io_bar_region->read8(RTL8169_IO_PHYSts) & RTL8169_PHYSts_LinkSts;
|
||||
dprintln(" link status {}", link_up() ? "UP" : "DOWN");
|
||||
if (link_up())
|
||||
if (m_link_up)
|
||||
dprintln(" link speed {}", link_speed());
|
||||
|
||||
TRY(enable_interrupt());
|
||||
dprintln(" interrupts enabled");
|
||||
|
||||
// lock config registers
|
||||
m_io_bar_region->write8(RTL8169_IO_9346CR, RTL8169_9346CR_MODE_NORMAL);
|
||||
|
||||
auto* thread = TRY(Thread::create_kernel([](void* rtl8169_ptr) {
|
||||
static_cast<RTL8169*>(rtl8169_ptr)->receive_thread();
|
||||
}, this));
|
||||
@@ -78,17 +79,17 @@ namespace Kernel
|
||||
delete thread;
|
||||
return ret.release_error();
|
||||
}
|
||||
m_rx_thread_is_dead = false;
|
||||
m_thread_is_dead = false;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
RTL8169::~RTL8169()
|
||||
{
|
||||
m_rx_thread_should_die = true;
|
||||
m_rx_blocker.unblock();
|
||||
m_thread_should_die = true;
|
||||
m_thread_blocker.unblock();
|
||||
|
||||
while (!m_rx_thread_is_dead)
|
||||
while (!m_thread_is_dead)
|
||||
Processor::yield();
|
||||
}
|
||||
|
||||
@@ -109,33 +110,35 @@ namespace Kernel
|
||||
m_rx_buffer_region = TRY(DMARegion::create(m_rx_descriptor_count * s_buffer_size, PageTable::MemoryType::Normal));
|
||||
m_rx_descriptor_region = TRY(DMARegion::create(m_rx_descriptor_count * sizeof(RTL8169Descriptor)));
|
||||
|
||||
auto* rx_descriptors = reinterpret_cast<volatile RTL8169Descriptor*>(m_rx_descriptor_region->vaddr());
|
||||
for (size_t i = 0; i < m_rx_descriptor_count; i++)
|
||||
{
|
||||
const paddr_t rx_buffer_paddr = m_rx_buffer_region->paddr() + i * s_buffer_size;
|
||||
rx_descriptors[i].command = 0x1FF8 | RTL8169_DESC_CMD_OWN;
|
||||
rx_descriptors[i].vlan = 0;
|
||||
rx_descriptors[i].buffer_low = rx_buffer_paddr & 0xFFFFFFFF;
|
||||
rx_descriptors[i].buffer_high = rx_buffer_paddr >> 32;
|
||||
|
||||
uint32_t command = 0x1FF8 | RTL8169_DESC_CMD_OWN;
|
||||
if (i == m_rx_descriptor_count - 1)
|
||||
command |= RTL8169_DESC_CMD_EOR;
|
||||
|
||||
auto& rx_descriptor = reinterpret_cast<volatile RTL8169Descriptor*>(m_rx_descriptor_region->vaddr())[i];
|
||||
rx_descriptor.command = command;
|
||||
rx_descriptor.vlan = 0;
|
||||
rx_descriptor.buffer_low = rx_buffer_paddr & 0xFFFFFFFF;
|
||||
rx_descriptor.buffer_high = rx_buffer_paddr >> 32;
|
||||
}
|
||||
rx_descriptors[m_rx_descriptor_count - 1].command |= RTL8169_DESC_CMD_EOR;
|
||||
|
||||
// configure rx descriptor addresses
|
||||
m_io_bar_region->write32(RTL8169_IO_RDSAR + 4, m_rx_descriptor_region->paddr() >> 32);
|
||||
m_io_bar_region->write32(RTL8169_IO_RDSAR + 0, m_rx_descriptor_region->paddr() & 0xFFFFFFFF);
|
||||
m_io_bar_region->write32(RTL8169_IO_RDSAR + 4, m_rx_descriptor_region->paddr() >> 32);
|
||||
|
||||
// configure receive control (no fifo threshold, max dma burst unlimited, broadcast, multicast, accept physical match)
|
||||
// configure receibe control (no fifo threshold, max dma burst 1024, accept physical match, broadcast, multicast)
|
||||
m_io_bar_region->write32(RTL8169_IO_RCR,
|
||||
RTL8169_RCR_RXFTH_NO | RTL8169_RCR_MXDMA_UNLIMITED | RTL8169_RCR_AB | RTL8169_RCR_AM | RTL8169_RCR_APM
|
||||
RTL8169_RCR_RXFTH_NO | RTL8169_RCR_MXDMA_1024 | RTL8169_RCR_AB | RTL8169_RCR_AM | RTL8169_RCR_APM
|
||||
);
|
||||
|
||||
m_io_bar_region->write32(0x44, 0b111111 | (0b111 << 8) | (0b111 << 13));
|
||||
|
||||
// configure max rx packet size
|
||||
m_io_bar_region->write16(RTL8169_IO_RMS, RTL8169_RMS_MAX);
|
||||
|
||||
// enable ip/tcp/udp checksum offloading
|
||||
// TODO: is this supported on all cards?
|
||||
m_io_bar_region->write16(RTL8169_IO_CPlusCR, 1 << 5);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -144,23 +147,27 @@ namespace Kernel
|
||||
m_tx_buffer_region = TRY(DMARegion::create(m_tx_descriptor_count * s_buffer_size, PageTable::MemoryType::Normal));
|
||||
m_tx_descriptor_region = TRY(DMARegion::create(m_tx_descriptor_count * sizeof(RTL8169Descriptor)));
|
||||
|
||||
auto* tx_descriptors = reinterpret_cast<volatile RTL8169Descriptor*>(m_tx_descriptor_region->vaddr());
|
||||
for (size_t i = 0; i < m_tx_descriptor_count; i++)
|
||||
{
|
||||
const paddr_t tx_buffer_paddr = m_tx_buffer_region->paddr() + i * s_buffer_size;
|
||||
tx_descriptors[i].command = 0;
|
||||
tx_descriptors[i].vlan = 0;
|
||||
tx_descriptors[i].buffer_low = tx_buffer_paddr & 0xFFFFFFFF;
|
||||
tx_descriptors[i].buffer_high = tx_buffer_paddr >> 32;
|
||||
|
||||
uint32_t command = 0;
|
||||
if (i == m_tx_descriptor_count - 1)
|
||||
command |= RTL8169_DESC_CMD_EOR;
|
||||
|
||||
auto& tx_descriptor = reinterpret_cast<volatile RTL8169Descriptor*>(m_tx_descriptor_region->vaddr())[i];
|
||||
tx_descriptor.command = command;
|
||||
tx_descriptor.vlan = 0;
|
||||
tx_descriptor.buffer_low = tx_buffer_paddr & 0xFFFFFFFF;
|
||||
tx_descriptor.buffer_high = tx_buffer_paddr >> 32;
|
||||
}
|
||||
tx_descriptors[m_tx_descriptor_count - 1].command |= RTL8169_DESC_CMD_EOR;
|
||||
|
||||
// configure tx descriptor addresses
|
||||
m_io_bar_region->write32(RTL8169_IO_TNPDS + 4, m_tx_descriptor_region->paddr() >> 32);
|
||||
m_io_bar_region->write32(RTL8169_IO_TNPDS + 0, m_tx_descriptor_region->paddr() & 0xFFFFFFFF);
|
||||
m_io_bar_region->write32(RTL8169_IO_TNPDS + 4, m_tx_descriptor_region->paddr() >> 32);
|
||||
|
||||
// configure transmit control (standard ifg, max dma burst unlimited)
|
||||
m_io_bar_region->write32(RTL8169_IO_TCR, RTL8169_TCR_IFG_0 | RTL8169_TCR_MXDMA_UNLIMITED);
|
||||
// configure transmit control (standard ifg, max dma burst 1024)
|
||||
m_io_bar_region->write32(RTL8169_IO_TCR, RTL8169_TCR_IFG_0 | RTL8169_TCR_MXDMA_1024);
|
||||
|
||||
// configure max tx packet size
|
||||
m_io_bar_region->write8(RTL8169_IO_MTPS, RTL8169_MTPS_MAX);
|
||||
@@ -174,13 +181,14 @@ namespace Kernel
|
||||
m_pci_device.enable_interrupt(0, *this);
|
||||
|
||||
m_io_bar_region->write16(RTL8169_IO_IMR,
|
||||
RTL8169_IR_ROK |
|
||||
RTL8169_IR_RER |
|
||||
RTL8169_IR_TOK |
|
||||
RTL8169_IR_TER |
|
||||
RTL8169_IR_RDU |
|
||||
RTL8169_IR_LinkChg |
|
||||
RTL8169_IR_FVOW
|
||||
RTL8169_IR_ROK
|
||||
| RTL8169_IR_RER
|
||||
| RTL8169_IR_TOK
|
||||
| RTL8169_IR_TER
|
||||
| RTL8169_IR_RDU
|
||||
| RTL8169_IR_LinkChg
|
||||
| RTL8169_IR_FVOW
|
||||
| RTL8169_IR_TDU
|
||||
);
|
||||
m_io_bar_region->write16(RTL8169_IO_ISR, 0xFFFF);
|
||||
|
||||
@@ -201,156 +209,122 @@ namespace Kernel
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> RTL8169::send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers)
|
||||
BAN::ErrorOr<void> RTL8169::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload)
|
||||
{
|
||||
if (!link_up())
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
|
||||
const auto interrupt_state = Processor::get_interrupt_state();
|
||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||
auto state = m_lock.lock();
|
||||
|
||||
const uint32_t tx_current_nowrap = m_tx_head.fetch_add(1);
|
||||
const uint32_t tx_current = tx_current_nowrap % m_tx_descriptor_count;
|
||||
const uint32_t tx_current = m_tx_current;
|
||||
m_tx_current = (m_tx_current + 1) % m_tx_descriptor_count;
|
||||
|
||||
auto& descriptor = reinterpret_cast<volatile RTL8169Descriptor*>(m_tx_descriptor_region->vaddr())[tx_current];
|
||||
if (descriptor.command & RTL8169_DESC_CMD_OWN)
|
||||
while (descriptor.command & RTL8169_DESC_CMD_OWN)
|
||||
{
|
||||
SpinLockGuard guard(m_tx_lock);
|
||||
while (descriptor.command & RTL8169_DESC_CMD_OWN)
|
||||
{
|
||||
SpinLockGuardAsMutex smutex(guard);
|
||||
m_tx_blocker.block_indefinite(&smutex);
|
||||
}
|
||||
SpinLockAsMutex smutex(m_lock, state);
|
||||
m_thread_blocker.block_indefinite(&smutex);
|
||||
}
|
||||
|
||||
m_lock.unlock(state);
|
||||
|
||||
auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + tx_current * s_buffer_size);
|
||||
|
||||
// write packet
|
||||
size_t packet_size = 0;
|
||||
for (const auto& buffer : buffers)
|
||||
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(tx_buffer);
|
||||
ethernet_header.dst_mac = destination;
|
||||
ethernet_header.src_mac = get_mac_address();
|
||||
ethernet_header.ether_type = protocol;
|
||||
|
||||
size_t packet_size = sizeof(EthernetHeader);
|
||||
for (const auto& buffer : payload)
|
||||
{
|
||||
ASSERT(packet_size + buffer.size() <= s_buffer_size);
|
||||
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
|
||||
packet_size += buffer.size();
|
||||
}
|
||||
|
||||
// give packet ownership to NIC
|
||||
uint32_t command = packet_size | RTL8169_DESC_CMD_OWN | RTL8169_DESC_CMD_LS | RTL8169_DESC_CMD_FS;
|
||||
if (tx_current == m_tx_descriptor_count - 1)
|
||||
if (tx_current >= m_tx_descriptor_count - 1)
|
||||
command |= RTL8169_DESC_CMD_EOR;
|
||||
descriptor.command = command;
|
||||
|
||||
// ring tx queue doorbell
|
||||
if (tx_current_nowrap == m_tx_commit.load())
|
||||
m_io_bar_region->write8(RTL8169_IO_TPPoll, RTL8169_TPPoll_NPQ);
|
||||
while (tx_current_nowrap != m_tx_commit.load())
|
||||
Processor::pause();
|
||||
m_tx_commit.add_fetch(1);
|
||||
|
||||
Processor::set_interrupt_state(interrupt_state);
|
||||
// notify NIC about new packet
|
||||
m_io_bar_region->write8(RTL8169_IO_TPPoll, RTL8169_TPPoll_NPQ);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void RTL8169::receive_thread()
|
||||
{
|
||||
SpinLockGuard rx_lock_guard(m_rx_lock);
|
||||
SpinLockGuard _(m_lock);
|
||||
|
||||
while (!m_rx_thread_should_die)
|
||||
while (!m_thread_should_die)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
auto& descriptor = reinterpret_cast<volatile RTL8169Descriptor*>(m_rx_descriptor_region->vaddr())[m_rx_head];
|
||||
|
||||
const auto command = descriptor.command;
|
||||
auto& descriptor = reinterpret_cast<volatile RTL8169Descriptor*>(m_rx_descriptor_region->vaddr())[m_rx_current];
|
||||
if (descriptor.command & RTL8169_DESC_CMD_OWN)
|
||||
break;
|
||||
|
||||
// packet buffer can only hold single packet, so we should not receive any multi-descriptor packets
|
||||
ASSERT((command & RTL8169_DESC_CMD_LS) && (command & RTL8169_DESC_CMD_FS));
|
||||
ASSERT((descriptor.command & RTL8169_DESC_CMD_LS) && (descriptor.command & RTL8169_DESC_CMD_FS));
|
||||
|
||||
const uint8_t protocol = (command >> 17) & 3;
|
||||
const uint16_t packet_length = command & 0x3FFF;
|
||||
const uint16_t packet_length = descriptor.command & 0x3FFF;
|
||||
if (packet_length > s_buffer_size)
|
||||
dwarnln("Got {} bytes to {} byte buffer", packet_length, s_buffer_size);
|
||||
else if (command & (1u << 21))
|
||||
dwarnln("descriptor error {4h}", command);
|
||||
else if (protocol == 1 && (command & (1u << 14)))
|
||||
dwarnln("TCP checksum error");
|
||||
else if (protocol == 2 && (command & (1u << 15)))
|
||||
dwarnln("UDP checksum error");
|
||||
else if (protocol != 0 && (command & (1u << 16)))
|
||||
dwarnln("IPv4 checksum error");
|
||||
else if (descriptor.command & (1u << 21))
|
||||
; // descriptor has an error
|
||||
else
|
||||
{
|
||||
m_rx_lock.unlock(InterruptState::Enabled);
|
||||
m_lock.unlock(InterruptState::Enabled);
|
||||
|
||||
uint32_t validated_cksums;
|
||||
switch (protocol)
|
||||
{
|
||||
case 0: validated_cksums = 0; break;
|
||||
case 1: validated_cksums = CKSUM_IPV4 | CKSUM_TCP; break;
|
||||
case 2: validated_cksums = CKSUM_IPV4 | CKSUM_UDP; break;
|
||||
case 3: validated_cksums = CKSUM_IPV4; break;
|
||||
}
|
||||
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
|
||||
reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + m_rx_current * s_buffer_size),
|
||||
packet_length
|
||||
});
|
||||
|
||||
const uint8_t* packet_data = reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + m_rx_head * s_buffer_size);
|
||||
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan { packet_data, packet_length }, validated_cksums);
|
||||
|
||||
m_rx_lock.lock();
|
||||
m_lock.lock();
|
||||
}
|
||||
|
||||
uint32_t new_command = 0x1FF8 | RTL8169_DESC_CMD_OWN;
|
||||
if (m_rx_head == m_rx_descriptor_count - 1)
|
||||
new_command |= RTL8169_DESC_CMD_EOR;
|
||||
descriptor.command = new_command;
|
||||
m_rx_current = (m_rx_current + 1) % m_rx_descriptor_count;
|
||||
|
||||
m_rx_head = (m_rx_head + 1) % m_rx_descriptor_count;
|
||||
descriptor.command = descriptor.command | RTL8169_DESC_CMD_OWN;
|
||||
}
|
||||
|
||||
SpinLockGuardAsMutex smutex(rx_lock_guard);
|
||||
m_rx_blocker.block_indefinite(&smutex);
|
||||
SpinLockAsMutex smutex(m_lock, InterruptState::Enabled);
|
||||
m_thread_blocker.block_indefinite(&smutex);
|
||||
}
|
||||
|
||||
m_rx_thread_is_dead = true;
|
||||
m_thread_is_dead = true;
|
||||
}
|
||||
|
||||
void RTL8169::handle_irq()
|
||||
{
|
||||
uint16_t isr;
|
||||
while ((isr = m_io_bar_region->read16(RTL8169_IO_ISR)))
|
||||
const uint16_t interrupt_status = m_io_bar_region->read16(RTL8169_IO_ISR);
|
||||
m_io_bar_region->write16(RTL8169_IO_ISR, interrupt_status);
|
||||
|
||||
if (interrupt_status & RTL8169_IR_LinkChg)
|
||||
{
|
||||
m_io_bar_region->write16(RTL8169_IO_ISR, isr);
|
||||
|
||||
if (isr & RTL8169_IR_LinkChg)
|
||||
{
|
||||
m_link_up = m_io_bar_region->read8(RTL8169_IO_PHYSts) & RTL8169_PHYSts_LinkSts;
|
||||
dprintln("link status {}", link_up() ? "UP" : "DOWN");
|
||||
if (link_up())
|
||||
dprintln("link speed {}", link_speed());
|
||||
}
|
||||
|
||||
if (isr & (RTL8169_IR_TER | RTL8169_IR_TOK))
|
||||
{
|
||||
SpinLockGuard _(m_tx_lock);
|
||||
m_tx_blocker.unblock();
|
||||
}
|
||||
|
||||
if (isr & (RTL8169_IR_RER | RTL8169_IR_ROK))
|
||||
{
|
||||
SpinLockGuard _(m_rx_lock);
|
||||
m_rx_blocker.unblock();
|
||||
}
|
||||
|
||||
if (isr & RTL8169_IR_RER)
|
||||
dwarnln("Rx error");
|
||||
if (isr & RTL8169_IR_TER)
|
||||
dwarnln("Tx error");
|
||||
if (isr & RTL8169_IR_RDU)
|
||||
dwarnln("Rx descriptor not available");
|
||||
if (isr & RTL8169_IR_FVOW)
|
||||
dwarnln("Rx FIFO overflow");
|
||||
m_link_up = m_io_bar_region->read8(RTL8169_IO_PHYSts) & RTL8169_PHYSts_LinkSts;
|
||||
dprintln("link status -> {}", m_link_up.load());
|
||||
}
|
||||
|
||||
if (interrupt_status & (RTL8169_IR_TOK | RTL8169_IR_ROK))
|
||||
{
|
||||
SpinLockGuard _(m_lock);
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
|
||||
if (interrupt_status & RTL8169_IR_RER)
|
||||
dwarnln("Rx error");
|
||||
if (interrupt_status & RTL8169_IR_TER)
|
||||
dwarnln("Tx error");
|
||||
if (interrupt_status & RTL8169_IR_RDU)
|
||||
dwarnln("Rx descriptor not available");
|
||||
if (interrupt_status & RTL8169_IR_FVOW)
|
||||
dwarnln("Rx FIFO overflow");
|
||||
// dont log TDU is sent after each sent packet
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> TCPSocket::ioctl_impl(unsigned long request, void* argument)
|
||||
BAN::ErrorOr<long> TCPSocket::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
@@ -572,7 +572,7 @@ namespace Kernel
|
||||
dprintln_if(DEBUG_TCP, " seq {}", (uint32_t)header.seq_number);
|
||||
}
|
||||
|
||||
void TCPSocket::receive_packet(BAN::ConstByteSpan packet, const sockaddr* sender, socklen_t sender_len, uint32_t validated_cksums)
|
||||
void TCPSocket::receive_packet(BAN::ConstByteSpan buffer, const sockaddr* sender, socklen_t sender_len)
|
||||
{
|
||||
if (m_state == State::Listen)
|
||||
{
|
||||
@@ -585,10 +585,9 @@ namespace Kernel
|
||||
}();
|
||||
|
||||
if (socket)
|
||||
return socket->receive_packet(packet, sender, sender_len, validated_cksums);
|
||||
return socket->receive_packet(buffer, sender, sender_len);
|
||||
}
|
||||
|
||||
if (!(validated_cksums & CKSUM_TCP))
|
||||
{
|
||||
uint16_t checksum = 0;
|
||||
|
||||
@@ -604,23 +603,23 @@ namespace Kernel
|
||||
.src_ipv4 = BAN::IPv4Address(addr_in.sin_addr.s_addr),
|
||||
.dst_ipv4 = interface->get_ipv4_address(),
|
||||
.protocol = NetworkProtocol::TCP,
|
||||
.length = packet.size(),
|
||||
.length = buffer.size(),
|
||||
};
|
||||
const BAN::ConstByteSpan buffers[] {
|
||||
BAN::ConstByteSpan::from(pseudo_header),
|
||||
packet
|
||||
buffer
|
||||
};
|
||||
checksum = calculate_internet_checksum({ buffers, sizeof(buffers) / sizeof(*buffers) });
|
||||
}
|
||||
else
|
||||
{
|
||||
dwarnln("no TCP checksum validation for socket family {}", sender->sa_family);
|
||||
dwarnln("No tcp checksum validation for socket family {}", sender->sa_family);
|
||||
return;
|
||||
}
|
||||
|
||||
if (checksum != 0)
|
||||
{
|
||||
dwarnln("checksum does not match");
|
||||
dprintln("Checksum does not match");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -629,7 +628,7 @@ namespace Kernel
|
||||
|
||||
const bool hungup_before = has_hungup_impl();
|
||||
|
||||
const auto& header = packet.as<const TCPHeader>();
|
||||
auto& header = buffer.as<const TCPHeader>();
|
||||
|
||||
dprintln_if(DEBUG_TCP, "receiving {} {8b}", (uint8_t)m_state, header.flags);
|
||||
dprintln_if(DEBUG_TCP, " ack {}", (uint32_t)header.ack_number);
|
||||
@@ -769,7 +768,7 @@ namespace Kernel
|
||||
if (header.ack_number > m_send_window.current_ack)
|
||||
m_send_window.current_ack = header.ack_number;
|
||||
|
||||
auto payload = packet.slice(header.data_offset * sizeof(uint32_t));
|
||||
auto payload = buffer.slice(header.data_offset * sizeof(uint32_t));
|
||||
|
||||
if (header.seq_number < expected_seq)
|
||||
{
|
||||
@@ -968,9 +967,6 @@ namespace Kernel
|
||||
if (m_last_sent_window_size == 0)
|
||||
m_should_send_zero_window = false;
|
||||
|
||||
if (m_last_sent_window_size == m_recv_window.buffer->free())
|
||||
m_should_send_window_update = false;
|
||||
|
||||
if (m_should_send_zero_window || m_should_send_window_update)
|
||||
{
|
||||
ASSERT(m_connection_info.has_value());
|
||||
|
||||
@@ -57,69 +57,21 @@ namespace Kernel
|
||||
header.checksum = 0xFFFF;
|
||||
}
|
||||
|
||||
void UDPSocket::receive_packet(BAN::ConstByteSpan packet, const sockaddr* sender, socklen_t sender_len, uint32_t validated_cksums)
|
||||
void UDPSocket::receive_packet(BAN::ConstByteSpan packet, const sockaddr* sender, socklen_t sender_len)
|
||||
{
|
||||
const auto header = packet.as<const UDPHeader>();
|
||||
|
||||
if (!(validated_cksums & CKSUM_UDP) && header.checksum)
|
||||
{
|
||||
uint16_t checksum = 0;
|
||||
|
||||
if (sender->sa_family == AF_INET)
|
||||
{
|
||||
auto interface_or_error = interface(sender, sender_len);
|
||||
if (interface_or_error.is_error())
|
||||
return;
|
||||
auto interface = interface_or_error.release_value();
|
||||
|
||||
auto& addr_in = *reinterpret_cast<const sockaddr_in*>(sender);
|
||||
const PseudoHeader pseudo_header {
|
||||
.src_ipv4 = BAN::IPv4Address(addr_in.sin_addr.s_addr),
|
||||
.dst_ipv4 = interface->get_ipv4_address(),
|
||||
.protocol = NetworkProtocol::UDP,
|
||||
.length = packet.size(),
|
||||
};
|
||||
const UDPHeader udp_header {
|
||||
.src_port = header.src_port,
|
||||
.dst_port = header.dst_port,
|
||||
.length = header.length,
|
||||
.checksum = 0,
|
||||
};
|
||||
const BAN::ConstByteSpan buffers[] {
|
||||
BAN::ConstByteSpan::from(pseudo_header),
|
||||
BAN::ConstByteSpan::from(udp_header),
|
||||
packet.slice(sizeof(UDPHeader))
|
||||
};
|
||||
checksum = calculate_internet_checksum({ buffers, sizeof(buffers) / sizeof(*buffers) });
|
||||
}
|
||||
else
|
||||
{
|
||||
dwarnln("no UDP checksum validation for socket family {}", sender->sa_family);
|
||||
return;
|
||||
}
|
||||
|
||||
const bool checksum_valid1 = (header.checksum == checksum);
|
||||
const bool checksum_valid2 = (header.checksum == 0xFFFF && checksum == 0);
|
||||
if (!checksum_valid1 && !checksum_valid2)
|
||||
{
|
||||
dwarnln("checksum does not match {4h}", checksum);
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto payload = packet.slice(sizeof(UDPHeader));
|
||||
|
||||
SpinLockGuard _(m_packet_lock);
|
||||
|
||||
if (m_packets.full())
|
||||
{
|
||||
dwarnln("Packet buffer full, dropping packet");
|
||||
dprintln("Packet buffer full, dropping packet");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto payload = packet.slice(sizeof(UDPHeader));
|
||||
|
||||
if (m_packet_total_size + payload.size() > m_packet_buffer->size())
|
||||
{
|
||||
dwarnln("Packet buffer full, dropping packet");
|
||||
dprintln("Packet buffer full, dropping packet");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -272,9 +224,7 @@ namespace Kernel
|
||||
address_len = message.msg_namelen;
|
||||
}
|
||||
|
||||
TRY(m_network_layer.sendto(*this, buffer.span(), address, address_len));
|
||||
|
||||
return buffer.size();
|
||||
return TRY(m_network_layer.sendto(*this, buffer.span(), address, address_len));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UDPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
|
||||
@@ -336,7 +286,7 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> UDPSocket::ioctl_impl(unsigned long request, void* argument)
|
||||
BAN::ErrorOr<long> UDPSocket::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
|
||||
@@ -704,25 +704,6 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UnixDomainSocket::getsockname_impl(sockaddr* address, socklen_t* address_len)
|
||||
{
|
||||
sockaddr_un sa_un {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = {},
|
||||
};
|
||||
|
||||
{
|
||||
LockGuard _(m_bind_mutex);
|
||||
strcpy(sa_un.sun_path, m_bound_file.canonical_path.data());
|
||||
}
|
||||
|
||||
const size_t to_copy = BAN::Math::min<socklen_t>(sizeof(sockaddr_un), *address_len);
|
||||
memcpy(address, &sa_un, to_copy);
|
||||
*address_len = to_copy;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
BAN::ErrorOr<void> UnixDomainSocket::getpeername_impl(sockaddr* address, socklen_t* address_len)
|
||||
{
|
||||
if (!m_info.has<ConnectionInfo>())
|
||||
@@ -732,7 +713,20 @@ namespace Kernel
|
||||
if (!connection)
|
||||
return BAN::Error::from_errno(ENOTCONN);
|
||||
|
||||
return connection->getsockname_impl(address, address_len);
|
||||
sockaddr_un sa_un {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = {},
|
||||
};
|
||||
|
||||
{
|
||||
LockGuard _(m_bind_mutex);
|
||||
strcpy(sa_un.sun_path, connection->m_bound_file.canonical_path.data());
|
||||
}
|
||||
|
||||
const size_t to_copy = BAN::Math::min<socklen_t>(sizeof(sockaddr_un), *address_len);
|
||||
memcpy(address, &sa_un, to_copy);
|
||||
*address_len = to_copy;
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UnixDomainSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
|
||||
@@ -749,24 +743,12 @@ namespace Kernel
|
||||
case SO_ERROR:
|
||||
result = 0;
|
||||
break;
|
||||
case SO_KEEPALIVE:
|
||||
result = 1;
|
||||
break;
|
||||
case SO_SNDBUF:
|
||||
result = m_sndbuf;
|
||||
break;
|
||||
case SO_RCVBUF:
|
||||
result = m_packet_buffer->size();
|
||||
break;
|
||||
case SO_TYPE:
|
||||
switch (m_socket_type)
|
||||
{
|
||||
case Type::STREAM: result = SOCK_STREAM; break;
|
||||
case Type::DGRAM: result = SOCK_DGRAM; break;
|
||||
case Type::SEQPACKET: result = SOCK_SEQPACKET; break;
|
||||
default: ASSERT_NOT_REACHED();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dwarnln("getsockopt(SOL_SOCKET, {})", option);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
||||
@@ -401,19 +401,11 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> OpenFileDescriptorSet::close(int fd)
|
||||
{
|
||||
BAN::RefPtr<OpenFileDescription> open_file;
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
TRY(validate_fd(fd));
|
||||
|
||||
TRY(validate_fd(fd));
|
||||
|
||||
open_file = m_open_files[fd];
|
||||
|
||||
m_open_files[fd]->file.inode->on_close(m_open_files[fd]->status_flags);
|
||||
m_open_files[fd] = {};
|
||||
remove_cloexec(fd);
|
||||
}
|
||||
auto& open_file = m_open_files[fd];
|
||||
|
||||
if (auto& flock = open_file->flock; Thread::current().has_process() && flock.lockers.contains(Process::current().pid()))
|
||||
{
|
||||
@@ -437,6 +429,10 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
open_file->file.inode->on_close(open_file->status_flags);
|
||||
open_file = {};
|
||||
remove_cloexec(fd);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -857,15 +853,6 @@ namespace Kernel
|
||||
return inode->sendmsg(message, flags | (is_nonblock ? MSG_DONTWAIT : 0));
|
||||
}
|
||||
|
||||
int OpenFileDescriptorSet::get_max_open_fd() const
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
for (int fd = m_open_files.size() - 1; fd > 0; fd--)
|
||||
if (m_open_files[fd])
|
||||
return fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
@@ -235,13 +235,11 @@ namespace Kernel::PCI
|
||||
switch (pci_device.subclass())
|
||||
{
|
||||
case 0x01:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
if (auto res = ATAController::create(pci_device); res.is_error())
|
||||
dprintln("ATA: {}", res.error());
|
||||
break;
|
||||
case 0x06:
|
||||
if (auto res = AHCIController::create(pci_device); res.is_error())
|
||||
dprintln("AHCI: {}", res.error());
|
||||
break;
|
||||
case 0x08:
|
||||
if (auto res = NVMeController::create(pci_device); res.is_error())
|
||||
dprintln("NVMe: {}", res.error());
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,3 @@
|
||||
#include <kernel/CPUID.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Memory/kmalloc.h>
|
||||
@@ -21,11 +20,10 @@ namespace Kernel
|
||||
static constexpr uint32_t MSR_IA32_FMASK = 0xC0000084;
|
||||
#endif
|
||||
|
||||
static constexpr uint32_t MSR_IA32_TSC_AUX = 0xC0000103;
|
||||
|
||||
ProcessorID Processor::s_bsp_id { PROCESSOR_NONE };
|
||||
BAN::Atomic<uint8_t> Processor::s_processor_count { 0 };
|
||||
BAN::Atomic<bool> Processor::s_is_smp_enabled { false };
|
||||
BAN::Atomic<bool> Processor::s_should_print_cpu_load { false };
|
||||
paddr_t Processor::s_shared_page_paddr { 0 };
|
||||
vaddr_t Processor::s_shared_page_vaddr { 0 };
|
||||
|
||||
@@ -222,9 +220,6 @@ namespace Kernel
|
||||
shared_page.gdt_cpu_offset = GDT::cpu_index_offset();
|
||||
shared_page.features = 0;
|
||||
|
||||
if (CPUID::has_rdtscp())
|
||||
shared_page.features |= API::SPF_RDTSCP;
|
||||
|
||||
ASSERT(Processor::count() + sizeof(Kernel::API::SharedPage) <= PAGE_SIZE);
|
||||
}
|
||||
|
||||
@@ -295,11 +290,13 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
void Processor::initialize_tsc(uint64_t realtime_seconds)
|
||||
void Processor::initialize_tsc(uint8_t shift, uint64_t mult, uint64_t realtime_seconds)
|
||||
{
|
||||
auto& shared_page = Processor::shared_page();
|
||||
shared_page.gettime_shared.realtime_s = realtime_seconds;
|
||||
shared_page.gettime_shared.realtime_ns = 0;
|
||||
|
||||
shared_page.gettime_shared.shift = shift;
|
||||
shared_page.gettime_shared.mult = mult;
|
||||
shared_page.gettime_shared.realtime_seconds = realtime_seconds;
|
||||
|
||||
update_tsc();
|
||||
|
||||
@@ -326,63 +323,23 @@ namespace Kernel
|
||||
|
||||
void Processor::update_tsc()
|
||||
{
|
||||
auto& lgettime = shared_page().cpus[current_index()].gettime_local;
|
||||
|
||||
const auto seq = BAN::atomic_load(lgettime.seq, BAN::memory_order_relaxed);
|
||||
|
||||
BAN::atomic_store(lgettime.seq, seq + 1, BAN::memory_order_release);
|
||||
|
||||
if (lgettime.seq == 1)
|
||||
{
|
||||
const auto tsc_info = SystemTimer::get().tsc_info();
|
||||
lgettime.shift = tsc_info.shift;
|
||||
lgettime.mult = tsc_info.mult;
|
||||
lgettime.last_ns = SystemTimer::get().ns_since_boot_no_tsc();
|
||||
lgettime.last_tsc = __builtin_ia32_rdtsc();
|
||||
|
||||
if (CPUID::has_rdtscp())
|
||||
asm volatile("wrmsr" :: "d"(0x00000000), "a"(current_index()), "c"(MSR_IA32_TSC_AUX));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto current_ns = SystemTimer::get().ns_since_boot_no_tsc();
|
||||
const auto current_tsc = __builtin_ia32_rdtsc();
|
||||
|
||||
auto delta_ns = current_tsc - lgettime.last_tsc;
|
||||
if (lgettime.shift >= 0)
|
||||
delta_ns <<= lgettime.shift;
|
||||
else
|
||||
delta_ns >>= -lgettime.shift;
|
||||
delta_ns = (delta_ns * lgettime.mult) >> 32;
|
||||
|
||||
lgettime.last_ns += delta_ns;
|
||||
lgettime.last_tsc = current_tsc;
|
||||
|
||||
// scale mult by [-0.25%, 0.25%] to fix for clock drift
|
||||
const auto error_ns = static_cast<int64_t>(current_ns) - static_cast<int64_t>(lgettime.last_ns);
|
||||
const auto correction_ppm = BAN::Math::clamp<int64_t>(error_ns * 1'000'000 / 1'000'000'000, -100, 100);
|
||||
const auto correction_delta = -lgettime.mult * correction_ppm / 1'000'000;
|
||||
lgettime.mult += correction_delta;
|
||||
}
|
||||
|
||||
BAN::atomic_store(lgettime.seq, seq + 2, BAN::memory_order_release);
|
||||
auto& sgettime = shared_page().cpus[current_index()].gettime_local;
|
||||
sgettime.seq = sgettime.seq + 1;
|
||||
sgettime.last_ns = SystemTimer::get().ns_since_boot_no_tsc();
|
||||
sgettime.last_tsc = __builtin_ia32_rdtsc();
|
||||
sgettime.seq = sgettime.seq + 1;
|
||||
}
|
||||
|
||||
uint64_t Processor::ns_since_boot_tsc()
|
||||
{
|
||||
const auto& shared_page = Processor::shared_page();
|
||||
const auto& sgettime = shared_page.gettime_shared;
|
||||
const auto& lgettime = shared_page.cpus[current_index()].gettime_local;
|
||||
|
||||
auto state = get_interrupt_state();
|
||||
set_interrupt_state(InterruptState::Disabled);
|
||||
|
||||
uint64_t current_ns = __builtin_ia32_rdtsc() - lgettime.last_tsc;
|
||||
if (lgettime.shift >= 0)
|
||||
current_ns <<= lgettime.shift;
|
||||
else
|
||||
current_ns >>= -lgettime.shift;
|
||||
current_ns = (current_ns * lgettime.mult) >> 32;
|
||||
current_ns += lgettime.last_ns;
|
||||
const auto current_ns = lgettime.last_ns + (((__builtin_ia32_rdtsc() - lgettime.last_tsc) * sgettime.mult) >> sgettime.shift);
|
||||
|
||||
set_interrupt_state(state);
|
||||
|
||||
@@ -641,26 +598,6 @@ namespace Kernel
|
||||
set_interrupt_state(state);
|
||||
}
|
||||
|
||||
Processor::LoadStats Processor::get_load_stats(size_t index)
|
||||
{
|
||||
ASSERT(index < Processor::count());
|
||||
|
||||
auto& processor = s_processors[s_processor_ids[index].as_u32()];
|
||||
|
||||
bool expected = false;
|
||||
while (!processor.m_load_stat_lock.compare_exchange(expected, true))
|
||||
{
|
||||
Processor::pause();
|
||||
expected = false;
|
||||
}
|
||||
|
||||
const auto load_stats = processor.m_load_stats;
|
||||
|
||||
processor.m_load_stat_lock.store(false);
|
||||
|
||||
return load_stats;
|
||||
}
|
||||
|
||||
void Processor::yield()
|
||||
{
|
||||
auto state = get_interrupt_state();
|
||||
@@ -668,32 +605,47 @@ namespace Kernel
|
||||
|
||||
ASSERT(!Thread::current().has_spinlock());
|
||||
|
||||
auto& processor = s_processors[current_id().as_u32()];
|
||||
auto& processor_info = s_processors[current_id().as_u32()];
|
||||
|
||||
{
|
||||
bool expected = false;
|
||||
while (!processor.m_load_stat_lock.compare_exchange(expected, true))
|
||||
{
|
||||
Processor::pause();
|
||||
expected = false;
|
||||
}
|
||||
constexpr uint64_t load_update_interval_ns = 1'000'000'000;
|
||||
|
||||
const uint64_t elapsed_ns = SystemTimer::get().ns_since_boot() - processor.m_load_start_ns;
|
||||
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||
|
||||
auto& load_stats = processor.m_load_stats;
|
||||
if (scheduler().is_idle())
|
||||
load_stats.ns_idle += elapsed_ns;
|
||||
load_stats.ns_total += elapsed_ns;
|
||||
processor_info.m_idle_ns += current_ns - processor_info.m_start_ns;
|
||||
|
||||
processor.m_load_stat_lock.store(false);
|
||||
if (current_ns >= processor_info.m_next_update_ns)
|
||||
{
|
||||
if (s_should_print_cpu_load && g_terminal_driver)
|
||||
{
|
||||
const uint64_t duration_ns = current_ns - processor_info.m_last_update_ns;
|
||||
const uint64_t load_x1000 = 100'000 * (duration_ns - BAN::Math::min(processor_info.m_idle_ns, duration_ns)) / duration_ns;
|
||||
|
||||
uint32_t x = g_terminal_driver->width() - 16;
|
||||
uint32_t y = current_id().as_u32();
|
||||
const auto proc_putc =
|
||||
[&x, y](char ch)
|
||||
{
|
||||
if (x < g_terminal_driver->width() && y < g_terminal_driver->height())
|
||||
g_terminal_driver->putchar_at(ch, x++, y, TerminalColor::WHITE, TerminalColor::BLACK);
|
||||
};
|
||||
|
||||
BAN::Formatter::print(proc_putc, "CPU { 2}: { 3}.{3}%", current_id(), load_x1000 / 1000, load_x1000 % 1000);
|
||||
}
|
||||
|
||||
processor_info.m_idle_ns = 0;
|
||||
processor_info.m_last_update_ns = current_ns;
|
||||
processor_info.m_next_update_ns += load_update_interval_ns;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scheduler().is_idle())
|
||||
Thread::current().set_cpu_time_stop();
|
||||
|
||||
asm_yield_trampoline(processor.stack_top_vaddr());
|
||||
asm_yield_trampoline(processor_info.stack_top_vaddr());
|
||||
|
||||
processor.m_load_start_ns = SystemTimer::get().ns_since_boot();
|
||||
processor_info.m_start_ns = SystemTimer::get().ns_since_boot();
|
||||
|
||||
if (!scheduler().is_idle())
|
||||
Thread::current().set_cpu_time_start();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <BAN/Optional.h>
|
||||
#include <BAN/Sort.h>
|
||||
#include <kernel/APIC.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Process.h>
|
||||
@@ -46,15 +45,12 @@ namespace Kernel
|
||||
m_tail = node;
|
||||
}
|
||||
|
||||
bool SchedulerQueue::add_thread_with_wake_time(Node* node)
|
||||
void SchedulerQueue::add_thread_with_wake_time(Node* node)
|
||||
{
|
||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||
|
||||
if (m_tail == nullptr || node->wake_time_ns >= m_tail->wake_time_ns)
|
||||
{
|
||||
add_thread_to_back(node);
|
||||
return node == m_head;
|
||||
}
|
||||
return add_thread_to_back(node);
|
||||
|
||||
Node* next = m_head;
|
||||
Node* prev = nullptr;
|
||||
@@ -68,8 +64,6 @@ namespace Kernel
|
||||
node->prev = prev;
|
||||
(next ? next->prev : m_tail) = node;
|
||||
(prev ? prev->next : m_head) = node;
|
||||
|
||||
return node == m_head;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
@@ -128,9 +122,15 @@ namespace Kernel
|
||||
m_idle_thread = TRY(Thread::create_kernel([](void*) { asm volatile("1: hlt; jmp 1b"); }, nullptr));
|
||||
ASSERT(m_idle_thread);
|
||||
|
||||
size_t processor_index = 0;
|
||||
for (; processor_index < Processor::count(); processor_index++)
|
||||
if (Processor::id_from_index(processor_index) == Processor::current_id())
|
||||
break;
|
||||
ASSERT(processor_index < Processor::count());
|
||||
|
||||
// each CPU does load balance at different times. This calulates the offset to other CPUs
|
||||
m_last_load_balance_ns = s_load_balance_interval_ns * Processor::current_index() / Processor::count();
|
||||
m_idle_ns = m_last_load_balance_ns;
|
||||
m_last_load_balance_ns = s_load_balance_interval_ns * processor_index / Processor::count();
|
||||
m_idle_ns = -m_last_load_balance_ns;
|
||||
|
||||
s_schedulers_initialized++;
|
||||
while (s_schedulers_initialized < Processor::count())
|
||||
@@ -139,6 +139,8 @@ namespace Kernel
|
||||
if (Processor::count() > 1)
|
||||
Processor::set_smp_enabled();
|
||||
|
||||
m_next_reschedule_ns = SystemTimer::get().ns_since_boot();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -230,14 +232,17 @@ namespace Kernel
|
||||
m_thread_count--;
|
||||
break;
|
||||
case Thread::State::Executing:
|
||||
{
|
||||
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||
m_current->thread->yield_registers() = *yield_registers;
|
||||
m_current->time_used_ns += SystemTimer::get().ns_since_boot() - m_current->last_start_ns;
|
||||
m_current->time_used_ns += current_ns - m_current->last_start_ns;
|
||||
add_current_to_most_loaded(m_current->blocked ? &m_block_queue : &m_run_queue);
|
||||
if (!m_current->blocked)
|
||||
m_run_queue.add_thread_to_back(m_current);
|
||||
else if (m_block_queue.add_thread_with_wake_time(m_current))
|
||||
update_wake_up_deadline();
|
||||
else
|
||||
m_block_queue.add_thread_with_wake_time(m_current);
|
||||
break;
|
||||
}
|
||||
case Thread::State::NotStarted:
|
||||
ASSERT(!m_current->blocked);
|
||||
m_current->time_used_ns = 0;
|
||||
@@ -316,50 +321,26 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::update_wake_up_deadline()
|
||||
{
|
||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||
|
||||
auto& interrupt_controller = InterruptController::get();
|
||||
|
||||
// TODO: support timer deadlines on non-apic timers and abstract it :)
|
||||
if (!interrupt_controller.is_using_apic())
|
||||
return;
|
||||
|
||||
wake_up_sleeping_threads();
|
||||
|
||||
uint64_t deadline_ns = m_next_reschedule_ns;
|
||||
if (!m_block_queue.empty())
|
||||
deadline_ns = BAN::Math::min(deadline_ns, m_block_queue.front()->wake_time_ns);
|
||||
if (Processor::is_smp_enabled())
|
||||
deadline_ns = BAN::Math::min(deadline_ns, m_last_load_balance_ns + s_load_balance_interval_ns);
|
||||
|
||||
static_cast<APIC&>(interrupt_controller).set_timer_dealine(deadline_ns);
|
||||
}
|
||||
|
||||
void Scheduler::reschedule_if_idle()
|
||||
{
|
||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||
|
||||
if (m_current == nullptr && !m_run_queue.empty())
|
||||
if (m_current != nullptr)
|
||||
return;
|
||||
|
||||
if (m_run_queue.empty())
|
||||
wake_up_sleeping_threads();
|
||||
|
||||
if (!m_run_queue.empty())
|
||||
Processor::yield();
|
||||
}
|
||||
|
||||
extern "C" void scheduler_on_yield_trampoline(YieldRegisters* yield_registers)
|
||||
extern "C" void scheduler_on_yield(YieldRegisters* yield_registers)
|
||||
{
|
||||
Processor::scheduler().on_yield(yield_registers);
|
||||
Processor::scheduler().reschedule(yield_registers);
|
||||
}
|
||||
|
||||
void Scheduler::on_yield(YieldRegisters* yield_registers)
|
||||
{
|
||||
reschedule(yield_registers);
|
||||
m_next_reschedule_ns = !is_idle()
|
||||
? SystemTimer::get().ns_since_boot() + s_reschedule_interval_ns
|
||||
: BAN::numeric_limits<uint64_t>::max();
|
||||
update_wake_up_deadline();
|
||||
}
|
||||
|
||||
void Scheduler::on_timer_interrupt()
|
||||
void Scheduler::timer_interrupt()
|
||||
{
|
||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||
|
||||
@@ -368,8 +349,11 @@ namespace Kernel
|
||||
|
||||
wake_up_sleeping_threads();
|
||||
|
||||
if (is_idle() || SystemTimer::get().ns_since_boot() >= m_next_reschedule_ns)
|
||||
if (SystemTimer::get().ns_since_boot() >= m_next_reschedule_ns)
|
||||
{
|
||||
m_next_reschedule_ns += s_reschedule_interval_ns;
|
||||
Processor::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::unblock_thread(SchedulerQueue::Node* node)
|
||||
@@ -410,8 +394,8 @@ namespace Kernel
|
||||
|
||||
if (!node->blocked)
|
||||
m_run_queue.add_thread_to_back(node);
|
||||
else if (m_block_queue.add_thread_with_wake_time(node))
|
||||
update_wake_up_deadline();
|
||||
else
|
||||
m_block_queue.add_thread_with_wake_time(node);
|
||||
|
||||
if (auto* thread = node->thread; thread->is_userspace() && thread->has_process())
|
||||
thread->update_processor_index_address();
|
||||
|
||||
@@ -7,16 +7,6 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<AHCIController>> AHCIController::create(PCI::Device& pci_device)
|
||||
{
|
||||
auto* controller_ptr = new AHCIController(pci_device);
|
||||
if (controller_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto controller = BAN::RefPtr<AHCIController>::adopt(controller_ptr);
|
||||
TRY(controller->initialize());
|
||||
return controller;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> AHCIController::initialize()
|
||||
{
|
||||
m_abar = TRY(m_pci_device.allocate_bar_region(5));
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Kernel
|
||||
|
||||
static void select_delay()
|
||||
{
|
||||
SystemTimer::get().sleep_for_ns(400);
|
||||
SystemTimer::get().sleep_ns(400);
|
||||
}
|
||||
|
||||
void ATABus::select_device(bool is_secondary)
|
||||
@@ -87,7 +87,7 @@ namespace Kernel
|
||||
io_write(ATA_PORT_LBA1, 0);
|
||||
io_write(ATA_PORT_LBA2, 0);
|
||||
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY);
|
||||
SystemTimer::get().sleep_for_ms(1);
|
||||
SystemTimer::get().sleep_ms(1);
|
||||
|
||||
// No device on port
|
||||
if (io_read(ATA_PORT_STATUS) == 0)
|
||||
@@ -112,7 +112,7 @@ namespace Kernel
|
||||
}
|
||||
|
||||
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET);
|
||||
SystemTimer::get().sleep_for_ms(1);
|
||||
SystemTimer::get().sleep_ms(1);
|
||||
}
|
||||
|
||||
TRY(wait(true));
|
||||
|
||||
@@ -9,12 +9,29 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<ATAController>> ATAController::create(PCI::Device& pci_device)
|
||||
BAN::ErrorOr<BAN::RefPtr<StorageController>> ATAController::create(PCI::Device& pci_device)
|
||||
{
|
||||
auto* controller_ptr = new ATAController(pci_device);
|
||||
StorageController* controller_ptr = nullptr;
|
||||
|
||||
switch (pci_device.subclass())
|
||||
{
|
||||
case 0x01:
|
||||
controller_ptr = new ATAController(pci_device);
|
||||
break;
|
||||
case 0x05:
|
||||
dwarnln("unsupported DMA ATA Controller");
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
case 0x06:
|
||||
controller_ptr = new AHCIController(pci_device);
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
if (controller_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto controller = BAN::RefPtr<ATAController>::adopt(controller_ptr);
|
||||
|
||||
auto controller = BAN::RefPtr<StorageController>::adopt(controller_ptr);
|
||||
TRY(controller->initialize());
|
||||
return controller;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/BootInfo.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Memory/PageTable.h>
|
||||
#include <kernel/Storage/DiskCache.h>
|
||||
|
||||
@@ -16,12 +16,12 @@ namespace Kernel
|
||||
return minor++;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<NVMeController>> NVMeController::create(PCI::Device& pci_device)
|
||||
BAN::ErrorOr<BAN::RefPtr<StorageController>> NVMeController::create(PCI::Device& pci_device)
|
||||
{
|
||||
auto* controller_ptr = new NVMeController(pci_device);
|
||||
if (controller_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto controller = BAN::RefPtr<NVMeController>::adopt(controller_ptr);
|
||||
auto controller = BAN::RefPtr<StorageController>::adopt(controller_ptr);
|
||||
TRY(controller->initialize());
|
||||
return controller;
|
||||
}
|
||||
@@ -115,6 +115,8 @@ namespace Kernel
|
||||
|
||||
DevFileSystem::get().add_device(this);
|
||||
|
||||
StorageController::ref();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace Kernel
|
||||
slave->m_write_blocker.unblock();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> PseudoTerminalMaster::ioctl_impl(unsigned long request, void* argument)
|
||||
BAN::ErrorOr<long> PseudoTerminalMaster::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
@@ -174,7 +174,7 @@ namespace Kernel
|
||||
return BAN::Error::from_errno(ENODEV);
|
||||
}
|
||||
|
||||
return CharacterDevice::ioctl_impl(request, argument);
|
||||
return CharacterDevice::ioctl(request, argument);
|
||||
}
|
||||
|
||||
PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid)
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace Kernel
|
||||
(void)Process::kill(-m_foreground_pgrp, SIGWINCH);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> TTY::ioctl_impl(unsigned long request, void* argument)
|
||||
BAN::ErrorOr<long> TTY::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
@@ -204,7 +204,7 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
return CharacterDevice::ioctl_impl(request, argument);
|
||||
return CharacterDevice::ioctl(request, argument);
|
||||
}
|
||||
|
||||
void TTY::on_key_event(LibInput::RawKeyEvent event)
|
||||
@@ -449,14 +449,9 @@ namespace Kernel
|
||||
void TTY::putchar_current(uint8_t ch)
|
||||
{
|
||||
ASSERT(s_tty);
|
||||
|
||||
while (!s_tty->m_write_lock.try_lock())
|
||||
Processor::pause();
|
||||
|
||||
LockGuard _(s_tty->m_write_lock);
|
||||
s_tty->putchar(ch);
|
||||
s_tty->after_write();
|
||||
|
||||
s_tty->m_write_lock.unlock();
|
||||
}
|
||||
|
||||
bool TTY::is_initialized()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user