Compare commits

..

No commits in common. "39802b56c10158cc6093d42ccc75b6cd02303f33" and "b8622f2b4bfc8b7d6055db1d05bfa59cdb788aaa" have entirely different histories.

33 changed files with 153 additions and 275 deletions

View File

@ -47,27 +47,6 @@
#define BOCHS_BREAK() asm volatile("xchgw %bx, %bx")
#define DEBUG_PCI 0
#define DEBUG_SCHEDULER 0
#define DEBUG_PS2 1
#define DEBUG_ARP 0
#define DEBUG_IPV4 0
#define DEBUG_ETHERTYPE 0
#define DEBUG_TCP 0
#define DEBUG_E1000 0
#define DEBUG_DISK_SYNC 0
#define DEBUG_NVMe 0
#define DEBUG_XHCI 0
#define DEBUG_USB 0
#define DEBUG_USB_HID 0
#define DEBUG_USB_KEYBOARD 0
#define DEBUG_USB_MOUSE 0
namespace Debug
{
void dump_stack_trace();

View File

@ -160,7 +160,6 @@ namespace Kernel
BAN::WeakPtr<SharedFileData> m_shared_region;
friend class FileBackedRegion;
friend class SharedFileData;
friend class TTY;
};
}

View File

@ -171,7 +171,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
static BAN::ErrorOr<void> kill(pid_t pid, int signal);
BAN::ErrorOr<long> sys_kill(pid_t pid, int signal);
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);

View File

@ -82,8 +82,6 @@ namespace Kernel
void timer_interrupt();
static BAN::ErrorOr<void> bind_thread_to_processor(Thread*, ProcessorID);
// if thread is already bound, this will never fail
BAN::ErrorOr<void> add_thread(Thread*);
void block_current_thread(ThreadBlocker* thread_blocker, uint64_t wake_time_ns);

View File

@ -28,7 +28,6 @@ namespace Kernel
static BAN::RefPtr<TTY> current();
void set_as_current();
static void keyboard_task(void*);
static void initialize_devices();
void on_key_event(LibInput::KeyEvent);
void handle_input_byte(uint8_t);

View File

@ -32,7 +32,7 @@ namespace Kernel
public:
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*, Process*);
static BAN::ErrorOr<Thread*> create_userspace(Process*, PageTable&);
static BAN::ErrorOr<Thread*> create_userspace(Process*);
~Thread();
BAN::ErrorOr<Thread*> clone(Process*, uintptr_t sp, uintptr_t ip);
@ -49,11 +49,11 @@ namespace Kernel
bool add_signal(int signal);
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout
BAN::ErrorOr<void> sleep_or_eintr_ms(uint64_t ms) { ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(ms, 1'000'000)); return sleep_or_eintr_ns(ms * 1'000'000); }
BAN::ErrorOr<void> sleep_or_eintr_ms(uint64_t ms) { return sleep_or_eintr_ns(ms * 1'000'000); }
BAN::ErrorOr<void> sleep_or_eintr_ns(uint64_t ns);
BAN::ErrorOr<void> block_or_eintr_indefinite(ThreadBlocker& thread_blocker);
BAN::ErrorOr<void> block_or_eintr_or_timeout_ms(ThreadBlocker& thread_blocker, uint64_t timeout_ms, bool etimedout) { ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(timeout_ms, 1'000'000)); return block_or_eintr_or_timeout_ns(thread_blocker, timeout_ms * 1'000'000, etimedout); }
BAN::ErrorOr<void> block_or_eintr_or_waketime_ms(ThreadBlocker& thread_blocker, uint64_t wake_time_ms, bool etimedout) { ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(wake_time_ms, 1'000'000)); return block_or_eintr_or_waketime_ns(thread_blocker, wake_time_ms * 1'000'000, etimedout); }
BAN::ErrorOr<void> block_or_eintr_or_timeout_ms(ThreadBlocker& thread_blocker, uint64_t timeout_ms, bool etimedout) { return block_or_eintr_or_timeout_ns(thread_blocker, timeout_ms * 1'000'000, etimedout); }
BAN::ErrorOr<void> block_or_eintr_or_waketime_ms(ThreadBlocker& thread_blocker, uint64_t wake_time_ms, bool etimedout) { return block_or_eintr_or_waketime_ns(thread_blocker, wake_time_ms * 1'000'000, etimedout); }
BAN::ErrorOr<void> block_or_eintr_or_timeout_ns(ThreadBlocker& thread_blocker, uint64_t timeout_ns, bool etimedout);
BAN::ErrorOr<void> block_or_eintr_or_waketime_ns(ThreadBlocker& thread_blocker, uint64_t wake_time_ns, bool etimedout);
@ -72,8 +72,6 @@ namespace Kernel
static Thread& current();
static pid_t current_tid();
void give_keep_alive_page_table(BAN::UniqPtr<PageTable>&& page_table) { m_keep_alive_page_table = BAN::move(page_table); }
Process& process();
const Process& process() const;
bool has_process() const { return m_process; }
@ -101,10 +99,6 @@ namespace Kernel
void on_exit();
private:
// NOTE: this is the first member to force it being last destructed
// {kernel,userspace}_stack has to be destroyed before page table
BAN::UniqPtr<PageTable> m_keep_alive_page_table;
static constexpr size_t m_kernel_stack_size { PAGE_SIZE * 64 };
static constexpr size_t m_userspace_stack_size { PAGE_SIZE * 64 };
BAN::UniqPtr<VirtualRange> m_kernel_stack;

