Created small static library to wrap system call ABI

This commit is contained in:
2023-09-07 00:58:57 -05:00
parent 112b4204a7
commit a5ce86147d
9 changed files with 275 additions and 119 deletions

View File

@@ -1 +1,2 @@
nobase_include_HEADERS = types/status.h types/syscallid.h types/physaddr.h types/syscallarg.h
nobase_include_HEADERS = types/status.h types/syscallid.h types/physaddr.h \
types/syscallarg.h sys/syscalls.h types/pid.h types/oid.h

View File

@@ -7,11 +7,13 @@
#include "syscalls.h"
#include "types/syscallid.h"
#include "types/status.h"
#include "types/pid.h"
#include "types/oid.h"
#include <libmalloc/memmap.h>
#include <stddef.h>
#define MAX_SYSCALL_ID 256
#define module_limit 8
#define MODULE_LIMIT 8
#define IO_OP 1 << 0
#define IO_SYNC 0 << 0
@@ -40,95 +42,48 @@ struct boot_info_t
size_t memory_size;
memory_map_t map;
size_t module_count;
struct module_t modules[module_limit];
struct module_t modules[MODULE_LIMIT];
};
struct message_t
{
unsigned long sender;
pid_t sender;
unsigned long code;
unsigned long args[6];
};
enum process_state_t
{
PROCESS_ACTIVE,
PROCESS_REQUESTING,
PROCESS_SENDING
};
struct process_t
{
unsigned long pid;
int priority;
physaddr_t page_table;
enum process_state_t state;
struct queue_t sending_queue;
struct queue_t message_queue;
struct message_t *message_buffer;
struct process_context_t *ctx;
};
struct port_t
{
unsigned long id;
unsigned long owner_pid;
};
struct signal_action_t
{
unsigned long pid;
signal_handler_t func_ptr;
void (*trampoline_ptr)();
void *userdata;
};
struct signal_context_t
{
unsigned long signal_id;
};
struct kernel_t
{
struct syscall_t syscall_table[MAX_SYSCALL_ID];
struct priority_queue_t priority_queue;
struct avltree_t *interrupt_handlers;
struct avltree_t *port_table;
struct avltree_t *process_table;
struct process_t *active_process;
int next_pid;
};
void kernel_initialize(struct boot_info_t *boot_info);
error_t set_syscall(int id, int arg_count, int pid, void *func_ptr);
error_t kernel_set_syscall(int id, int arg_count, pid_t pid, void *func_ptr);
size_t do_syscall(syscall_id_t id, syscall_arg_t arg1, syscall_arg_t arg2, syscall_arg_t arg3, void *pc, void *stack, unsigned long flags);
size_t kernel_do_syscall(syscall_id_t id, syscall_arg_t arg1, syscall_arg_t arg2, syscall_arg_t arg3, void *pc, void *stack, unsigned long flags);
error_t kernel_load_module(struct module_t *module);
unsigned long kernel_current_pid();
pid_t kernel_current_pid();
struct process_context_t *kernel_current_context();
error_t kernel_store_active_context(struct process_context_t *context);
unsigned long kernel_spawn_process(void *program_entry, int priority, physaddr_t address_space);
pid_t kernel_spawn_process(void *program_entry, int priority, physaddr_t address_space);
struct process_context_t *kernel_advance_scheduler();
error_t kernel_terminate_process(size_t process_id);
error_t kernel_terminate_process(pid_t process_id);
error_t kernel_create_port(unsigned long id);
error_t kernel_remove_port(unsigned long id);
unsigned long kernel_get_port_owner(unsigned long id);
pid_t kernel_get_port_owner(unsigned long id);
error_t kernel_send_message(unsigned long recipient, struct message_t *message);
error_t kernel_queue_message(unsigned long recipient, struct message_t *message);
int kernel_receive_message(struct message_t *buffer, int flags);
error_t kernel_register_interrupt_handler(unsigned long interrupt, signal_handler_t handler, void *userdata);
error_t kernel_remove_interrupt_handler(unsigned long interrupt);
@@ -137,6 +92,10 @@ error_t kernel_execute_interrupt_handler(unsigned long interrupt);
error_t kernel_signal_return();
int receive_message(struct message_t *buffer, int flags);
error_t kernel_create_object(size_t size, unsigned long flags, oid_t *id);
void panic(const char *message) __attribute__ ((noreturn));
error_t kernel_attach_object(oid_t id, void *virt_addr);
error_t kernel_release_object(oid_t id);
void kernel_panic(const char *message) __attribute__ ((noreturn));

