Squash commits for public release

This commit is contained in:
2025-02-12 09:54:05 -05:00
commit 7118adc514
1108 changed files with 80873 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
#ifndef _KERNEL_TASKING_BITS_DUMP_H
#define _KERNEL_TASKING_BITS_DUMP_H
#include <libkern/types.h>
#include <tasking/proc.h>
typedef int (*dump_saver_t)(const char*);
typedef ssize_t (*sym_resolver_t)(void* symtab, size_t syms_n, uintptr_t tp);
struct dump_data {
proc_t* p;
uintptr_t entry_point;
void* syms;
size_t symsn;
char* strs;
dump_saver_t writer;
sym_resolver_t sym_resolver;
};
typedef struct dump_data dump_data_t;
#endif // _KERNEL_TASKING_BITS_DUMP_H

View File

@@ -0,0 +1,29 @@
#ifndef _KERNEL_TASKING_BITS_SCHED_H
#define _KERNEL_TASKING_BITS_SCHED_H
#define MAX_PRIO 0
#define MIN_PRIO 11
#define IDLE_PRIO (MIN_PRIO + 1)
#define PROC_PRIOS_COUNT (MIN_PRIO - MAX_PRIO + 1)
#define TOTAL_PRIOS_COUNT (IDLE_PRIO - MAX_PRIO + 1)
#define DEFAULT_PRIO 6
#define SCHED_INT 10
#define LAST_CPU_NOT_SET 0xffff
struct thread;
struct runqueue {
struct thread* head;
struct thread* tail;
};
typedef struct runqueue runqueue_t;
struct sched_data {
int next_read_prio;
runqueue_t* master_buf;
runqueue_t* slave_buf;
int enqueued_tasks;
};
typedef struct sched_data sched_data_t;
#endif // _KERNEL_TASKING_BITS_SCHED_H

View File

@@ -0,0 +1,45 @@
#ifndef _KERNEL_TASKING_CPU_H
#define _KERNEL_TASKING_CPU_H
#include <platform/generic/cpu.h>
#include <platform/generic/fpu/fpu.h>
#include <tasking/bits/sched.h>
#include <tasking/proc.h>
#include <tasking/thread.h>
#define RUNNING_THREAD (THIS_CPU->running_thread)
static inline cpu_state_t cpu_enter_kernel_space()
{
cpu_state_t prev = THIS_CPU->current_state;
THIS_CPU->current_state = CPU_IN_KERNEL;
return prev;
}
static inline cpu_state_t cpu_get_state()
{
return THIS_CPU->current_state;
}
static inline void cpu_set_state(cpu_state_t state)
{
THIS_CPU->current_state = state;
}
static inline void cpu_enter_user_space()
{
THIS_CPU->current_state = CPU_IN_USERLAND;
}
static inline void cpu_tick()
{
if (!THIS_CPU->running_thread) {
THIS_CPU->stat_system_and_idle_ticks++;
} else if (THIS_CPU->running_thread->process->is_kthread) {
THIS_CPU->stat_system_and_idle_ticks++;
} else {
THIS_CPU->stat_user_ticks++;
}
}
#endif // _KERNEL_TASKING_CPU_H

View File

@@ -0,0 +1,12 @@
#ifndef _KERNEL_TASKING_DUMP_H
#define _KERNEL_TASKING_DUMP_H
#include <platform/generic/tasking/trapframe.h>
#include <tasking/proc.h>
void dump_and_kill(proc_t* p);
int dump_prepare_kernel_data();
int dump_kernel(const char* err);
int dump_kernel_from_tf(const char* err, trapframe_t* tf);
#endif // _KERNEL_TASKING_DUMP_H

View File