View File

@ -1,6 +1,5 @@
#pragma once
#include <BAN/Math.h>
#include <kernel/Lock/SpinLock.h>
#include <kernel/Scheduler.h>
@ -11,8 +10,8 @@ namespace Kernel
{
public:
void block_indefinite();
void block_with_timeout_ms(uint64_t timeout_ms) { ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(timeout_ms, 1'000'000)); return block_with_timeout_ns(timeout_ms * 1'000'000); }
void block_with_wake_time_ms(uint64_t wake_time_ms) { ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(wake_time_ms, 1'000'000)); return block_with_wake_time_ns(wake_time_ms * 1'000'000); }
void block_with_timeout_ms(uint64_t timeout_ms) { return block_with_timeout_ns(timeout_ms * 1'000'000); }
void block_with_wake_time_ms(uint64_t wake_time_ms) { return block_with_wake_time_ns(wake_time_ms * 1'000'000); }
void block_with_timeout_ns(uint64_t timeout_ns);
void block_with_wake_time_ns(uint64_t wake_time_ns);
void unblock();

View File

@ -43,7 +43,7 @@ namespace Kernel
virtual bool pre_scheduler_sleep_needs_lock() const override;
virtual void pre_scheduler_sleep_ns(uint64_t) override;
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_ms(uint64_t ms) const { return sleep_ns(ms * 1'000'000); }
void sleep_ns(uint64_t ns) const;
timespec real_time() const;

View File

