157 lines
5.1 KiB
C
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);
|