65
include/sys/syscalls.h Normal file
View File

@@ -0,0 +1,65 @@
#ifndef _QUARK_SYSCALLS_H
#define _QUARK_SYSCALLS_S
#include <types/syscallarg.h>
#include <types/syscallid.h>
#include <types/physaddr.h>
unsigned long _do_syscall(syscall_id_t id, syscall_arg_t arg1, syscall_arg_t arg2, syscall_arg_t arg3);
static inline int kprint(const char *s)
{
syscall_arg_t arg1;
syscall_arg_t arg2;
syscall_arg_t arg3;
arg1.ptr = (void*)s;
arg2.unsigned_int = 0UL;
arg3.signed_int = 0UL;
return (int) _do_syscall(SYSCALL_TEST, arg1, arg2, arg3);
}
static inline int mmap(void *addr, unsigned long length, long flags)
{
syscall_arg_t arg1;
syscall_arg_t arg2;
syscall_arg_t arg3;
arg1.ptr = addr;
arg2.unsigned_int = length;
arg3.signed_int = flags;
return (int) _do_syscall(SYSCALL_MMAP, arg1, arg2, arg3);
}
static inline int munmap(void *addr, unsigned long length)
{
syscall_arg_t arg1;
syscall_arg_t arg2;
syscall_arg_t arg3;
arg1.ptr = addr;
arg2.unsigned_int = length;
arg3.unsigned_int = 0UL;
return (int) _do_syscall(SYSCALL_MUNMAP, arg1, arg2, arg3);
}
static inline int map_physical(void *addr, physaddr_t phys_addr, unsigned long length)
{
syscall_arg_t arg1;
syscall_arg_t arg2;
syscall_arg_t arg3;
arg1.ptr = addr;
arg2.unsigned_int = phys_addr;
arg3.unsigned_int = length;
return (int) _do_syscall(SYSCALL_MAP_PHYS, arg1, arg2, arg3);
}
static inline int unmap_physical(void *addr, unsigned long length)
{
syscall_arg_t arg1;
syscall_arg_t arg2;
syscall_arg_t arg3;
arg1.ptr = addr;
arg2.unsigned_int = length;
arg3.unsigned_int = 0UL;
return (int) _do_syscall(SYSCALL_UNMAP_PHYS, arg1, arg2, arg3);
}
#endif

View File

@@ -28,20 +28,26 @@ struct syscall_t
size_t test_syscall(syscall_arg_t str);
size_t mmap(syscall_arg_t location, syscall_arg_t length, syscall_arg_t flags);
size_t syscall_mmap(syscall_arg_t location, syscall_arg_t length, syscall_arg_t flags);
size_t munmap(syscall_arg_t location, syscall_arg_t length);
size_t syscall_munmap(syscall_arg_t location, syscall_arg_t length);
size_t map_physical(syscall_arg_t arg_addr, syscall_arg_t arg_phys_addr, syscall_arg_t arg_length);
size_t syscall_map_physical(syscall_arg_t arg_addr, syscall_arg_t arg_phys_addr, syscall_arg_t arg_length);
size_t unmap_physical(syscall_arg_t arg_addr, syscall_arg_t arg_length);
size_t syscall_unmap_physical(syscall_arg_t arg_addr, syscall_arg_t arg_length);
size_t terminate_self();
size_t syscall_terminate_self();
size_t send(syscall_arg_t recipient, syscall_arg_t message, syscall_arg_t flags);
size_t syscall_create_object();
size_t receive(syscall_arg_t buffer, syscall_arg_t flags);
size_t syscall_aquire_object();
size_t open_port(syscall_arg_t id);
size_t syscall_release_object();
size_t close_port(syscall_arg_t id);
size_t syscall_send(syscall_arg_t recipient, syscall_arg_t message, syscall_arg_t flags);
size_t syscall_receive(syscall_arg_t buffer, syscall_arg_t flags);
size_t syscall_open_port(syscall_arg_t id);
size_t syscall_close_port(syscall_arg_t id);

