calcite/src/kernel/process.h

157 lines
5.1 KiB
C

/* Calcite, src/kernel/process.h
* Copyright 2025 Benji Dial
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "fs.h"
#include <kernel-public/framebuffer.h>
#include <kernel-public/files.h>
#include <kernel-public/ipc.h>
struct ipc_dgram_box;
struct process_file_info {
const struct fs_info *fs;
void *node;
struct fs_stat stat;
};
struct process_ipc_dgram_handle_info {
//0 if this handle number is not used.
struct ipc_dgram_box *box;
//1 if this is a receiver handle, 0 if this is a sender handle.
int is_receiver;
};
struct process {
uint64_t p4_physical_base;
uint64_t *p4_virtual_base;
uint64_t p3_physical_base;
uint64_t *p3_virtual_base;
int n_threads;
//handles are indices into this.
//0 for fs means unused handle.
struct process_file_info *files;
int files_buffer_size;
struct process_ipc_dgram_handle_info *ipc_dgram_handles;
int ipc_dgram_handles_buffer_size;
//0 for missing levels. just bottom p3 of address space.
uint64_t *p2_virtual_bases[512];
uint64_t **p1_virtual_bases[512];
//also just bottom p3. bit set indicates we should free
//the physical page when we clean up this process.
uint8_t **owned_pages_bitmaps[512];
};
//returns 0 if that handle is not used.
//return value might be invalidated by future allocation of file handles for this process.
struct process_file_info *get_file_info(struct process *process, file_handle_t handle);
struct thread {
struct process *process;
//both page-aligned
void *stack_bottom;
void *stack_top;
};
extern struct thread *running_thread;
void create_process(struct process *process_out);
void create_thread(struct process *process, struct thread *thread_out);
//physical and virtual bases must be page-aligned.
//virtual base must be in bottom p3 and not zero.
void map_page_for_process(
struct process *process, uint64_t physical_base,
void *virtual_base, int writable, int executable, int owned);
//virtual base must be page-aligned, in bottom p3, and not zero.
void unmap_page_for_process(
struct process *process, void *virtual_base);
//finds a free memory region in the bottom p3
//of the address space, and not the bottom p2.
void *find_free_process_region(
struct process *process, uint64_t page_count);
//returns 0 on failure, 1 on success.
int load_elf(
struct process *process, uint64_t *entry_out,
const struct fs_info *fs_info, void *fs_node);
//returns 0 on failure, 1 on success.
//creates a process and a thread in that process, loads the elf into the process,
//and schedules a ready task that sets the running thread to the new thread and
//starts user mode at the elf's entry point.
int start_elf(const char *uri);
int syscall_start_elf(const char *uri);
void destroy_process(struct process *process);
void destroy_thread(struct thread *thread);
[[noreturn]] void syscall_illegal_args();
//returs 1 if [start, start + length) is writable by process, otherwise 0.
int is_mapped_writable(struct process *process, const void *start, uint64_t length);
//returs 1 if [start, start + length) is readable by process, otherwise 0.
int is_mapped_readable(struct process *process, const void *start, uint64_t length);
//return 1 if the entire null-terminated string starting at start is readable by process, otherwise 0.
int is_mapped_readable_string(struct process *process, const char *start);
[[noreturn]] void syscall_end_thread();
void syscall_map_framebuffer(struct framebuffer_info *info_out);
enum fs_access_result syscall_open_file(const char *path, file_handle_t *handle_out);
void syscall_close_file(file_handle_t handle);
enum fs_access_result syscall_get_file_size(file_handle_t handle, uint64_t *bytes_out);
enum fs_access_result syscall_read_file(struct read_file_parameter *parameter);
void *syscall_map_pages(uint64_t count);
enum ipc_dgram_result syscall_ipc_create_dgram_receiver(
const char *address, ipc_dgram_receiver_handle_t *handle_out);
enum ipc_dgram_result syscall_ipc_create_dgram_sender(
const char *address, ipc_dgram_sender_handle_t *handle_out);
//on entry, bytes is maximum accepted packet length.
//on exit, if result was IPR_SUCCESS or IPR_TOO_BIG, bytes is actual packet length.
//actual packet length will always be positive.
enum ipc_dgram_result syscall_ipc_receive_dgram(
ipc_dgram_receiver_handle_t handle, void *buffer, int *bytes);
//bytes must be positive.
enum ipc_dgram_result syscall_ipc_send_dgram(
ipc_dgram_sender_handle_t handle, const void *data, int bytes);
//f should not return.
void syscall_create_thread(void (*f)(uint64_t x), uint64_t x);