diff options
51 files changed, 2080 insertions, 99 deletions
diff --git a/Makefile.in b/Makefile.in index 8b098c6..f4336a7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -47,6 +47,8 @@ else override LD = $(shell pwd)/cross/bin/$(ARCH)-hyra-ld endif override AS = $(CC) +override LDSO = $(shell pwd)/base/usr/lib/ld.so +override USER_MKFLGS = CC=$(CC) LD=$(LD) LDSO=$(LDSO) ########################## # Architecture specifics @@ -69,10 +71,28 @@ override KERNEL_ASMOBJECTS = $(KERNEL_ASMFILES:.S=.S.o) override KERNEL_HEADER_DEPS = $(KERNEL_CFILES:.c=.d) .PHONY: all -all: base/boot/hyra-kernel +all: base lib userland base/usr/lib/ld.so base/boot/hyra-kernel rm -f sys/include/machine rm -rf iso_root +base/usr/sbin/init: + cd usr.sbin/; make $(USER_MKFLGS) + mv usr.sbin/init/init base/usr/sbin/ + +# TODO: Make this more flexible +.PHONY: userland +userland: base/usr/sbin/init + +base: + mkdir -p base/usr/lib/ + mkdir -p base/usr/sbin/ + mkdir -p base/boot/ + +.PHONY: lib +lib: + cd lib/; make $(USER_MKFLGS) + cp lib/libc/build/ld.so base/usr/lib/ + .PHONY: run run: $(QEMU) $(QEMU_FLAGS) @@ -82,6 +102,15 @@ cross: bash tools/cross.sh $(ARCH) .PHONY: clean +distclean: + make clean + rm -f $(KERNEL_ASMOBJECTS) $(KERNEL_OBJECTS) $(KERNEL_HEADER_DEPS) + rm -f sys/include/machine + rm -f base/usr/lib/ld.so + rm -f base/boot/init + cd lib/; make clean + +.PHONY: clean clean: rm -f $(KERNEL_ASMOBJECTS) $(KERNEL_OBJECTS) $(KERNEL_HEADER_DEPS) rm -f sys/include/machine @@ -91,7 +120,6 @@ sys/include/machine/: base/boot/hyra-kernel: $(KERNEL_OBJECTS) $(KERNEL_ASMOBJECTS) rm -rf iso_root - mkdir -p base/boot/ $(PROMPT) " LD " $(shell pwd)/base/boot/hyra-kernel $(LD) $(KERNEL_LDFLAGS) $(KERNEL_OBJECTS) $(KERNEL_ASMOBJECTS) -o base/boot/hyra-kernel tools/ksyms sys/kern/ksyms.c base/boot/hyra-kernel diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..3881833 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,7 @@ +.PHONY: libc +libc: + cd libc; make CC=$(CC) + +.PHONY: clean +clean: + cd libc/; make clean diff --git a/lib/libc/.gitignore b/lib/libc/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/lib/libc/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/lib/libc/Makefile b/lib/libc/Makefile new file mode 100644 index 0000000..aa09a4c --- /dev/null +++ b/lib/libc/Makefile @@ -0,0 +1,28 @@ +CFLAGS = -c -fno-stack-protector -nostdlib -static -Iinclude/ +LIBC_CFILES = $(shell find src/ -name "*.c") +LIBC_ASMFILES = $(shell find src/ -name "*.S") + +LIBC_OBJ = $(LIBC_CFILES:.c=.o) +LIBC_ASMOBJ = $(LIBC_ASMFILES:.S=.S.o) + +all: $(LIBC_OBJ) build/ld.so + +build/ld.so: build/ linker/entry.c linker/entry.S + mkdir -p $(@D) + $(CC) $(CFLAGS) linker/entry.S -o build/entry.S.o + $(CC) $(CFLAGS) linker/entry.c -o build/entry.o + $(LD) build/entry.o build/entry.S.o -o $(LIBC_OBJ) -o $@ + +%.o: %.c + $(CC) $(CFLAGS) $< -o $@ + +%.S.o: %.S + gcc $(CFLAGS) $< -o $@ + +.PHONY: +build/: + mkdir -p build/ + +.PHONY: clean +clean: + rm -rf build/ diff --git a/lib/libc/include/bits/_types.h b/lib/libc/include/bits/_types.h new file mode 100644 index 0000000..5f84e5e --- /dev/null +++ b/lib/libc/include/bits/_types.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BITS__TYPES_H +#define _BITS__TYPES_H + +typedef unsigned long __size_t; +typedef long __ssize_t; +typedef long __ptrdiff_t; + +typedef __UINT8_TYPE__ __uint8_t; +typedef __UINT16_TYPE__ __uint16_t; +typedef __UINT32_TYPE__ __uint32_t; +typedef __UINT64_TYPE__ __uint64_t; + +typedef __INT8_TYPE__ __int8_t; +typedef __INT16_TYPE__ __int16_t; +typedef __INT32_TYPE__ __int32_t; +typedef __INT64_TYPE__ __int64_t; + +#endif /* !_BITS__TYPES_H */ diff --git a/lib/libc/include/elf.h b/lib/libc/include/elf.h new file mode 100644 index 0000000..4e0c1eb --- /dev/null +++ b/lib/libc/include/elf.h @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_ELF_H_ +#define _SYS_ELF_H_ + +#include <stdint.h> + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ +#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_IAMCU 6 /* Intel MCU */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + /* reserved 11-14 */ +#define EM_PARISC 15 /* HPPA */ + /* reserved 16 */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ +#define EM_SPU 23 /* IBM SPU/SPC */ + /* reserved 24-35 */ +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam */ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ +#define EM_PDP10 64 /* Digital PDP-10 */ +#define EM_PDP11 65 /* Digital PDP-11 */ +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit emb.proc */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit emb.proc */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_COMPACT 93 /* ARC International ARCompact */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Proc */ +#define EM_NS32K 97 /* National Semi. 32000 */ +#define EM_TPC 98 /* Tenor Network TPC */ +#define EM_SNP1K 99 /* Trebia SNP 1000 */ +#define EM_ST200 100 /* STMicroelectronics ST200 */ +#define EM_IP2K 101 /* Ubicom IP2xxx */ +#define EM_MAX 102 /* MAX processor */ +#define EM_CR 103 /* National Semi. CompactRISC */ +#define EM_F2MC16 104 /* Fujitsu F2MC16 */ +#define EM_MSP430 105 /* Texas Instruments msp430 */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin DSP */ +#define EM_SE_C33 107 /* Seiko Epson S1C33 family */ +#define EM_SEP 108 /* Sharp embedded microprocessor */ +#define EM_ARCA 109 /* Arca RISC */ +#define EM_UNICORE 110 /* PKU-Unity & MPRC Peking Uni. mc series */ +#define EM_EXCESS 111 /* eXcess configurable cpu */ +#define EM_DXP 112 /* Icera Semi. Deep Execution Processor */ +#define EM_ALTERA_NIOS2 113 /* Altera Nios II */ +#define EM_CRX 114 /* National Semi. CompactRISC CRX */ +#define EM_XGATE 115 /* Motorola XGATE */ +#define EM_C166 116 /* Infineon C16x/XC16x */ +#define EM_M16C 117 /* Renesas M16C */ +#define EM_DSPIC30F 118 /* Microchip Technology dsPIC30F */ +#define EM_CE 119 /* Freescale Communication Engine RISC */ +#define EM_M32C 120 /* Renesas M32C */ + /* reserved 121-130 */ +#define EM_TSK3000 131 /* Altium TSK3000 */ +#define EM_RS08 132 /* Freescale RS08 */ +#define EM_SHARC 133 /* Analog Devices SHARC family */ +#define EM_ECOG2 134 /* Cyan Technology eCOG2 */ +#define EM_SCORE7 135 /* Sunplus S+core7 RISC */ +#define EM_DSP24 136 /* New Japan Radio (NJR) 24-bit DSP */ +#define EM_VIDEOCORE3 137 /* Broadcom VideoCore III */ +#define EM_LATTICEMICO32 138 /* RISC for Lattice FPGA */ +#define EM_SE_C17 139 /* Seiko Epson C17 */ +#define EM_TI_C6000 140 /* Texas Instruments TMS320C6000 DSP */ +#define EM_TI_C2000 141 /* Texas Instruments TMS320C2000 DSP */ +#define EM_TI_C5500 142 /* Texas Instruments TMS320C55x DSP */ +#define EM_TI_ARP32 143 /* Texas Instruments App. Specific RISC */ +#define EM_TI_PRU 144 /* Texas Instruments Prog. Realtime Unit */ + /* reserved 145-159 */ +#define EM_MMDSP_PLUS 160 /* STMicroelectronics 64bit VLIW DSP */ +#define EM_CYPRESS_M8C 161 /* Cypress M8C */ +#define EM_R32C 162 /* Renesas R32C */ +#define EM_TRIMEDIA 163 /* NXP Semi. TriMedia */ +#define EM_QDSP6 164 /* QUALCOMM DSP6 */ +#define EM_8051 165 /* Intel 8051 and variants */ +#define EM_STXP7X 166 /* STMicroelectronics STxP7x */ +#define EM_NDS32 167 /* Andes Tech. compact code emb. RISC */ +#define EM_ECOG1X 168 /* Cyan Technology eCOG1X */ +#define EM_MAXQ30 169 /* Dallas Semi. MAXQ30 mc */ +#define EM_XIMO16 170 /* New Japan Radio (NJR) 16-bit DSP */ +#define EM_MANIK 171 /* M2000 Reconfigurable RISC */ +#define EM_CRAYNV2 172 /* Cray NV2 vector architecture */ +#define EM_RX 173 /* Renesas RX */ +#define EM_METAG 174 /* Imagination Tech. META */ +#define EM_MCST_ELBRUS 175 /* MCST Elbrus */ +#define EM_ECOG16 176 /* Cyan Technology eCOG16 */ +#define EM_CR16 177 /* National Semi. CompactRISC CR16 */ +#define EM_ETPU 178 /* Freescale Extended Time Processing Unit */ +#define EM_SLE9X 179 /* Infineon Tech. SLE9X */ +#define EM_L10M 180 /* Intel L10M */ +#define EM_K10M 181 /* Intel K10M */ + /* reserved 182 */ +#define EM_AARCH64 183 /* ARM AARCH64 */ + /* reserved 184 */ +#define EM_AVR32 185 /* Amtel 32-bit microprocessor */ +#define EM_STM8 186 /* STMicroelectronics STM8 */ +#define EM_TILE64 187 /* Tileta TILE64 */ +#define EM_TILEPRO 188 /* Tilera TILEPro */ +#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */ +#define EM_CUDA 190 /* NVIDIA CUDA */ +#define EM_TILEGX 191 /* Tilera TILE-Gx */ +#define EM_CLOUDSHIELD 192 /* CloudShield */ +#define EM_COREA_1ST 193 /* KIPO-KAIST Core-A 1st gen. */ +#define EM_COREA_2ND 194 /* KIPO-KAIST Core-A 2nd gen. */ +#define EM_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */ +#define EM_OPEN8 196 /* Open8 RISC */ +#define EM_RL78 197 /* Renesas RL78 */ +#define EM_VIDEOCORE5 198 /* Broadcom VideoCore V */ +#define EM_78KOR 199 /* Renesas 78KOR */ +#define EM_56800EX 200 /* Freescale 56800EX DSC */ +#define EM_BA1 201 /* Beyond BA1 */ +#define EM_BA2 202 /* Beyond BA2 */ +#define EM_XCORE 203 /* XMOS xCORE */ +#define EM_MCHP_PIC 204 /* Microchip 8-bit PIC(r) */ + /* reserved 205-209 */ +#define EM_KM32 210 /* KM211 KM32 */ +#define EM_KMX32 211 /* KM211 KMX32 */ +#define EM_EMX16 212 /* KM211 KMX16 */ +#define EM_EMX8 213 /* KM211 KMX8 */ +#define EM_KVARC 214 /* KM211 KVARC */ +#define EM_CDP 215 /* Paneve CDP */ +#define EM_COGE 216 /* Cognitive Smart Memory Processor */ +#define EM_COOL 217 /* Bluechip CoolEngine */ +#define EM_NORC 218 /* Nanoradio Optimized RISC */ +#define EM_CSR_KALIMBA 219 /* CSR Kalimba */ +#define EM_Z80 220 /* Zilog Z80 */ +#define EM_VISIUM 221 /* Controls and Data Services VISIUMcore */ +#define EM_FT32 222 /* FTDI Chip FT32 */ +#define EM_MOXIE 223 /* Moxie processor */ +#define EM_AMDGPU 224 /* AMD GPU */ + /* reserved 225-242 */ +#define EM_RISCV 243 /* RISC-V */ + +#define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */ + +#define EM_NUM 248 + +/* Old spellings/synonyms. */ + +#define EM_ARC_A5 EM_ARC_COMPACT + +/* If it is necessary to assign new unofficial EM_* values, please + pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the + chances of collision with official or non-GNU unofficial values. */ + +#define EM_ALPHA 0x9026 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +#define EI_NIDENT (16) + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_PRFPREG 2 /* Contains copy of fpregset + struct. */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ +#define NT_SIGINFO 0x53494749 /* Contains copy of siginfo_t, + size might increase */ +#define NT_FILE 0x46494c45 /* Contains information about mapped + files */ +#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ +#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ +#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ +#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ +#define NT_PPC_TAR 0x103 /* Target Address Register */ +#define NT_PPC_PPR 0x104 /* Program Priority Register */ +#define NT_PPC_DSCR 0x105 /* Data Stream Control Register */ +#define NT_PPC_EBB 0x106 /* Event Based Branch Registers */ +#define NT_PPC_PMU 0x107 /* Performance Monitor Registers */ +#define NT_PPC_TM_CGPR 0x108 /* TM checkpointed GPR Registers */ +#define NT_PPC_TM_CFPR 0x109 /* TM checkpointed FPR Registers */ +#define NT_PPC_TM_CVMX 0x10a /* TM checkpointed VMX Registers */ +#define NT_PPC_TM_CVSX 0x10b /* TM checkpointed VSX Registers */ +#define NT_PPC_TM_SPR 0x10c /* TM Special Purpose Registers */ +#define NT_PPC_TM_CTAR 0x10d /* TM checkpointed Target Address + Register */ +#define NT_PPC_TM_CPPR 0x10e /* TM checkpointed Program Priority + Register */ +#define NT_PPC_TM_CDSCR 0x10f /* TM checkpointed Data Stream Control + Register */ +#define NT_PPC_PKEY 0x110 /* Memory Protection Keys + registers. */ +#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ +#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ +#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ +#define NT_S390_TIMER 0x301 /* s390 timer register */ +#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ +#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ +#define NT_S390_CTRS 0x304 /* s390 control registers */ +#define NT_S390_PREFIX 0x305 /* s390 prefix register */ +#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ +#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ +#define NT_S390_TDB 0x308 /* s390 transaction diagnostic block */ +#define NT_S390_VXRS_LOW 0x309 /* s390 vector registers 0-15 + upper half. */ +#define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31. */ +#define NT_S390_GS_CB 0x30b /* s390 guarded storage registers. */ +#define NT_S390_GS_BC 0x30c /* s390 guarded storage + broadcast control block. */ +#define NT_S390_RI_CB 0x30d /* s390 runtime instrumentation. */ +#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ +#define NT_ARM_TLS 0x401 /* ARM TLS register */ +#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ +#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ +#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */ +#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension + registers */ +#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note. */ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +typedef struct { + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct { + Elf64_Word sh_name; /* Section name, index in string tbl */ + Elf64_Word sh_type; /* Type of section */ + Elf64_Xword sh_flags; /* Miscellaneous section attributes */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Size of section in bytes */ + Elf64_Word sh_link; /* Index of another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +#endif /* _SYS_ELF_H_ */ diff --git a/lib/libc/include/stddef.h b/lib/libc/include/stddef.h new file mode 100644 index 0000000..70b3ccf --- /dev/null +++ b/lib/libc/include/stddef.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _STDDEF_H +#define _STDDEF_H + +#include <bits/_types.h> + +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) +#define NULL 0L +#else +#define NULL ((void *) 0) +#endif + +typedef __size_t size_t; + +#endif /* !_STDDEF_H */ diff --git a/lib/libc/include/stdint.h b/lib/libc/include/stdint.h new file mode 100644 index 0000000..ed6aa08 --- /dev/null +++ b/lib/libc/include/stdint.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _STDINT_H +#define _STDINT_H + +#include <bits/_types.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef __uint8_t uint8_t; +typedef __uint16_t uint16_t; +typedef __uint32_t uint32_t; +typedef __uint64_t uint64_t; + +typedef __int8_t int8_t; +typedef __int16_t int16_t; +typedef __int32_t int32_t; +typedef __int64_t int64_t; + +/* Signed fixed-width limits */ +#define INT8_MAX __INT8_MAX +#define INT16_MAX __INT16_MAX +#define INT32_MAX __INT32_MAX +#define INT64_MAX __INT64_MAX + +/* Unsigned fixed-width limits */ +#define UINT8_MAX __UINT8_MAX +#define UINT16_MAX __UINT16_MAX +#define UINT32_MAX __UINT32_MAX +#define UINT64_MAX __UINT64_MAX + +#if defined(__cplusplus) +} +#endif + +#endif /* !_STDINT_H */ diff --git a/lib/libc/include/sys/auxv.h b/lib/libc/include/sys/auxv.h new file mode 100644 index 0000000..b06d01c --- /dev/null +++ b/lib/libc/include/sys/auxv.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_AUXV_H +#define _SYS_AUXV_H + +#include <stdint.h> + +#define AT_NULL 0 +#define AT_ENTRY 1 +#define AT_PHDR 2 +#define AT_PHENT 3 +#define AT_PHNUM 4 +#define AT_EXECPATH 5 +#define AT_SECURE 6 +#define AT_RANDOM 7 +#define AT_EXECFN 8 + +#define AT_MAX_COUNT 9 + +struct auxv_entry { + uint64_t tag; + union { + uint64_t val; + void* ptr; + }; +}; + +#endif /* _SYS_AUXV_H */ diff --git a/lib/libc/include/sys/syscall.h b/lib/libc/include/sys/syscall.h new file mode 100644 index 0000000..34f762d --- /dev/null +++ b/lib/libc/include/sys/syscall.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#if !defined(__ASSEMBLER__) +#include <stdint.h> +#endif + +#define SYS_exit 1 + +#if !defined(__ASSEMBLER__) +__attribute__((__always_inline__)) +static inline long +syscall0(uint64_t code) +{ + volatile long ret; + asm volatile("int $0x80" : "=a"(ret) : "a"(code)); + return ret; +} + +__attribute__((__always_inline__)) +static inline long +syscall1(uint64_t code, uint64_t arg0) +{ + volatile long ret; + asm volatile("int $0x80" : "=a"(ret) : "a"(code), "D"(arg0) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static long inline +syscall2(uint64_t code, uint64_t arg0, uint64_t arg1) +{ + volatile long ret; + asm volatile("int $0x80" : "=a"(ret) : "a"(code), "D"(arg0), "S"(arg1) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static inline long +syscall3(uint64_t code, uint64_t arg0, uint64_t arg1, uint64_t arg2) +{ + volatile long ret; + asm volatile("int $0x80" : "=a"(ret) : "a"(code), "D"(arg0), "S"(arg1), "d"(arg2) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static inline long +syscall4(uint64_t code, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3) +{ + volatile long ret; + register uint64_t _arg3 asm("r10") = arg3; + asm volatile("int $0x80" : "=a"(ret) : "a"(code), "D"(arg0), "S"(arg1), "d"(arg2), "r"(_arg3) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static inline long +syscall5(uint64_t code, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) +{ + volatile long ret; + register uint64_t _arg3 asm("r10") = arg3; + register uint64_t _arg4 asm("r9") = arg4; + asm volatile("int $0x80" : "=a"(ret) : "a"(code), "D"(arg0), "S"(arg1), "d"(arg2), "r"(_arg3), "r"(_arg4) : "memory"); + return ret; +} + +__attribute__((__always_inline__)) +static inline long +syscall6(uint64_t code, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) { + volatile long ret; + register uint64_t _arg3 asm("r10") = arg3; + register uint64_t _arg4 asm("r9") = arg4; + register uint64_t _arg5 asm("r8") = arg5; + asm volatile("int $0x80" : "=a"(ret) : "a"(code), "D"(arg0), "S"(arg1), "d"(arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) : "memory"); + return ret; +} + +#define _SYSCALL_N(a0, a1, a2, a3, a4, a5, a6, name, ...) \ + name + +#define syscall(...) \ +_SYSCALL_N(__VA_ARGS__, syscall6, syscall5, \ + syscall4, syscall3, syscall2, syscall1, \ + syscall0)(__VA_ARGS__) +#endif /* !defined(__ASSEMBLER__) */ +#endif /* !_SYS_SYSCALL_H */ diff --git a/lib/libc/include/unistd.h b/lib/libc/include/unistd.h new file mode 100644 index 0000000..47cde66 --- /dev/null +++ b/lib/libc/include/unistd.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#if defined(__cplusplus) +extern "C" { +#endif + +_Noreturn void _exit(int status); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_UNISTD_H */ + diff --git a/lib/libc/linker/entry.S b/lib/libc/linker/entry.S new file mode 100644 index 0000000..1f982f9 --- /dev/null +++ b/lib/libc/linker/entry.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(__hyra__) +#error "Hyra supported only" +#endif + +#include <sys/syscall.h> + +.section .text, "ax", @progbits +.globl _start +_start: + // Mark end of callstack + xor %rbp, %rbp + + // Load process context as per the sysv AMD64 ABI + lea (%rsp), %rdi + call entry + + // We are done, now we exit + mov $SYS_exit, %rax + xor %rdi, %rdi + int $0x80 + nop + ud2 diff --git a/lib/libc/linker/entry.c b/lib/libc/linker/entry.c new file mode 100644 index 0000000..55bf312 --- /dev/null +++ b/lib/libc/linker/entry.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/syscall.h> +#include <sys/auxv.h> +#include <stdint.h> +#include <stddef.h> +#include <elf.h> + +#if !defined(__hyra__) +#error "Hyra supported only" +#endif + +void +entry(const uint64_t *ctx) +{ + uint64_t argc = *ctx; + uint64_t auxv[AT_MAX_COUNT] = {0}; + int envc; + + const char **argv = (const char **)(ctx + 1); + const char **envp = (const char **)(argv + argc + 1); + struct auxv_entry *auxvp; + + /* Read-in auxiliary vector */ + auxvp = (struct auxv_entry *)(envp + envc + 1); + for (; auxvp->tag != AT_NULL; ++auxvp) { + if (auxvp->tag < AT_MAX_COUNT) { + auxv[auxvp->tag] = auxvp->val; + } + } + + /* TODO */ +} diff --git a/lib/libc/src/exit.c b/lib/libc/src/exit.c new file mode 100644 index 0000000..3b35ec6 --- /dev/null +++ b/lib/libc/src/exit.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/syscall.h> + +_Noreturn void +_exit(int status) +{ + syscall(SYS_exit, status); + __builtin_unreachable(); +} diff --git a/share/man/man9/arch.9 b/share/man/man9/arch.9 index adbc437..5bcac2d 100644 --- a/share/man/man9/arch.9 +++ b/share/man/man9/arch.9 @@ -24,7 +24,7 @@ .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. -.Dd Jan 12 2024 +.Dd Mar 13 2024 .Dt ARCH 9 .Os Hyra .Sh NAME @@ -113,5 +113,21 @@ header, should be a struct containing information about the address space. This header MUST be implemented or compiler errors will occur. +There also exists a +.Ft pcb +(Process Control Block) structure in the +.Ft machine/pcb.h +header which contains arch specific information per thread. + +This structure must be implemented per arch, this structure shall be set up +by the machdep subsystem, specifically in the +.Ft processor_init_pcb() +routine. + +The +.Ft processor_free_pcb() +routine shall also be implemented per arch to deallocate +resources when the thread is killed. + .Sh AUTHORS .An Ian Moffett Aq Mt ian@osmora.org diff --git a/share/man/man9/pmap.9 b/share/man/man9/pmap.9 index 9e4d5e0..e50a8ab 100644 --- a/share/man/man9/pmap.9 +++ b/share/man/man9/pmap.9 @@ -24,7 +24,7 @@ .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. -.Dd Jan 12 2024 +.Dd Mar 13 2024 .Dt PMAP 9 .Os Hyra .Sh NAME @@ -32,8 +32,11 @@ .Sh SYNOPSIS .In vm/pmap.h -.Ft pmap_map(struct vm_ctx *, vaddr_t, paddr_t, vm_prot_t); -.Ft pmap_unmap(struct vm_ctx *, vaddr_t); +.Bd -literal +int pmap_map(struct vm_ctx *, vaddr_t, paddr_t, vm_prot_t); +int pmap_unmap(struct vm_ctx *, vaddr_t); +.Ed + .Sh DESCRIPTION The machine dependent virtual memory layer contains a standard set of functions that shall be implemented per architecture and left alone @@ -48,13 +51,13 @@ vm_prot_t is used to give a mapping certain access rules. These rules are described below: The -.Ft PMAP_WRITABLE +.Ft PROT_WRITABLE bit tells pmap_map() to allow writes to the page. Writes to pages without this bit will result in an exception, on AMD64 a #PF will occur. The -.Ft PMAP_EXEC +.Ft PROT_EXEC bit tells pmap_map() to allow this page to be executable. On platforms like AMD64, execution of pages without this bit will result in an exception from the diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 6342aab..47d6dd0 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -40,6 +40,7 @@ #include <machine/spectre.h> #include <machine/cpu.h> #include <machine/uart.h> +#include <machine/cpuid.h> #include <vm/vm.h> #include <vm/dynalloc.h> #include <vm/physseg.h> @@ -56,6 +57,8 @@ __KERNEL_META("$Hyra$: machdep.c, Ian Marco Moffett, " #define INIT_FLAG_IOAPIC 0x00000001U #define INIT_FLAG_ACPI 0x00000002U +void syscall_isr(void); + static inline void init_tss(struct cpu_info *cur_cpu) { @@ -78,18 +81,28 @@ interrupts_init(void) idt_set_desc(0x8, IDT_TRAP_GATE_FLAGS, ISR(double_fault), 0); idt_set_desc(0xA, IDT_TRAP_GATE_FLAGS, ISR(invl_tss), 0); idt_set_desc(0xB, IDT_TRAP_GATE_FLAGS, ISR(segnp), 0); + idt_set_desc(0xC, IDT_TRAP_GATE_FLAGS, ISR(ss_fault), 0); idt_set_desc(0xD, IDT_TRAP_GATE_FLAGS, ISR(general_prot), 0); idt_set_desc(0xE, IDT_TRAP_GATE_FLAGS, ISR(page_fault), 0); + idt_set_desc(0x80, IDT_INT_GATE_USER, ISR(syscall_isr), 0); idt_load(); } +static bool +is_sse_supported(void) +{ + uint32_t edx, unused; + + __CPUID(0x00000001, unused, unused, unused, edx); + return __TEST(edx, __BIT(25)) && __TEST(edx, __BIT(26)); +} + void processor_halt(void) { __ASMV("cli; hlt"); } - /* * Send char to serial for debugging purposes. */ @@ -144,11 +157,63 @@ intr_unmask(void) __ASMV("sti"); } +int +processor_init_pcb(struct proc *proc) +{ + struct pcb *pcb = &proc->pcb; + const uint16_t FPU_FCW = 0x33F; + const uint32_t SSE_MXCSR = 0x1F80; + + /* Allocate FPU save area, aligned on a 16 byte boundary */ + pcb->fpu_state = PHYS_TO_VIRT(vm_alloc_pageframe(1)); + if (pcb->fpu_state == NULL) { + return -1; + } + + /* + * Setup x87 FPU control word and SSE MXCSR bits + * as per the sysv ABI + */ + __ASMV("fldcw %0\n" + "ldmxcsr %1" + :: "m" (FPU_FCW), + "m" (SSE_MXCSR) : "memory"); + + amd64_fxsave(pcb->fpu_state); + return 0; +} + +int +processor_free_pcb(struct proc *proc) +{ + struct pcb *pcb = &proc->pcb; + + if (pcb->fpu_state == NULL) { + return -1; + } + + vm_free_pageframe(VIRT_TO_PHYS(pcb->fpu_state), 1); + return 0; +} + +void +processor_switch_to(struct proc *old_td, struct proc *new_td) +{ + struct pcb *old_pcb = (old_td != NULL) ? &old_td->pcb : NULL; + struct pcb *new_pcb = &new_td->pcb; + + if (old_pcb != NULL) { + amd64_fxsave(old_pcb->fpu_state); + } + amd64_fxrstor(new_pcb->fpu_state); +} + void processor_init(void) { /* Indicates what doesn't need to be init anymore */ static uint8_t init_flags = 0; + static uint64_t reg_tmp; struct cpu_info *cur_cpu; /* Create our cpu_info structure */ @@ -159,6 +224,21 @@ processor_init(void) /* Set %GS to cpu_info */ amd64_write_gs_base((uintptr_t)cur_cpu); + if (is_sse_supported()) { + /* Enable SSE/SSE2 */ + reg_tmp = amd64_read_cr0(); + reg_tmp &= ~(__BIT(2)); + reg_tmp |= __BIT(1); + amd64_write_cr0(reg_tmp); + + /* Enable FXSAVE/FXRSTOR */ + reg_tmp = amd64_read_cr4(); + reg_tmp |= 3 << 9; + amd64_write_cr4(reg_tmp); + } else { + panic("SSE/SSE2 not supported!\n"); + } + CPU_INFO_LOCK(cur_cpu); init_tss(cur_cpu); diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index 2760532..54d4ca3 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -228,6 +228,19 @@ pmap_switch_vas(struct vm_ctx *ctx, struct vas vas) : "memory"); } +/* + * TODO: During the mapping of a virtual address, a level + * may be allocated. This function does not handle the + * freeing of allocated levels. We should keep track + * of levels allocated and free them here. + */ +int +pmap_free_vas(struct vm_ctx *ctx, struct vas vas) +{ + vm_free_pageframe(vas.top_level, 1); + return 0; +} + struct vas pmap_read_vas(void) { diff --git a/sys/arch/amd64/amd64/spectre.c b/sys/arch/amd64/amd64/spectre.c index 1247607..05aa557 100644 --- a/sys/arch/amd64/amd64/spectre.c +++ b/sys/arch/amd64/amd64/spectre.c @@ -62,13 +62,18 @@ __weak int try_spectre_mitigate(void) { uint64_t tmp; + static bool should_log = true; if (!__can_mitigate_spectre()) { KINFO("IBRS not supported; spectre mitigation NOT enabled\n"); return EXIT_FAILURE; } - KINFO("IBRS supported; spectre mitigation enabled\n"); + /* This is called per processor, only log once */ + if (should_log) { + KINFO("IBRS supported; spectre mitigation enabled\n"); + should_log = false; + } tmp = rdmsr(IA32_SPEC_CTL); tmp |= __BIT(0); /* IBRS */ diff --git a/sys/arch/amd64/amd64/syscall.S b/sys/arch/amd64/amd64/syscall.S new file mode 100644 index 0000000..fe70523 --- /dev/null +++ b/sys/arch/amd64/amd64/syscall.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #include <sys/cdefs.h> + #include <machine/frameasm.h> + +__KERNEL_META "$Hyra$: syscall.S, Ian Marco Moffett, \ + Syscall ISR code" + +.text +.globl syscall_isr +syscall_isr: + push_trapframe $0 + mov %rsp, %rdi + call __syscall + pop_trapframe + iretq diff --git a/sys/arch/amd64/amd64/syscall.c b/sys/arch/amd64/amd64/syscall.c new file mode 100644 index 0000000..68235d5 --- /dev/null +++ b/sys/arch/amd64/amd64/syscall.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/syscall.h> + +void +__syscall(struct trapframe *tf) +{ + struct syscall_args args = { + .code = tf->rax, + .arg0 = tf->rdi, + .arg1 = tf->rsi, + .arg2 = tf->rcx, + .arg3 = tf->r8, + .arg4 = tf->r9, + .sp = tf->rsp + }; + + if (args.code < __MAX_SYSCALLS && args.code > 0) { + args.code -= 1; + tf->rax = g_syscall_table[args.code](&args); + } +} diff --git a/sys/arch/amd64/amd64/trap.S b/sys/arch/amd64/amd64/trap.S index 5a77955..66dd2a9 100644 --- a/sys/arch/amd64/amd64/trap.S +++ b/sys/arch/amd64/amd64/trap.S @@ -144,3 +144,13 @@ nmi: /* TODO */ cli hlt + +.globl ss_fault +ss_fault: + push_trapframe_ec $TRAP_SS + + handle_trap + + /* TODO */ + cli + hlt diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c index b73048d..f1e58f1 100644 --- a/sys/arch/amd64/amd64/trap.c +++ b/sys/arch/amd64/amd64/trap.c @@ -44,7 +44,8 @@ static const char *trap_type[] = { [TRAP_SEGNP] = "segment not present", [TRAP_PROTFLT] = "general protection", [TRAP_PAGEFLT] = "page fault", - [TRAP_NMI] = "non-maskable interrupt" + [TRAP_NMI] = "non-maskable interrupt", + [TRAP_SS] = "stack-segment fault" }; static const int TRAP_COUNT = __ARRAY_COUNT(trap_type); @@ -54,12 +55,17 @@ dbg_errcode(struct trapframe *tf) { uint64_t ec = tf->error_code; - if (tf->trapno == TRAP_PAGEFLT) { + switch (tf->trapno) { + case TRAP_PAGEFLT: kprintf("bits (pwui): %c%c%c%c\n", __TEST(ec, __BIT(0)) ? 'p' : '-', __TEST(ec, __BIT(1)) ? 'w' : '-', __TEST(ec, __BIT(2)) ? 'u' : '-', __TEST(ec, __BIT(4)) ? 'i' : '-'); + break; + case TRAP_SS: + kprintf("ss: 0x%x\n", ec); + break; } } @@ -115,5 +121,5 @@ trap_handler(struct trapframe *tf) } regdump(tf); - panic("Caught pre-sched exception\n"); + panic("Halted\n"); } diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c index c0eaa0c..6da0929 100644 --- a/sys/fs/initramfs.c +++ b/sys/fs/initramfs.c @@ -103,7 +103,7 @@ vop_vget(struct vnode *parent, const char *name, struct vnode **vp) return -ENOENT; } - if (hdr->type != TAR_TYPEFLAG_DIR) { + if (hdr->type == TAR_TYPEFLAG_DIR) { vtype = VDIR; } @@ -149,8 +149,8 @@ static char * get_module(const char *path, uint64_t *size) { for (uint64_t i = 0; i < mod_req.response->module_count; ++i) { if (strcmp(mod_req.response->modules[i]->path, path) == 0) { - *size = mod_req.response->modules[i]->size; - return mod_req.response->modules[i]->address; + *size = mod_req.response->modules[i]->size; + return mod_req.response->modules[i]->address; } } @@ -173,6 +173,7 @@ static int initramfs_init(struct fs_info *info) { initramfs = get_module("/boot/initramfs.tar", &initramfs_size); + info->caps = FSCAP_FULLPATH; if (initramfs == NULL) { panic("Failed to load initramfs\n"); @@ -221,7 +222,7 @@ initramfs_open(const char *path) } hdr = initramfs_from_path((void *)initramfs, path); - return hdr_to_contents(hdr); + return (hdr == NULL) ? NULL : hdr_to_contents(hdr); } struct vfsops g_initramfs_ops = { diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h index e2ed851..ee9bad7 100644 --- a/sys/include/arch/amd64/cpu.h +++ b/sys/include/arch/amd64/cpu.h @@ -110,6 +110,46 @@ amd64_read_gs_base(void) return rdmsr(IA32_KERNEL_GS_BASE); } +static inline uint64_t +amd64_read_cr0(void) +{ + uint64_t cr0; + __ASMV("mov %%cr0, %0" : "=r" (cr0) :: "memory"); + return cr0; +} + +static inline void +amd64_write_cr0(uint64_t val) +{ + __ASMV("mov %0, %%cr0" :: "r" (val) : "memory"); +} + +static inline uint64_t +amd64_read_cr4(void) +{ + uint64_t cr4; + __ASMV("mov %%cr4, %0" : "=r" (cr4) :: "memory"); + return cr4; +} + +static inline void +amd64_write_cr4(uint64_t val) +{ + __ASMV("mov %0, %%cr4" :: "r" (val) : "memory"); +} + +static inline void +amd64_fxsave(void *area) +{ + __ASMV("fxsave (%0)" :: "r" (area) : "memory"); +} + +static inline void +amd64_fxrstor(void *area) +{ + __ASMV("fxrstor (%0)" :: "r" (area) : "memory"); +} + struct cpu_info *amd64_this_cpu(void); #endif /* !_AMD64_CPU_H_ */ diff --git a/sys/include/arch/amd64/frame.h b/sys/include/arch/amd64/frame.h index a2e1a05..298a836 100644 --- a/sys/include/arch/amd64/frame.h +++ b/sys/include/arch/amd64/frame.h @@ -67,5 +67,12 @@ struct trapframe { (FRAME)->rsp = SP; \ (FRAME)->ss = 0x10; \ +#define init_frame_user(FRAME, IP, SP) \ + (FRAME)->rip = IP; \ + (FRAME)->cs = 0x18 | 3; \ + (FRAME)->rflags = 0x202; \ + (FRAME)->rsp = SP; \ + (FRAME)->ss = 0x20 | 3; \ + #endif /* !defined(__ASSEMBLER__) */ #endif /* !_AMD64_FRAME_H_ */ diff --git a/sys/include/arch/amd64/pcb.h b/sys/include/arch/amd64/pcb.h new file mode 100644 index 0000000..0e0aab8 --- /dev/null +++ b/sys/include/arch/amd64/pcb.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _AMD64_PCB_H_ +#define _AMD64_PCB_H_ + +#include <sys/types.h> + +struct pcb { + uint8_t *fpu_state; +}; + +#endif /* !_AMD64_PCB_H_ */ diff --git a/sys/include/arch/amd64/trap.h b/sys/include/arch/amd64/trap.h index 1019999..c75fa28 100644 --- a/sys/include/arch/amd64/trap.h +++ b/sys/include/arch/amd64/trap.h @@ -47,6 +47,7 @@ #define TRAP_PROTFLT 9 /* General protection */ #define TRAP_PAGEFLT 10 /* Page fault */ #define TRAP_NMI 11 /* Non-maskable interrupt */ +#define TRAP_SS 12 /* Stack-segment fault */ /* Trap is coming from user mode */ #define TRAP_USER 0x100 @@ -65,6 +66,7 @@ void segnp(void *sf); void general_prot(void *sf); void page_fault(void *sf); void nmi(void *sf); +void ss_fault(void *sf); void trap_handler(struct trapframe *tf); #else .macro handle_trap diff --git a/sys/include/sys/filedesc.h b/sys/include/sys/filedesc.h new file mode 100644 index 0000000..ef74fb1 --- /dev/null +++ b/sys/include/sys/filedesc.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_FILEDESC_H_ +#define _SYS_FILEDESC_H_ + +#include <sys/vnode.h> +#include <sys/spinlock.h> +#include <sys/types.h> + +struct proc; + +struct filedesc { + int fdno; + off_t offset; + bool is_dir; + struct vnode *vnode; + struct spinlock lock; +}; + +#if defined(_KERNEL) +struct filedesc *fd_alloc(struct proc *td); +struct filedesc *fd_from_fdnum(const struct proc *td, int fdno); +void fd_close_fdnum(struct proc *td, int fdno); +#endif + +#endif diff --git a/sys/include/sys/loader.h b/sys/include/sys/loader.h index c1aa426..74a325c 100644 --- a/sys/include/sys/loader.h +++ b/sys/include/sys/loader.h @@ -33,17 +33,22 @@ #include <sys/types.h> #include <vm/pmap.h> -#define AT_NULL 0 -#define AT_IGNORE 1 -#define AT_EXECFD 2 -#define AT_PHDR 3 -#define AT_PHENT 4 -#define AT_PHNUM 5 -#define AT_PAGESZ 6 -#define AT_BASE 7 -#define AT_FLAGS 8 -#define AT_ENTRY 9 -#define AT_SECURE 10 +/* DANGER!: DO NOT CHANGE THESE DEFINES */ +#define AT_NULL 0 +#define AT_ENTRY 1 +#define AT_PHDR 2 +#define AT_PHENT 3 +#define AT_PHNUM 4 +#define AT_EXECPATH 5 +#define AT_SECURE 6 +#define AT_RANDOM 7 +#define AT_EXECFN 8 + +#define STACK_PUSH(ptr, val) *(--ptr) = val +#define AUXVAL(ptr, tag, val) __extension__ ({ \ + STACK_PUSH(ptr, val); \ + STACK_PUSH(ptr, tag); \ +}); /* Auxiliary Vector */ struct auxval { diff --git a/sys/include/sys/machdep.h b/sys/include/sys/machdep.h index 713b7db..0c06374 100644 --- a/sys/include/sys/machdep.h +++ b/sys/include/sys/machdep.h @@ -32,11 +32,15 @@ #include <sys/types.h> #include <sys/cdefs.h> +#include <sys/proc.h> #if defined(_KERNEL) #define MAXCPUS 32 +int processor_init_pcb(struct proc *proc); +int processor_free_pcb(struct proc *proc); +void processor_switch_to(struct proc *old_td, struct proc *new_td); void processor_init(void); void processor_halt(void); void intr_mask(void); diff --git a/sys/include/sys/mount.h b/sys/include/sys/mount.h index 3ac7ec7..209fa3e 100644 --- a/sys/include/sys/mount.h +++ b/sys/include/sys/mount.h @@ -33,6 +33,7 @@ #include <sys/types.h> #include <sys/queue.h> #include <sys/vnode.h> +#include <sys/cdefs.h> #define FS_NAME_MAX 16 /* Max length of FS type name including nul */ @@ -54,9 +55,15 @@ struct fs_info { char name[FS_NAME_MAX]; /* Filesystem type name */ struct vfsops *vfsops; /* Filesystem operations */ struct mount *mp_root; + uint16_t caps; }; /* + * Filesystem capabilities + */ +#define FSCAP_FULLPATH __BIT(0) /* Requires full path per lookup */ + +/* * Mount flags */ #define MNT_RDONLY 0x00000001 diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index f45e4c6..c6046d7 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -32,8 +32,13 @@ #include <sys/types.h> #include <sys/queue.h> +#include <sys/filedesc.h> #include <machine/cpu.h> #include <machine/frame.h> +#include <machine/pcb.h> +#include <vm/vm.h> + +#define PROC_MAX_FDS 256 /* * A task running on the CPU e.g., a process or @@ -43,6 +48,11 @@ struct proc { pid_t pid; struct cpu_info *cpu; struct trapframe *tf; + struct pcb pcb; + struct vas addrsp; + uintptr_t stack_base; + uint8_t is_user; + struct filedesc *fds[PROC_MAX_FDS]; TAILQ_ENTRY(proc) link; }; diff --git a/sys/include/sys/sched.h b/sys/include/sys/sched.h index d803df0..1fa947e 100644 --- a/sys/include/sys/sched.h +++ b/sys/include/sys/sched.h @@ -37,7 +37,9 @@ #include <machine/cpu.h> #include <machine/frame.h> +struct proc *this_td(void); void sched_init(void); +void sched_exit(void); void sched_context_switch(struct trapframe *tf); __noreturn diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h new file mode 100644 index 0000000..66dc5f3 --- /dev/null +++ b/sys/include/sys/syscall.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_SYSCALL_H_ +#define _SYS_SYSCALL_H_ + +#include <sys/types.h> +#if defined(_KERNEL) +#include <machine/frame.h> +#endif + +/* Do not reorder */ +enum { + SYS_exit = 1, + __MAX_SYSCALLS +}; + +struct syscall_args { + uint64_t code; + uint64_t arg0, arg1, arg2, arg3, arg4; + uint64_t ip; + uint64_t sp; +}; + +#if defined(_KERNEL) +extern uint64_t(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args); +void __syscall(struct trapframe *tf); +#endif + +#endif diff --git a/sys/include/sys/vfs.h b/sys/include/sys/vfs.h index a684c3f..c1bef53 100644 --- a/sys/include/sys/vfs.h +++ b/sys/include/sys/vfs.h @@ -42,7 +42,7 @@ void vfs_init(void); struct fs_info *vfs_byname(const char *name); int vfs_vget(struct vnode *parent, const char *name, struct vnode **vp); -struct vnode *vfs_path_to_node(const char *path); +int vfs_path_to_node(const char *path, struct vnode **vp); char *vfs_get_fname_at(const char *path, size_t idx); int vfs_rootname(const char *path, char **new_path); bool vfs_is_valid_path(const char *path); diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h index f584356..545e38f 100644 --- a/sys/include/sys/vnode.h +++ b/sys/include/sys/vnode.h @@ -47,6 +47,7 @@ struct vnode { struct mount *mp; /* Ptr to vfs vnode is in */ struct vops *vops; struct vnode *parent; + struct fs_info *fs; /* Filesystem this vnode belongs to, can be NULL */ void *data; /* Filesystem specific data */ }; diff --git a/sys/include/vm/pmap.h b/sys/include/vm/pmap.h index ebabd32..3380199 100644 --- a/sys/include/vm/pmap.h +++ b/sys/include/vm/pmap.h @@ -90,6 +90,12 @@ struct vas pmap_read_vas(void); int pmap_map(struct vm_ctx *, struct vas, vaddr_t, paddr_t, vm_prot_t); /* + * Get rid of a virtual address space and free + * resources. + */ +int pmap_free_vas(struct vm_ctx *, struct vas); + +/* * Unmap a page. */ int pmap_unmap(struct vm_ctx *, struct vas, vaddr_t); diff --git a/sys/include/vm/vm.h b/sys/include/vm/vm.h index 2a24d76..48e1b8f 100644 --- a/sys/include/vm/vm.h +++ b/sys/include/vm/vm.h @@ -61,5 +61,6 @@ vm_get_page_size(void) void vm_init(void); struct vm_ctx *vm_get_ctx(void); +struct vas vm_get_kvas(void); #endif /* !_VM_H_ */ diff --git a/sys/kern/kern_filedesc.c b/sys/kern/kern_filedesc.c new file mode 100644 index 0000000..a943714 --- /dev/null +++ b/sys/kern/kern_filedesc.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/filedesc.h> +#include <sys/proc.h> +#include <sys/sched.h> +#include <vm/dynalloc.h> +#include <assert.h> +#include <string.h> + +/* + * Allocate a file descriptor. + * + * @td: Thread to allocate from, NULL for current thread. + */ +struct filedesc * +fd_alloc(struct proc *td) +{ + struct filedesc *fd; + + if (td == NULL) { + td = this_td(); + __assert(td != NULL); + } + + for (size_t i = 0; i < PROC_MAX_FDS; ++i) { + if (td->fds[i] != NULL) { + continue; + } + + fd = dynalloc(sizeof(struct filedesc)); + memset(fd, 0, sizeof(struct filedesc)); + + if (fd == NULL) { + return NULL; + } + + fd->fdno = i; + td->fds[i] = fd; + return fd; + } + + return NULL; +} + +/* + * Fetch a file descriptor from a file descriptor + * number. + * + * @td: Thread to fetch from, NULL for current thread. + * @fdno: File descriptor to fetch + */ +struct filedesc * +fd_from_fdnum(const struct proc *td, int fdno) +{ + if (td == NULL) { + td = this_td(); + __assert(td != NULL); + } + + if (fdno < 0 || fdno > PROC_MAX_FDS) { + return NULL; + } + + for (size_t i = 0; i < PROC_MAX_FDS; ++i) { + if (i == fdno && td->fds[i] != NULL) { + return td->fds[i]; + } + } + + return NULL; +} + +/* + * Close a file descriptor from its fd number. + * + * @td: Thread to fetch from, NULL for current thread. + * @fdno: File descriptor number to close. + */ +void +fd_close_fdnum(struct proc *td, int fdno) +{ + struct filedesc *fd; + + if (td == NULL) { + td = this_td(); + __assert(td != NULL); + } + + fd = fd_from_fdnum(td, fdno); + if (fd == NULL) { + return; + } + + dynfree(fd); + td->fds[fdno] = NULL; +} diff --git a/sys/kern/kern_loader.c b/sys/kern/kern_loader.c index 53ba8c2..23249ea 100644 --- a/sys/kern/kern_loader.c +++ b/sys/kern/kern_loader.c @@ -61,12 +61,10 @@ int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, vm_prot_t prot = PROT_USER; uintptr_t physmem; - uintptr_t max_addr, map_addr; - size_t misalign, page_count; - + size_t misalign, page_count, map_len; int status; - const size_t GRANULE = vm_get_page_size(); + const size_t GRANULE = vm_get_page_size(); void *tmp_ptr; if (auxv == NULL) { @@ -93,26 +91,8 @@ int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, misalign = phdr->p_vaddr & (GRANULE - 1); page_count = __DIV_ROUNDUP(phdr->p_memsz + misalign, GRANULE); - max_addr = phdr->p_vaddr + (GRANULE * page_count); - - /* - * We are assuming this is a user program that we are loading. - * All user programs should be on the lower half of the address - * space. We will check that before we begin doing anything here. - * - * We are also going to check if the virtual address the program - * header refers to overflows into the higher half. If anything - * goes into the higher half, we won't simply drop the phdr, - * we'll instead assume caller error and return -EINVAL. - */ - if (phdr->p_vaddr >= VM_HIGHER_HALF) { - return -EINVAL; - } else if (max_addr >= VM_HIGHER_HALF) { - /* Overflows into higher half */ - return -EINVAL; - } - physmem = vm_alloc_pageframe(page_count); + map_len = page_count * GRANULE; /* Do we not have enough page frames? */ if (physmem == 0) { @@ -121,14 +101,9 @@ int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, return -ENOMEM; } - map_addr = phdr->p_vaddr + load_base; - status = vm_map_create(vas, map_addr, physmem, prot, page_count*GRANULE); + status = vm_map_create(vas, phdr->p_vaddr + load_base, physmem, prot, map_len); if (status != 0) { - DBG("Failed to map 0x%p - 0x%p\n", - phdr->p_vaddr + load_base, - (phdr->p_vaddr + load_base) + (page_count * GRANULE)); - return status; } diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index f61c592..7b3776d 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -34,10 +34,36 @@ #include <sys/timer.h> #include <sys/cdefs.h> #include <sys/spinlock.h> +#include <sys/loader.h> +#include <sys/panic.h> +#include <sys/machdep.h> +#include <sys/filedesc.h> +#include <fs/initramfs.h> #include <vm/dynalloc.h> +#include <vm/physseg.h> +#include <vm/pmap.h> +#include <vm/map.h> +#include <vm/vm.h> #include <assert.h> #include <string.h> +#define STACK_PAGES 8 +#define STACK_SIZE (STACK_PAGES*vm_get_page_size()) + +/* + * The PHYS_TO_VIRT/VIRT_TO_PHYS macros convert + * addresses to lower and higher half addresses. + * Userspace addresses are on the lower half, + * therefore, we can just wrap over these to + * keep things simple. + * + * XXX: TODO: This won't work when not identity mapping + * lowerhalf addresses. Once that is updated, + * get rid of this. + */ +#define USER_TO_KERN(user) PHYS_TO_VIRT(user) +#define KERN_TO_USER(kern) VIRT_TO_PHYS(kern) + /* * Thread ready queue - all threads ready to be * scheduled should be added to this queue. @@ -51,9 +77,6 @@ static size_t nthread = 0; */ static struct spinlock tdq_lock = {0}; -/* In sys/<machine>/<machine>/switch.S */ -void __sched_switch_to(struct trapframe *tf); - static inline void sched_oneshot(void) { @@ -97,13 +120,11 @@ sched_dequeue_td(void) spinlock_acquire(&tdq_lock); - if (TAILQ_EMPTY(&td_queue)) { - goto done; + if (!TAILQ_EMPTY(&td_queue)) { + td = TAILQ_FIRST(&td_queue); + TAILQ_REMOVE(&td_queue, td, link); } - td = TAILQ_FIRST(&td_queue); - TAILQ_REMOVE(&td_queue, td, link); -done: spinlock_release(&tdq_lock); return td; } @@ -121,12 +142,101 @@ sched_enter(void) } } +static uintptr_t +sched_init_stack(void *stack_top, char *argvp[], char *envp[], struct auxval auxv) +{ + uintptr_t *sp = stack_top; + void *env_ptr = NULL, *argv_ptr = NULL; + size_t argc, envc, len; + + /* Copy argument and environment strings */ + for (envc = 0; envp[envc] != NULL; ++envc) { + len = strlen(envp[envc]); + sp -= len - 1; + memcpy(sp, envp[envc], len); + } + + __assert(envc >= 1); + env_ptr = sp; + + for (argc = 0; argvp[argc] != NULL; ++argc) { + len = strlen(argvp[argc]); + sp -= len - 1; + memcpy(sp, argvp[argc], len); + } + + __assert(argc >= 1); + argv_ptr = sp; + + /* Ensure the stack is aligned */ + sp = (void *)__ALIGN_DOWN((uintptr_t)sp, 16); + if (((argc + envc + 1) & 1) != 0) + --sp; + + AUXVAL(sp, AT_NULL, 0x0); + AUXVAL(sp, AT_SECURE, 0x0); + AUXVAL(sp, AT_ENTRY, auxv.at_entry); + AUXVAL(sp, AT_PHDR, auxv.at_phdr); + AUXVAL(sp, AT_PHNUM, auxv.at_phnum); + STACK_PUSH(sp, 0); + + /* Push environment string pointers */ + for (int i = 0; i < envc; ++i) { + len = strlen(env_ptr); + sp -= len; + + *sp = (uintptr_t)KERN_TO_USER((uintptr_t)env_ptr); + env_ptr = (char *)env_ptr + len; + } + + /* Push argument string pointers */ + STACK_PUSH(sp, 0); + for (int i = 0; i < argc; ++i) { + len = strlen(argv_ptr); + sp -= len; + + *sp = (uintptr_t)KERN_TO_USER((uintptr_t)argv_ptr); + argv_ptr = (char *)argv_ptr + len; + } + + STACK_PUSH(sp, argc); + + return (uintptr_t)sp; +} + +static uintptr_t +sched_create_stack(struct vas vas, bool user, char *argvp[], + char *envp[], struct auxval auxv, struct proc *td) +{ + int status; + uintptr_t stack; + const vm_prot_t USER_STACK_PROT = PROT_WRITE | PROT_USER; + + if (!user) { + stack = (uintptr_t)dynalloc(STACK_SIZE); + td->stack_base = (uintptr_t)stack; + return sched_init_stack((void *)(stack + STACK_SIZE), argvp, envp, auxv); + } + + stack = vm_alloc_pageframe(STACK_PAGES); + td->stack_base = stack; + status = vm_map_create(vas, stack, stack, USER_STACK_PROT, STACK_SIZE); + + if (status != 0) { + return 0; + } + + memset(USER_TO_KERN(stack), 0, STACK_SIZE); + stack = sched_init_stack((void *)USER_TO_KERN(stack + STACK_SIZE), argvp, envp, auxv); + return stack; +} + static struct proc * -sched_create_td(uintptr_t rip) +sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, + struct vas vas, bool is_user) { - const size_t STACK_SIZE = 0x100000; /* 1 MiB */ struct proc *td; - void *stack; + uintptr_t stack; struct trapframe *tf; tf = dynalloc(sizeof(struct trapframe)); @@ -134,32 +244,103 @@ sched_create_td(uintptr_t rip) return NULL; } - stack = dynalloc(STACK_SIZE); - if (stack == NULL) { + td = dynalloc(sizeof(struct proc)); + if (td == NULL) { + /* TODO: Free stack */ dynfree(tf); return NULL; } - td = dynalloc(sizeof(struct proc)); - if (td == NULL) { + stack = sched_create_stack(vas, is_user, argvp, envp, auxv, td); + if (stack == 0) { dynfree(tf); - dynfree(stack); + dynfree(td); return NULL; } memset(tf, 0, sizeof(struct trapframe)); - memset(stack, 0, STACK_SIZE); + memset(td, 0, sizeof(struct proc)); /* Setup process itself */ td->pid = 0; /* Don't assign PID until enqueued */ td->cpu = NULL; /* Not yet assigned a core */ td->tf = tf; + td->addrsp = vas; + td->is_user = is_user; + processor_init_pcb(td); + + /* Allocate standard file descriptors */ + __assert(fd_alloc(td) != NULL); /* STDIN */ + __assert(fd_alloc(td) != NULL); /* STDOUT */ + __assert(fd_alloc(td) != NULL); /* STDERR */ /* Setup trapframe */ - init_frame(tf, rip, (uintptr_t)stack + STACK_SIZE - 1); + if (!is_user) { + init_frame(tf, rip, (uintptr_t)stack); + } else { + init_frame_user(tf, rip, KERN_TO_USER(stack)); + } return td; } +static void +sched_destroy_td(struct proc *td) +{ + processor_free_pcb(td); + + /* + * User stacks are allocated with vm_alloc_pageframe(), + * while kernel stacks are allocated with dynalloc(). + * We want to check if we are a user program or kernel + * program to perform the proper deallocation method. + */ + if (td->is_user) { + vm_free_pageframe(td->stack_base, STACK_PAGES); + } else { + dynfree((void *)td->stack_base); + } + + /* Close all of the file descriptors */ + for (size_t i = 0; i < PROC_MAX_FDS; ++i) { + fd_close_fdnum(td, i); + } + + pmap_free_vas(vm_get_ctx(), td->addrsp); + dynfree(td); +} + +void +sched_exit(void) +{ + struct proc *td; + struct vas kvas = vm_get_kvas(); + + intr_mask(); + + td = this_td(); + + /* Switch back to the kernel address space and destroy ourself */ + pmap_switch_vas(vm_get_ctx(), kvas); + sched_destroy_td(td); + + intr_unmask(); + sched_enter(); +} + +/* + * Get the current running thread. + */ +struct proc * +this_td(void) +{ + struct sched_state *state; + struct cpu_info *ci; + + ci = this_cpu(); + state = &ci->sched_state; + return state->td; +} + /* * Thread context switch routine */ @@ -174,43 +355,73 @@ sched_context_switch(struct trapframe *tf) * If we have no threads, we should not * preempt at all. */ - if (nthread == 0) { - goto done; - } else if ((next_td = sched_dequeue_td()) == NULL) { - /* Empty */ - goto done; + if (nthread == 0 || (next_td = sched_dequeue_td()) == NULL) { + sched_oneshot(); + return; } + /* + * If we have a thread currently running and we are switching + * to another, we shall save our current register state + * by copying the trapframe. + */ if (state->td != NULL) { - /* Save our trapframe */ td = state->td; memcpy(td->tf, tf, sizeof(struct trapframe)); } - /* Copy to stack */ + /* Copy over the next thread's register state to us */ memcpy(tf, next_td->tf, sizeof(struct trapframe)); td = state->td; state->td = next_td; + /* Re-enqueue the previous thread if it exists */ if (td != NULL) { sched_enqueue_td(td); } -done: + + /* Do architecture specific context switch logic */ + processor_switch_to(td, next_td); + + /* Done, switch out our vas and oneshot */ + pmap_switch_vas(vm_get_ctx(), next_td->addrsp); sched_oneshot(); } void sched_init(void) { + struct proc *init; + struct auxval auxv = {0}, ld_auxv = {0}; + struct vas vas = pmap_create_vas(vm_get_ctx()); + const char *init_bin, *ld_bin; + + char *ld_path; + char *argv[] = {"/usr/sbin/init", NULL}; + char *envp[] = {"", NULL}; + TAILQ_INIT(&td_queue); - /* - * TODO: Create init with sched_create_td() - * and enqueue with sched_enqueue_td() - */ - (void)sched_create_td; - (void)sched_enqueue_td; + if ((init_bin = initramfs_open("/usr/sbin/init")) == NULL) { + panic("Could not open /usr/boot/init\n"); + } + if (loader_load(vas, init_bin, &auxv, 0, &ld_path) != 0) { + panic("Could not load init\n"); + } + if ((ld_bin = initramfs_open(ld_path)) == NULL) { + panic("Could not open %s\n", ld_path); + } + if (loader_load(vas, ld_bin, &ld_auxv, 0x00, NULL) != 0) { + panic("Could not load %s\n", ld_path); + } + + init = sched_create_td((uintptr_t)ld_auxv.at_entry, argv, envp, ld_auxv, vas, true); + if (init == NULL) { + panic("Failed to create thread for init\n"); + } + + sched_enqueue_td(init); } /* diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c new file mode 100644 index 0000000..b6e31d1 --- /dev/null +++ b/sys/kern/kern_syscall.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/syscall.h> +#include <sys/sched.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +__noreturn static uint64_t +sys_exit(struct syscall_args *args) +{ + sched_exit(); + __builtin_unreachable(); +} + +uint64_t(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args) = { + sys_exit, +}; diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index 18ab3ac..0d8d194 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -40,8 +40,10 @@ __MODULE_NAME("vfs"); __KERNEL_META("$Hyra$: vfs.c, Ian Marco Moffett, " "Hyra Virtual File System"); +#define INITRAMFS_ID 0 + static struct fs_info filesystems[] = { - { "initramfs", &g_initramfs_ops } + [INITRAMFS_ID] = { "initramfs", &g_initramfs_ops } }; struct vnode *g_root_vnode = NULL; @@ -76,4 +78,5 @@ vfs_init(void) } g_root_vnode->vops = &g_initramfs_vops; + g_root_vnode->fs = &filesystems[INITRAMFS_ID]; } diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 748d5e2..1398964 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -29,11 +29,13 @@ #include <sys/types.h> #include <sys/vfs.h> +#include <sys/mount.h> +#include <sys/errno.h> #include <vm/dynalloc.h> #include <string.h> /* - * Fetches the filename within a past at + * Fetches the filename within a path at * the nth index denoted by `idx' * * Returns memory allocated by dynalloc() @@ -115,9 +117,58 @@ vfs_get_fname_at(const char *path, size_t idx) return ret; } -struct vnode * -vfs_path_to_node(const char *path) +/* + * Fetches a vnode from a path. + * + * @path: Path to fetch vnode from. + * @vp: Output var for fetched vnode. + * + * Returns 0 on success. + */ +int +vfs_path_to_node(const char *path, struct vnode **vp) { - /* TODO */ - return NULL; + struct vnode *vnode = g_root_vnode; + struct fs_info *fs; + char *name; + int s = 0, fs_caps = 0; + + if (strcmp(path, "/") == 0 || !vfs_is_valid_path(path)) { + return -1; + } else if (*path != '/') { + return -1; + } + + /* Fetch filesystem capabilities if we can */ + if (vnode->fs != NULL) { + fs = vnode->fs; + fs_caps = fs->caps; + } + + /* + * If the filesystem requires full-path lookups, we can try + * throwing the full path at the filesystem to see if + * it'll give us a vnode. + */ + if (__TEST(fs_caps, FSCAP_FULLPATH)) { + s = vfs_vget(g_root_vnode, path, &vnode); + goto done; + } + + for (size_t i = 0;; ++i) { + name = vfs_get_fname_at(path, i); + if (name == NULL) break; + + s = vfs_vget(vnode, name, &vnode); + dynfree(name); + + if (s != 0) break; + } + +done: + if (vp != NULL && s == 0) { + *vp = vnode; + } + + return s; } diff --git a/sys/vm/vm_init.c b/sys/vm/vm_init.c index f15cb0b..6096059 100644 --- a/sys/vm/vm_init.c +++ b/sys/vm/vm_init.c @@ -59,6 +59,15 @@ vm_get_ctx(void) return &bsp_vm_ctx; } +/* + * Return the kernel VAS. + */ +struct vas +vm_get_kvas(void) +{ + return kernel_vas; +} + void vm_init(void) { diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 0d27738..f65bad2 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -78,12 +78,13 @@ int vm_map_create(struct vas vas, vaddr_t va, paddr_t pa, vm_prot_t prot, size_t bytes) { size_t granule = vm_get_page_size(); + size_t misalign = va & (granule - 1); int s; struct vm_ctx *ctx = vm_get_ctx(); /* We want bytes to be aligned by the granule */ - bytes = __ALIGN_UP(bytes, granule); + bytes = __ALIGN_UP(bytes + misalign, granule); /* Align VA/PA by granule */ va = __ALIGN_DOWN(va, granule); @@ -115,10 +116,11 @@ vm_map_destroy(struct vas vas, vaddr_t va, size_t bytes) { struct vm_ctx *ctx = vm_get_ctx(); size_t granule = vm_get_page_size(); + size_t misalign = va & (granule - 1); int s; /* We want bytes to be aligned by the granule */ - bytes = __ALIGN_UP(bytes, granule); + bytes = __ALIGN_UP(bytes + misalign, granule); /* Align VA by granule */ va = __ALIGN_DOWN(va, granule); diff --git a/tools/cross.sh b/tools/cross.sh index 5a0784a..52e7b1b 100644 --- a/tools/cross.sh +++ b/tools/cross.sh @@ -140,7 +140,7 @@ rm -rf $GCC_NAME-copy echo "Configuring $GCC_NAME..." mkdir build-gcc cd build-gcc -../$GCC_NAME/configure --target="$TARGET" --with-sysroot=/ --prefix="$PREFIX" --disable-nls --enable-languages=c --disable-multilib +../$GCC_NAME/configure --target="$TARGET" --with-sysroot=/ --prefix="$PREFIX" --disable-nls --enable-languages=c,c++,lto --disable-multilib echo "Building all-gcc..." $MAKE all-gcc -j"$CORES" echo "Building all-target-libgcc..." diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile new file mode 100644 index 0000000..c75ebd0 --- /dev/null +++ b/usr.sbin/Makefile @@ -0,0 +1,7 @@ +CC = +LD = +LDSO = + +.PHONY: all +all: + cd init/; make LDSO=$(LDSO) CC=$(CC) LD=$(LD) diff --git a/usr.sbin/init/Makefile b/usr.sbin/init/Makefile new file mode 100644 index 0000000..fa65c8d --- /dev/null +++ b/usr.sbin/init/Makefile @@ -0,0 +1,8 @@ +CC = +LD = +LDSO = + +.PHONY: all +all: + $(CC) -c main.c -o main.o; + $(LD) --dynamic-linker /usr/lib/ld.so $(LDSO) main.o -o init -e main diff --git a/usr.sbin/init/main.c b/usr.sbin/init/main.c new file mode 100644 index 0000000..af62d76 --- /dev/null +++ b/usr.sbin/init/main.c @@ -0,0 +1,6 @@ +int +main(void) +{ + /* Do nothing */ + while (1); +} |