diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 770233583..3268b2146 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -10,7 +10,7 @@ on: push: branches: ["main"] pull_request: - branches: ["main"] + branches: ["main", "144-support-musl"] jobs: formatting-check: diff --git a/so3/arch/arm32/include/asm/mmu.h b/so3/arch/arm32/include/asm/mmu.h index 1593b94fb..0817a0fcc 100644 --- a/so3/arch/arm32/include/asm/mmu.h +++ b/so3/arch/arm32/include/asm/mmu.h @@ -39,6 +39,9 @@ #define USER_SPACE_VADDR 0x1000ul +/* Anonymous start virtual address */ +#define USER_ANONYMOUS_VADDR UL(CONFIG_KERNEL_VADDR / 2) + /* Memory space all I/O mapped registers and additional mappings */ #define IO_MAPPING_BASE 0xe0000000 diff --git a/so3/arch/arm32/include/asm/syscall_number.h b/so3/arch/arm32/include/asm/syscall_number.h index 7474f8f2e..1da6a2f71 100644 --- a/so3/arch/arm32/include/asm/syscall_number.h +++ b/so3/arch/arm32/include/asm/syscall_number.h @@ -78,4 +78,7 @@ #define SYSCALL_SETSOCKOPT 110 #define SYSCALL_RECVFROM 111 +#define SYSCALL_READV 145 +#define SYSCALL_WRITEV 146 + #endif /* ARCH_ARM32_SYSCALL_NUMBER_H */ diff --git a/so3/arch/arm64/include/asm/mmu.h b/so3/arch/arm64/include/asm/mmu.h index e6e4d0ddb..34c913043 100644 --- a/so3/arch/arm64/include/asm/mmu.h +++ b/so3/arch/arm64/include/asm/mmu.h @@ -35,6 +35,9 @@ /* Fixmap page used for temporary mapping */ #define FIXMAP_MAPPING UL(0xffffb00000000000) +/* Anonymous start virtual address */ +#define USER_ANONYMOUS_VADDR UL(0x0000000100000000) + /* The user space can be up to bits [47:0] and uses ttbr0_el1 * as main L0 page table. */ @@ -45,6 +48,9 @@ /* Fixmap page used for temporary mapping */ #define FIXMAP_MAPPING UL(0xffffffd800000000) +/* Anonymous start virtual address */ +#define USER_ANONYMOUS_VADDR UL(0x0000000100000000) + /* The user space can be up to bits [38:0] and uses ttbr0_el1 * as main L0 page table. */ diff --git a/so3/arch/arm64/include/asm/syscall_number.h b/so3/arch/arm64/include/asm/syscall_number.h index d81a0858a..2cbbea82d 100644 --- a/so3/arch/arm64/include/asm/syscall_number.h +++ b/so3/arch/arm64/include/asm/syscall_number.h @@ -71,6 +71,9 @@ #define SYSCALL_MUTEX_LOCK 60 #define SYSCALL_MUTEX_UNLOCK 61 +#define SYSCALL_READV 65 +#define SYSCALL_WRITEV 66 + #define SYSCALL_NANOSLEEP 70 #define SYSCALL_SYSINFO 99 diff --git a/so3/devices/serial/pl011.c b/so3/devices/serial/pl011.c index 6bd6bee18..601be88f2 100644 --- a/so3/devices/serial/pl011.c +++ b/so3/devices/serial/pl011.c @@ -119,7 +119,7 @@ static irq_return_t pl011_int(int irq, void *dummy) #ifdef CONFIG_IPC_SIGNAL if (current()->pcb != NULL) - do_kill(current()->pcb->pid, SIGINT); + sys_do_kill(current()->pcb->pid, SIGINT); #endif } diff --git a/so3/fs/elf.c b/so3/fs/elf.c index dce824587..0489e7de5 100644 --- a/so3/fs/elf.c +++ b/so3/fs/elf.c @@ -35,12 +35,12 @@ uint8_t *elf_load_buffer(const char *filename) struct stat st; /* open and read file */ - fd = do_open(filename, O_RDONLY); + fd = sys_do_open(filename, O_RDONLY); if (fd < 0) return NULL; - if (do_stat(filename, &st)) + if (sys_do_stat(filename, &st)) return NULL; if (!st.st_size) @@ -52,9 +52,9 @@ uint8_t *elf_load_buffer(const char *filename) return NULL; } - do_read(fd, buffer, st.st_size); + sys_do_read(fd, buffer, st.st_size); - do_close(fd); + sys_do_close(fd); return buffer; } diff --git a/so3/fs/vfs.c b/so3/fs/vfs.c index 3f1ac96a2..7c0ee97bb 100644 --- a/so3/fs/vfs.c +++ b/so3/fs/vfs.c @@ -380,7 +380,8 @@ int vfs_clone_fd(int *fd_src, int *fd_dst) /**************************** Syscall implementation ****************************/ -SYSCALL_DEFINE3(read, int, fd, void *, buffer, int, count) +/* Low Level read */ +static int do_read(int fd, void *buffer, int count) { int gfd; int ret; @@ -421,10 +422,8 @@ SYSCALL_DEFINE3(read, int, fd, void *, buffer, int, count) return ret; } -/** - * @brief This function writes a REGULAR FILE/FOLDER. It only support regular file, dirs and pipes - */ -SYSCALL_DEFINE3(write, int, fd, const void *, buffer, int, count) +/* Low Level write */ +static int do_write(int fd, const void *buffer, int count) { int gfd; int ret; @@ -464,6 +463,88 @@ SYSCALL_DEFINE3(write, int, fd, const void *, buffer, int, count) return ret; } +/* Low Level mmap */ +static int do_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offset) +{ + int gfd; + struct file_operations *fops; + + /* Get the fops associated to the file descriptor. */ + gfd = vfs_get_gfd(fd); + if (-1 == gfd) { + printk("%s: could not get global fd.\n", __func__); + return -EBADF; + } + + mutex_lock(&vfs_lock); + fops = vfs_get_fops(gfd); + if (!fops) { + printk("%s: could not get device fops.\n", __func__); + mutex_unlock(&vfs_lock); + return -EBADF; + } + + mutex_unlock(&vfs_lock); + + if (!fops->mmap) { + printk("%s: device doesn't support mmap.\n", __func__); + return -EACCES; + } + + /* Call the mmap fops that will do the actual mapping. */ + return (long) fops->mmap(fd, virt_addr, page_count, offset); +} + +/* Low Level mmap - Anonymous case */ +static int do_mmap_anon(int fd, addr_t virt_addr, uint32_t page_count, off_t offset) +{ + uint32_t page; + pcb_t *pcb; + int i; + + if (offset != 0) { + printk("%s: Offset should be 0 with MAP_ANONYMOUS flag\n", __func__); + return -EINVAL; + } + + pcb = current()->pcb; + + /* Start is smaller or NULL than initial virt_addr pointer */ + if (virt_addr < pcb->next_anon_start) + virt_addr = pcb->next_anon_start; + + for (i = 0; i < page_count; i++) { + page = get_free_page(); + BUG_ON(!page); + + create_mapping(pcb->pgtable, virt_addr + (i * PAGE_SIZE), page, PAGE_SIZE, false); + add_page_to_proc(pcb, phys_to_page(page)); + } + + memset((void *) virt_addr, 0, page_count * PAGE_SIZE); + + /* WARNIMG - This is a simple/basic way to set the start virtual address: + It only increment the start address after each mmap call, no algorithm + to search for available spaces. + */ + pcb->next_anon_start = virt_addr + (page_count * PAGE_SIZE); + + return virt_addr; +} + +SYSCALL_DEFINE3(read, int, fd, void *, buffer, int, count) +{ + return do_read(fd, buffer, count); +} + +/** + * @brief This function writes a REGULAR FILE/FOLDER. It only support regular file, dirs and pipes + */ +SYSCALL_DEFINE3(write, int, fd, const void *, buffer, int, count) +{ + return do_write(fd, buffer, count); +} + /** * @brief This function opens a file. Not all file types are supported. */ @@ -655,7 +736,7 @@ SYSCALL_DEFINE2(dup2, int, oldfd, int, newfd) } if (vfs_get_gfd(oldfd) != vfs_get_gfd(newfd)) - do_close(newfd); + sys_do_close(newfd); vfs_link_fd(newfd, vfs_get_gfd(oldfd)); @@ -726,29 +807,9 @@ SYSCALL_DEFINE2(stat, const char *, path, struct stat *, st) /** * An mmap() implementation in VFS. */ -SYSCALL_DEFINE5(mmap, addr_t, start, size_t, length, int, prot, int, fd, off_t, offset) +SYSCALL_DEFINE6(mmap, addr_t, start, size_t, length, int, prot, int, flags, int, fd, off_t, offset) { - int gfd; uint32_t page_count; - struct file_operations *fops; - - /* Get the fops associated to the file descriptor. */ - - gfd = vfs_get_gfd(fd); - if (-1 == gfd) { - printk("%s: could not get global fd.\n", __func__); - return -EBADF; - } - - mutex_lock(&vfs_lock); - fops = vfs_get_fops(gfd); - if (!fops) { - printk("%s: could not get device fops.\n", __func__); - mutex_unlock(&vfs_lock); - return -EBADF; - } - - mutex_unlock(&vfs_lock); /* Page count to allocate to the current process to be able to map the desired region. */ page_count = length / PAGE_SIZE; @@ -756,13 +817,10 @@ SYSCALL_DEFINE5(mmap, addr_t, start, size_t, length, int, prot, int, fd, off_t, page_count++; } - if (!fops->mmap) { - printk("%s: device doesn't support mmap.\n", __func__); - return -EACCES; - } - - /* Call the mmap fops that will do the actual mapping. */ - return (long) fops->mmap(fd, start, page_count, offset); + if (flags & MAP_ANONYMOUS) + return do_mmap_anon(fd, start, page_count, offset); + else + return do_mmap(fd, start, page_count, offset); } SYSCALL_DEFINE3(ioctl, int, fd, unsigned long, cmd, unsigned long, args) @@ -824,6 +882,57 @@ SYSCALL_DEFINE3(fcntl, int, fd, unsigned long, cmd, unsigned long, args) return 0; } +/* + * Implementation of the writev syscall + */ +SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec *, vec, unsigned long, vlen) +{ + int i; + int ret = 0; + int total = 0; + + for (i = 0; i < vlen; i++) { + ret = do_write(fd, (const void *) vec[i].iov_base, vec[i].iov_len); + if (ret < 0) { + break; + } else if ((ret >= 0) && (ret < vec[i].iov_len)) { + total += ret; + break; + } + + total += ret; + } + + if (total == 0) + return ret; + else + return total; +} + +SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec *, vec, unsigned long, vlen) +{ + int i; + int ret = 0; + int total = 0; + + for (i = 0; i < vlen; i++) { + ret = do_read(fd, vec[i].iov_base, vec[i].iov_len); + if (ret < 0) { + break; + } else if ((ret >= 0) && (ret < vec[i].iov_len)) { + total += ret; + break; + } + + total += ret; + } + + if (total == 0) + return ret; + else + return total; +} + static void vfs_gfd_init(void) { memset(open_fds, 0, MAX_FDS * sizeof(struct fd *)); diff --git a/so3/include/process.h b/so3/include/process.h index 1623daa1b..83fceefe7 100644 --- a/so3/include/process.h +++ b/so3/include/process.h @@ -76,6 +76,9 @@ struct pcb { /* current position of the heap pointer */ addr_t heap_pointer; + /* next anonymous start pointer */ + addr_t next_anon_start; + /* Number of pages required by this process (including binary image) */ size_t page_count; diff --git a/so3/include/syscall.h b/so3/include/syscall.h index eaf3ed73b..1c1031576 100644 --- a/so3/include/syscall.h +++ b/so3/include/syscall.h @@ -84,20 +84,20 @@ * __sys_SYSCALL_NAME taking syscall_args_t as arguments allowing for * a common interface between all syscall to put them in an array. * - * do_SYSCALL_NAME actual function with the syscall implementation with + * sys_do_SYSCALL_NAME actual function with the syscall implementation with * arguments define like a normal function. That function is automatically * called by __sys_SYCALL_NAME with the correct argument number and cast. */ #define SYSCALL_DECLARE(name, ...) \ long __sys_##name(syscall_args_t *args); \ - inline long do_##name(__VA_ARGS__); + inline long sys_do_##name(__VA_ARGS__); #define SYSCALL_DEFINE0(name) \ long __sys_##name(syscall_args_t *unused) \ { \ - return do_##name(); \ + return sys_do_##name(); \ } \ - inline long do_##name(void) + inline long sys_do_##name(void) #define SYSCALL_DEFINE1(...) __SYSCALL_DEFINEx(1, __VA_ARGS__) #define SYSCALL_DEFINE2(...) __SYSCALL_DEFINEx(2, __VA_ARGS__) #define SYSCALL_DEFINE3(...) __SYSCALL_DEFINEx(3, __VA_ARGS__) @@ -105,12 +105,12 @@ #define SYSCALL_DEFINE5(...) __SYSCALL_DEFINEx(5, __VA_ARGS__) #define SYSCALL_DEFINE6(...) __SYSCALL_DEFINEx(6, __VA_ARGS__) -#define __SYSCALL_DEFINEx(x, name, ...) \ - long __sys_##name(syscall_args_t *args) \ - { \ - return do_##name(__MAP_ARGS(x, args->args, __VA_ARGS__)); \ - } \ - inline long do_##name(__MAP(x, __M_DECL, __VA_ARGS__)) +#define __SYSCALL_DEFINEx(x, name, ...) \ + long __sys_##name(syscall_args_t *args) \ + { \ + return sys_do_##name(__MAP_ARGS(x, args->args, __VA_ARGS__)); \ + } \ + inline long sys_do_##name(__MAP(x, __M_DECL, __VA_ARGS__)) typedef struct { unsigned long args[6]; diff --git a/so3/include/vfs.h b/so3/include/vfs.h index a6956db23..89430c6c4 100644 --- a/so3/include/vfs.h +++ b/so3/include/vfs.h @@ -91,6 +91,9 @@ #define DT_LNK 10 /* Symbolic link */ #define DT_SOCK 12 /* Socket device */ +/* mmap flags options */ +#define MAP_ANONYMOUS 0x10 /* don't use a file */ + /* Return error values */ #define MAP_FAILED ((void *) -1) /* mmap fail */ @@ -103,6 +106,13 @@ #include +struct iovec { + void *iov_base; + size_t iov_len; +}; + +#define iovec iovec + struct file_operations { int (*open)(int fd, const char *path); int (*close)(int fd); @@ -158,10 +168,12 @@ SYSCALL_DECLARE(close, int fd); SYSCALL_DECLARE(dup, int oldfd); SYSCALL_DECLARE(dup2, int oldfd, int newfd); SYSCALL_DECLARE(stat, const char *path, struct stat *st); -SYSCALL_DECLARE(mmap, addr_t start, size_t length, int prot, int fd, off_t offset); +SYSCALL_DECLARE(mmap, addr_t start, size_t length, int prot, int flags, int fd, off_t offset); SYSCALL_DECLARE(ioctl, int fd, unsigned long cmd, unsigned long args); SYSCALL_DECLARE(fcntl, int fd, unsigned long cmd, unsigned long args); SYSCALL_DECLARE(lseek, int fd, off_t off, int whence); +SYSCALL_DECLARE(writev, unsigned long fd, const struct iovec *vec, unsigned long vlen); +SYSCALL_DECLARE(readv, unsigned long fd, const struct iovec *vec, unsigned long vlen); /* VFS common interface */ diff --git a/so3/kernel/process.c b/so3/kernel/process.c index bc065224a..21a21f628 100644 --- a/so3/kernel/process.c +++ b/so3/kernel/process.c @@ -185,6 +185,8 @@ pcb_t *new_process(void) pcb->state = PROC_STATE_NEW; + pcb->next_anon_start = USER_ANONYMOUS_VADDR; + /* Reset the ptrace request indicator */ pcb->ptrace_pending_req = PTRACE_NO_REQUEST; @@ -925,7 +927,7 @@ SYSCALL_DEFINE1(exit, int, exit_status) * locking in the low layers. */ for (i = 0; i < FD_MAX; i++) - do_close(i); + sys_do_close(i); local_irq_disable(); @@ -944,7 +946,7 @@ SYSCALL_DEFINE1(exit, int, exit_status) #ifdef CONFIG_IPC_SIGNAL /* Send the SIGCHLD signal to the parent */ - do_kill(pcb->parent->pid, SIGCHLD); + sys_do_kill(pcb->parent->pid, SIGCHLD); #endif /* CONFIG_IPC_SIGNAL */ diff --git a/so3/kernel/syscalls.c b/so3/kernel/syscalls.c index 4c61b0b16..68e15083f 100644 --- a/so3/kernel/syscalls.c +++ b/so3/kernel/syscalls.c @@ -60,6 +60,8 @@ static const syscall_fn_t syscall_table[NR_SYSCALLS] = { [SYSCALL_IOCTL] = __sys_ioctl, [SYSCALL_FCNTL] = __sys_fcntl, [SYSCALL_LSEEK] = __sys_lseek, + [SYSCALL_READV] = __sys_readv, + [SYSCALL_WRITEV] = __sys_writev, #ifdef CONFIG_IPC_PIPE [SYSCALL_PIPE] = __sys_pipe, #endif diff --git a/so3/kernel/thread.c b/so3/kernel/thread.c index 868c31835..363ec1520 100644 --- a/so3/kernel/thread.c +++ b/so3/kernel/thread.c @@ -272,7 +272,7 @@ void thread_exit(int *exit_status) remove_tcb_from_pcb(current()); #ifdef CONFIG_PROC_ENV - do_exit(0); + sys_do_exit(0); #endif } else { diff --git a/so3/net/net.c b/so3/net/net.c index 7ca28cb3f..d638f0797 100644 --- a/so3/net/net.c +++ b/so3/net/net.c @@ -413,7 +413,7 @@ SYSCALL_DEFINE3(socket, int, domain, int, type, int, protocol) lwip_fd = lwip_socket(domain, type, protocol); if (lwip_fd < 0) { - do_close(fd); + sys_do_close(fd); return lwip_return(lwip_fd); } @@ -505,7 +505,7 @@ SYSCALL_DEFINE3(accept, int, sockfd, struct sockaddr *, addr, socklen_t *, addrl lwip_bind_fd = lwip_accept(lwip_fd, addr_ptr, addrlen); if (lwip_bind_fd < 0) { - do_close(fd); + sys_do_close(fd); return lwip_return(lwip_bind_fd); }