@@ -0,0 +1,270 @@
#ifndef _KERNEL_TASKING_ELF_H
#define _KERNEL_TASKING_ELF_H
#define ELF_CLASS_32 1
#define ELF_CLASS_64 2
#define ELF_DATA2_LSB 1
#define ELF_DATA2_MSB 2
enum E_IDENT_FIELDS {
EI_MAG0,
EI_MAG1,
EI_MAG2,
EI_MAG3,
EI_CLASS,
EI_DATA,
EI_VERSION,
EI_OSABI,
EI_ABIVERSION,
};
enum E_TYPE_FIELDS {
ET_NONE,
ET_REL,
ET_EXEC,
ET_DYN,
ET_CORE,
};
enum E_MACHINE_FIELDS {
EM_NONE = 0x0,
EM_386 = 0x03,
EM_ARM = 0x28,
EM_AMD64 = 0x3e,
EM_AARCH64 = 0xB7,
EM_RISCV = 0xF3,
};
typedef struct {
uint8_t e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint32_t e_entry;
uint32_t e_phoff;
uint32_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} elf_header_32_t;
typedef struct {
uint8_t e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} elf_header_64_t;
enum P_TYPE_FIELDS {
PT_NULL,
PT_LOAD,
PT_DYNAMIC,
PT_INTERP,
PT_NOTE,
PT_SHLIB,
PT_PHDR,
PT_TLS,
PT_LOOS = 0x60000000,
PT_HIOS = 0x6FFFFFFF,
PT_LOPROC = 0x70000000,
PT_HIPROC = 0x7FFFFFFF,
};
enum P_FLAGS_FIELDS {
PF_X = 0x1,
PF_W = 0x2,
PF_R = 0x4,
PF_MASKPROC = 0xf0000000,
};
typedef struct {
uint32_t p_type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
} elf_program_header_32_t;
typedef struct {
uint32_t p_type;
uint32_t p_flags;
uint64_t p_offset;
uint64_t p_vaddr;
uint64_t p_paddr;
uint64_t p_filesz;
uint64_t p_memsz;
uint64_t p_align;
} elf_program_header_64_t;
enum SH_TYPE_FIELDS {
SHT_NULL,
SHT_PROGBITS,
SHT_SYMTAB,
SHT_STRTAB,
SHT_RELA,
SHT_HASH,
SHT_DYNAMIC,
SHT_NOTE,
SHT_NOBITS,
SHT_REL,
SHT_SHLIB,
SHT_DYNSYM,
SHT_INIT_ARRAY,
SHT_FINI_ARRAY,
SHT_PREINIT_ARRAY,
SHT_GROUP,
SHT_SYMTAB_SHNDX,
SHT_LOOS = 1610612736,
SHT_HIOS = 1879048191,
SHT_LOPROC = 1879048192,
SHT_HIPROC = 2147483647,
SHT_LOUSER = 2147483648,
SHT_HIUSER = 4294967295,
};
enum SH_FLAGS_FIELDS {
SHF_WRITE = 0x1,
SHF_ALLOC = 0x2,
SHF_EXECINSTR = 0x4,
SHF_MERGE = 0x10,
SHF_STRINGS = 0x20,
SHF_INFO_LINK = 0x40,
SHF_LINK_ORDER = 0x80,
SHF_OS_NONCONFORMING = 0x100,
SHF_GROUP = 0x200,
SHF_TLS = 0x400,
SHF_COMPRESSED = 0x800,
SHF_MASKOS = 0x0ff00000,
SHF_MASKPROC = 0xf0000000
};
typedef struct {
uint32_t sh_name;
uint32_t sh_type;
uint32_t sh_flags;
uint32_t sh_addr;
uint32_t sh_offset;
uint32_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint32_t sh_addralign;
uint32_t sh_entsize;
} elf_section_header_32_t;
typedef struct {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
} elf_section_header_64_t;
typedef struct {
uint32_t st_name; // name - index into string table
uint32_t st_value; // symbol value
uint32_t st_size; // symbol size
uint8_t st_info; // type and binding
uint8_t st_other; // 0 - no defined meaning
uint16_t st_shndx; // section header index
} elf_sym_32_t;
typedef struct {
uint32_t st_name;
uint8_t st_info;
uint8_t st_other;
uint16_t st_shndx;
uint64_t st_value;
uint64_t st_size;
} elf_sym_64_t;
enum ST_BINDING_FIELDS {
STB_LOCAL = 0,
STB_GLOBAL = 1,
STB_WEAK = 2,
STB_NUM = 3,
STB_LOPROC = 13,
STB_HIPROC = 15
};
enum ST_TYPE_FIELDS {
STT_NOTYPE = 0,
STT_OBJECT = 1,
STT_FUNC = 2,
STT_SECTION = 3,
STT_FILE = 4,
STT_TLS = 6,
STT_LOPROC = 13,
STT_HIPROC = 15
};
struct proc;
struct file_descriptor;
#ifdef __i386__
#define MACHINE_ARCH EM_386
typedef elf_header_32_t elf_header_t;
typedef elf_section_header_32_t elf_section_header_t;
typedef elf_program_header_32_t elf_program_header_t;
typedef elf_sym_32_t elf_sym_t;
#define USER_STACK_SIZE (16 << 10) // 16KB
#elif __x86_64__
#define MACHINE_ARCH EM_AMD64
typedef elf_header_64_t elf_header_t;
typedef elf_section_header_64_t elf_section_header_t;
typedef elf_program_header_64_t elf_program_header_t;
typedef elf_sym_64_t elf_sym_t;
#define USER_STACK_SIZE (4 << 20) // 4MB
#elif __arm__
#define MACHINE_ARCH EM_ARM
typedef elf_header_32_t elf_header_t;
typedef elf_section_header_32_t elf_section_header_t;
typedef elf_program_header_32_t elf_program_header_t;
typedef elf_sym_32_t elf_sym_t;
#define USER_STACK_SIZE (16 << 10) // 16KB
#elif __aarch64__
#define MACHINE_ARCH EM_AARCH64
typedef elf_header_64_t elf_header_t;
typedef elf_section_header_64_t elf_section_header_t;
typedef elf_program_header_64_t elf_program_header_t;
typedef elf_sym_64_t elf_sym_t;
#define USER_STACK_SIZE (4 << 20) // 4MB
#elif defined(__riscv) && (__riscv_xlen == 64)
#define MACHINE_ARCH EM_RISCV
typedef elf_header_64_t elf_header_t;
typedef elf_section_header_64_t elf_section_header_t;
typedef elf_program_header_64_t elf_program_header_t;
typedef elf_sym_64_t elf_sym_t;
#define USER_STACK_SIZE (4 << 20) // 4MB
#endif
int elf_check_header(elf_header_t* header);
int elf_load(struct proc* p, struct file_descriptor* fd);
int elf_find_symtab_unchecked(void* mapped_data, void** symtab, size_t* symtab_entries, char** strtab);
ssize_t elf_find_function_in_symtab(void* symtab, size_t syms_n, uintptr_t ip);
#endif // _KERNEL_TASKING_ELF_H

