From 466cd4021fa324c726d1fa68eebc202c53aec5f0 Mon Sep 17 00:00:00 2001 From: Amelia Coutard Date: Mon, 27 Nov 2023 00:53:46 +0100 Subject: [PATCH] Changed the future API a bit. Also, changed the syscall handler a bit because 1) %rdx was broken and 2) I was actually probably never gonna need the second return register, because of that new API --- doc.txt | 107 +++++++++++++++++++-------------------------- kernel/src/ring3.S | 4 +- 2 files changed, 46 insertions(+), 65 deletions(-) diff --git a/doc.txt b/doc.txt index 142373f..2c6622e 100644 --- a/doc.txt +++ b/doc.txt @@ -12,30 +12,25 @@ isos documentation: 0000'7FFF'FFFF'0000 ↔ 0000'8000'0000'0000 - stack: 64KiB -- Invalid addresses -- FFFF'8000'0000'0000 ↔ FFFF'C000'0000'0000 - physical memory: 64TiB -FFFF'C000'0000'0000 ↔ ____'____'____'____ - process information table: 2048 processes, 4093 ports/process -____'____'____'____ ↔ FFFF'FFFF'8000'0000 - unmapped +FFFF'C000'0000'0000 ↔ FFFF'FFFF'8000'0000 - process information tables: + open file descriptors, namespaces, etc. FFFF'FFFF'8000'0000 ↔10000'0000'0000'0000 - kernel: 2GiB --------------------------- -The port is the IPC method of this kernel. There are two types of ports. -Server ports are points where a server will receive a message. They can receive - a message from any number of client ports. -Client ports are points where a client can send a message. A client port always points - to a single server port. +All the IPC is handled via many, many files. +Also, a filename must be a sequence of non-0, non-\n, non-control-character, legal utf-8 codepoints. +A directory will, for the purposes of system calls that operate on file contents, appear as a read-only + file containing each of the file names of its contents, each file name followed by a single \n. +At boot, the first module gets access to a special filesystem, that only it has access to. + - /serial: R/W, serial I/O +All the other modules get only a single open file, corresponding to the file system exposed by the first module's process. --------------------------- Data types: -pid_t = int64_t; -sport_t = int64_t; -cport_t = int64_t; -port_t = int64_t; // Either a server port or a client port. -struct handler { - pid_t pid; - cport_t port; -}; +fd_t = int64_t; // Client-side file (or directory) descriptor. --------------------------- @@ -43,50 +38,38 @@ The system calls: Input registers in order: %rdi, %rsi, %rdx, %r10, %r8, %r9. In %rax, the syscall id is specified. -If the operation succeeds, %rax contains the result (think SystemV ABI) (≥ 0). If it fails, %rax contains the opposite of the error code. (< 0) -The only registers clobbered are %rcx, %r11, %rax, %rdx. (The last two are the return registers.) - -sport_t make_sport(); - Creates a server port, with no associated clients. -cport_t make_cport(sport_t); - Creates a client port associated with the given server port. -cport_t copy_cport(cport_t); - Takes a client port, and returns a new client port that points to the same server port. - -bool has_cports(sport_t); - Takes a server port, and returns whether or not it has any client ports. -void close(port_t); - Close a port. It no longer exists in this process. - If it was a server port, any use of any of its client ports for the purpose - of communication will fail with ERR_CLOSED_P. - If it was a client port, - If it wasn't the server's last client, nothing happens. - If it was, however, the server will be notified by way of singnalling on the next wait call. -Program termination implicitly calls close on all the program's ports. - -sport_t wait(); - Block until one of the server ports of this process receives a message or loses its last client. - Returns the server port in question. - -{int64_t out_s, uint64_t user_error_code} call(cport_t p, int64_t in_s, const void* in, cport_t* io_p, int64_t out_s, void* out); - Blocks until the server refered to by p replies. //, or reports an error. -handler receive(sport_t p); - Block until any client sends a message to the port p. -int64_t receive_size(handler client); - Get the size of the message that client is sending. -cport_t receive_message(handler client, int64_t out_s, void* out); - Gets the data of the message that client is sending. - If the client is sending a port as well, return it, return 0 otherwise. - -void reply(handler caller, int64_t in_s, const void* in, cport_t in_p); - Invalidates caller. - Replies to the caller with the data of length in_s in `in`. - If in_p is non-0, a copy of it is sent as well. -// void forward(cport_t to, handler caller, int64_t sub_begin, int64_t sub_len); - // Invalidates caller. - // Transfers message to `to` (reply will go to the original client still). - // 0 ≤ sub_begin ≤ receive_size(client) and 0 ≤ sub_len ≤ receive_size(client) - sub_begin. - // The data transferred will only be that in data[sub_begin; sub_begin + sub_len[, ∅ if sub_len == 0. -// void error(handler caller, uint64_t error_code); - // Invalidates caller. - // Call gets ERR_USER, with the second value set to error_code. +If the operation succeeds, %rax contains the result (think SystemV ABI) (≥ 0). If it fails, %rax contains -1. +The only registers clobbered are %rcx, %r11, and %rax. + +enum open_options { + MODE_RO = 0x1 + MODE_WO = 0x2 + MODE_RW = MODE_RO | MODE_WO + MODE_DIRECTORY = 0x4 + OPTION_INPLACE = 0x8 +}; + +fd_t open(fd_t wd, char const path[path_len], ssize_t path_len, open_options options /* See enum above. */); + Options must be one of ro, wo or rw, |-ed with any (including multiple) of MODE_DIRECTORY and OPTION_INPLACE + Try to open path, relative to wd. + If path is absolute, wd can actually not be an open file (but it still needs to be >= 0, for in_place to work). + If OPTION_INPLACE, makes wd point to the opened file/folder in case of success, and return wd. + If not, doesn't change wd, and returns a new fd pointing to the opened file/folder. + If MODE_DIRECTORY, open fails if path refers to a non-directory file. + If not, open fails if path refers to a directory. + When open fails, it returns -1 (as all syscalls) and the program continues as though open was never called. + +ssize_t read(fd_t file, char data[len], ssize_t len); + Read up to len characters from file. + Return the number of actually read characters, or -1 on error. + +ssize_t write(fd_t file, char data[len], ssize_t len); + Write up to len characters to file. + Return the number of actually written characters, or -1 on error. + +ssize_t fseek(fd_t file, ssize_t offset, int from); + If from is 0, seek offset bytes from start. + If from is 1, seek offset bytes from current file position. + If from is 2, seek offset bytes from end of file. + In the case of non-seekable files (i.e. pipes 'n shit), this is a noop. + Returns the new file position, in bytes from the start. diff --git a/kernel/src/ring3.S b/kernel/src/ring3.S index 43c8192..4bb41c7 100644 --- a/kernel/src/ring3.S +++ b/kernel/src/ring3.S @@ -66,7 +66,6 @@ syscall_64bit_handler: callq *syscalls_call_table(, %rax, 8) syscall_end: mov %rax, %rbp # Save the return - mov %rdx, %rbx # registers. # Get process data location: mov current_pid, %rdi call get_process @@ -75,8 +74,7 @@ syscall_end: mov 8 + \reg * 8(%rax), %rbx # Get %r\reg mov %rbx, save_regs_tmp + \reg * 8 # And restore it. .endr - mov %rbp, save_reg_tmp_rax # Restore the return - mov %rbx, save_reg_tmp_rdx # registers as well. + mov %rbp, save_reg_tmp_rax # Restore the return register as well. mov 0x88(%rax), %rbx # Save the rip in place of rcx, because this is sysret. mov %rbx, save_reg_tmp_rcx # Really restore all regs: -- 2.47.0