View File

@@ -4,6 +4,9 @@ quark_kernel_LDADD = -lgcc -lmalloc
quark_kernel_CFLAGS = -I$(top_srcdir)/include -I$(prefix)/include -ffreestanding -mgeneral-regs-only -O0 -Wall -ggdb
quark_kernel_LDFLAGS = -L$(prefix)/lib -nostdlib
lib_LIBRARIES = libquark-syscall.a
libquark_syscall_a_CFLAGS = -I$(top_srcdir)/include -I$(prefix)/include -ffreestanding -mgeneral-regs-only -O0 -Wall -ggdb
if x86
quark_kernel_SOURCES += x86/paging.c \
x86/putc.c \
@@ -18,6 +21,7 @@ quark_kernel_SOURCES += x86/paging.c \
x86/preempt.S \
x86/quark_x86.c \
x86/entry.S
libquark_syscall_a_SOURCES = x86/do_syscall.S
quark_kernel_LDFLAGS += -T x86/linker.ld
quark_kernel_DEPENDENCIES = x86/linker.ld
endif

View File

@@ -13,7 +13,71 @@
#include "types/status.h"
#include "types/syscallid.h"
struct kernel_t kernel;
struct shared_object_t
{
physaddr_t phys_addr;
size_t size;
unsigned long access_flags;
unsigned long refcount;
struct avltree_t *users;
};
struct shared_object_mapping_t
{
void *virt_addr;
};
enum process_state_t
{
PROCESS_ACTIVE,
PROCESS_REQUESTING,
PROCESS_SENDING
};
struct process_t
{
pid_t pid;
int priority;
physaddr_t page_table;
struct avltree_t *shared_objects;
enum process_state_t state;
struct queue_t sending_queue;
struct queue_t message_queue;
struct message_t *message_buffer;
struct process_context_t *ctx;
};
struct port_t
{
unsigned long id;
pid_t owner_pid;
};
struct signal_action_t
{
pid_t pid;
signal_handler_t func_ptr;
void (*trampoline_ptr)();
void *userdata;
};
struct signal_context_t
{
unsigned long signal_id;
};
struct kernel_t
{
struct syscall_t syscall_table[MAX_SYSCALL_ID];
struct priority_queue_t priority_queue;
struct avltree_t *interrupt_handlers;
struct avltree_t *port_table;
struct avltree_t *object_table;
struct avltree_t *process_table;
struct process_t *active_process;
pid_t next_pid;
oid_t next_oid;
} kernel;
void kernel_initialize(struct boot_info_t *boot_info)
{
@@ -38,50 +102,52 @@ void kernel_initialize(struct boot_info_t *boot_info)
memmap_insert_region(&boot_info->map, (physaddr_t)&_kernel_pstart, (physaddr_t)&_kernel_pend - (physaddr_t)&_kernel_pstart, M_UNAVAILABLE);
if(initialize_page_map(&boot_info->map, (physaddr_t*)&_kernel_end, boot_info->memory_size, page_size))
{
panic("Failed to initialize page allocator.");
kernel_panic("Failed to initialize page allocator.");
}
if(kminit(page_map_end(), 0xFFC00000 - (size_t)page_map_end()))
{
panic("Failed to initialize heap.");
kernel_panic("Failed to initialize heap.");
}
kernel.active_process = NULL;
kernel.next_pid = 1;
kernel.next_oid = 1;
kernel.process_table = NULL;
kernel.port_table = NULL;
kernel.object_table = NULL;
if(construct_priority_queue(&kernel.priority_queue, 512) != ENONE)
{
panic("Failed to construct priority queue.");
kernel_panic("Failed to construct priority queue.");
}
memset(kernel.syscall_table, 0, sizeof(struct syscall_t) * MAX_SYSCALL_ID);
set_syscall(SYSCALL_TEST, 1, 0, test_syscall);
set_syscall(SYSCALL_MMAP, 3, 0, mmap);
set_syscall(SYSCALL_MUNMAP, 2, 0, munmap);
set_syscall(SYSCALL_MAP_PHYS, 3, 0, map_physical);
set_syscall(SYSCALL_UNMAP_PHYS, 2, 0, unmap_physical);
set_syscall(SYSCALL_SEND, 3, 0, send);
set_syscall(SYSCALL_RECEIVE, 2, 0, receive);
set_syscall(SYSCALL_OPEN_PORT, 1, 0, open_port);
set_syscall(SYSCALL_CLOSE_PORT, 1, 0, close_port);
kernel_set_syscall(SYSCALL_TEST, 1, 0, test_syscall);
kernel_set_syscall(SYSCALL_MMAP, 3, 0, syscall_mmap);
kernel_set_syscall(SYSCALL_MUNMAP, 2, 0, syscall_munmap);
kernel_set_syscall(SYSCALL_MAP_PHYS, 3, 0, syscall_map_physical);
kernel_set_syscall(SYSCALL_UNMAP_PHYS, 2, 0, syscall_unmap_physical);
kernel_set_syscall(SYSCALL_SEND, 3, 0, syscall_send);
kernel_set_syscall(SYSCALL_RECEIVE, 2, 0, syscall_receive);
kernel_set_syscall(SYSCALL_OPEN_PORT, 1, 0, syscall_open_port);
kernel_set_syscall(SYSCALL_CLOSE_PORT, 1, 0, syscall_close_port);
for(int i = 0; i < boot_info->module_count; i++)
{
if(kernel_load_module(&boot_info->modules[i]) != ENONE)
{
panic("Failed to load modules.");
kernel_panic("Failed to load modules.");
}
}
if(initialize_interrupts() != ENONE)
{
panic("Failed to initialize interrupts.");
kernel_panic("Failed to initialize interrupts.");
}
irq_enable();
load_context(kernel_advance_scheduler());
}
error_t set_syscall(int id, int arg_count, int pid, void *func_ptr)
error_t kernel_set_syscall(int id, int arg_count, pid_t pid, void *func_ptr)
{
if(id < 0 || id > MAX_SYSCALL_ID)
{
@@ -110,7 +176,7 @@ error_t set_syscall(int id, int arg_count, int pid, void *func_ptr)
return ENONE;
}
size_t do_syscall(syscall_id_t id, syscall_arg_t arg1, syscall_arg_t arg2, syscall_arg_t arg3, void *pc, void *stack, unsigned long flags)
size_t kernel_do_syscall(syscall_id_t id, syscall_arg_t arg1, syscall_arg_t arg2, syscall_arg_t arg3, void *pc, void *stack, unsigned long flags)
{
if(id < 0 || id > MAX_SYSCALL_ID)
{
@@ -162,7 +228,7 @@ error_t kernel_load_module(struct module_t *module)
{
physaddr_t module_address_space = create_address_space();
if(module_address_space == ENOMEM) {
panic("failed to create address space for module: out of memory");
kernel_panic("failed to create address space for module: out of memory");
}
paging_load_address_space(module_address_space);
void *const load_base = (void*)0x80000000;
@@ -173,9 +239,9 @@ error_t kernel_load_module(struct module_t *module)
switch(status)
{
case ENOMEM:
panic("ran out of memory while mapping module");
kernel_panic("ran out of memory while mapping module");
case EOUTOFBOUNDS:
panic("got out-of-bounds error while mapping module");
kernel_panic("got out-of-bounds error while mapping module");
}
load_offset += page_size;
@@ -184,9 +250,9 @@ error_t kernel_load_module(struct module_t *module)
switch(status)
{
case ENOMEM:
panic("ran out of memory while reading ELF file");
kernel_panic("ran out of memory while reading ELF file");
case EOUTOFBOUNDS:
panic("got out-of-bounds error while reading ELF file");
kernel_panic("got out-of-bounds error while reading ELF file");
}
void *module_entry = ((struct elf_file_header_t*)load_base)->entry;
printf("loaded module with entry point %08x\n", (unsigned int)module_entry);
@@ -197,9 +263,9 @@ error_t kernel_load_module(struct module_t *module)
switch(status)
{
case ENOMEM:
panic("ran out of memory while unmapping module");
kernel_panic("ran out of memory while unmapping module");
case EOUTOFBOUNDS:
panic("got out-of-bounds error while unmapping module");
kernel_panic("got out-of-bounds error while unmapping module");
}
load_offset += page_size;
}
@@ -213,7 +279,7 @@ error_t kernel_load_module(struct module_t *module)
}
}
unsigned long kernel_current_pid()
pid_t kernel_current_pid()
{
if(kernel.active_process == NULL)
{
@@ -237,7 +303,7 @@ struct process_context_t *kernel_current_context()
}
}
unsigned long kernel_spawn_process(void *program_entry, int priority, physaddr_t address_space)
pid_t kernel_spawn_process(void *program_entry, int priority, physaddr_t address_space)
{
struct process_t *new_process = (struct process_t*) kmalloc(sizeof(struct process_t));
if(new_process == NULL)
@@ -286,12 +352,12 @@ struct process_context_t *kernel_advance_scheduler()
printf("entering process %08x cr3=%08x ctx=%08x sched=%i.\n", kernel.active_process->pid, kernel.active_process->page_table, kernel.active_process->ctx, kernel.priority_queue.size);
return kernel.active_process->ctx;
}
panic("no processes available to enter!");
kernel_panic("no processes available to enter!");
}
error_t kernel_terminate_process(size_t process_id)
error_t kernel_terminate_process(pid_t pid)
{
struct process_t *process = avl_get(kernel.process_table, process_id);
struct process_t *process = avl_get(kernel.process_table, pid);
if(process == NULL)
{
return EDOESNTEXIST;
@@ -300,7 +366,7 @@ error_t kernel_terminate_process(size_t process_id)
{
kernel.active_process = NULL;
}
kernel.process_table = avl_remove(kernel.process_table, process_id);
kernel.process_table = avl_remove(kernel.process_table, pid);
priorityqueue_remove(&kernel.priority_queue, process);
for(struct message_t *msg = queue_get_next(&process->message_queue); msg != NULL; msg = queue_get_next(&process->message_queue))
{
@@ -361,7 +427,7 @@ error_t kernel_remove_port(unsigned long id)
return ENONE;
}
unsigned long kernel_get_port_owner(unsigned long id)
pid_t kernel_get_port_owner(unsigned long id)
{
struct port_t *port = avl_get(kernel.port_table, id);
if(port == NULL)
@@ -423,7 +489,7 @@ error_t kernel_queue_message(unsigned long recipient, struct message_t *message)
}
}
int receive_message(struct message_t *buffer, int flags)
int kernel_receive_message(struct message_t *buffer, int flags)
{
if(kernel.active_process->message_queue.count > 0)
{
@@ -513,13 +579,49 @@ error_t kernel_signal_return()
context_stack_pop_struct(kernel.active_process->ctx, kernel.active_process->ctx, sizeof(*kernel.active_process->ctx));
if(kernel.active_process->state == PROCESS_REQUESTING)
{
receive_message(kernel.active_process->message_buffer, 0);
kernel_receive_message(kernel.active_process->message_buffer, 0);
load_context(kernel.active_process->ctx);
}
return ENONE;
}
void panic(const char *message)
error_t kernel_create_object(size_t size, unsigned long flags, oid_t *id)
{
physaddr_t phys_addr = reserve_pages(size);
if(phys_addr == ENOMEM)
{
return ENOMEM;
}
struct shared_object_t *obj = kmalloc(sizeof(struct shared_object_t));
if(obj == NULL)
{
free_pages(phys_addr, size);
return ENOMEM;
}
obj->phys_addr = phys_addr;
obj->size = size;
obj->access_flags = flags;
obj->refcount = 0;
obj->users = NULL;
kernel.object_table = avl_insert(kernel.object_table, kernel.next_oid, obj);
*id = kernel.next_oid;
kernel.next_oid++;
return ENONE;
}
error_t kernel_attach_object(oid_t id, void *virt_addr)
{
}
error_t kernel_release_object(oid_t id)
{
}
void kernel_panic(const char *message)
{
printf("panic: %s", message);
asm("cli");

View File

@@ -11,7 +11,7 @@ size_t test_syscall(syscall_arg_t str)
return 17;
}
size_t mmap(syscall_arg_t arg_location, syscall_arg_t arg_length, syscall_arg_t arg_flags)
size_t syscall_mmap(syscall_arg_t arg_location, syscall_arg_t arg_length, syscall_arg_t arg_flags)
{
unsigned long location = arg_location.unsigned_int;
unsigned long length = arg_length.unsigned_int;
@@ -42,7 +42,7 @@ size_t mmap(syscall_arg_t arg_location, syscall_arg_t arg_length, syscall_arg_t
status = map_page((void*)(location + n), frame, PAGE_USERMODE | PAGE_RW);
if(status != ENONE && free_page(frame) != ENONE)
{
panic("critical error reached during mmap.");
kernel_panic("critical error reached during mmap.");
}
n += page_size;
}
@@ -51,14 +51,14 @@ size_t mmap(syscall_arg_t arg_location, syscall_arg_t arg_length, syscall_arg_t
break;
}
}
if(status != ENONE && munmap(arg_location, arg_length) != ENONE)
if(status != ENONE && syscall_munmap(arg_location, arg_length) != ENONE)
{
panic("critical error reached during mmap.");
kernel_panic("critical error reached during mmap.");
}
return status;
}
size_t munmap(syscall_arg_t arg_location, syscall_arg_t arg_length)
size_t syscall_munmap(syscall_arg_t arg_location, syscall_arg_t arg_length)
{
unsigned long location = arg_location.unsigned_int;
unsigned long length = arg_length.unsigned_int;
@@ -88,7 +88,7 @@ size_t munmap(syscall_arg_t arg_location, syscall_arg_t arg_length)
return status;
}
size_t map_physical(syscall_arg_t arg_addr, syscall_arg_t arg_phys_addr, syscall_arg_t arg_length)
size_t syscall_map_physical(syscall_arg_t arg_addr, syscall_arg_t arg_phys_addr, syscall_arg_t arg_length)
{
void *addr = arg_addr.ptr;
physaddr_t frame = arg_phys_addr.unsigned_int;
@@ -105,7 +105,7 @@ size_t map_physical(syscall_arg_t arg_addr, syscall_arg_t arg_phys_addr, syscall
return status;
}
size_t unmap_physical(syscall_arg_t arg_addr, syscall_arg_t arg_length)
size_t syscall_unmap_physical(syscall_arg_t arg_addr, syscall_arg_t arg_length)
{
void *addr = arg_addr.ptr;
unsigned long length = arg_length.unsigned_int;
@@ -121,12 +121,12 @@ size_t unmap_physical(syscall_arg_t arg_addr, syscall_arg_t arg_length)
return status;
}
size_t terminate_self()
size_t syscall_terminate_self()
{
return kernel_terminate_process(kernel_current_pid());
}
size_t send(syscall_arg_t recipient, syscall_arg_t message, syscall_arg_t flags)
size_t syscall_send(syscall_arg_t recipient, syscall_arg_t message, syscall_arg_t flags)
{
unsigned long op_type = flags.unsigned_int & IO_OP;
unsigned long dest_type = flags.unsigned_int & IO_RECIPIENT_TYPE;
@@ -154,17 +154,17 @@ size_t send(syscall_arg_t recipient, syscall_arg_t message, syscall_arg_t flags)
}
}
size_t receive(syscall_arg_t buffer, syscall_arg_t flags)
size_t syscall_receive(syscall_arg_t buffer, syscall_arg_t flags)
{
return receive_message(buffer.ptr, flags.unsigned_int);
return kernel_receive_message(buffer.ptr, flags.unsigned_int);
}
size_t open_port(syscall_arg_t id)
size_t syscall_open_port(syscall_arg_t id)
{
return kernel_create_port(id.unsigned_int);
}
size_t close_port(syscall_arg_t id)
size_t syscall_close_port(syscall_arg_t id)
{
return kernel_remove_port(id.unsigned_int);
}

19
src/x86/do_syscall.S Normal file
View File

@@ -0,0 +1,19 @@
.global _do_syscall
.type _do_syscall, @function
_do_syscall:
push %ebp
mov %esp, %ebp
push %esi
push %edi
push %ebx
mov 0x08(%ebp), %eax
mov 0x0C(%ebp), %ebx
mov 0x10(%ebp), %ecx
mov 0x14(%ebp), %edx
int $0x80
pop %ebx
pop %edi
pop %esi
pop %ebp
ret
.size _do_syscall, . - _do_syscall

View File

@@ -20,7 +20,7 @@ isr_syscall:
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
call do_syscall
call kernel_do_syscall
mov %ebp, %esp
mov $0x23, %cx
mov %cx, %ds