View File

@@ -0,0 +1,112 @@
#ifndef _KERNEL_TASKING_PROC_H
#define _KERNEL_TASKING_PROC_H
#include <algo/dynamic_array.h>
#include <fs/vfs.h>
#include <io/tty/vconsole.h>
#include <libkern/atomic.h>
#include <libkern/lock.h>
#include <libkern/types.h>
#include <mem/kmemzone.h>
#include <mem/memzone.h>
#include <mem/vm_address_space.h>
#include <mem/vmm.h>
#define MAX_PROCESS_COUNT 1024
#define MAX_OPENED_FILES 16
struct blocker;
enum PROC_STATUS {
PROC_INVALID = 0,
PROC_ALIVE,
PROC_DEAD,
PROC_DYING,
PROC_ZOMBIE,
};
struct thread;
struct proc {
vm_address_space_t* address_space;
pid_t pid;
pid_t ppid;
pid_t pgid;
uint32_t prio;
uint32_t status;
struct thread* main_thread;
spinlock_t lock;
uid_t uid;
gid_t gid;
uid_t euid;
gid_t egid;
uid_t suid;
gid_t sgid;
file_t* proc_file;
path_t cwd;
file_descriptor_t* fds;
int exit_code;
bool is_kthread;
// Trace data
bool is_tracee;
};
typedef struct proc proc_t;
/**
* PROC FUNCTIONS
*/
pid_t proc_alloc_pid();
struct thread* thread_by_pid(pid_t pid);
int proc_init_storage();
int proc_setup(proc_t* p);
int proc_setup_with_uid(proc_t* p, uid_t uid, gid_t gid);
int proc_setup_vconsole(proc_t* p, vconsole_entry_t* vconsole);
int proc_fill_up_stack(proc_t* p, int argc, char** argv, char** env);
int proc_free(proc_t* p);
int proc_free_locked(proc_t* p);
struct thread* proc_alloc_thread();
struct thread* proc_create_thread(proc_t* p);
void proc_kill_all_threads(proc_t* p);
void proc_kill_all_threads_except(proc_t* p, struct thread* gthread);
/**
* KTHREAD FUNCTIONS
*/
int kthread_setup(proc_t* p);
int kthread_setup_regs(proc_t* p, void* entry_point);
void kthread_setup_segment_regs(proc_t* p);
int kthread_fill_up_stack(struct thread* thread, void* data);
int proc_load(proc_t* p, struct thread* main_thread, const char* path);
int proc_fork_from(proc_t* new_proc, struct thread* from_thread);
int proc_die(proc_t* p, int exit_code);
int proc_block_all_threads(proc_t* p, const struct blocker* blocker);
/**
* PROC FD FUNCTIONS
*/
int proc_chdir(proc_t* p, const char* path);
file_descriptor_t* proc_get_free_fd(proc_t* p);
file_descriptor_t* proc_get_fd(proc_t* p, size_t index);
int proc_get_fd_id(proc_t* proc, file_descriptor_t* fd);
int proc_copy_fd(file_descriptor_t* oldfd, file_descriptor_t* newfd);
/**
* PROC HELPER FUNCTIONS
*/
static ALWAYS_INLINE bool proc_is_su(proc_t* p) { return p->euid == 0; }
static ALWAYS_INLINE int proc_is_alive(proc_t* p) { return p->status == PROC_ALIVE; }
#endif // _KERNEL_TASKING_PROC_H