@ -41,12 +41,6 @@ namespace Debug
BAN::Formatter::print(Debug::putchar, "\e[36mStack trace:\r\n");
while (frame)
{
if (!PageTable::is_valid_pointer((vaddr_t)frame))
{
derrorln("invalid pointer {H}", (vaddr_t)frame);
break;
}
if (PageTable::current().is_page_free((vaddr_t)frame & PAGE_ADDR_MASK))
{
derrorln(" {} not mapped", frame);

View File

@ -9,6 +9,8 @@
#include <kernel/IO.h>
#include <kernel/Timer/Timer.h>
#define DEBUG_PS2 1
namespace Kernel::Input
{

View File

@ -167,18 +167,13 @@ namespace Kernel
void ARPTable::add_arp_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
{
if (buffer.size() < sizeof(ARPPacket))
{
dwarnln_if(DEBUG_ARP, "ARP packet too small");
return;
}
auto& arp_packet = buffer.as<const ARPPacket>();
SpinLockGuard _(m_pending_lock);
if (m_pending_packets.full())
{
dwarnln_if(DEBUG_ARP, "ARP packet queue full");
dprintln("arp packet queue full");
return;
}

View File

@ -6,6 +6,8 @@
#include <kernel/Networking/E1000/E1000.h>
#include <kernel/Networking/NetworkManager.h>
#define DEBUG_E1000 1
namespace Kernel
{
@ -66,8 +68,10 @@ namespace Kernel
detect_eeprom();
TRY(read_mac_address());
#if DEBUG_E1000
dprintln("E1000 at PCI {}:{}.{}", m_pci_device.bus(), m_pci_device.dev(), m_pci_device.func());
dprintln(" MAC: {}", m_mac_address);
#endif
TRY(initialize_rx());
TRY(initialize_tx());
@ -77,12 +81,14 @@ namespace Kernel
m_link_up = !!(read32(REG_STATUS) & STATUS_LU);
#if DEBUG_E1000
dprintln(" link up: {}", link_up());
if (link_up())
{
int speed = link_speed();
dprintln(" link speed: {} Mbps", speed);
}
#endif
return {};
}
@ -279,8 +285,6 @@ namespace Kernel
while (descriptor.status == 0)
continue;
dprintln_if(DEBUG_E1000, "sent {} bytes", sizeof(EthernetHeader) + buffer.size());
return {};
}
@ -299,8 +303,6 @@ namespace Kernel
break;
ASSERT(descriptor.length <= E1000_RX_BUFFER_SIZE);
dprintln_if(DEBUG_E1000, "got {} bytes", (uint16_t)descriptor.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

View File

@ -9,6 +9,8 @@
#include <netinet/in.h>
#define DEBUG_IPV4 0
namespace Kernel
{
@ -116,9 +118,7 @@ namespace Kernel
return BAN::Error::from_errno(EAFNOSUPPORT);
auto& sockaddr_in = *reinterpret_cast<const struct sockaddr_in*>(address);
const uint16_t port = BAN::host_to_network_endian(sockaddr_in.sin_port);
if (port == NetworkSocket::PORT_NONE)
return bind_socket_to_unused(socket, address, address_len);
uint16_t port = BAN::host_to_network_endian(sockaddr_in.sin_port);
SpinLockGuard _(m_bound_socket_lock);
@ -201,7 +201,6 @@ namespace Kernel
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ByteSpan packet)
{
ASSERT(packet.size() >= sizeof(IPv4Header));
auto& ipv4_header = packet.as<const IPv4Header>();
auto ipv4_data = packet.slice(sizeof(IPv4Header));
@ -214,11 +213,6 @@ namespace Kernel
{
case NetworkProtocol::ICMP:
{
if (ipv4_data.size() < sizeof(ICMPHeader))
{
dwarnln("IPv4 packet too small for ICMP");
return {};
}
auto& icmp_header = ipv4_data.as<const ICMPHeader>();
switch (icmp_header.type)
{
@ -251,11 +245,6 @@ namespace Kernel
}
case NetworkProtocol::UDP:
{
if (ipv4_data.size() < sizeof(UDPHeader))
{
dwarnln("IPv4 packet too small for UDP");
return {};
}
auto& udp_header = ipv4_data.as<const UDPHeader>();
dst_port = udp_header.dst_port;
src_port = udp_header.src_port;
@ -263,11 +252,6 @@ namespace Kernel
}
case NetworkProtocol::TCP:
{
if (ipv4_data.size() < sizeof(TCPHeader))
{
dwarnln("IPv4 packet too small for TCP");
return {};
}
auto& tcp_header = ipv4_data.as<const TCPHeader>();
dst_port = tcp_header.dst_port;
src_port = tcp_header.src_port;
@ -338,7 +322,7 @@ namespace Kernel
const size_t ipv4_packet_size = reinterpret_cast<const IPv4Header*>(buffer_start)->total_length;
if (auto ret = handle_ipv4_packet(pending.interface, BAN::ByteSpan(buffer_start, ipv4_packet_size)); ret.is_error())
dwarnln_if(DEBUG_IPV4, "{}", ret.error());
dwarnln("{}", ret.error());
SpinLockGuard _(m_pending_lock);
m_pending_total_size -= ipv4_packet_size;
@ -349,38 +333,32 @@ namespace Kernel
void IPv4Layer::add_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
{
if (buffer.size() < sizeof(IPv4Header))
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet too small");
return;
}
SpinLockGuard _(m_pending_lock);
if (m_pending_packets.full())
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet queue full");
dwarnln("IPv4 packet queue full");
return;
}
if (m_pending_total_size + buffer.size() > m_pending_packet_buffer->size())
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet queue full");
dwarnln("IPv4 packet queue full");
return;
}
auto& ipv4_header = buffer.as<const IPv4Header>();
if (calculate_internet_checksum(BAN::ConstByteSpan::from(ipv4_header), {}) != 0)
{
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
dwarnln("Invalid IPv4 packet");
return;
}
if (ipv4_header.total_length > buffer.size() || ipv4_header.total_length > interface.payload_mtu())
{
if (ipv4_header.flags_frament & IPv4Flags::DF)
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
dwarnln("Invalid IPv4 packet");
else
dwarnln_if(DEBUG_IPV4, "IPv4 fragmentation not supported");
dwarnln("IPv4 fragmentation not supported");
return;
}

View File

@ -10,6 +10,8 @@
#include <kernel/Networking/UDPSocket.h>
#include <kernel/Networking/UNIX/Socket.h>
#define DEBUG_ETHERTYPE 0
namespace Kernel
{

View File

@ -7,6 +7,8 @@
#include <fcntl.h>
#include <netinet/in.h>
#define DEBUG_TCP 0
namespace Kernel
{

View File

@ -27,6 +27,8 @@
#define PCI_CMD_BUS_MASTER (1 << 2)
#define PCI_CMD_INTERRUPT_DISABLE (1 << 10)
#define DEBUG_PCI 0
namespace Kernel::PCI
{

View File

@ -168,7 +168,7 @@ namespace Kernel
process->m_userspace_info.argv = argv;
process->m_userspace_info.envp = nullptr;
auto* thread = MUST(Thread::create_userspace(process, process->page_table()));
auto* thread = MUST(Thread::create_userspace(process));
process->add_thread(thread);
process->register_to_scheduler();
return process;
@ -477,13 +477,10 @@ namespace Kernel
{
LockGuard _(m_process_lock);
auto new_page_table = BAN::UniqPtr<PageTable>::adopt(TRY(PageTable::create_userspace()));
TRY(validate_string_access(path));
auto absolute_path = TRY(absolute_path_of(path));
auto executable_file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_EXEC));
auto executable_inode = executable_file.inode;
auto executable_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_EXEC)).inode;
BAN::Vector<BAN::String> str_argv;
for (int i = 0; argv && argv[i]; i++)
@ -501,18 +498,35 @@ namespace Kernel
TRY(str_envp.emplace_back(envp[i]));
}
auto executable = TRY(ELF::load_from_inode(executable_inode, m_credentials, *new_page_table));
auto new_mapped_regions = BAN::move(executable.regions);
m_open_file_descriptors.close_cloexec();
int file_fd = -1;
m_mapped_regions.clear();
auto executable = TRY(ELF::load_from_inode(executable_inode, m_credentials, page_table()));
m_mapped_regions = BAN::move(executable.regions);
if (executable_inode->mode().mode & +Inode::Mode::ISUID)
m_credentials.set_euid(executable_inode->uid());
if (executable_inode->mode().mode & +Inode::Mode::ISGID)
m_credentials.set_egid(executable_inode->gid());
m_userspace_info.entry = executable.entry_point;
if (executable.has_interpreter)
{
VirtualFileSystem::File file;
file.canonical_path = BAN::move(executable_file.canonical_path);
TRY(file.canonical_path.append("<self>"));
file.inode = executable_inode;
file_fd = TRY(m_open_file_descriptors.open(BAN::move(file), O_RDONLY));
m_userspace_info.file_fd = TRY(m_open_file_descriptors.open(BAN::move(file), O_RDONLY));
}
BAN::ScopeGuard file_closer([&] { if (file_fd != -1) MUST(m_open_file_descriptors.close(file_fd)); });
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
{
m_signal_handlers[i].sa_handler = SIG_DFL;
m_signal_handlers[i].sa_flags = 0;
}
ASSERT(m_threads.size() == 1);
ASSERT(&Process::current() == this);
// allocate memory on the new process for arguments and environment
auto create_region =
@ -526,9 +540,9 @@ namespace Kernel
bytes += PAGE_SIZE - rem;
auto region = TRY(MemoryBackedRegion::create(
*new_page_table,
page_table(),
bytes,
{ .start = executable.entry_point, .end = KERNEL_OFFSET },
{ .start = m_userspace_info.entry, .end = KERNEL_OFFSET },
MemoryRegion::Type::PRIVATE,
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present
));
@ -548,62 +562,20 @@ namespace Kernel
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
};
TRY(new_mapped_regions.reserve(new_mapped_regions.size() + 2));
MUST(new_mapped_regions.push_back(TRY(create_region(str_argv.span()))));
MUST(new_mapped_regions.push_back(TRY(create_region(str_envp.span()))));
auto argv_region = MUST(create_region(str_argv.span()));
m_userspace_info.argv = (char**)argv_region->vaddr();
MUST(m_mapped_regions.push_back(BAN::move(argv_region)));
auto* new_thread = TRY(Thread::create_userspace(this, *new_page_table));
ASSERT(Processor::get_interrupt_state() == InterruptState::Enabled);
Processor::set_interrupt_state(InterruptState::Disabled);
// NOTE: bind new thread to this processor so it wont be rescheduled before end of this function
if (auto ret = Scheduler::bind_thread_to_processor(new_thread, Processor::current_id()); ret.is_error())
{
Processor::set_interrupt_state(InterruptState::Enabled);
return ret.release_error();
}
// after this point, everything is initialized and nothing can fail!
ASSERT(m_threads.size() == 1);
ASSERT(&Thread::current() == m_threads.front());
// Make current thread standalone and terminated
// We need to give it the current page table to keep it alive
// while its kernel stack is in use
m_threads.front()->m_state = Thread::State::Terminated;
m_threads.front()->m_process = nullptr;
m_threads.front()->give_keep_alive_page_table(BAN::move(m_page_table));
m_threads.front() = new_thread;
MUST(Processor::scheduler().add_thread(m_threads.front()));
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
{
m_signal_handlers[i].sa_handler = SIG_DFL;
m_signal_handlers[i].sa_flags = 0;
}
if (executable_inode->mode().mode & +Inode::Mode::ISUID)
m_credentials.set_euid(executable_inode->uid());
if (executable_inode->mode().mode & +Inode::Mode::ISGID)
m_credentials.set_egid(executable_inode->gid());
m_open_file_descriptors.close_cloexec();
m_mapped_regions = BAN::move(new_mapped_regions);
m_page_table = BAN::move(new_page_table);
file_closer.disable();
auto envp_region = MUST(create_region(str_envp.span()));
m_userspace_info.envp = (char**)envp_region->vaddr();
MUST(m_mapped_regions.push_back(BAN::move(envp_region)));
m_userspace_info.argc = str_argv.size();
m_userspace_info.argv = reinterpret_cast<char**>(m_mapped_regions[m_mapped_regions.size() - 2]->vaddr());
m_userspace_info.envp = reinterpret_cast<char**>(m_mapped_regions[m_mapped_regions.size() - 1]->vaddr());
m_userspace_info.entry = executable.entry_point;
m_userspace_info.file_fd = file_fd;
m_cmdline = BAN::move(str_argv);
m_environ = BAN::move(str_envp);
Processor::set_interrupt_state(InterruptState::Disabled);
}
m_has_called_exec = true;
@ -1875,13 +1847,20 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<void> Process::kill(pid_t pid, int signal)
BAN::ErrorOr<long> Process::sys_kill(pid_t pid, int signal)
{
if (pid == 0 || pid == -1)
return BAN::Error::from_errno(ENOTSUP);
if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX))
return BAN::Error::from_errno(EINVAL);
if (pid == m_pid)
{
if (signal)
add_pending_signal(signal);
return 0;
}
bool found = false;
for_each_process(
[&](Process& process)
@ -1901,26 +1880,8 @@ namespace Kernel
);
if (found)
return {};
return BAN::Error::from_errno(ESRCH);
}
BAN::ErrorOr<long> Process::sys_kill(pid_t pid, int signal)
{
if (pid == 0 || pid == -1)
return BAN::Error::from_errno(ENOTSUP);
if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX))
return BAN::Error::from_errno(EINVAL);
if (pid == m_pid)
{
if (signal)
add_pending_signal(signal);
return 0;
}
TRY(kill(pid, signal));
return 0;
return BAN::Error::from_errno(ESRCH);
}
BAN::ErrorOr<long> Process::sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact)