View File

@@ -0,0 +1,30 @@
#ifndef _KERNEL_TASKING_SCHED_H
#define _KERNEL_TASKING_SCHED_H
#include <libkern/types.h>
#include <mem/vmm.h>
#include <tasking/bits/sched.h>
#include <tasking/tasking.h>
void scheduler_init();
void schedule_activate_cpu();
void resched_dont_save_context();
void resched();
void sched();
void sched_enqueue(thread_t* thread);
void sched_dequeue(thread_t* thread);
size_t active_cpu_count();
static inline void sched_tick()
{
if (!RUNNING_THREAD) {
return;
}
RUNNING_THREAD->ticks_until_preemption--;
if (!RUNNING_THREAD->ticks_until_preemption) {
resched();
}
}
#endif // _KERNEL_TASKING_SCHED_H

View File

@@ -0,0 +1,17 @@
#ifndef _KERNEL_TASKING_SIGNAL_H
#define _KERNEL_TASKING_SIGNAL_H
#include <libkern/bits/signal.h>
#include <libkern/types.h>
#define SIGNALS_CNT 32
enum SIGNAL_ACTION {
SIGNAL_ACTION_ABNORMAL_TERMINATE,
SIGNAL_ACTION_TERMINATE,
SIGNAL_ACTION_STOP,
SIGNAL_ACTION_CONTINUE,
SIGNAL_ACTION_IGNORE,
};
#endif // _KERNEL_TASKING_SIGNAL_H

View File

@@ -0,0 +1,76 @@
#ifndef _KERNEL_TASKING_TASKING_H
#define _KERNEL_TASKING_TASKING_H
#include <fs/vfs.h>
#include <libkern/types.h>
#include <mem/kmemzone.h>
#include <mem/vmm.h>
#include <platform/generic/fpu/fpu.h>
#include <platform/generic/tasking/context.h>
#include <platform/generic/tasking/trapframe.h>
#include <tasking/cpu.h>
#include <tasking/proc.h>
#include <tasking/thread.h>
#define MAX_PROCESS_COUNT 1024
#define MAX_DYING_PROCESS_COUNT 8
#define MAX_OPENED_FILES 16
#define SIGNALS_CNT 32
extern proc_t proc[MAX_PROCESS_COUNT];
proc_t* tasking_get_proc(pid_t pid);
/**
* CPU FUNCTIONS
*/
void switch_uthreads(thread_t* p);
/**
* TASK LOADING FUNCTIONS
*/
void tasking_start_init_proc();
proc_t* tasking_create_kernel_thread(void* entry_point, void* data);
proc_t* tasking_run_kernel_thread(void* entry_point, void* data);
/**
* TASKING RELATED FUNCTIONS
*/
void tasking_init();
void tasking_kill_dying();
bool tasking_should_become_zombie(proc_t* p);
void tasking_evict_proc_entry(proc_t* p);
void tasking_evict_zombies_waiting_for(proc_t* p);
pid_t tasking_get_proc_count();
/**
* SYSCALL IMPLEMENTATION
*/
void tasking_fork();
int tasking_exec(const char __user* path, const char __user** argv, const char __user** env);
void tasking_exit(int exit_code);
int tasking_waitpid(int pid, int* status, int options);
int tasking_signal(thread_t* thread, int signo);
/**
* SIGNALS
*/
void signal_init();
int signal_set_handler(thread_t* thread, int signo, uintptr_t handler);
int signal_set_allow(thread_t* thread, int signo);
int signal_set_private(thread_t* thread, int signo);
int signal_set_pending(thread_t* thread, int signo);
int signal_rem_pending(thread_t* thread, int signo);
int signal_restore_thread_after_handling_signal(thread_t* thread);
int signal_send(thread_t* thread, int signo);
int signal_dispatch_pending(thread_t* thread);
#endif // _KERNEL_TASKING_TASKING_H

View File