View File

@ -6,6 +6,7 @@
#include <kernel/Thread.h>
#include <kernel/Timer/Timer.h>
#define DEBUG_SCHEDULER 0
#define SCHEDULER_ASSERT 1
#define SCHEDULER_LOAD_BALANCE 0
@ -567,37 +568,25 @@ namespace Kernel
}
#endif
BAN::ErrorOr<void> Scheduler::bind_thread_to_processor(Thread* thread, ProcessorID processor_id)
BAN::ErrorOr<void> Scheduler::add_thread(Thread* thread)
{
ASSERT(thread->m_scheduler_node == nullptr);
auto* new_node = new SchedulerQueue::Node(thread);
if (new_node == nullptr)
return BAN::Error::from_errno(ENOMEM);
ASSERT(processor_id != PROCESSOR_NONE);
const size_t processor_index = s_next_processor_index++ % Processor::count();
const auto processor_id = Processor::id_from_index(processor_index);
new_node->processor_id = processor_id;
thread->m_scheduler_node = new_node;
return {};
}
BAN::ErrorOr<void> Scheduler::add_thread(Thread* thread)
{
if (thread->m_scheduler_node == nullptr)
{
const size_t processor_index = s_next_processor_index++ % Processor::count();
const auto processor_id = Processor::id_from_index(processor_index);
TRY(bind_thread_to_processor(thread, processor_id));
}
auto* node = thread->m_scheduler_node;
if (node->processor_id == Processor::current_id())
add_thread(node);
if (processor_id == Processor::current_id())
add_thread(new_node);
else
{
Processor::send_smp_message(node->processor_id, {
Processor::send_smp_message(processor_id, {
.type = Processor::SMPMessage::Type::NewThread,
.new_thread = node
.new_thread = new_node
});
}

View File

@ -4,6 +4,8 @@
#include <kernel/Storage/DiskCache.h>
#include <kernel/Storage/StorageDevice.h>
#define DEBUG_SYNC 0
namespace Kernel
{
@ -125,7 +127,7 @@ namespace Kernel
sector_start++;
else
{
dprintln_if(DEBUG_DISK_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
dprintln_if(DEBUG_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size);
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
sector_start += sector_count + 1;
@ -135,7 +137,7 @@ namespace Kernel
if (sector_count > 0)
{
dprintln_if(DEBUG_DISK_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
dprintln_if(DEBUG_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size);
TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
}

View File

@ -7,6 +7,8 @@
#include <sys/sysmacros.h>
#define DEBUG_NVMe 1
namespace Kernel
{
@ -63,8 +65,8 @@ namespace Kernel
return BAN::Error::from_errno(ENOTSUP);
}
dprintln("NVMe controller");
dprintln(" version: {}.{}", (uint16_t)vs.major, (uint8_t)vs.minor);
dprintln_if(DEBUG_NVMe, "NVMe controller");
dprintln_if(DEBUG_NVMe, " version: {}.{}", (uint16_t)vs.major, (uint8_t)vs.minor);
auto& cap = m_controller_registers->cap;
if (!(cap.css & NVMe::CAP_CSS_NVME))
@ -158,7 +160,7 @@ namespace Kernel
return BAN::Error::from_errno(EFAULT);
}
dprintln(" model: '{}'", BAN::StringView { (char*)dma_page->vaddr() + 24, 20 });
dprintln_if(DEBUG_NVMe, " model: '{}'", BAN::StringView { (char*)dma_page->vaddr() + 24, 20 });
return {};
}

View File

@ -59,10 +59,7 @@ namespace Kernel
else if (syscall == SYS_FORK)
ret = sys_fork_trampoline();
else
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wmaybe-uninitialized"
ret = (Process::current().*s_syscall_handlers[syscall])(arg1, arg2, arg3, arg4, arg5);
#pragma GCC diagnostic pop
asm volatile("cli");

View File

@ -8,7 +8,6 @@
#include <kernel/Lock/LockGuard.h>
#include <kernel/Process.h>
#include <kernel/Terminal/TTY.h>
#include <kernel/Timer/Timer.h>
#include <LibInput/KeyboardLayout.h>
#include <fcntl.h>
@ -96,47 +95,35 @@ namespace Kernel
return {};
}
void TTY::keyboard_task(void*)
{
BAN::RefPtr<Inode> keyboard_inode;
if (auto ret = VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/keyboard"_sv, O_RDONLY); !ret.is_error())
keyboard_inode = ret.value().inode;
else
{
dprintln("could not open keyboard device: {}", ret.error());
return;
}
while (true)
{
while (!TTY::current()->m_tty_ctrl.receive_input)
TTY::current()->m_tty_ctrl.thread_blocker.block_indefinite();
while (TTY::current()->m_tty_ctrl.receive_input)
{
LockGuard _(keyboard_inode->m_mutex);
if (!keyboard_inode->can_read())
{
SystemTimer::get().sleep_ms(1);
continue;
}
LibInput::RawKeyEvent event;
[[maybe_unused]] const size_t read = MUST(keyboard_inode->read(0, BAN::ByteSpan::from(event)));
ASSERT(read == sizeof(event));
TTY::current()->on_key_event(LibInput::KeyboardLayout::get().key_event_from_raw(event));
}
}
}
void TTY::initialize_devices()
{
static bool initialized = false;
ASSERT(!initialized);
auto* thread = MUST(Thread::create_kernel(&TTY::keyboard_task, nullptr, nullptr));
MUST(Processor::scheduler().add_thread(thread));
Process::create_kernel(
[](void*)
{
auto file_or_error = VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/keyboard"_sv, O_RDONLY);
if (file_or_error.is_error())
{
dprintln("no keyboard found");
return;
}
auto inode = file_or_error.value().inode;
while (true)
{
while (!TTY::current()->m_tty_ctrl.receive_input)
TTY::current()->m_tty_ctrl.thread_blocker.block_indefinite();
LibInput::RawKeyEvent event;
size_t read = MUST(inode->read(0, BAN::ByteSpan::from(event)));
ASSERT(read == sizeof(event));
TTY::current()->on_key_event(LibInput::KeyboardLayout::get().key_event_from_raw(event));
}
}, nullptr
);
initialized = true;
}
@ -273,7 +260,7 @@ namespace Kernel
// ^C
if (ch == '\x03')
{
if (auto ret = Process::kill(-m_foreground_pgrp, SIGINT); ret.is_error())
if (auto ret = Process::current().sys_kill(-m_foreground_pgrp, SIGINT); ret.is_error())
dwarnln("TTY: {}", ret.error());
return;
}

View File

@ -74,7 +74,7 @@ namespace Kernel
return thread;
}
BAN::ErrorOr<Thread*> Thread::create_userspace(Process* process, PageTable& page_table)
BAN::ErrorOr<Thread*> Thread::create_userspace(Process* process)
{
ASSERT(process);
@ -87,7 +87,7 @@ namespace Kernel
thread->m_is_userspace = true;
thread->m_kernel_stack = TRY(VirtualRange::create_to_vaddr_range(
page_table,
process->page_table(),
0x300000, KERNEL_OFFSET,
m_kernel_stack_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
@ -95,7 +95,7 @@ namespace Kernel
));
thread->m_userspace_stack = TRY(VirtualRange::create_to_vaddr_range(
page_table,
process->page_table(),
0x300000, KERNEL_OFFSET,
m_userspace_stack_size,
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,

View File

@ -2,6 +2,7 @@
#include <kernel/USB/Device.h>
#include <kernel/USB/HID/HIDDriver.h>
#define DEBUG_USB 0
#define USB_DUMP_DESCRIPTORS 0
namespace Kernel

View File

@ -5,6 +5,7 @@
#include <kernel/USB/HID/Keyboard.h>
#include <kernel/USB/HID/Mouse.h>
#define DEBUG_HID 0
#define DUMP_HID_REPORT 0
namespace Kernel
@ -134,12 +135,12 @@ namespace Kernel
}
const auto& hid_descriptor = *reinterpret_cast<const HIDDescriptor*>(m_interface.misc_descriptors[hid_descriptor_index].data());
dprintln_if(DEBUG_USB_HID, "HID descriptor ({} bytes)", m_interface.misc_descriptors[hid_descriptor_index].size());
dprintln_if(DEBUG_USB_HID, " bLength: {}", hid_descriptor.bLength);
dprintln_if(DEBUG_USB_HID, " bDescriptorType: {}", hid_descriptor.bDescriptorType);
dprintln_if(DEBUG_USB_HID, " bcdHID: {H}.{2H}", hid_descriptor.bcdHID >> 8, hid_descriptor.bcdHID & 0xFF);
dprintln_if(DEBUG_USB_HID, " bCountryCode: {}", hid_descriptor.bCountryCode);
dprintln_if(DEBUG_USB_HID, " bNumDescriptors: {}", hid_descriptor.bNumDescriptors);
dprintln_if(DEBUG_HID, "HID descriptor ({} bytes)", m_interface.misc_descriptors[hid_descriptor_index].size());
dprintln_if(DEBUG_HID, " bLength: {}", hid_descriptor.bLength);
dprintln_if(DEBUG_HID, " bDescriptorType: {}", hid_descriptor.bDescriptorType);
dprintln_if(DEBUG_HID, " bcdHID: {H}.{2H}", hid_descriptor.bcdHID >> 8, hid_descriptor.bcdHID & 0xFF);
dprintln_if(DEBUG_HID, " bCountryCode: {}", hid_descriptor.bCountryCode);
dprintln_if(DEBUG_HID, " bNumDescriptors: {}", hid_descriptor.bNumDescriptors);
uint32_t report_descriptor_index = 0;
BAN::Vector<Collection> collections;
@ -149,7 +150,7 @@ namespace Kernel
if (static_cast<HIDDescriptorType>(descriptor.bDescriptorType) != HIDDescriptorType::Report)
{
dprintln_if(DEBUG_USB_HID, "Skipping HID descriptor type 0x{2H}", descriptor.bDescriptorType);
dprintln_if(DEBUG_HID, "Skipping HID descriptor type 0x{2H}", descriptor.bDescriptorType);
continue;
}
@ -175,7 +176,7 @@ namespace Kernel
}
}
dprintln_if(DEBUG_USB_HID, "Parsing {} byte report descriptor", +descriptor.wItemLength);
dprintln_if(DEBUG_HID, "Parsing {} byte report descriptor", +descriptor.wItemLength);
auto report_data = BAN::ConstByteSpan(reinterpret_cast<uint8_t*>(dma_buffer->vaddr()), descriptor.wItemLength);
auto new_collections = TRY(parse_report_descriptor(report_data, m_uses_report_id));
@ -274,7 +275,7 @@ namespace Kernel
return;
}
if constexpr(DEBUG_USB_HID)
if constexpr(DEBUG_HID)
{
const auto nibble_to_hex = [](uint8_t x) -> char { return x + (x < 10 ? '0' : 'A' - 10); };
@ -288,7 +289,7 @@ namespace Kernel
}
*ptr = '\0';
dprintln_if(DEBUG_USB_HID, "Received {} bytes from endpoint {}: {}", data.size(), endpoint_id, buffer);
dprintln_if(DEBUG_HID, "Received {} bytes from endpoint {}: {}", data.size(), endpoint_id, buffer);
}
const auto extract_bits =

View File

@ -2,6 +2,8 @@
#include <kernel/USB/HID/Keyboard.h>
#include <LibInput/KeyEvent.h>
#define DEBUG_KEYBOARD 0
namespace Kernel
{
@ -64,7 +66,7 @@ namespace Kernel
const bool pressed = m_keyboard_state_temp[i];
if (pressed)
dprintln_if(DEBUG_USB_KEYBOARD, "Pressed {2H}", i);
dprintln_if(DEBUG_KEYBOARD, "Pressed {2H}", i);
auto opt_keycode = s_scancode_to_keycode[i];
if (opt_keycode.has_value())
@ -100,7 +102,7 @@ namespace Kernel
if (usage_page != 0x07)
{
dprintln_if(DEBUG_USB_KEYBOARD, "Unsupported keyboard usage page {2H}", usage_page);
dprintln_if(DEBUG_KEYBOARD, "Unsupported keyboard usage page {2H}", usage_page);
return;
}
if (!state)
@ -115,7 +117,7 @@ namespace Kernel
if (usage_page != 0x07)
{
dprintln_if(DEBUG_USB_KEYBOARD, "Unsupported keyboard usage page {2H}", usage_page);
dprintln_if(DEBUG_KEYBOARD, "Unsupported keyboard usage page {2H}", usage_page);
return;
}
if (usage >= 4 && usage < m_keyboard_state_temp.size())

View File

@ -1,6 +1,8 @@
#include <kernel/USB/HID/Mouse.h>
#include <LibInput/MouseEvent.h>
#define DEBUG_MOUSE 0
namespace Kernel
{
@ -14,7 +16,7 @@ namespace Kernel
{
if (m_pointer_x || m_pointer_y)
{
dprintln_if(DEBUG_USB_MOUSE, "Mouse move event {}, {}", m_pointer_x, m_pointer_y);
dprintln_if(DEBUG_MOUSE, "Mouse move event {}, {}", m_pointer_x, m_pointer_y);
LibInput::MouseEvent event;
event.type = LibInput::MouseEventType::MouseMoveEvent;
@ -28,7 +30,7 @@ namespace Kernel
if (m_wheel)
{
dprintln_if(DEBUG_USB_MOUSE, "Mouse scroll event {}", m_wheel);
dprintln_if(DEBUG_MOUSE, "Mouse scroll event {}", m_wheel);
LibInput::MouseEvent event;
event.type = LibInput::MouseEventType::MouseScrollEvent;
@ -45,7 +47,7 @@ namespace Kernel
const bool pressed = m_button_state_temp[i];
dprintln_if(DEBUG_USB_MOUSE, "Mouse button event {}: {}", i, pressed);
dprintln_if(DEBUG_MOUSE, "Mouse button event {}: {}", i, pressed);
LibInput::MouseEvent event;
event.type = LibInput::MouseEventType::MouseButtonEvent;
@ -74,7 +76,7 @@ namespace Kernel
m_wheel = state;
break;
default:
dprintln_if(DEBUG_USB_MOUSE, "Unsupported mouse usage {2H} on page {2H}", usage, usage_page);
dprintln_if(DEBUG_MOUSE, "Unsupported mouse usage {2H} on page {2H}", usage, usage_page);
break;
}
break;
@ -84,14 +86,14 @@ namespace Kernel
m_button_state_temp[usage - 1] = state;
break;
default:
dprintln_if(DEBUG_USB_MOUSE, "Unsupported mouse usage page {2H}", usage_page);
dprintln_if(DEBUG_MOUSE, "Unsupported mouse usage page {2H}", usage_page);
break;
}
}
void USBMouse::handle_array(uint16_t usage_page, uint16_t usage)
{
dprintln_if(DEBUG_USB_MOUSE, "Unhandled array report {2H}:{2H}", usage_page, usage);
dprintln_if(DEBUG_MOUSE, "Unhandled array report {2H}:{2H}", usage_page, usage);
}
}

View File

@ -7,6 +7,8 @@
#include <kernel/USB/XHCI/Controller.h>
#include <kernel/USB/XHCI/Device.h>
#define DEBUG_XHCI 0
namespace Kernel
{

View File

@ -5,6 +5,8 @@
#include <kernel/Timer/Timer.h>
#include <kernel/USB/XHCI/Device.h>
#define DEBUG_XHCI 0
namespace Kernel
{

View File

@ -75,11 +75,6 @@ extern "C"
builtin_check_kind kind;
};
struct unreachable_data
{
struct source_location location;
};
using value_handle = uintptr_t;
static const char* type_check_kinds[] = {
@ -119,8 +114,6 @@ extern "C"
HANDLER(__ubsan_handle_invalid_builtin, false, invalid_builtin_data* data);
HANDLER(__ubsan_handle_builtin_unreachable, true, unreachable_data* data);
void __ubsan_handle_type_mismatch_v1(type_mismatch_data* data, value_handle pointer)
{
print_location(data->location);

View File

@ -19,8 +19,6 @@ foreach(library ${USERSPACE_LIBRARIES})
add_dependencies(libraries ${library_lower})
# This is to allow cmake to link when libc updates
target_link_options(${library_lower} PRIVATE -nolibc)
# Default compile options
target_compile_options(${library_lower} PRIVATE -g -O2)
target_compile_definitions(${library_lower} PRIVATE __enable_sse=${BANAN_ENABLE_SSE})
if (NOT BANAN_ENABLE_SSE)

View File

@ -5,6 +5,7 @@ set(LIBIMAGE_SOURCES
)
add_library(libimage ${LIBIMAGE_SOURCES})
target_compile_options(libimage PRIVATE -O3)
banan_link_library(libimage libc)
banan_link_library(libimage ban)

View File

@ -518,14 +518,8 @@ Rectangle Terminal::putchar(uint8_t ch)
m_cursor.y++;
}
if (m_cursor.y >= rows())
{
const uint32_t scroll = m_cursor.y - rows() + 1;
m_cursor.y -= scroll;
m_window->shift_vertical(-scroll * (int32_t)m_font.height());
m_window->fill_rect(0, m_window->height() - scroll * m_font.height(), m_window->width(), scroll * m_font.height(), m_bg_color);
should_invalidate = { 0, 0, m_window->width(), m_window->height() };
}
// scrolling is already handled in `read_shell()`
ASSERT(m_cursor.y < rows());
return should_invalidate;
}