@@ -0,0 +1,165 @@
#ifndef _KERNEL_TASKING_THREAD_H
#define _KERNEL_TASKING_THREAD_H
#include <fs/vfs.h>
#include <libkern/lock.h>
#include <libkern/types.h>
#include <platform/generic/fpu/fpu.h>
#include <platform/generic/tasking/context.h>
#include <platform/generic/tasking/trapframe.h>
#include <tasking/signal.h>
#include <time/time_manager.h>
enum THREAD_STATUS {
THREAD_STATUS_INVALID = 0,
THREAD_STATUS_ALLOCATED,
THREAD_STATUS_RUNNING,
THREAD_STATUS_STOPPED,
THREAD_STATUS_BLOCKED,
THREAD_STATUS_DYING,
};
struct thread;
struct blocker {
int reason;
bool (*should_unblock)(struct thread* thread);
bool should_unblock_for_signal;
};
typedef struct blocker blocker_t;
enum BLOCKER_REASON {
BLOCKER_INVALID,
BLOCKER_JOIN,
BLOCKER_READ,
BLOCKER_WRITE,
BLOCKER_SLEEP,
BLOCKER_SELECT,
BLOCKER_DUMPING,
BLOCKER_STOP, // Just waiting for signal which will continue the thread.
};
struct blocker_join {
struct thread* joinee;
int join_pid;
};
typedef struct blocker_join blocker_join_t;
struct blocker_rw {
file_descriptor_t* fd;
};
typedef struct blocker_rw blocker_rw_t;
struct blocker_sleep {
timespec_t until;
};
typedef struct blocker_sleep blocker_sleep_t;
struct blocker_select {
int nfds;
fd_set_t readfds;
fd_set_t writefds;
fd_set_t exceptfds;
bool is_until_time_set;
timespec_t until;
};
typedef struct blocker_select blocker_select_t;
struct proc;
struct thread {
struct proc* process;
pid_t tid;
uint32_t status;
/* Kernel data */
kmemzone_t kstack;
context_t* context; // context of kernel's registers
trapframe_t* tf;
#ifdef FPU_ENABLED
fpu_state_t* fpu_state;
#endif
/* Scheduler data */
struct thread* sched_prev;
struct thread* sched_next;
int last_cpu;
time_t ticks_until_preemption;
time_t start_time_in_ticks; // Time when the task was put to run.
/* Blocker data */
blocker_t blocker;
union {
blocker_join_t join;
blocker_rw_t rw;
blocker_sleep_t sleep;
blocker_select_t select;
} blocker_data;
/* Stat data */
time_t stat_total_running_ticks;
uint32_t signals_mask;
uint32_t pending_signals_mask;
void* signal_handlers[SIGNALS_CNT];
};
typedef struct thread thread_t;
#define THREADS_PER_NODE (128)
struct thread_list_node {
thread_t thread_storage[THREADS_PER_NODE];
struct thread_list_node* next;
int empty_spots;
};
typedef struct thread_list_node thread_list_node_t;
struct thread_list {
struct thread_list_node* head;
struct thread_list_node* next_empty_node;
int next_empty_index;
spinlock_t lock;
struct thread_list_node* tail;
};
typedef struct thread_list thread_list_t;
/**
* THREAD FUNCTIONS
*/
int thread_setup_main(struct proc* p, thread_t* thread);
int thread_setup(struct proc* p, thread_t* thread);
int thread_setup_kstack(thread_t* thread);
int thread_copy_of(thread_t* thread, thread_t* from_thread);
int thread_fill_up_stack(thread_t* thread, int argc, char** argv, int envc, char** envp);
int thread_kstack_free(thread_t* thread);
int thread_free(thread_t* thread);
int thread_die(thread_t* thread);
int thread_zombie(thread_t* thread);
int thread_stop(thread_t* thread);
int thread_stop_and_resched(thread_t* thread);
int thread_continue(thread_t* thread);
static ALWAYS_INLINE int thread_is_freed(thread_t* thread) { return (thread->status == THREAD_STATUS_INVALID); }
static ALWAYS_INLINE int thread_is_alive(thread_t* thread) { return !thread_is_freed(thread); }
/**
* BLOCKER FUNCTIONS
*/
int thread_init_blocker(thread_t* thread, const struct blocker* blocker);
int init_join_blocker(thread_t* thread, int wait_for_pid);
int init_read_blocker(thread_t* thread, file_descriptor_t* bfd);
int init_write_blocker(thread_t* thread, file_descriptor_t* bfd);
int init_sleep_blocker(thread_t* thread, timespec_t ts);
int init_select_blocker(thread_t* thread, int nfds, fd_set_t* readfds, fd_set_t* writefds, fd_set_t* exceptfds, timeval_t* timeout);
/**
* DEBUG FUNCTIONS
*/
int thread_dump_frame(thread_t* thread);
int thread_print_backtrace();
#endif /* _KERNEL_TASKING_THREAD_H */