├── inc ├── limits.h ├── stdio.h ├── stdlib.h ├── stdnoreturn.h ├── stdarg.h ├── stddef.h ├── lj-libc │ ├── errno.h │ ├── stdio.h │ ├── time.h │ ├── locale.h │ ├── math.h │ └── limits.h ├── luck │ ├── arch │ │ └── x86_64 │ │ │ ├── io │ │ │ ├── ps2.h │ │ │ └── port.h │ │ │ ├── gdt.h │ │ │ ├── interrupts │ │ │ ├── idt.h │ │ │ ├── pic.h │ │ │ └── lapic.h │ │ │ ├── msr.h │ │ │ ├── acpi │ │ │ ├── acpi.h │ │ │ └── madt.h │ │ │ └── cpu.h │ ├── lua │ │ └── kernel.h │ ├── io │ │ ├── console.h │ │ ├── framebuffer.h │ │ └── log.h │ ├── memory │ │ ├── manager.h │ │ └── magazines.h │ ├── bootloader │ │ └── limine.h │ └── processes │ │ ├── scheduler.h │ │ └── ipc.h ├── stdbool.h ├── luasyntax.h ├── lock.h ├── stdint.h ├── memory.h ├── common.h ├── string.h ├── stdatomic.h └── macro_util.h ├── .DS_Store ├── res ├── font.bin ├── powered-by-lua.bmp └── linker.ld ├── compile_flags.txt ├── .idea ├── Kernel.iml ├── modules.xml ├── vcs.xml ├── misc.xml ├── workspace.xml └── editor.xml ├── .vscode ├── settings.json ├── launch.json └── tasks.json ├── .gitignore ├── Kernel.sublime-project ├── CONTRIBUTING.md ├── .gitmodules ├── .builds └── ci.yml ├── README.md ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── src ├── arch │ └── x86_64 │ │ ├── acpi │ │ ├── madt.c │ │ ├── rsdp.c │ │ └── sdt.c │ │ ├── cpu.c │ │ ├── io │ │ ├── port.c │ │ └── ps2.c │ │ ├── map.c │ │ ├── gdt.c │ │ └── interrupts │ │ ├── pic.c │ │ ├── interrupts.asm │ │ ├── idt.c │ │ └── lapic.c ├── lib │ ├── libsupport.c │ ├── string.c │ ├── math.c │ └── ljsupport.c ├── io │ ├── console.c │ ├── framebuffer.c │ └── log.c ├── processes │ ├── ipc.c │ └── scheduler.c ├── bootloader │ └── limine.c ├── lua │ └── kernel.c ├── memory │ ├── kalloc.c │ └── magazines.c └── start.c ├── .clang-tidy └── Makefile /inc/limits.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /inc/stdio.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /inc/stdlib.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /inc/stdnoreturn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define noreturn _Noreturn 4 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLuaOSProject/Kernel/HEAD/.DS_Store -------------------------------------------------------------------------------- /res/font.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLuaOSProject/Kernel/HEAD/res/font.bin -------------------------------------------------------------------------------- /compile_flags.txt: -------------------------------------------------------------------------------- 1 | -Iinc 2 | -Iextern/ 3 | -target 4 | x86_64-elf 5 | -ffreestanding 6 | -std=gnu2x 7 | -------------------------------------------------------------------------------- /res/powered-by-lua.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheLuaOSProject/Kernel/HEAD/res/powered-by-lua.bmp -------------------------------------------------------------------------------- /.idea/Kernel.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "licenser.projectName": "LuaOS", 3 | "licenser.license": "GPLv3", 4 | "Lua.runtime.version": "LuaJIT" 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | compile_commands.json 3 | .cache/ 4 | luaos.log 5 | .gdb_history 6 | extern/ovmf-x64 7 | Kernel.sublime-workspace 8 | 9 | res/limine.cfg 10 | /luarocks 11 | /lua 12 | /lua_modules 13 | /.luarocks 14 | 15 | /lsp 16 | -------------------------------------------------------------------------------- /Kernel.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "LSP": { 9 | "LSP-lua": { 10 | "settings": { 11 | "Lua.diagnostics.globals": ["_llchannel"] 12 | } 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /inc/stdarg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef __builtin_va_list va_list; 4 | 5 | #define va_start(v, l) __builtin_va_start(v, l) 6 | #define va_end(v) __builtin_va_end(v) 7 | #define va_arg(v, l) __builtin_va_arg(v, l) 8 | #define va_copy(d, s) __builtin_va_copy(d, s) 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /inc/stddef.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef unsigned long size_t; 6 | typedef long ssize_t; 7 | 8 | #define nullable _Nullable 9 | #define nonnull _Nonnull 10 | 11 | #define NULL ((void *nullable)0) 12 | #define nullptr ((void *nullable)0) 13 | 14 | #define offsetof(s, m) __builtin_offsetof(s, m) 15 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution guidelines 2 | 3 | Firstly, thank you very much for contributing to LuaOS! Your contributions will be greatly appreciated. 4 | 5 | ## Issues 6 | 7 | - Issues must be marked with labels to specify what the issue is effecting 8 | - You can find the list of labels on the right side of the screen when you create an issue, the "labels" 9 | 10 | ## Pull requests 11 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "extern/LuaJIT"] 2 | path = extern/LuaJIT 3 | url = https://github.com/TheLuaOSProject/LuaJIT.git 4 | [submodule "extern/limine"] 5 | path = extern/limine 6 | url = https://github.com/limine-bootloader/limine.git 7 | branch = v4.x-branch-binary 8 | [submodule "extern/terminal"] 9 | path = extern/terminal 10 | url = https://github.com/limine-bootloader/terminal 11 | [submodule "Userland"] 12 | path = Userland 13 | url = https://github.com/TheLuaOSProject/Userland.git 14 | -------------------------------------------------------------------------------- /.builds/ci.yml: -------------------------------------------------------------------------------- 1 | image: alpine/edge 2 | packages: 3 | - clang 4 | - make 5 | - nasm 6 | - git 7 | - p7zip 8 | - lld 9 | - xorriso 10 | - luajit 11 | - luajit-dev 12 | - luarocks5.1 13 | artifacts: 14 | - Kernel/build/bin/luaos.iso 15 | - Kernel/extern/LuaJIT/libluajit_luck.o 16 | tasks: 17 | - download: | 18 | git clone https://github.com/TheLuaOSProject/Kernel --recursive 19 | - make: | 20 | luarocks-5.1 config variables.LUA_INCDIR /usr/include/luajit-2.1/ 21 | cd Kernel && make -j 3 22 | 23 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "gdb", 6 | 7 | "request": "attach", 8 | "name": "Attach to gdbserver", 9 | "executable": "./build/bin/luck.elf", 10 | "target": ":1234", 11 | "remote": true, 12 | "cwd": "${workspaceRoot}", 13 | "valuesFormatting": "parseText", 14 | // "preLaunchTask": "QEMU" 15 | } 16 | 17 | ], 18 | "compounds": [] 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Luck - The LuaOS kernel 2 | 3 | Luck is the kernel for LuaOS, it is a microkernel. 4 | 5 | ## Building 6 | 7 | Get the source with: 8 | 9 | `git clone --recursive https://github.com/TheLuaOSProject/Kernel.git` 10 | 11 | ### Dependencies 12 | 13 | #### General 14 | 15 | - `clang` 16 | - `nasm` 17 | - `curl` 18 | - `ld.lld` 19 | - `xorriso` 20 | 21 | #### arch 22 | 23 | - 'lld' (`ld.lld`) 24 | - 'libisoburn' (`xorriso`) 25 | 26 | ```sh 27 | make 28 | ``` 29 | 30 | ## Testing 31 | 32 | ### Dependencies 33 | 34 | - `qemu-system-x86_64` 35 | 36 | ```sh 37 | make uefi 38 | ``` 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Build", 6 | "command": "make", 7 | "type": "process", 8 | "args": [ 9 | "all", "-j8" 10 | ], 11 | "problemMatcher": [ 12 | "$gcc" 13 | ], 14 | "presentation": { 15 | "reveal": "always" 16 | }, 17 | "group": "build" 18 | }, 19 | { 20 | "label": "QEMU", 21 | "type": "process", 22 | "command": "make", 23 | "args": [ 24 | "screened", "-j8" 25 | ], 26 | "problemMatcher": [ 27 | "$gcc" 28 | ] 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /inc/lj-libc/errno.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "limits.h" 21 | -------------------------------------------------------------------------------- /inc/lj-libc/stdio.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "limits.h" 21 | -------------------------------------------------------------------------------- /inc/lj-libc/time.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "limits.h" 21 | -------------------------------------------------------------------------------- /inc/lj-libc/locale.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "limits.h" 21 | 22 | -------------------------------------------------------------------------------- /inc/lj-libc/math.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "limits.h" 21 | 22 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/io/ps2.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitulst 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | char ps2_getc(void); 23 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /inc/stdbool.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #define bool _Bool 23 | #define true 1 24 | #define false 0 25 | -------------------------------------------------------------------------------- /inc/luck/lua/kernel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | 24 | int luaopen_kernel(lua_State *L); 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. MacOS] 28 | - Version [e.g. 13] 29 | - `clang` version [`clang --version`] 30 | - `ld.lld` version [`ld.lld --version`] 31 | - `qemu` version 32 | 33 | **Additional context** 34 | Add any other context about the problem here. 35 | -------------------------------------------------------------------------------- /inc/luck/io/console.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal, pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "common.h" 23 | 24 | #include 25 | 26 | $nonnull_begin 27 | 28 | void terminal_init(); 29 | void console_write(const char *str); 30 | void console_write_char(char c); 31 | 32 | $nonnull_end 33 | -------------------------------------------------------------------------------- /src/arch/x86_64/acpi/madt.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/arch/x86_64/acpi/acpi.h" 21 | #include "luck/arch/x86_64/acpi/madt.h" 22 | 23 | struct MADT *madt_init(const struct RSDP *rsdp) 24 | { 25 | struct MADT *madt = (struct MADT *nullable)sdt_find(rsdp, "APIC", 0); 26 | if (madt == nullptr) return nullptr; 27 | 28 | /*TODO*/ 29 | 30 | return madt; 31 | } 32 | -------------------------------------------------------------------------------- /inc/luck/io/framebuffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "olive.h" 21 | 22 | #include "common.h" 23 | 24 | #include 25 | 26 | #include 27 | 28 | $nonnull_begin 29 | 30 | Olivec_Canvas framebuffer_init(); 31 | 32 | 33 | /// Gets the lua table for the framebuffer, for `luaopen_kernel` to add it to `kernel` table. 34 | int luaopen_framebuffer(lua_State *L); 35 | 36 | $nonnull_end 37 | -------------------------------------------------------------------------------- /inc/luasyntax.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #define if if ( 23 | #define then ) 24 | #define else } else 25 | #define elseif else if ( 26 | #define do do { 27 | #define while while ( 28 | #define repeat do 29 | #define until(...) while __VA_ARGS__) 30 | #define for(init, cond, inc) for (__auto_type init; cond; inc) 31 | #define end } 32 | #define _FUNC_END(...) (__VA_ARGS__) { 33 | #define function(name) name _FUNC_END 34 | -------------------------------------------------------------------------------- /src/lib/libsupport.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "memory.h" 21 | 22 | void *memcpy(void *dst, const void *src, size_t n) 23 | { return memory_copy(dst, src, n); } 24 | 25 | void *memset(void *dst, int c, size_t n) 26 | { return memory_set(dst, c, n); } 27 | 28 | int memcmp(const void *b1, const void *b2, size_t n) 29 | { return memory_compare(b1, b2, n); } 30 | 31 | void *memmove(void *dst, const void *src, size_t n) 32 | { return memory_move(dst, src, n); } 33 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/gdt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "common.h" 23 | 24 | $nonnull_begin 25 | 26 | struct [[gnu::aligned(4096)]] TSSDescriptor { 27 | byte tss[0x6B]; 28 | }; 29 | 30 | struct GlobalDescriptorTable { 31 | uint64_t descriptors[11]; 32 | struct TSSDescriptor task_state_segment; 33 | }; 34 | 35 | 36 | struct [[gnu::packed]] GDTRegister { 37 | word limit; 38 | qword base; 39 | }; 40 | 41 | void gdt_init(void); 42 | 43 | $nonnull_end 44 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/io/port.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal, pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "common.h" 23 | 24 | $nonnull_begin 25 | 26 | byte port_in_byte(word port); 27 | void port_out_byte(word port, byte data); 28 | 29 | word port_in_word(word port); 30 | void port_out_word(word port, word data); 31 | 32 | #define $port_in(T) (_Generic(typeof(T), word: port_in_word, default: port_in_byte)) 33 | #define $port_out(T) (_Generic(typeof(T), word: port_out_word, default: port_out_byte)) 34 | 35 | $nonnull_end 36 | -------------------------------------------------------------------------------- /inc/lock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "stdatomic.h" 23 | #include "common.h" 24 | 25 | $nonnull_begin 26 | 27 | typedef _Atomic(bool) Lock; 28 | 29 | static inline void acquire_lock(Lock *b) 30 | { 31 | bool spin = false; 32 | do { 33 | while (atomic_load_explicit(b, memory_order_relaxed)) { spin = true; $asm("pause"); } 34 | } while (atomic_exchange(b, true)); 35 | } 36 | static inline void release_lock(Lock *b) 37 | { atomic_store(b, false); } 38 | 39 | $nonnull_end 40 | -------------------------------------------------------------------------------- /src/arch/x86_64/cpu.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal, pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/arch/x86_64/cpu.h" 21 | 22 | enum CPUVendor cpu_get_vendor() 23 | { 24 | char vendor[13] = {0}; 25 | $asm("mov $0, %%eax" : : : "eax"); 26 | $asm("cpuid" : "=b"(vendor[0]), "=d"(vendor[4]), "=c"(vendor[8]) : : "eax"); 27 | vendor[12] = '\0'; 28 | for (enum CPUVendor i = 0; i < CPUVendor_UNKNOWN; i++) { 29 | if (string_compare(12, vendor, 12, CPU_VENDORS[i]) == 0) 30 | return i; 31 | } 32 | return CPUVendor_UNKNOWN; 33 | } 34 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/interrupts/idt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "common.h" 23 | 24 | $nonnull_begin 25 | 26 | struct IDTEntry { 27 | word offset_low, selector; 28 | byte interrupt_stack_table, flags; 29 | word offset_middle; 30 | dword offset_high, reserved; 31 | }; 32 | 33 | 34 | struct [[gnu::packed]] IDTRegister { 35 | word limit; 36 | qword base; 37 | }; 38 | 39 | void idt_init(void); 40 | void idt_register_int(byte int_no, [[gnu::interrupt]] void(*routine)(void*)); 41 | 42 | $nonnull_end 43 | -------------------------------------------------------------------------------- /src/arch/x86_64/acpi/rsdp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/arch/x86_64/acpi/acpi.h" 21 | #include "luck/io/log.h" 22 | 23 | #include 24 | #include "string.h" 25 | 26 | #include "luck/bootloader/limine.h" 27 | 28 | struct RSDP *rsdp_init(void) 29 | { 30 | if (bootloader_rsdp == nullptr || bootloader_rsdp->address == nullptr) 31 | return nullptr; 32 | 33 | struct RSDP *nonnull rsdp = bootloader_rsdp->address; 34 | 35 | if (rsdp->revision < 2) 36 | $info(" XSDT not supported on this machine; using RSDT"); 37 | 38 | return rsdp; 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/arch/x86_64/io/port.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/arch/x86_64/io/port.h" 21 | 22 | byte port_in_byte(word port) 23 | { 24 | byte data; 25 | $asm("INB %1, %0" : "=a"(data) : "Nd"(port)); 26 | return data; 27 | } 28 | 29 | void port_out_byte(word port, byte data) 30 | { 31 | $asm("OUTB %0, %1" : : "a"(data), "Nd"(port)); 32 | } 33 | 34 | word port_in_word(word port) 35 | { 36 | word data; 37 | $asm("INW %1, %0" : "=a"(data) : "Nd"(port)); 38 | return data; 39 | } 40 | 41 | void port_out_word(word port, word data) 42 | { 43 | $asm("OUTW %0, %1" : : "a"(data), "Nd"(port)); 44 | } 45 | -------------------------------------------------------------------------------- /inc/luck/memory/manager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | 24 | $nonnull_begin 25 | 26 | extern qword VIRTUAL_MEMORY_HIGH; 27 | #define VIRTUAL_MEMORY_HIGH ((const qword)VIRTUAL_MEMORY_HIGH) 28 | 29 | /// page allocation /// 30 | $closed_enum PageType { 31 | PageType_PAGETABLE, 32 | PageType_REGULAR 33 | }; 34 | 35 | qword page_alloc(enum PageType pty); 36 | 37 | /// mapping pages /// 38 | void pmap_map(qword addr, qword phys); 39 | void pmap_map_rwx(qword addr, qword phys); 40 | 41 | /// kalloc /// 42 | void kalloc_init(void); 43 | void *kalloc(qword size); 44 | void kfree(void *ptr, qword size); 45 | 46 | $nonnull_end 47 | -------------------------------------------------------------------------------- /src/arch/x86_64/acpi/sdt.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/arch/x86_64/acpi/acpi.h" 21 | 22 | #include "memory.h" 23 | #include "luck/io/log.h" 24 | #include "luck/bootloader/limine.h" 25 | 26 | struct SDTHeader *sdt_find(const struct RSDP *rsdp, const char id[static 4], int idx) 27 | { 28 | struct RSDT *rsdt = $virt(rsdp->rsdt_address, struct RSDT); 29 | size_t nent = (rsdt->length - sizeof(struct SDTHeader)) / sizeof(dword); 30 | for (size_t i = 0;i < nent;i++) { 31 | struct SDTHeader *sdt = $virt(rsdt->pointers[i], struct SDTHeader); 32 | if (!memcmp(sdt->signature, id, 4) && idx-- == 0) return sdt; 33 | } 34 | 35 | return nullptr; 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/msr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include 22 | 23 | #include "common.h" 24 | 25 | //#define APIC_BASE_MSR 0x1B 26 | $closed_enum ModelSpecificRegister: dword { 27 | ModelSpecificRegister_APIC_BASE = 0x1B 28 | }; 29 | 30 | static inline qword read_msr(register enum ModelSpecificRegister msr) 31 | { 32 | register dword low, high; 33 | $asm("RDMSR" : "=a"(low), "=d"(high) : "c"(msr)); 34 | return ((qword)high << 32) | low; 35 | } 36 | 37 | static inline void write_msr(register enum ModelSpecificRegister msr, qword value) 38 | { 39 | register dword low = value & 0xFFFFFFFF; 40 | register dword high = value >> 32; 41 | $asm("WRMSR" : : "a"(low), "d"(high), "c"(msr)); 42 | } 43 | -------------------------------------------------------------------------------- /inc/luck/bootloader/limine.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include "common.h" 23 | 24 | $nonnull_begin 25 | 26 | #define $bootloader_module(name) \ 27 | extern const volatile struct limine_##name##_response *nullable bootloader_##name 28 | 29 | $bootloader_module(hhdm); 30 | $bootloader_module(kernel_address); 31 | $bootloader_module(module); 32 | $bootloader_module(framebuffer); 33 | $bootloader_module(rsdp); 34 | $bootloader_module(memmap); 35 | 36 | #undef $bootloader_module 37 | 38 | void bootloader_init(void); 39 | 40 | qword limine_virt_to_phys(qword virt); 41 | qword limine_phys_to_virt(qword phys); 42 | 43 | struct limine_file *nullable find_module(const char *nonnull name); 44 | 45 | #define $phys(value) limine_virt_to_phys((qword)(value)) 46 | #define $virt(value, ...) \ 47 | (__VA_OPT__((__VA_ARGS__ *))(qword) limine_phys_to_virt(value)) 48 | 49 | $nonnull_end 50 | -------------------------------------------------------------------------------- /src/arch/x86_64/map.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "common.h" 21 | #include "luck/memory/manager.h" 22 | #include "luck/bootloader/limine.h" 23 | 24 | static qword* get_pte(qword addr) 25 | { 26 | addr <<= (64 - 48); 27 | qword cr3; 28 | $asm("MOVQ %%CR3, %0" : "=r"(cr3)); 29 | qword* mod; 30 | #define STEP(isfinal) \ 31 | { \ 32 | qword off = (addr >> (64 - 9)) & 0x1ff; \ 33 | addr <<= 9; \ 34 | qword* ptep = &$virt(cr3, qword)[off]; \ 35 | if (!isfinal && !(*ptep & 1)) { \ 36 | *ptep = 7 | page_alloc(PageType_PAGETABLE); \ 37 | } \ 38 | if (isfinal) return ptep; \ 39 | cr3 = *ptep & ~0xfff; \ 40 | } 41 | 42 | STEP(0) 43 | STEP(0) 44 | STEP(0) 45 | STEP(1) 46 | } 47 | 48 | void pmap_map(qword addr, qword phys) 49 | { 50 | *get_pte(addr) = 3 | phys; 51 | } 52 | 53 | void pmap_map_rwx(qword addr, qword phys) 54 | { 55 | *get_pte(addr) = 7 | phys; 56 | } 57 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/acpi/acpi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "common.h" 22 | 23 | $nonnull_begin 24 | 25 | struct SDTHeader { 26 | char signature[4]; 27 | dword length; 28 | byte revision, checksum; 29 | char oem_id[6], oem_table_id[8]; 30 | dword oem_revision, creator_id, creator_revision; 31 | }; 32 | 33 | struct RSDT { 34 | struct SDTHeader; 35 | dword pointers[]; 36 | }; 37 | 38 | struct [[gnu::packed]] XSDT { 39 | struct SDTHeader; 40 | qword pointers[]; 41 | }; 42 | 43 | struct [[gnu::packed]] RSDP { 44 | //1.0 45 | char signature[8]; 46 | byte checksum; 47 | char oem_id[6]; 48 | byte revision; 49 | dword rsdt_address; 50 | 51 | //2.0 52 | dword length; 53 | qword xsdt_address; 54 | byte extended_checksum, reserved[3]; 55 | }; 56 | 57 | struct RSDP *nullable rsdp_init(void); 58 | struct SDTHeader *nullable sdt_find(const struct RSDP *table, const char id[static 4], int idx); 59 | 60 | $nonnull_end 61 | -------------------------------------------------------------------------------- /inc/luck/memory/magazines.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "common.h" 23 | #include "lock.h" 24 | 25 | typedef union { 26 | struct { 27 | Lock locked; 28 | qword *current; 29 | qword *previous; 30 | }; 31 | char padding[64]; // force cache line size to avoid false sharing 32 | } MagazinePerCPU; 33 | 34 | typedef struct { 35 | Lock locked; 36 | 37 | qword num_ready_mags; 38 | qword *ready_mags[16]; 39 | 40 | qword num_free_mags; 41 | qword *free_mags[16]; 42 | 43 | qword (*get)(void* ctx); 44 | void (*put)(void* ctx, qword item); 45 | void* ctx; 46 | MagazinePerCPU* mag_percpu; 47 | } Magazine; 48 | 49 | #define MAG_MUSTGET 1 50 | 51 | Magazine* mag_new(qword(*get)(void* ctx), void (*put)(void* ctx, qword item), void* ctx); 52 | void mag_destroy(Magazine* mag); 53 | void mag_put(Magazine* mag, qword item); 54 | bool mag_xget(Magazine* mag, qword* out, uint64_t flags); 55 | qword mag_get(Magazine* mag); 56 | void mag_100ms_adjust(void); 57 | void magazine_init(void); 58 | -------------------------------------------------------------------------------- /src/arch/x86_64/gdt.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal, pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/arch/x86_64/gdt.h" 21 | 22 | #include "luck/io/log.h" 23 | 24 | static struct GlobalDescriptorTable gdt; 25 | static struct GDTRegister gdtr = {.base = (qword)&gdt, .limit = sizeof(gdt) - 1}; 26 | 27 | void gdt_init(void) 28 | { 29 | gdt.descriptors[0] = 0x0000000000000000; // null 30 | gdt.descriptors[1] = 0x00009a000000ffff; // 16-bit code 31 | gdt.descriptors[2] = 0x000093000000ffff; // 16-bit data 32 | gdt.descriptors[3] = 0x00cf9a000000ffff; // 32-bit code 33 | gdt.descriptors[4] = 0x00cf93000000ffff; // 32-bit data 34 | gdt.descriptors[5] = 0x00af9b000000ffff; // 64-bit code 35 | gdt.descriptors[6] = 0x00af93000000ffff; // 64-bit data 36 | gdt.descriptors[7] = 0x00affb000000ffff; // usermode 64-bit code 37 | gdt.descriptors[8] = 0x00aff3000000ffff; // usermode 64-bit data 38 | 39 | gdt.task_state_segment.tss[0x66] = 0x13; 40 | 41 | $asm("LGDT %0" :: "m"(gdtr)); 42 | $success("Done"); 43 | } 44 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/acpi/madt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "common.h" 22 | #include "acpi.h" 23 | 24 | 25 | $nonnull_begin 26 | 27 | struct [[gnu::packed]] MADTEntryHeader { 28 | byte id, length; 29 | }; 30 | 31 | 32 | struct [[gnu::packed]] MADT { 33 | struct SDTHeader descriptor; 34 | 35 | dword controller_address, flags; 36 | 37 | /// @warning THIS IS MISLEADING! ENTRIES ARE VARIABLE LENGTH! DO NOT TRY AND INDEX 38 | byte entries[]; 39 | }; 40 | 41 | //#define MADT_ENTRY_ID_LAPIC (0) 42 | $closed_enum MADTEntryID { 43 | MADTEntryID_LAPIC = 0, 44 | }; 45 | 46 | struct [[gnu::packed]] MADTEntry_LAPIC { 47 | struct MADTEntryHeader; 48 | 49 | byte processor_id, apic_id; 50 | dword flags; 51 | }; 52 | 53 | struct MADTEntry_IOAPIC { 54 | struct MADTEntryHeader; 55 | 56 | byte io_id; 57 | byte reserved; 58 | dword address, global_system_interrupt_base; 59 | }; 60 | 61 | struct MADT *nullable madt_init(const struct RSDP *rsdp); 62 | 63 | 64 | $nonnull_end 65 | -------------------------------------------------------------------------------- /inc/luck/processes/scheduler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include "common.h" 23 | #include "lock.h" 24 | #include "luck/arch/x86_64/cpu.h" 25 | #include "luck/processes/ipc.h" 26 | 27 | $nonnull_begin 28 | 29 | typedef struct Futex { 30 | struct Thread *head; 31 | Lock lock; 32 | } Futex; 33 | 34 | typedef struct Thread { 35 | char name[64]; 36 | CPUContext cpu_context; 37 | void *stack_base; 38 | struct Thread *nullable next_task, *nullable previous_task; 39 | lua_State *lua; 40 | bool ready, kill; 41 | Lock lock; 42 | 43 | Futex *nullable next_mutex; //? 44 | } Thread; 45 | 46 | enum { 47 | Thread_STACKSIZE = 0x4000, 48 | Thread_COUNT = 0x100, 49 | }; 50 | 51 | void wait_for_thread(Thread *thread); 52 | void wake_futex(Futex *mtx); 53 | void wake_all_futexes(Futex *mutexes); 54 | 55 | Thread *nullable spawn_thread(void *addr, size_t size, const char *vpi); 56 | void reschedule(CPUContext *ctx); 57 | void scheduler_init(void); 58 | 59 | int luaopen_scheduler(lua_State *L); 60 | 61 | $nonnull_end 62 | -------------------------------------------------------------------------------- /res/linker.ld: -------------------------------------------------------------------------------- 1 | /* Tell the linker that we want an x86_64 ELF64 output file */ 2 | OUTPUT_FORMAT(elf64-x86-64) 3 | OUTPUT_ARCH(i386:x86-64) 4 | 5 | /* We want the symbol _start to be our entry point */ 6 | ENTRY(kernel_start) 7 | 8 | /* Define the program headers we want so the bootloader gives us the right */ 9 | /* MMU permissions */ 10 | PHDRS 11 | { 12 | text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ 13 | rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ 14 | data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ 15 | } 16 | 17 | SECTIONS 18 | { 19 | /* We wanna be placed in the topmost 2GiB of the address space, for optimisations */ 20 | /* and because that is what the Limine spec mandates. */ 21 | /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */ 22 | /* that is the beginning of the region. */ 23 | . = 0xffffffff80000000; 24 | 25 | .text : { 26 | *(.text .text.*) 27 | } :text 28 | 29 | /* Move to the next memory page for .rodata */ 30 | . += CONSTANT(MAXPAGESIZE); 31 | 32 | .rodata : { 33 | *(.rodata .rodata.*) 34 | } :rodata 35 | 36 | /* Move to the next memory page for .data */ 37 | . += CONSTANT(MAXPAGESIZE); 38 | 39 | .data : { 40 | *(.data .data.*) 41 | } :data 42 | 43 | /* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */ 44 | /* unnecessary zeros will be written to the binary. */ 45 | /* If you need, for example, .init_array and .fini_array, those should be placed */ 46 | /* above this. */ 47 | .bss : { 48 | *(COMMON) 49 | *(.bss .bss.*) 50 | } :data 51 | 52 | /* Discard .note.* and .eh_frame since they may cause issues on some hosts. */ 53 | /DISCARD/ : { 54 | *(.eh_frame) 55 | *(.note .note.*) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/io/console.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "luck/io/console.h" 26 | #include "luck/memory/manager.h" 27 | #include "luck/bootloader/limine.h" 28 | 29 | static struct term_context *term_ctx; 30 | static uint32_t term_pal[8] = {0x161A21, 0xF8485D, 0x4FD93D, 0xFF9B28, 0x0CB2FF, 0xCA87FF, 0x65E0B8, 0xBBBBBB}; 31 | static uint32_t term_pal_bright[8] = {0x565555, 0xFF4D62, 0x8ED71C, 0xECA02D, 0x18B7FF, 0xCA87FF, 0x6AE6BE, 0xFEFFFF}; 32 | static uint32_t term_bg = 0x0B0E13, term_fg = 0xDBDBDB; 33 | 34 | void terminal_init() 35 | { 36 | struct limine_framebuffer *nonnull fb = bootloader_framebuffer->framebuffers[0]; 37 | 38 | term_ctx = fbterm_init(kalloc, fb->address, fb->width, fb->height, fb->pitch, nullptr, term_pal, term_pal_bright, &term_bg, &term_fg, &term_bg, &term_fg, nullptr, 0, 0, 0, 1, 1, 0); 39 | } 40 | 41 | void console_write(const char *str) 42 | { if (term_ctx) term_write(term_ctx, str, string_length(str)); } 43 | void console_write_char(char c) 44 | { if (term_ctx) term_write(term_ctx, &c, 1); } 45 | -------------------------------------------------------------------------------- /inc/luck/processes/ipc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "common.h" 21 | #include "lock.h" 22 | 23 | #include "luck/memory/manager.h" 24 | 25 | $nonnull_begin 26 | 27 | struct Message { 28 | struct Message *nullable next, *nullable previous; 29 | size_t length; 30 | byte data[]; 31 | }; 32 | 33 | struct Channel { 34 | struct Message *nullable read, *nullable write; 35 | size_t byte_count, byte_max; 36 | size_t message_count, message_max; 37 | Lock lock; 38 | }; 39 | 40 | static inline void channel_destroy(struct Channel *nonnull channel) 41 | { 42 | struct Message *nullable msg = channel->read; 43 | while (msg != nullptr) { 44 | struct Message *next = msg->next; 45 | kfree((struct Message *)msg, sizeof(struct Message) + msg->length); 46 | msg = next; 47 | } 48 | } 49 | 50 | struct Message *nullable message_create(struct Message *nonnull *nullable head, size_t length, const byte data[static nonnull length]); 51 | 52 | int channel_send(struct Channel *nonnull channel, struct Message *message); 53 | struct Message *nullable channel_receive(struct Channel *nonnull channel); 54 | 55 | $nonnull_end 56 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/cpu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "common.h" 23 | 24 | #include 25 | 26 | typedef struct [[gnu::packed]] { 27 | qword r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax, rbp; 28 | 29 | qword interrupt_number, error, rip, cs, rflags, rsp, ss; 30 | } CPUContext; 31 | 32 | $closed_enum CPUVendor { 33 | CPUVendor_INTEL, 34 | CPUVendor_AMD, 35 | CPUVendor_QEMU, 36 | CPUVendor_KVM, 37 | CPUVendor_VMWARE, 38 | CPUVendor_VIRTUALBOX, 39 | CPUVendor_UNKNOWN, 40 | }; 41 | 42 | static const char CPU_VENDORS[][12] = { 43 | [CPUVendor_INTEL] = "Intel", 44 | [CPUVendor_AMD] = "AMD", 45 | [CPUVendor_QEMU] = "QEMU", 46 | [CPUVendor_KVM] = "KVM", 47 | [CPUVendor_VMWARE] = "VMWare", 48 | [CPUVendor_VIRTUALBOX] = "VirtualBox", 49 | [CPUVendor_UNKNOWN] = "Unknown", 50 | }; 51 | 52 | enum CPUVendor cpu_get_vendor(void); 53 | 54 | static inline qword ticks_to_nanoseconds(qword x) 55 | { return (x >> 1) + (x >> 2) + (x >> 4) + (x >> 6) + (x >> 7) + (x >> 9) + (x >> 13) + (x >> 14) + (x >> 16) + (x >> 17) + (x >> 18); } 56 | -------------------------------------------------------------------------------- /inc/lj-libc/limits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma clang assume_nonnull begin 4 | 5 | #define EXIT_FAILURE 1 6 | #define BUFSIZ 4096 7 | 8 | typedef struct { 9 | void (*read)(const char *buf, int count); 10 | void (*write)(const char *buf, int count); 11 | } FILE; 12 | 13 | typedef struct { 14 | int errno; 15 | FILE *stdin, *stdout, *stderr; 16 | } PCB; 17 | extern PCB *_get_pcb(); 18 | 19 | #define errno (_get_pcb()->errno) 20 | #define stdin (_get_pcb()->stdin) 21 | #define stdout (_get_pcb()->stdout) 22 | #define stderr (_get_pcb()->stderr) 23 | 24 | #define INT_MAX 0x7fffffff 25 | 26 | #define SEEK_SET 0 27 | #define SEEK_CUR 1 28 | #define SEEK_END 2 29 | 30 | #define _IOFBF 0 31 | #define _IOLBF 1 32 | #define _IONBF 2 33 | 34 | FILE* tmpfile(void); 35 | void clearerr(FILE* fd); 36 | 37 | #define EOF (-1) 38 | 39 | char* getenv(const char* name); 40 | 41 | _Noreturn void exit(int code); 42 | 43 | double acos(double x); 44 | double asin(double x); 45 | double atan(double x); 46 | double atan2(double y, double x); 47 | double cos(double x); 48 | double cosh(double x); 49 | double exp(double x); 50 | double log(double x); 51 | double log10(double x); 52 | double log2(double x); 53 | double sin(double x); 54 | double sinh(double x); 55 | double tan(double x); 56 | double tanh(double x); 57 | double frexp(double value, int *exp); 58 | 59 | double fmod(double x, double y); 60 | double ldexp(double x, int y); 61 | double modf(double x, double* y); 62 | double pow(double x, double y); 63 | 64 | // fclose 65 | // feof 66 | // ferror 67 | // fflush 68 | // fgets 69 | // fopen 70 | // fputc 71 | // fputs 72 | // fread 73 | // free realloc 74 | // fscanf 75 | // fseek 76 | // ftell 77 | // fwrite 78 | // getc 79 | // getenv 80 | // luaopen_os 81 | // memchr memcmp memcpy memmove memset 82 | // putchar setvbuf strchr strcmp strcpy strerror strlen strncpy strrchr strstr strtoul tmpfile ungetc 83 | 84 | #pragma clang assume_nonnull end 85 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/interrupts/pic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "common.h" 23 | 24 | $nonnull_begin 25 | 26 | //#define MASTER_PIC (0x20) 27 | //#define SLAVE_PIC (0xA0) 28 | //#define MASTER_PIC_CMD (MASTER_PIC) 29 | //#define MASTER_PIC_DATA (MASTER_PIC + 1) 30 | //#define SLAVE_PIC_CMD (SLAVE_PIC) 31 | //#define SLAVE_PIC_DATA (SLAVE_PIC + 1) 32 | //#define PIC_END_OF_INT (0x20) 33 | $closed_enum PIC { 34 | PIC_MASTER = 0x20, 35 | PIC_SLAVE = 0xA0, 36 | PIC_MASTER_CMD = PIC_MASTER, 37 | PIC_MASTER_DATA = PIC_MASTER + 1, 38 | PIC_SLAVE_CMD = PIC_SLAVE, 39 | PIC_SLAVE_DATA = PIC_SLAVE + 1, 40 | PIC_END_OF_INT = 0x20, 41 | }; 42 | 43 | $closed_enum ICW1 { 44 | ICW1_ICW4 = 0x1, 45 | ICW1_SINGLE = 0x2, 46 | ICW1_INTERVAL4 = 0x4, 47 | ICW1_LEVEL = 0x8, 48 | ICW1_INIT = 0x10, 49 | }; 50 | 51 | $closed_enum ICW4 { 52 | ICW4_8086 = 0x1, 53 | ICW4_AUTO = 0x2, 54 | ICW4_BUF_SLAVE = 0x8, 55 | ICW4_BUF_MASTER = 0xC, 56 | ICW4_SFNM = 0x10, 57 | }; 58 | 59 | void pic_init(int master_offset, int slave_offset); 60 | void pic_send_end_of_interrupt(byte irq); 61 | 62 | $nonnull_end 63 | -------------------------------------------------------------------------------- /src/arch/x86_64/interrupts/pic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/arch/x86_64/interrupts/pic.h" 21 | 22 | #include "luck/arch/x86_64/io/port.h" 23 | 24 | void pic_init(int master_offset, int slave_offset) 25 | { 26 | byte master_mask = port_in_byte(PIC_MASTER), slave_mask = port_in_byte(PIC_SLAVE); 27 | 28 | // Init init sequence 29 | port_out_byte(PIC_MASTER, ICW1_INIT | ICW1_ICW4); 30 | port_out_byte(PIC_SLAVE, ICW1_INIT | ICW1_ICW4); 31 | 32 | // Set offsets 33 | port_out_byte(PIC_MASTER_DATA, master_offset); 34 | port_out_byte(PIC_SLAVE_DATA, slave_offset); 35 | 36 | // Tell master about slave 37 | port_out_byte(PIC_MASTER_DATA, 0b00000100/* IRQ2 */); 38 | port_out_byte(PIC_SLAVE_DATA, 0b00000010/* Cascade identity */); 39 | 40 | // Set mode 41 | port_out_byte(PIC_MASTER_DATA, ICW4_8086); 42 | port_out_byte(PIC_SLAVE_DATA, ICW4_8086); 43 | 44 | // Restore masks 45 | port_out_byte(PIC_MASTER_DATA, master_mask); 46 | port_out_byte(PIC_SLAVE_DATA, slave_mask); 47 | } 48 | 49 | void pic_send_end_of_interrupt(byte irq) 50 | { 51 | if (irq >= 8) port_out_byte(PIC_SLAVE_CMD, PIC_END_OF_INT); 52 | port_out_byte(PIC_MASTER_CMD, PIC_END_OF_INT); 53 | } 54 | -------------------------------------------------------------------------------- /inc/luck/arch/x86_64/interrupts/lapic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "common.h" 22 | #include "luck/memory/manager.h" 23 | 24 | $nonnull_begin 25 | 26 | #define PIT_DIVIDEND ((qword)(0x1234DE)) 27 | 28 | $closed_enum LAPICRegister: dword { 29 | LAPICRegister_IN_SERVICE = 0x10, 30 | LAPICRegister_ID = 0x20, 31 | LAPICRegister_VERSION = 0x30, 32 | LAPICRegister_PRIORITY = 0x80, 33 | LAPICRegister_END_OF_INTERRUPT = 0xB0, 34 | LAPICRegister_INTERRUPT_REQUEST = 0x100, 35 | LAPICRegister_INTERRUPT_COMMAND = 0x300, 36 | LAPICRegister_LVT_TIMER = 0x320, 37 | LAPICRegister_INITAL_COUNT = 0x380, 38 | LAPICRegister_DIVIDE_CONFIG = 0x3E0, 39 | LAPICRegister_INTERRUPT_MASK = 0x1000 40 | }; 41 | 42 | extern volatile dword *lapic_base; 43 | #if !defined(LAPIC_IMPL) 44 | # define lapic_base ((const dword *const)lapic_base) 45 | #endif 46 | 47 | static inline qword read_tsc(void) 48 | { 49 | qword tsc; 50 | $asm("RDTSC" : "=A"(tsc)); 51 | return tsc; 52 | } 53 | 54 | void lapic_init(void); 55 | dword lapic_read(enum LAPICRegister reg); 56 | void lapic_write(enum LAPICRegister reg, dword value); 57 | 58 | void pit_set_frequency(dword frequency); 59 | 60 | $nonnull_end 61 | -------------------------------------------------------------------------------- /src/lib/string.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "string.h" 21 | #include "luck/memory/manager.h" 22 | 23 | char *strchr(const char *s, int c) { 24 | while (*s) if (*s++ == c) return (char*)s; 25 | return (char*)s; 26 | } 27 | char *strrchr(const char *s, int c) 28 | { 29 | const char* o = s + string_length(s); 30 | while (*s) if (*s++ == c) o = s-1; 31 | return (char*)o; 32 | } 33 | size_t strlen(const char *s) 34 | { return string_length(s); } 35 | 36 | int strcmp(const char *s1, const char *s2) 37 | { return string_compare(string_length(s1), s1, string_length(s2), s2); } 38 | 39 | char *strcpy(char *dst, const char *src) 40 | { 41 | size_t bufsiz = string_length(src) + 1; 42 | string_copy(bufsiz, dst, bufsiz, src); 43 | return dst; 44 | } 45 | 46 | char *strncpy(char *dst, const char *src, size_t n) 47 | { 48 | string_copy(n, dst, n, src); 49 | return dst; 50 | } 51 | 52 | char *strstr(const char *haystack, char const *needle) 53 | { 54 | if (!needle || !(*needle)) 55 | return (char*)haystack; 56 | size_t len1 = strlen(haystack), len2 = strlen(needle); 57 | for (size_t i = 0; i <= len1 - len2; i++) { 58 | if (!memcmp(haystack + i, needle, len2)) 59 | return (char*)(haystack + i); 60 | } 61 | return NULL; 62 | } 63 | -------------------------------------------------------------------------------- /inc/stdint.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | typedef __UINT8_TYPE__ uint8_t; 23 | typedef __UINT16_TYPE__ uint16_t; 24 | typedef __UINT32_TYPE__ uint32_t; 25 | typedef __UINT64_TYPE__ uint64_t; 26 | 27 | typedef __UINT_LEAST8_TYPE__ uint_least8_t; 28 | typedef __UINT_LEAST16_TYPE__ uint_least16_t; 29 | typedef __UINT_LEAST32_TYPE__ uint_least32_t; 30 | typedef __UINT_LEAST64_TYPE__ uint_least64_t; 31 | 32 | typedef __UINT_FAST8_TYPE__ uint_fast8_t; 33 | typedef __UINT_FAST16_TYPE__ uint_fast16_t; 34 | typedef __UINT_FAST32_TYPE__ uint_fast32_t; 35 | typedef __UINT_FAST64_TYPE__ uint_fast64_t; 36 | 37 | typedef __INT8_TYPE__ int8_t; 38 | typedef __INT16_TYPE__ int16_t; 39 | typedef __INT32_TYPE__ int32_t; 40 | typedef __INT64_TYPE__ int64_t; 41 | 42 | typedef __INT_LEAST8_TYPE__ int_least8_t; 43 | typedef __INT_LEAST16_TYPE__ int_least16_t; 44 | typedef __INT_LEAST32_TYPE__ int_least32_t; 45 | typedef __INT_LEAST64_TYPE__ int_least64_t; 46 | 47 | typedef __INT_FAST8_TYPE__ int_fast8_t; 48 | typedef __INT_FAST16_TYPE__ int_fast16_t; 49 | typedef __INT_FAST32_TYPE__ int_fast32_t; 50 | typedef __INT_FAST64_TYPE__ int_fast64_t; 51 | 52 | typedef __UINTPTR_TYPE__ uintptr_t; 53 | typedef __INTPTR_TYPE__ intptr_t; 54 | 55 | typedef __UINTMAX_TYPE__ uintmax_t; 56 | typedef __INTMAX_TYPE__ intmax_t; 57 | 58 | typedef char wchar_t; 59 | typedef long ptrdiff_t; 60 | -------------------------------------------------------------------------------- /inc/memory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | 24 | $nonnull_begin 25 | 26 | static void *memory_copy(void *dst, const void *src, size_t n) 27 | { 28 | for (size_t i = 0; i < n; i++) 29 | ((byte *)dst)[i] = ((byte *)src)[i]; 30 | 31 | return dst; 32 | } 33 | 34 | static void *memory_set(void *dst, int c, size_t n) 35 | { 36 | for (size_t i = 0; i < n; i++) 37 | ((byte *)dst)[i] = c; 38 | 39 | return dst; 40 | } 41 | 42 | static int memory_compare(const void *b1, const void *b2, size_t n) 43 | { 44 | for (size_t i = 0; i < n; i++) { 45 | if (((byte *)b1)[i] < ((byte *)b2)[i]) return -1; 46 | if (((byte *)b1)[i] > ((byte *)b2)[i]) return 1; 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | static void *memory_move(void *dst, const void *src, size_t n) 53 | { 54 | if (src < dst) { 55 | for (size_t i = n; i > 0; i--) 56 | ((byte *)dst)[i - 1] = ((byte *)src)[i - 1]; 57 | } else { 58 | for (size_t i = 0; i < n; i++) 59 | ((byte *)dst)[i] = ((byte *)src)[i]; 60 | } 61 | 62 | return dst; 63 | } 64 | 65 | void *memcpy(void *dst, const void *src, size_t n), 66 | *memmove(void *dst, const void *src, size_t n); 67 | 68 | void *memset(void *dst, int c, size_t n); 69 | 70 | int memcmp(const void *b1, const void *b2, size_t n); 71 | 72 | $nonnull_end 73 | -------------------------------------------------------------------------------- /src/lib/math.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Louis Dupraz 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | // These are macros defined in math.h. 21 | // They are not used yet but will be used in the future for error handling. 22 | // They may also be used in other files. 23 | 24 | #include "../../inc/common.h" 25 | #define NAN 0.0 / 0.0 26 | #define HUGE_VAL 1e10000 27 | #define HUGE_VALF 1e10000f 28 | #define DBL_MAX 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 29 | #define INFINITY INF 30 | 31 | typedef union { 32 | float f; 33 | dword d; 34 | } float_bytes; 35 | 36 | typedef union { 37 | double d; 38 | qword q; 39 | } double_bytes; 40 | 41 | int isnan(double x) 42 | { 43 | double_bytes bytes = {x}; 44 | bytes.q &= 0x7FFFFFFFFFFFFFFF; 45 | return ((bytes.q & 0x7FF0000000000000) == 0x7FF0000000000000 && !(bytes.q & 0x000FFFFFFFFFFFFF)); 46 | } 47 | 48 | int isinf(double x) 49 | { 50 | double_bytes bytes = {x}; 51 | bytes.q &= 0x7FFFFFFFFFFFFFFF; 52 | return (bytes.q == 0x7FF0000000000000); 53 | } 54 | 55 | double fabs(double x) 56 | { 57 | double_bytes bytes = {x}; 58 | bytes.q &= 0x7FFFFFFFFFFFFFFF; 59 | return bytes.d; 60 | } 61 | 62 | float fabsf(float x) 63 | { 64 | float_bytes bytes = {x}; 65 | bytes.d &= 0x7FFFFFFF; 66 | return bytes.f; 67 | } 68 | -------------------------------------------------------------------------------- /src/arch/x86_64/interrupts/interrupts.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Copyright (C) 2021-2024 pitust 3 | ; 4 | ; This file is part of LuaOS. 5 | ; 6 | ; LuaOS is free software: you can redistribute it and/or modify 7 | ; it under the terms of the GNU General Public License as published by 8 | ; the Free Software Foundation, either version 3 of the License, or 9 | ; (at your option) any later version. 10 | ; 11 | ; LuaOS is distributed in the hope that it will be useful, 12 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ; GNU General Public License for more details. 15 | ; 16 | ; You should have received a copy of the GNU General Public License 17 | ; along with LuaOS. If not, see . 18 | ; 19 | 20 | bits 64 21 | 22 | extern handle_interrupt 23 | 24 | %macro idtend 1 25 | dq isr%1 26 | %endmacro 27 | 28 | %macro isrgen 1 29 | 30 | isr%1: 31 | %if (%1 >= 0x8 && %1 <= 0xE) || %1 == 0x11 || %1 == 0x1E 32 | ; i'm a expert at the morgan's tehorems or whatever theyre called 33 | %else 34 | push 0 35 | %endif 36 | push %1 37 | push rbp 38 | push rax 39 | push rbx 40 | push rcx 41 | push rdx 42 | push rsi 43 | push rdi 44 | push r8 45 | push r9 46 | push r10 47 | push r11 48 | push r12 49 | push r13 50 | push r14 51 | push r15 52 | 53 | xor rbp, rbp 54 | xor rax, rax 55 | xor rbx, rbx 56 | xor rcx, rcx 57 | xor rdx, rdx 58 | xor rsi, rsi 59 | xor rdi, rdi 60 | xor r8, r8 61 | xor r9, r9 62 | xor r10, r10 63 | xor r11, r11 64 | xor r12, r12 65 | xor r13, r13 66 | xor r14, r14 67 | xor r15, r15 68 | 69 | lea rdi, [rsp] 70 | call handle_interrupt 71 | pop r15 72 | pop r14 73 | pop r13 74 | pop r12 75 | pop r11 76 | pop r10 77 | pop r9 78 | pop r8 79 | pop rdi 80 | pop rsi 81 | pop rdx 82 | pop rcx 83 | pop rbx 84 | pop rax 85 | pop rbp 86 | add rsp, 16 87 | iretq 88 | 89 | %endmacro 90 | 91 | section .text 92 | 93 | global get_idt_targets 94 | get_idt_targets: 95 | lea rax, [rel idt_targets] 96 | ret 97 | 98 | %assign i 0 99 | %rep 256 100 | isrgen i 101 | %assign i i+1 102 | %endrep 103 | 104 | section .rodata 105 | 106 | global idt_targets 107 | idt_targets: 108 | %assign i 0 109 | %rep 256 110 | idtend i 111 | %assign i i+1 112 | %endrep 113 | -------------------------------------------------------------------------------- /inc/common.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #if __STDC_VERSION__ > 201710L 29 | #define $C2X true 30 | #else 31 | #define $C2X false 32 | #endif 33 | 34 | #define $closed_enum enum [[clang::enum_extensibility(closed)]] 35 | 36 | #define $pragma(...) _Pragma(#__VA_ARGS__) 37 | #define $asm __asm__ __volatile__ 38 | 39 | #define $nonnull_begin $pragma(clang assume_nonnull begin) 40 | #define $nonnull_end $pragma(clang assume_nonnull end) 41 | 42 | #define auto __auto_type 43 | 44 | //Panic if x is null 45 | #define $assert_nonnull(x, msg, ...) ({ \ 46 | auto _val = (x); \ 47 | if (_val == 0) \ 48 | $panic(msg, ##__VA_ARGS__); \ 49 | (typeof(typeof(*_val) *nonnull))_val; \ 50 | }) 51 | 52 | typedef uint8_t byte; 53 | typedef uint16_t word; 54 | typedef uint32_t dword; 55 | typedef uint64_t qword; 56 | 57 | typedef int8_t sbyte; 58 | /** 59 | * @attention This is literally the only reason why I forced usage of *word, 60 | * because then we can have "sword" and thats really cool 61 | */ 62 | typedef int16_t sword; 63 | typedef int32_t sdword; 64 | typedef int64_t sqword; 65 | 66 | typedef const void *label; 67 | 68 | //[[noreturn]] 69 | static inline noreturn void halt() { 70 | while (true) 71 | $asm("STI\n" 72 | "HLT\n"); 73 | __builtin_unreachable(); 74 | } 75 | 76 | static const char *nullable get_file_name(const char *nonnull cmdline) 77 | { 78 | const char *nullable current = nullptr; 79 | char c; 80 | while ((c = *cmdline++) != '\0') { 81 | if (c == '/') 82 | current = cmdline; 83 | } 84 | return current; 85 | } 86 | -------------------------------------------------------------------------------- /src/processes/ipc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Frityet 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/processes/ipc.h" 21 | #include "common.h" 22 | #include "memory.h" 23 | 24 | $nonnull_begin 25 | 26 | struct Message *nullable message_create(struct Message *nonnull *nullable head, size_t length, const byte data[static nonnull length]) 27 | { 28 | struct Message *message = kalloc(sizeof(struct Message) + length); 29 | if (message == nullptr) return nullptr; 30 | message->length = length; 31 | memory_copy(message->data, data, length); 32 | message->next = nullptr; 33 | message->previous = nullptr; 34 | if (head != nullptr) { 35 | (*head)->previous = message; 36 | message->next = *head; 37 | *head = message; 38 | } 39 | 40 | return message; 41 | } 42 | 43 | int channel_send(struct Channel *nonnull channel, struct Message *message) 44 | { 45 | if (channel->byte_count + message->length > channel->byte_max) 46 | return -1; 47 | 48 | if (channel->message_count + 1 > channel->message_max) 49 | return -1; 50 | 51 | if (channel->write == nullptr) { 52 | channel->write = message; 53 | channel->read = message; 54 | } else { 55 | message->next = channel->write; 56 | channel->write->previous = message; 57 | channel->write = message; 58 | } 59 | channel->byte_count += message->length; 60 | channel->message_count += 1; 61 | return 0; 62 | } 63 | 64 | struct Message *nullable channel_receive(struct Channel *nonnull channel) 65 | { 66 | if (channel->read == nullptr) 67 | return nullptr; 68 | 69 | struct Message *message = channel->read; 70 | channel->read = message->previous; 71 | if (channel->read != nullptr) 72 | channel->read->next = nullptr; 73 | else 74 | channel->write = nullptr; 75 | 76 | channel->byte_count -= message->length; 77 | channel->message_count -= 1; 78 | return message; 79 | } 80 | 81 | $nonnull_end 82 | -------------------------------------------------------------------------------- /inc/string.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "common.h" 23 | #include "memory.h" //Must keep this header! 24 | 25 | $nonnull_begin 26 | 27 | [[gnu::always_inline]] 28 | static inline size_t string_length(const char *str) 29 | { 30 | size_t len = 0; 31 | while (str[len++] != '\0'); 32 | return len; 33 | } 34 | 35 | [[gnu::always_inline]] 36 | static inline int string_compare(size_t len1, const char str1[static len1], size_t len2, const char str2[static len2]) 37 | { 38 | size_t len = len1 < len2 ? len1 : len2; 39 | 40 | for (size_t i = 0; i < len; i++) { 41 | if (str1[i] < str2[i]) return -1; 42 | if (str1[i] > str2[i]) return 1; 43 | } 44 | if (len1 < len2) return -1; 45 | if (len1 > len2) return 1; 46 | return 0; 47 | } 48 | 49 | [[gnu::always_inline]] 50 | static inline void string_copy(size_t bufsiz, char dest[static bufsiz], size_t n, const char src[static n]) 51 | { 52 | size_t i; 53 | for (i = 0; i < n && i < bufsiz - 1 && src[i] != '\0'; i++) 54 | dest[i] = src[i]; 55 | 56 | dest[i] = '\0'; 57 | } 58 | 59 | [[gnu::always_inline]] 60 | static inline char *string_concatenate(size_t bufsiz, char dest[static bufsiz], size_t n, const char src[static n]) 61 | { 62 | size_t len = string_length(dest); 63 | string_copy(bufsiz - len, dest + len, n, src); 64 | return dest; 65 | } 66 | 67 | static char *integer_to_string(size_t length, char dest[static length], sqword i) 68 | { 69 | size_t len = 0; 70 | bool negative = false; 71 | if (i < 0) { 72 | negative = true; 73 | i = -i; 74 | } 75 | do { 76 | dest[len++] = '0' + i % 10; 77 | i /= 10; 78 | } while (i != 0); 79 | if (negative) dest[len++] = '-'; 80 | dest[len] = '\0'; 81 | for (size_t i = 0; i < len / 2; i++) { 82 | char temp = dest[i]; 83 | dest[i] = dest[len - i - 1]; 84 | dest[len - i - 1] = temp; 85 | } 86 | return dest; 87 | } 88 | 89 | //libc compat 90 | size_t strlen(const char *str); 91 | int strcmp(const char *str1, const char *str2); 92 | char *strcpy(char *dest, const char *src), 93 | *strncpy(char *dest, const char *src, size_t n); 94 | 95 | $nonnull_end 96 | -------------------------------------------------------------------------------- /src/arch/x86_64/interrupts/idt.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/arch/x86_64/interrupts/idt.h" 21 | #include "luck/arch/x86_64/cpu.h" 22 | 23 | #include "luck/io/log.h" 24 | 25 | extern void int_div_by_zero(void *); 26 | extern void int_breakpoint(void *); 27 | extern void int_double_fault(void *); 28 | extern void int_general_protection(void *); 29 | extern void int_debug(void *); 30 | extern void int_invalid_opcode(void *); 31 | 32 | 33 | static struct IDTEntry idt[256]; 34 | static struct IDTRegister idtr = { 35 | .limit = sizeof(struct IDTEntry) * 256 - 1, 36 | .base = (qword)idt, 37 | }; 38 | 39 | qword* get_idt_targets(void); 40 | 41 | void idt_init() 42 | { 43 | qword* handlers = get_idt_targets(); 44 | for (int i = 0;i < 256;i++) { 45 | qword handler = handlers[i]; 46 | idt[i] = (struct IDTEntry) { 47 | .offset_low = (dword)handler, 48 | .selector = 0x28, 49 | .interrupt_stack_table = 0, 50 | .flags = 0x8E, 51 | .offset_middle = handler >> 16, 52 | .offset_high = handler >> 32, 53 | .reserved = 0 54 | }; 55 | } 56 | 57 | $asm("LIDT %0" :: "m"(idtr)); 58 | } 59 | 60 | [[gnu::always_inline]] 61 | static inline void print_cpu_info(CPUContext ctx) 62 | { 63 | $info("CPU Info"); 64 | $info("RAX: {} | RBX: {} | RCX: {} | RDX: {}", (void *)ctx.rax, (void *)ctx.rbx, (void *)ctx.rcx, (void *)ctx.rdx); 65 | $info("RSI: {} | RDI: {} | RSP: {} | RBP: {}", (void *)ctx.rsi, (void *)ctx.rdi, (void *)ctx.rsp, (void *)ctx.rbp); 66 | $info("R8: {} | R9: {} | R10: {} | R11: {}", (void *)ctx.r8, (void *)ctx.r9, (void *)ctx.r10, (void *)ctx.r11); 67 | $info("R12: {} | R13: {} | R14: {} | R15: {}", (void *)ctx.r12, (void *)ctx.r13, (void *)ctx.r14, (void *)ctx.r15); 68 | $info("RIP: {} | RFL: {} | ERR: {} | ISR: {}", (void *)ctx.rip, (void *)ctx.rflags, (void*)ctx.error, (void*)ctx.interrupt_number); 69 | } 70 | 71 | void handle_lapic_irq(CPUContext *ctx); 72 | void handle_interrupt(CPUContext *cpu) 73 | { 74 | // INT3 is used by the threadsweeper (the special pseudo-thread we spawn when a thread is gonna die with a fixed 16k stack) 75 | if (cpu->interrupt_number == 0xEF || cpu->interrupt_number == 0x03) { 76 | handle_lapic_irq(cpu); 77 | return; 78 | } 79 | print_cpu_info(*cpu); 80 | $panic("unexpected interrupt!"); 81 | } 82 | -------------------------------------------------------------------------------- /src/lib/ljsupport.c: -------------------------------------------------------------------------------- 1 | #include "lj-libc/limits.h" 2 | #include "common.h" 3 | #include "luck/io/log.h" 4 | #include "luck/memory/manager.h" 5 | #include "memory.h" 6 | 7 | #pragma GCC diagnostic ignored "-Wunused-parameter" 8 | 9 | double acos(double x) { $panic("todo: acos"); } 10 | double asin(double x) { $panic("todo: asin"); } 11 | double atan(double x) { $panic("todo: atan"); } 12 | double atan2(double y, double x) { $panic("todo: atan2"); } 13 | double cos(double x) { $panic("todo: cos"); } 14 | double cosh(double x) { $panic("todo: cosh"); } 15 | double exp(double x) { $panic("todo: exp"); } 16 | double log(double x) { $panic("todo: log10"); } 17 | double log10(double x) { $panic("todo: log10"); } 18 | double log2(double x) { $panic("todo: log2"); } 19 | double sin(double x) { $panic("todo: sin"); } 20 | double sinh(double x) { $panic("todo: sinh"); } 21 | double tan(double x) { $panic("todo: tan"); } 22 | double tanh(double x) { $panic("todo: tanh"); } 23 | double frexp(double value, int *exp) { $panic("todo: frexp"); } 24 | 25 | double fmod(double x, double y) { $panic("todo: fmod"); } 26 | double ldexp(double x, int y) { $panic("todo: ldexp"); } 27 | double modf(double x, double* y) { $panic("todo: modf"); } 28 | double pow(double x, double y) { $panic("todo: pow"); } 29 | 30 | void fclose() {$panic("todo:fclose");} 31 | void feof() {$panic("todo:feof");} 32 | void ferror() {$panic("todo:ferror");} 33 | void fopen() {$panic("todo:fopen");} 34 | void fputs() {$panic("todo:fputs");} 35 | void fputc() {$panic("todo:fputc");} 36 | void fread() {$panic("todo:fread");} 37 | void fflush() {$panic("todo:fflush");} 38 | void fgets() {$panic("todo:fgets");} 39 | // void strncpy() {$panic("todo:strncpy");} 40 | void strerror() {$panic("todo:strerror");} 41 | void strtoul() {$panic("todo:strtoul");} 42 | 43 | PCB* _get_pcb() { static PCB pcb; return &pcb; } 44 | 45 | void realloc() {$panic("todo:realloc");} 46 | void free() {$panic("todo:free");} 47 | 48 | [[noreturn]] void exit(int code){$panic("exit");} 49 | 50 | size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream) { 51 | if (!stream) $panic("null stream pointer?"); 52 | if (!stream->write) $panic("write to nonwriteable file"); 53 | stream->write(ptr, (int)(size * nitems)); 54 | return (int)(size * nitems); 55 | } 56 | void putchar(char c) { 57 | fwrite(&c, 1, 1, stdout); 58 | } 59 | 60 | void *ljsup_alloc(void *ud, void *ptr, size_t osize, size_t nsize) { 61 | void* nptr = kalloc(nsize); 62 | if (osize < nsize) memory_copy(nptr, ptr, osize); 63 | else memory_copy(nptr, ptr, nsize); 64 | if (ptr) kfree(ptr, osize); 65 | return nptr; 66 | } 67 | 68 | void *memchr(const void *s, byte c, size_t n) 69 | { 70 | const byte *bytes = (const byte*)s; 71 | for (size_t i = 0; i < n; i++) { 72 | if (*(bytes + i) == c) 73 | return (void*)(bytes + i); 74 | } 75 | return NULL; 76 | } 77 | 78 | void *memrchr(const void *s, byte c, size_t n) 79 | { 80 | const byte *bytes = (const byte*)s; 81 | for (size_t i = n - 1; i < n; i--) { 82 | if (*(bytes + i) == c) 83 | return (void*)(bytes + i); 84 | } 85 | return NULL; 86 | } 87 | -------------------------------------------------------------------------------- /src/arch/x86_64/io/ps2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitulst 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/io/log.h" 21 | #include "stdint.h" 22 | #include "stdbool.h" 23 | #include "luck/arch/x86_64/io/ps2.h" 24 | #include "luck/arch/x86_64/io/port.h" 25 | 26 | static const uint8_t key_codes[] = { 27 | 0, /*todo:escape*/ 0, 28 | 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x1b, 29 | 0x28, 0x29, 0x34, 0, 30 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 31 | 0x2a, 0x2b, 0x33, 0, 32 | 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 33 | 0x25, 0x30, 0x32, 0x53, 0x2c, 34 | 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 35 | 0x31, 0x2f, 0x2e, 36 | 0x53, // technically rshift is 0x54, but the bootrom does not recognize it correctly. 37 | 0, 0, 0x26, 38 | }; 39 | static char c1[] = "\e 1234567890-=\b\tqwertyuiop[]\n\0asdfghjkl;'`\0\\zxcvbnm,./\0\0\0 "; 40 | static char c2[] = "\e !@#$%^&*()_+\b\tQWERTYUIOP{}\n\0ASDFGHJKL:\"~\0|ZXCVBNM<>?\0\0\0 "; 41 | extern bool kbd_state[0x100]; 42 | extern bool kbd_enable_lsic; 43 | static bool is_extended = false; 44 | static bool shift = false; 45 | char ps2_getc(void) { 46 | while (true) { 47 | if (port_in_byte(0x64) & 1) { 48 | uint8_t byte = port_in_byte(0x60); 49 | if (byte == 0xe0) { 50 | is_extended = true; 51 | continue; 52 | } 53 | bool pressed = byte & 0x80 ? false : true; 54 | const char* mode = byte & 0x80 ? "release" : "press"; 55 | byte &= ~0x80; 56 | if (is_extended) { 57 | // uint8_t keycode = 0; 58 | // if (byte == 0x48) keycode = 0x3a; 59 | // if (byte == 0x4b) keycode = 0x37; 60 | // if (byte == 0x4d) keycode = 0x38; 61 | // if (byte == 0x50) keycode = 0x39; 62 | // if (keycode) kbd_state[keycode - 1] = pressed; 63 | // $warning("todo ps2 ext {} {:#x}", *mode, byte); 64 | is_extended = false; 65 | continue; 66 | } 67 | if (byte == 0x36) { 68 | shift = pressed; 69 | } 70 | if (byte < sizeof(c1)) { 71 | char c = (shift?c2:c1)[byte]; 72 | if (c && c != '\e' && pressed) return c; 73 | continue; 74 | } else { 75 | $warning("todo ps2 norm {} {:#x}", *mode, byte); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/bootloader/limine.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/io/log.h" 21 | 22 | #include "luck/bootloader/limine.h" 23 | 24 | 25 | #define DECLARE_MODULE(name) \ 26 | volatile const struct limine_##name##_response *nullable bootloader_##name 27 | 28 | #define MODULE_REQUEST(name) \ 29 | static volatile struct limine_##name##_request name##_request = 30 | 31 | DECLARE_MODULE(hhdm); 32 | DECLARE_MODULE(kernel_address); 33 | DECLARE_MODULE(module); 34 | DECLARE_MODULE(framebuffer); 35 | DECLARE_MODULE(rsdp); 36 | DECLARE_MODULE(memmap); 37 | 38 | 39 | MODULE_REQUEST(hhdm) { LIMINE_HHDM_REQUEST, 0, nullptr }; 40 | MODULE_REQUEST(kernel_address) { LIMINE_KERNEL_ADDRESS_REQUEST, 0, nullptr }; 41 | MODULE_REQUEST(module) { LIMINE_MODULE_REQUEST, 0, nullptr }; 42 | MODULE_REQUEST(framebuffer) { LIMINE_FRAMEBUFFER_REQUEST, 0, nullptr }; 43 | MODULE_REQUEST(rsdp) { LIMINE_RSDP_REQUEST, 0, nullptr }; 44 | MODULE_REQUEST(memmap) { LIMINE_MEMMAP_REQUEST, 0, nullptr }; 45 | 46 | qword VIRTUAL_MEMORY_HIGH = 0; 47 | 48 | uint64_t limine_virt_to_phys(uint64_t virt) { 49 | if (VIRTUAL_MEMORY_HIGH == 0) VIRTUAL_MEMORY_HIGH = hhdm_request.response->offset; 50 | if (virt >= kernel_address_request.response->virtual_base) return virt - kernel_address_request.response->virtual_base + kernel_address_request.response->physical_base; 51 | if (virt >= 0xffff800000000000) return virt - hhdm_request.response->offset; 52 | $panic("invalid call to virt_to_phys({:#x}) [invalid va]", virt); 53 | } 54 | 55 | uint64_t limine_phys_to_virt(uint64_t phys) { 56 | if (VIRTUAL_MEMORY_HIGH == 0) VIRTUAL_MEMORY_HIGH = hhdm_request.response->offset; 57 | if (phys >= 0xffff800000000000) $panic("invalid call to phys_to_virt()"); 58 | return phys + hhdm_request.response->offset; 59 | } 60 | 61 | struct limine_file *nullable find_module(const char *nonnull name) 62 | { 63 | size_t name_len = string_length(name); 64 | for (size_t i = 0; i < module_request.response->module_count; i++) { 65 | const char *nullable modnam = get_file_name(module_request.response->modules[i]->cmdline); 66 | if (modnam && string_compare(string_length((const char *nonnull)modnam), (const char *nonnull)modnam, name_len, name) == 0) 67 | return module_request.response->modules[i]; 68 | } 69 | return nullptr; 70 | } 71 | 72 | void bootloader_init() 73 | { 74 | bootloader_hhdm = hhdm_request.response; 75 | bootloader_kernel_address = kernel_address_request.response; 76 | bootloader_module = module_request.response; 77 | bootloader_framebuffer = framebuffer_request.response; 78 | bootloader_rsdp = rsdp_request.response; 79 | bootloader_memmap = memmap_request.response; 80 | } 81 | -------------------------------------------------------------------------------- /src/arch/x86_64/interrupts/lapic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #define LAPIC_IMPL 21 | #include "luck/arch/x86_64/interrupts/lapic.h" 22 | 23 | #include 24 | 25 | #include "luck/processes/scheduler.h" 26 | #include "luck/arch/x86_64/cpu.h" 27 | #include "luck/arch/x86_64/interrupts/idt.h" 28 | #include "luck/arch/x86_64/msr.h" 29 | #include "luck/arch/x86_64/io/port.h" 30 | #include "luck/io/log.h" 31 | 32 | #define VECTOR_ID (0xEF) 33 | #define TIMER_DIV (0x10) 34 | 35 | static volatile dword counter; 36 | volatile dword *lapic_base; 37 | extern void int_lapic_timer(void *); 38 | 39 | dword lapic_read(enum LAPICRegister reg) 40 | { return lapic_base[reg / 4]; } 41 | 42 | void lapic_write(enum LAPICRegister reg, dword value) 43 | { lapic_base[reg / 4] = value; } 44 | 45 | static word pit_count(void) 46 | { 47 | port_out_byte(0x43, 0x00); 48 | return port_in_byte(0x40) | (port_in_byte(0x40) << 8); 49 | } 50 | 51 | static void set_pit(word count) 52 | { 53 | port_out_byte(0x43, 0x30); 54 | port_out_byte(0x40, count & 0xFF); 55 | port_out_byte(0x40, count >> 8); 56 | } 57 | 58 | void pit_set_frequency(dword frequency) 59 | { 60 | qword div = PIT_DIVIDEND / frequency; 61 | if (PIT_DIVIDEND % frequency > frequency / 2) 62 | div++; 63 | 64 | set_pit(div); 65 | } 66 | 67 | void handle_lapic_irq(CPUContext *ctx) 68 | { 69 | if (ctx->interrupt_number == 0xEF) { 70 | lapic_write(LAPICRegister_END_OF_INTERRUPT, 0x0); 71 | lapic_write(LAPICRegister_INITAL_COUNT, 1000000); // re-arm timeout 72 | } 73 | 74 | reschedule(ctx); 75 | } 76 | 77 | void lapic_init(void) 78 | { 79 | qword apic_base_msr = read_msr(ModelSpecificRegister_APIC_BASE); 80 | apic_base_msr |= (1 << 11); 81 | write_msr(ModelSpecificRegister_APIC_BASE, apic_base_msr); 82 | 83 | lapic_base = (volatile dword *)((apic_base_msr & 0xFFFFF000) + 0xFFFF800000000000); 84 | 85 | // Set task priority to the lowest (allow all interrupts) 86 | lapic_write(LAPICRegister_PRIORITY, 0); 87 | 88 | dword timer = lapic_read(LAPICRegister_LVT_TIMER); 89 | timer &= ~(1 << 16); //clear mask to enable interrupt 90 | timer |= VECTOR_ID; 91 | lapic_write(LAPICRegister_LVT_TIMER, timer); 92 | 93 | //setup for div config 94 | // no, i do *not* know what 0x03 does. it worked for xtrix so it must work here 95 | // https://git.sr.ht/~pitust/xtrix/tree/trunk/item/src/xtrm/interrupt/lapic.d#L29 96 | lapic_write(LAPICRegister_DIVIDE_CONFIG, 0x03); 97 | 98 | //Set the init count to smth big 99 | lapic_write(LAPICRegister_INITAL_COUNT, 1000000); 100 | 101 | // Initalise PIT and sync with it 102 | pit_set_frequency(1000); 103 | 104 | 105 | } 106 | -------------------------------------------------------------------------------- /inc/luck/io/log.h: -------------------------------------------------------------------------------- 1 | /*nonnull *nonnull 2 | * Copyright (C) 2021-2024 Amrit Bhogal, pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "common.h" 23 | #include "macro_util.h" 24 | #include "string.h" 25 | 26 | #include "luck/arch/x86_64/cpu.h" 27 | 28 | $nonnull_begin 29 | 30 | void _log_level_success(void); 31 | void _log_level_info(void); 32 | void _log_level_debug(void); 33 | void _log_level_warning(void); 34 | void _log_level_error(void); 35 | void _log_level_panic(void); 36 | 37 | void _log_begin(const char* file, const char *line, const char* function); 38 | 39 | void _log_level_common_end(const char *nonnull *nonnull fmtref); 40 | noreturn void _log_level_panic_end(const char *nonnull *nonnull fmtref); 41 | 42 | #define _log_level_success_end _log_level_common_end 43 | #define _log_level_info_end _log_level_common_end 44 | #define _log_level_debug_end _log_level_common_end 45 | #define _log_level_warning_end _log_level_common_end 46 | #define _log_level_error_end _log_level_common_end 47 | 48 | #define _log__formatters(X) \ 49 | X(char, char) \ 50 | X(string, const char *) \ 51 | X(signed8, signed char) \ 52 | X(signed16, short) \ 53 | X(signed32, int) \ 54 | X(signedptr, long) \ 55 | X(signed64, long long) \ 56 | X(unsigned8, unsigned char) \ 57 | X(unsigned16, unsigned short) \ 58 | X(unsigned32, unsigned int) \ 59 | X(unsignedptr, unsigned long) \ 60 | X(unsigned64, unsigned long long) \ 61 | X(cpucontext, CPUContext)\ 62 | X(voidptr, const void *nullable) 63 | 64 | #define _log__defines(name, type) void _log_##name(const char *nonnull *nonnull fmtref, type value); 65 | _log__formatters(_log__defines) 66 | #undef _log__defines 67 | 68 | #define _log__eachtype_cb(name, type) , type: _log_##name 69 | 70 | #define _log__one(_, argument) \ 71 | {\ 72 | __auto_type _argument = (argument);\ 73 | _Generic(_argument _log__formatters(_log__eachtype_cb), char *: _log_string, \ 74 | default: _log_voidptr)(&_fmt, _argument);\ 75 | } 76 | 77 | #define $write_log(level, fmt, ...) ({ \ 78 | _log_level_##level(); \ 79 | _log_begin(__FILE_NAME__, $stringify(__LINE__), __FUNCTION__); \ 80 | const char* _fmt = (fmt); \ 81 | $foreach(_log__one, _ __VA_OPT__(,) __VA_ARGS__) \ 82 | _log_level_##level##_end(&_fmt); \ 83 | }) 84 | 85 | #define $success(fmt, ...) $write_log(success, fmt __VA_OPT__(,) __VA_ARGS__) 86 | #define $info(fmt, ...) $write_log(info, fmt __VA_OPT__(,) __VA_ARGS__) 87 | #define $debug(fmt, ...) $write_log(debug, fmt __VA_OPT__(,) __VA_ARGS__) 88 | #define $warning(fmt, ...) $write_log(warning, fmt __VA_OPT__(,) __VA_ARGS__) 89 | #define $error(fmt, ...) $write_log(error, fmt __VA_OPT__(,) __VA_ARGS__) 90 | #define $panic(fmt, ...) $write_log(panic, fmt __VA_OPT__(,) __VA_ARGS__) 91 | 92 | $nonnull_end 93 | -------------------------------------------------------------------------------- /inc/stdatomic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #include 24 | 25 | typedef enum memory_order { 26 | memory_order_relaxed = __ATOMIC_RELAXED, 27 | memory_order_acquire = __ATOMIC_ACQUIRE, 28 | memory_order_release = __ATOMIC_RELEASE, 29 | memory_order_acq_rel = __ATOMIC_ACQ_REL, 30 | memory_order_seq_cst = __ATOMIC_SEQ_CST 31 | } memory_order; 32 | 33 | #define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj))) 34 | 35 | typedef _Atomic(_Bool) atomic_bool; 36 | typedef _Atomic(char) atomic_char; 37 | typedef _Atomic(signed char) atomic_schar; 38 | typedef _Atomic(unsigned char) atomic_uchar; 39 | typedef _Atomic(short) atomic_short; 40 | typedef _Atomic(unsigned short) atomic_ushort; 41 | typedef _Atomic(int) atomic_int; 42 | typedef _Atomic(unsigned int) atomic_uint; 43 | typedef _Atomic(long) atomic_long; 44 | typedef _Atomic(unsigned long) atomic_ulong; 45 | typedef _Atomic(long long) atomic_llong; 46 | typedef _Atomic(unsigned long long) atomic_ullong; 47 | typedef _Atomic(uint_least16_t) atomic_char16_t; 48 | typedef _Atomic(uint_least32_t) atomic_char32_t; 49 | typedef _Atomic(wchar_t) atomic_wchar_t; 50 | typedef _Atomic(int_least8_t) atomic_int_least8_t; 51 | typedef _Atomic(uint_least8_t) atomic_uint_least8_t; 52 | typedef _Atomic(int_least16_t) atomic_int_least16_t; 53 | typedef _Atomic(uint_least16_t) atomic_uint_least16_t; 54 | typedef _Atomic(int_least32_t) atomic_int_least32_t; 55 | typedef _Atomic(uint_least32_t) atomic_uint_least32_t; 56 | typedef _Atomic(int_least64_t) atomic_int_least64_t; 57 | typedef _Atomic(uint_least64_t) atomic_uint_least64_t; 58 | typedef _Atomic(int_fast8_t) atomic_int_fast8_t; 59 | typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t; 60 | typedef _Atomic(int_fast16_t) atomic_int_fast16_t; 61 | typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t; 62 | typedef _Atomic(int_fast32_t) atomic_int_fast32_t; 63 | typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t; 64 | typedef _Atomic(int_fast64_t) atomic_int_fast64_t; 65 | typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t; 66 | typedef _Atomic(intptr_t) atomic_intptr_t; 67 | typedef _Atomic(uintptr_t) atomic_uintptr_t; 68 | typedef _Atomic(size_t) atomic_size_t; 69 | typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t; 70 | typedef _Atomic(intmax_t) atomic_intmax_t; 71 | typedef _Atomic(uintmax_t) atomic_uintmax_t; 72 | 73 | #define atomic_store(object, desired) __c11_atomic_store(object, desired, __ATOMIC_SEQ_CST) 74 | #define atomic_store_explicit __c11_atomic_store 75 | 76 | #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST) 77 | #define atomic_load_explicit __c11_atomic_load 78 | 79 | #define atomic_exchange(object, desired) __c11_atomic_exchange(object, desired, __ATOMIC_SEQ_CST) 80 | #define atomic_exchange_explicit __c11_atomic_exchange 81 | 82 | #define atomic_compare_exchange_strong(object, expected, desired) \ 83 | __c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) 84 | #define atomic_compare_exchange_strong_explicit __c11_atomic_compare_exchange_strong 85 | 86 | #define atomic_compare_exchange_weak(object, expected, desired) \ 87 | __c11_atomic_compare_exchange_weak(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) 88 | #define atomic_compare_exchange_weak_explicit __c11_atomic_compare_exchange_weak 89 | 90 | #define atomic_fetch_add(object, operand) __c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST) 91 | #define atomic_fetch_add_explicit __c11_atomic_fetch_add 92 | 93 | #define atomic_fetch_sub(object, operand) __c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST) 94 | #define atomic_fetch_sub_explicit __c11_atomic_fetch_sub 95 | 96 | #define atomic_fetch_or(object, operand) __c11_atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST) 97 | #define atomic_fetch_or_explicit __c11_atomic_fetch_or 98 | 99 | #define atomic_fetch_xor(object, operand) __c11_atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST) 100 | #define atomic_fetch_xor_explicit __c11_atomic_fetch_xor 101 | 102 | #define atomic_fetch_and(object, operand) __c11_atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST) 103 | #define atomic_fetch_and_explicit __c11_atomic_fetch_and 104 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | # Generated from CLion Inspection settings 2 | --- 3 | Checks: '-*, 4 | bugprone-argument-comment, 5 | bugprone-assert-side-effect, 6 | bugprone-bad-signal-to-kill-thread, 7 | bugprone-branch-clone, 8 | bugprone-copy-constructor-init, 9 | bugprone-dangling-handle, 10 | bugprone-dynamic-static-initializers, 11 | bugprone-fold-init-type, 12 | bugprone-forward-declaration-namespace, 13 | bugprone-forwarding-reference-overload, 14 | bugprone-inaccurate-erase, 15 | bugprone-incorrect-roundings, 16 | bugprone-integer-division, 17 | bugprone-lambda-function-name, 18 | bugprone-macro-parentheses, 19 | bugprone-macro-repeated-side-effects, 20 | bugprone-misplaced-operator-in-strlen-in-alloc, 21 | bugprone-misplaced-pointer-arithmetic-in-alloc, 22 | bugprone-misplaced-widening-cast, 23 | bugprone-move-forwarding-reference, 24 | bugprone-multiple-statement-macro, 25 | bugprone-no-escape, 26 | bugprone-not-null-terminated-result, 27 | bugprone-parent-virtual-call, 28 | bugprone-posix-return, 29 | bugprone-sizeof-container, 30 | bugprone-sizeof-expression, 31 | bugprone-spuriously-wake-up-functions, 32 | bugprone-string-constructor, 33 | bugprone-string-integer-assignment, 34 | bugprone-string-literal-with-embedded-nul, 35 | bugprone-suspicious-enum-usage, 36 | bugprone-suspicious-include, 37 | bugprone-suspicious-memory-comparison, 38 | bugprone-suspicious-memset-usage, 39 | bugprone-suspicious-missing-comma, 40 | bugprone-suspicious-semicolon, 41 | bugprone-suspicious-string-compare, 42 | bugprone-swapped-arguments, 43 | bugprone-terminating-continue, 44 | bugprone-throw-keyword-missing, 45 | bugprone-too-small-loop-variable, 46 | bugprone-undefined-memory-manipulation, 47 | bugprone-undelegated-constructor, 48 | bugprone-unhandled-self-assignment, 49 | bugprone-unused-raii, 50 | bugprone-unused-return-value, 51 | bugprone-use-after-move, 52 | bugprone-virtual-near-miss, 53 | cert-dcl21-cpp, 54 | cert-dcl58-cpp, 55 | cert-err34-c, 56 | cert-err52-cpp, 57 | cert-err60-cpp, 58 | cert-flp30-c, 59 | cert-msc50-cpp, 60 | cert-msc51-cpp, 61 | cert-str34-c, 62 | cppcoreguidelines-interfaces-global-init, 63 | cppcoreguidelines-narrowing-conversions, 64 | cppcoreguidelines-pro-type-member-init, 65 | cppcoreguidelines-pro-type-static-cast-downcast, 66 | cppcoreguidelines-slicing, 67 | google-default-arguments, 68 | google-explicit-constructor, 69 | google-runtime-operator, 70 | hicpp-exception-baseclass, 71 | hicpp-multiway-paths-covered, 72 | misc-misplaced-const, 73 | misc-new-delete-overloads, 74 | misc-no-recursion, 75 | misc-non-copyable-objects, 76 | misc-throw-by-value-catch-by-reference, 77 | misc-unconventional-assign-operator, 78 | misc-uniqueptr-reset-release, 79 | modernize-avoid-bind, 80 | modernize-concat-nested-namespaces, 81 | modernize-deprecated-headers, 82 | modernize-deprecated-ios-base-aliases, 83 | modernize-loop-convert, 84 | modernize-make-shared, 85 | modernize-make-unique, 86 | modernize-pass-by-value, 87 | modernize-raw-string-literal, 88 | modernize-redundant-void-arg, 89 | modernize-replace-auto-ptr, 90 | modernize-replace-disallow-copy-and-assign-macro, 91 | modernize-replace-random-shuffle, 92 | modernize-return-braced-init-list, 93 | modernize-shrink-to-fit, 94 | modernize-unary-static-assert, 95 | modernize-use-auto, 96 | modernize-use-bool-literals, 97 | modernize-use-emplace, 98 | modernize-use-equals-default, 99 | modernize-use-equals-delete, 100 | modernize-use-nodiscard, 101 | modernize-use-noexcept, 102 | modernize-use-nullptr, 103 | modernize-use-override, 104 | modernize-use-transparent-functors, 105 | modernize-use-uncaught-exceptions, 106 | mpi-buffer-deref, 107 | mpi-type-mismatch, 108 | openmp-use-default-none, 109 | performance-faster-string-find, 110 | performance-for-range-copy, 111 | performance-implicit-conversion-in-loop, 112 | performance-inefficient-algorithm, 113 | performance-inefficient-string-concatenation, 114 | performance-inefficient-vector-operation, 115 | performance-move-const-arg, 116 | performance-move-constructor-init, 117 | performance-no-automatic-move, 118 | performance-noexcept-move-constructor, 119 | performance-trivially-destructible, 120 | performance-type-promotion-in-math-fn, 121 | performance-unnecessary-copy-initialization, 122 | performance-unnecessary-value-param, 123 | portability-simd-intrinsics, 124 | readability-avoid-const-params-in-decls, 125 | readability-const-return-type, 126 | readability-container-size-empty, 127 | readability-convert-member-functions-to-static, 128 | readability-delete-null-pointer, 129 | readability-deleted-default, 130 | readability-make-member-function-const, 131 | readability-misleading-indentation, 132 | readability-misplaced-array-index, 133 | readability-non-const-parameter, 134 | readability-redundant-control-flow, 135 | readability-redundant-declaration, 136 | readability-redundant-function-ptr-dereference, 137 | readability-redundant-smartptr-get, 138 | readability-redundant-string-cstr, 139 | readability-redundant-string-init, 140 | readability-simplify-subscript-expr, 141 | readability-static-accessed-through-instance, 142 | readability-static-definition-in-anonymous-namespace, 143 | readability-string-compare, 144 | readability-uniqueptr-delete-release, 145 | readability-use-anyofallof' -------------------------------------------------------------------------------- /src/lua/kernel.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include 21 | #include "luck/io/log.h" 22 | 23 | #include "lj-libc/limits.h" 24 | #include 25 | 26 | #include "luck/io/framebuffer.h" 27 | #include "luck/processes/scheduler.h" 28 | #include "luck/io/console.h" 29 | #include "luck/arch/x86_64/io/ps2.h" 30 | #include "string.h" 31 | 32 | 33 | #define $lua_write_log(source, line, func, level, fmt, ...) ({ \ 34 | char buf[32] = {0};\ 35 | _log_level_##level(); \ 36 | _log_begin(source, integer_to_string(32, buf, line), func); \ 37 | const char* _fmt = (fmt); \ 38 | $foreach(_log__one, _ __VA_OPT__(,) __VA_ARGS__) \ 39 | _log_level_##level##_end(&_fmt); \ 40 | }) 41 | 42 | static void stdout_write(const char *str, size_t siz) 43 | { 44 | while (siz) { 45 | console_write_char(*str++); 46 | siz--; 47 | } 48 | } 49 | 50 | static size_t ps2_gets(char *buf) 51 | { 52 | size_t n = 0; 53 | char *start = buf; 54 | while (true) { 55 | char c = ps2_getc(); 56 | if (c == '\n') { 57 | stdout_write("\n", 1); 58 | *buf = 0; 59 | return n; 60 | } 61 | if (c == '\b') { 62 | if (buf == start) continue; 63 | buf--; 64 | stdout_write("\b \b", 3); 65 | continue; 66 | } 67 | n++; 68 | *buf++ = c; 69 | stdout_write(&c, 1); 70 | } 71 | } 72 | 73 | 74 | static int kernel_log_debug(lua_State *L) 75 | { 76 | const char *msg = luaL_checkstring(L, 1); 77 | struct lua_Debug dbg = {0}; 78 | lua_getstack(L, 1, &dbg); 79 | lua_getinfo(L, "nSl", &dbg); 80 | $lua_write_log(dbg.source, dbg.currentline, dbg.name, debug, msg); 81 | return 0; 82 | } 83 | 84 | static int kernel_log_info(lua_State *L) 85 | { 86 | const char *msg = luaL_checkstring(L, 1); 87 | struct lua_Debug dbg = {0}; 88 | lua_getstack(L, 1, &dbg); 89 | lua_getinfo(L, "nSl", &dbg); 90 | $lua_write_log(dbg.source, dbg.currentline, dbg.name, info, msg); 91 | return 0; 92 | } 93 | 94 | static int kernel_log_warning(lua_State *L) 95 | { 96 | const char *msg = luaL_checkstring(L, 1); 97 | struct lua_Debug dbg = {0}; 98 | lua_getstack(L, 1, &dbg); 99 | lua_getinfo(L, "nSl", &dbg); 100 | $lua_write_log(dbg.source, dbg.currentline, dbg.name, warning, msg); 101 | return 0; 102 | } 103 | 104 | static int kernel_log_error(lua_State *L) 105 | { 106 | const char *msg = luaL_checkstring(L, 1); 107 | struct lua_Debug dbg = {0}; 108 | lua_getstack(L, 1, &dbg); 109 | lua_getinfo(L, "nSl", &dbg); 110 | $lua_write_log(dbg.source, dbg.currentline, dbg.name, error, msg); 111 | return 0; 112 | } 113 | 114 | static int kernel_log_panic(lua_State *L) 115 | { 116 | const char *msg = luaL_checkstring(L, 1); 117 | struct lua_Debug dbg = {0}; 118 | lua_getstack(L, 1, &dbg); 119 | lua_getinfo(L, "nSl", &dbg); 120 | $lua_write_log(dbg.source, dbg.currentline, dbg.name, panic, msg); 121 | return 0; 122 | } 123 | 124 | static const luaL_Reg libkernel_log[] = { 125 | { "debug", kernel_log_debug }, 126 | { "info", kernel_log_info }, 127 | { "warning", kernel_log_warning }, 128 | { "error", kernel_log_error }, 129 | { "panic", kernel_log_panic }, 130 | { nullptr, nullptr } 131 | }; 132 | 133 | static int kernel_write(lua_State *L) 134 | { 135 | size_t n = 0; 136 | const char *str = luaL_checklstring(L, 1, &n); 137 | stdout_write(str, n); 138 | 139 | return 0; 140 | } 141 | 142 | static int kernel_read(lua_State *L) 143 | { 144 | static char buf[1024 * 1024] = {0}; 145 | size_t n = ps2_gets(buf); 146 | lua_pushlstring(L, buf, n); 147 | return 1; 148 | } 149 | 150 | static const luaL_Reg libkernel[] = { 151 | { "write", kernel_write }, 152 | { "read", kernel_read }, 153 | { nullptr, nullptr } 154 | }; 155 | 156 | int luaopen_kernel(lua_State *L) 157 | { 158 | luaL_newlib(L, libkernel); 159 | lua_setglobal(L, "kernel"); 160 | 161 | #define $add_module(named) ({ \ 162 | lua_getglobal(L, "kernel"); \ 163 | luaopen_##named(L); \ 164 | lua_setfield(L, -2, #named); \ 165 | }) 166 | 167 | lua_getglobal(L, "kernel"); 168 | luaL_newlib(L, libkernel_log); 169 | lua_setfield(L, -2, "log"); 170 | 171 | $add_module(framebuffer); 172 | $add_module(scheduler); 173 | 174 | #undef $add_module 175 | 176 | return 0; 177 | } 178 | -------------------------------------------------------------------------------- /src/memory/kalloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include 21 | #include "common.h" 22 | 23 | #include "luck/bootloader/limine.h" 24 | #include "luck/memory/manager.h" 25 | #include "luck/memory/magazines.h" 26 | #include "luck/io/log.h" 27 | 28 | static qword kalloc_size_arr[16] = { 29 | 16, 32, 48, 64, 96, 128, 176, 224, 288, 368, 480, 624, 800, 1024, 1360, 2048 30 | }; 31 | 32 | #define $raw_slabs(name, convert, oom) \ 33 | static qword name##_slab_list_head = 0; \ 34 | static qword name##_slab_list_alloc(void* ctx) { \ 35 | (void)ctx; \ 36 | if (name##_slab_list_head == 0) { oom } \ 37 | qword cur = name##_slab_list_head; \ 38 | name##_slab_list_head = *convert(name##_slab_list_head); \ 39 | return cur; \ 40 | } \ 41 | static void name##_slab_list_free(void* ctx, qword pg) { \ 42 | (void)ctx; \ 43 | *convert(pg) = name##_slab_list_head; \ 44 | name##_slab_list_head = pg; \ 45 | } 46 | 47 | #define $convert_pg(X) $virt(X, qword) 48 | #define $convert_kalloc(X) ((qword*)(void*)(X)) 49 | 50 | static qword current_region = 0; 51 | 52 | $raw_slabs(page, $convert_pg, { 53 | while (current_region < bootloader_memmap->entry_count) { 54 | struct limine_memmap_entry *region = bootloader_memmap->entries[current_region]; 55 | if (region->type == LIMINE_MEMMAP_USABLE) { 56 | if (region->length >= 0x1000 && (region->base & 0xfff) == 0) { 57 | region->base += 0x1000; 58 | region->length -= 0x1000; 59 | return region->base - 0x1000; 60 | } 61 | } 62 | current_region++; 63 | } 64 | $panic("we ran out of fresh pages to allocate!"); 65 | }); 66 | 67 | static Magazine* page_mag = nullptr; 68 | static Magazine* kalloc_mags[32] = {nullptr}; 69 | static qword kalloc_heads[32] = {0}; 70 | static atomic_ullong addr = 0x0000700000000000; 71 | 72 | static qword kalloc_inner(void* ctx) { 73 | qword i = (qword)ctx; 74 | if (kalloc_heads[i] == 0) { 75 | qword pa = page_alloc(PageType_REGULAR); 76 | qword va = atomic_fetch_add(&addr, 4096); 77 | pmap_map(va, pa); 78 | 79 | qword ssiz = kalloc_size_arr[i]; 80 | if (ssiz > 4096) { 81 | $panic("todo: kalloc with size > 4096 (siz={})", ssiz); 82 | } 83 | qword cnt = 4096/ssiz; 84 | if (cnt == 1) { 85 | return va; 86 | } 87 | for (qword ii = 0;ii < cnt;ii++) { 88 | qword slab = va + ii * ssiz; 89 | *(qword*)slab = kalloc_heads[i]; 90 | kalloc_heads[i] = slab; 91 | } 92 | } 93 | qword cur = kalloc_heads[i]; 94 | kalloc_heads[i] = *(qword*)kalloc_heads[i]; 95 | return cur; 96 | } 97 | static void kfree_inner(void* ctx, qword pg) { 98 | qword i = (qword)ctx; 99 | *(qword*)pg = kalloc_heads[i]; 100 | kalloc_heads[i] = pg; 101 | } 102 | 103 | void kalloc_init(void) { 104 | page_mag = mag_new(page_slab_list_alloc, page_slab_list_free, nullptr); 105 | qword idx_special = 0xffff; 106 | for (int i = 0; i < 16 ;i++) { 107 | if (kalloc_size_arr[i] == 368) idx_special = i; 108 | } 109 | if (idx_special == 0xffff) $panic("update 368 with whatever new kalloc size is big enough to hold a Magazine (>312 bytes)"); 110 | kalloc_mags[idx_special] = mag_new(kalloc_inner, kfree_inner, (void*)idx_special); 111 | for (qword i = 0;i < 32;i++) { 112 | if (i != idx_special) kalloc_mags[i] = mag_new(kalloc_inner, kfree_inner, (void*)i); 113 | } 114 | } 115 | 116 | qword page_alloc(enum PageType pty) { 117 | (void)pty; // for now :P 118 | 119 | qword addr = mag_get(page_mag); 120 | memset($virt(addr, void), 0, 4096); 121 | return addr; 122 | } 123 | 124 | static qword find_kalloc_mag(qword size) { 125 | if (size > kalloc_size_arr[15]) $panic("cannot kalloc() or kfree() more than {} bytes! (attempted to kalloc/kfree {})", kalloc_size_arr[15], size); 126 | for (qword i = 0;i < 16;i++) { 127 | if (kalloc_size_arr[i] >= size) return i; 128 | } 129 | $panic("wtf"); 130 | } 131 | void *kalloc(qword size) { 132 | if (size > kalloc_size_arr[15]) { 133 | size = (size + 0xfff) & ~0xfff; 134 | qword this_addr = atomic_fetch_add(&addr, size); 135 | for (qword i = 0;i < size;i += 4096) pmap_map(this_addr + i, page_alloc(PageType_REGULAR)); 136 | return (void*)this_addr; 137 | } 138 | qword mag = find_kalloc_mag(size); 139 | earlykalloc: 140 | if (!kalloc_mags[mag]) { 141 | if (kalloc_size_arr[mag] < 336) { 142 | mag = find_kalloc_mag(336); 143 | goto earlykalloc; 144 | } 145 | $panic("cannot (yet) kalloc {} [earlykalloc mode], sclass {}", size, kalloc_size_arr[mag]); 146 | } 147 | void* b = (void*)mag_get(kalloc_mags[mag]); 148 | memset(b, 0xcc, kalloc_size_arr[mag]); 149 | memset(b, 0x00, size); 150 | return b; 151 | } 152 | 153 | void kfree(void* ptr, qword size) { 154 | if (size > kalloc_size_arr[15]) { 155 | size = (size + 0xfff) & ~0xfff; 156 | $warning("leaking {} bytes at {}", size, ptr); 157 | return; 158 | } 159 | memset(ptr, 0xa5, size); 160 | qword mag = find_kalloc_mag(size); 161 | mag_put(kalloc_mags[mag], (qword)ptr); 162 | } 163 | 164 | -------------------------------------------------------------------------------- /src/start.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include "common.h" 23 | #include "lj-libc/limits.h" 24 | #include "luck/io/log.h" 25 | 26 | #include "luck/arch/x86_64/acpi/madt.h" 27 | #include "luck/arch/x86_64/acpi/acpi.h" 28 | #include "luck/io/console.h" 29 | #include "luck/io/framebuffer.h" 30 | #include "luck/arch/x86_64/gdt.h" 31 | #include "luck/arch/x86_64/interrupts/idt.h" 32 | #include "luck/arch/x86_64/interrupts/lapic.h" 33 | #include "luck/arch/x86_64/io/ps2.h" 34 | #include "luck/processes/scheduler.h" 35 | #include "luck/memory/manager.h" 36 | #include "luck/memory/magazines.h" 37 | #include "luck/bootloader/limine.h" 38 | 39 | #undef stdin 40 | #undef stdout 41 | #undef stderr 42 | 43 | $nonnull_begin 44 | 45 | static const char *nullable extension(size_t buflen, const char buf[buflen]) 46 | { 47 | //Find the last dot 48 | size_t i = buflen; 49 | while (i > 0 && buf[i] != '.') i--; 50 | 51 | if (i == 0) return nullptr; 52 | return &buf[i + 1]; 53 | } 54 | 55 | static void stdout_write(const char *str, int siz) 56 | { 57 | while (siz) { 58 | console_write_char(*str++); 59 | siz--; 60 | } 61 | } 62 | 63 | static void ps2_gets(char *buf) 64 | { 65 | char *start = buf; 66 | while (true) { 67 | char c = ps2_getc(); 68 | if (c == '\n') { 69 | stdout_write("\n", 1); 70 | *buf = 0; 71 | return; 72 | } 73 | if (c == '\b') { 74 | if (buf == start) continue; 75 | buf--; 76 | stdout_write("\b \b", 3); 77 | continue; 78 | } 79 | *buf++ = c; 80 | stdout_write(&c, 1); 81 | } 82 | } 83 | 84 | [[gnu::used]] noreturn void kernel_start() 85 | { 86 | $asm ( 87 | ".intel_syntax noprefix\n" 88 | "mov rax, cr0\n" 89 | "and ax, 0xFFFB\n" 90 | "or ax, 0x2\n" 91 | "mov cr0, rax\n" 92 | "mov rax, cr4\n" 93 | "or ax, 3 << 9\n" 94 | "mov cr4, rax\n" 95 | ".att_syntax\n" 96 | ); 97 | 98 | qword cr3; 99 | $asm("MOVQ %%CR3, %0" : "=r"(cr3)); 100 | for (qword i = 0; i < 256; i++) 101 | $virt(cr3, qword)[i] = 0; 102 | 103 | $asm("MOVQ %0, %%CR3" :: "r"(cr3) : "memory"); 104 | 105 | 106 | $success("Started LuaOS"); 107 | 108 | $info("CPU Vendor: {}", cpu_get_vendor()); 109 | 110 | $info("Initialising bootloader"); 111 | bootloader_init(); 112 | $success("Done"); 113 | 114 | $info("Initialising GDT"); 115 | gdt_init(); 116 | $success("Done"); 117 | 118 | $info("Initialising IDT"); 119 | idt_init(); 120 | $success("Done"); 121 | $asm("STI"); 122 | 123 | $info("Initialising memory"); 124 | { 125 | $info(" Magazines..."); 126 | magazine_init(); 127 | $success(" Done"); 128 | 129 | $info(" Kernel memory allocator..."); 130 | kalloc_init(); 131 | $success(" Done"); 132 | } 133 | $success("Done"); 134 | 135 | terminal_init(); 136 | framebuffer_init(); 137 | 138 | if (bootloader_framebuffer == nullptr || bootloader_framebuffer->framebuffer_count == 0) 139 | $panic("No framebuffer found!"); 140 | 141 | $info("Initialising APIC"); 142 | auto rsdp = $assert_nonnull(rsdp_init(), "No RSDP found"); 143 | auto madt = $assert_nonnull(madt_init(rsdp), "No MADT found"); 144 | 145 | size_t core_c = 0; 146 | 147 | for (struct MADTEntryHeader *entry = (struct MADTEntryHeader *)madt->entries; 148 | (uintptr_t)entry < (uintptr_t)(((uintptr_t)madt->entries) + madt->descriptor.length - sizeof(struct MADT)); 149 | entry = (struct MADTEntryHeader *)((byte *)entry + (entry)->length)) { 150 | 151 | $debug(" Found entry with ID {}", entry->id); 152 | switch (entry->id) { 153 | case MADTEntryID_LAPIC: { 154 | struct MADTEntry_LAPIC *lapic = (struct MADTEntry_LAPIC *) entry; 155 | $success(" Found LAPIC at core {} (address: {})", core_c++, lapic); 156 | $debug(" Processor ID: {}", lapic->processor_id); 157 | $debug(" APIC ID: {}", lapic->apic_id); 158 | $debug(" Flags: {}", lapic->flags); 159 | break; 160 | } 161 | } 162 | } 163 | $success("Done"); 164 | 165 | $info("Initalising LAPIC"); 166 | lapic_init(); 167 | $info("LAPIC base: {}", lapic_base); 168 | $success("Done"); 169 | 170 | static FILE stdout = { 171 | .write = stdout_write, 172 | 173 | }; 174 | _get_pcb()->stdout = &stdout; 175 | 176 | if (bootloader_module == nullptr) $panic("no modules available!"); 177 | if (bootloader_module->module_count == 0) $panic("more than one module available!"); 178 | $info("Initialising scheduler"); 179 | scheduler_init(); 180 | $success("Done"); 181 | 182 | $success("Initialisation complete"); 183 | 184 | $info("Loading {} programs", bootloader_module->module_count); 185 | Thread *nonnull active_threads[bootloader_module->module_count]; 186 | for (size_t i = 0; i < bootloader_module->module_count; i++) { 187 | struct limine_file *m = bootloader_module->modules[i]; 188 | auto ext_ptr = extension(string_length(m->cmdline), m->cmdline); 189 | if (ext_ptr == nullptr) continue; 190 | auto ext = (const char *nonnull)ext_ptr; 191 | if (string_compare(string_length(ext), ext, 3, "lua") != 0) continue; 192 | $info(" Loading {}...", m->cmdline); 193 | active_threads[i] = $assert_nonnull(spawn_thread(m->address, m->size, m->cmdline), "Failed to load lua module {}!", m->cmdline); 194 | $success(" Done"); 195 | } 196 | 197 | halt(); 198 | } 199 | 200 | $nonnull_end 201 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021-2024 Amrit Bhogal 2 | # 3 | # This file is part of LuaOS. 4 | # 5 | # LuaOS is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # LuaOS is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with LuaOS. If not, see . 17 | 18 | 19 | 20 | CC = clang 21 | LD = ld.lld 22 | LUAJIT= luajit 23 | 24 | GDB := x86_64-elf-gdb 25 | 26 | CFLAGS = -g -O0 -pipe -Wall -Wextra -Werror -Wno-unused -fms-extensions -Wno-microsoft 27 | NASMFLAGS = -F dwarf -g -f elf64 28 | 29 | CFLAGS += \ 30 | -std=gnu2x \ 31 | -ffreestanding \ 32 | -fno-stack-protector \ 33 | -fno-stack-check \ 34 | -fno-lto \ 35 | -fno-pie \ 36 | -fno-pic \ 37 | -m64 \ 38 | -march=x86-64 \ 39 | -mabi=sysv \ 40 | -mno-80387 \ 41 | -mno-mmx \ 42 | -mno-sse \ 43 | -mno-sse2 \ 44 | -mno-red-zone \ 45 | -mcmodel=kernel \ 46 | -MMD \ 47 | -target x86_64-elf \ 48 | -nostdinc \ 49 | -isystem extern/ \ 50 | -isystem extern/LuaJIT/src \ 51 | -Iinc \ 52 | -Wno-unused-command-line-argument \ 53 | -Wanon-enum-enum-conversion \ 54 | -Wassign-enum \ 55 | -Wenum-conversion \ 56 | -Wenum-enum-conversion \ 57 | -Wno-unused-function \ 58 | -Wno-unused-parameter \ 59 | -Wnull-dereference \ 60 | -Wnull-conversion \ 61 | -Wnullability-completeness \ 62 | -Wnullable-to-nonnull-conversion \ 63 | -Wno-missing-field-initializers \ 64 | -fno-omit-frame-pointer \ 65 | -Wno-deprecated-attributes \ 66 | -fms-extensions\ 67 | -fblocks 68 | 69 | LDFLAGS += \ 70 | -nostdlib \ 71 | -static \ 72 | -m elf_x86_64 \ 73 | -z max-page-size=0x1000 \ 74 | -T res/linker.ld \ 75 | -no-pie 76 | 77 | ASFLAGS = -f elf64 78 | 79 | CFILES := $(shell find ./src -type f -name '*.c') extern/terminal/term.c extern/terminal/backends/framebuffer.c 80 | ASFILES := $(shell find ./src -type f -name '*.asm') 81 | 82 | USERLAND_FILES := $(shell find ./Userland -type f -name '*.lua') 83 | 84 | COBJS := $(addprefix build/obj/,$(CFILES:.c=.c.o)) 85 | ASOBJS := $(addprefix build/obj/,$(ASFILES:.asm=.asm.o)) 86 | 87 | QEMUFLAGS := -smp 2 -m 2G -monitor stdio -serial file:luaos.log -vga std 88 | 89 | QDF ?= -s 90 | 91 | .PHONY: all 92 | all: build/bin/luaos.iso extern/ovmf-x64 93 | 94 | .PHONY: uefi 95 | uefi: extern/ovmf-x64 build/bin/luaos.iso 96 | qemu-system-x86_64 -M q35 $(QEMUFLAGS) -bios extern/ovmf-x64/OVMF.fd -cdrom build/bin/luaos.iso -boot d $(QDF) 97 | 98 | .PHONY: bios 99 | bios: build/bin/luaos.iso 100 | qemu-system-x86_64 -M q35 $(QEMUFLAGS) -cdrom build/bin/luaos.iso -boot d $(QDF) 101 | 102 | extern/LuaJIT/libluajit_luck.o: 103 | @/usr/bin/printf "[\033[1;35mKernel - extern\033[0m] \033[32mBuilding LuaJIT\n\033[0m" 104 | @$(MAKE) -C extern/LuaJIT CC="$(CC) -Wno-implicit-function-declaration" 105 | 106 | extern/ovmf-x64: 107 | @/usr/bin/printf "[\033[1;35mKernel\033[0m] \033[32mDownloading OVMF\n\033[0m" 108 | @mkdir -p $@ 109 | cd $@ && curl -o OVMF-X64.zip https://efi.akeo.ie/OVMF/OVMF-X64.zip && 7z x OVMF-X64.zip 110 | 111 | extern/limine/limine-deploy: 112 | @/usr/bin/printf "[\033[1;35mKernel - extern\033[0m] \033[32mBuilding Limine\n\033[0m" 113 | @$(MAKE) -C extern/limine 114 | 115 | extern/LuaJIT/src/lua.h: extern/LuaJIT 116 | 117 | user-land: build-userland.lua 118 | @/usr/bin/printf "[\033[1;35mUserland\033[0m] \033[32mBuilding userland\n\033[0m" 119 | @$(LUAJIT) build-userland.lua 120 | 121 | 122 | 123 | res/limine.cfg: user-land 124 | 125 | build/bin/luaos.iso: extern/limine extern/limine/limine-deploy build/bin/luck.elf res/limine.cfg user-land 126 | @/usr/bin/printf "[\033[1;35mKernel\033[0m] \033[32mBuilding ISO\n\033[0m" 127 | @mkdir -p $(dir $@)/iso 128 | 129 | # All files in Userland/lua_modules/share/lua/5.1/ will be copied to the root of the ISO 130 | cp -r Userland/lua_modules/share/lua/5.1/* $(dir $@)/iso 131 | 132 | cp \ 133 | build/bin/luck.elf res/powered-by-lua.bmp res/limine.cfg \ 134 | res/font.bin extern/limine/limine-cd.bin extern/limine/limine.sys \ 135 | extern/limine/limine-cd-efi.bin\ 136 | $(dir $@)/iso 137 | xorriso -as mkisofs\ 138 | -b limine-cd.bin\ 139 | -no-emul-boot\ 140 | -boot-load-size 4\ 141 | -boot-info-table\ 142 | --efi-boot limine-cd-efi.bin\ 143 | -efi-boot-part\ 144 | --efi-boot-image\ 145 | --protective-msdos-label\ 146 | $(dir $@)/iso -o $@ 147 | rm -rf $(dir $@)/iso 148 | 149 | extern/limine/limine-deploy $@ 150 | @/usr/bin/printf "[\033[1;35mKernel\033[0m] \033[32mISO built at \033[33m$@\n\033[0m" 151 | 152 | build/bin/luck.elf: $(COBJS) $(ASOBJS) extern/LuaJIT/libluajit_luck.o 153 | @/usr/bin/printf "[\033[1;35mKernel\033[0m] \033[32mLinking \033[33m$@\n\033[0m" 154 | @mkdir -p $(dir $@) 155 | $(LD) $(LDFLAGS) -o $@ $^ 156 | 157 | build/obj/extern/%.c.o: extern/limine extern/terminal extern/LuaJIT 158 | @/usr/bin/printf "[\033[1;35mKernel - extern\033[0m] \033[32mCompiling \033[33m$<\n\033[0m" 159 | @mkdir -p $(dir $@) 160 | $(CC) $(CFLAGS) -c $(shell echo "$@" | sed 's/build\/obj\///g' | sed 's/\.o//g') -o $@ 161 | 162 | build/obj/./src/%.c.o: src/%.c extern/limine extern/terminal extern/LuaJIT 163 | @/usr/bin/printf "[\033[1;35mKernel\033[0m] \033[32mCompiling \033[33m$<\n\033[0m" 164 | @mkdir -p $(dir $@) 165 | $(CC) $(CFLAGS) -c $< -o $@ 166 | 167 | build/obj/%.asm.o: %.asm 168 | @/usr/bin/printf "[\033[1;35mKernel\033[0m] \033[32mAssembling \033[33m$^\n\033[0m" 169 | @mkdir -p $(dir $@) 170 | nasm $(NASMFLAGS) $^ -o $@ 171 | 172 | .PHONY: clean 173 | clean: 174 | rm -rf build 175 | find . -type f -name '*.o' -delete 176 | rm -rf Userland/.luarocks 177 | rm -rf Userland/lua_modules 178 | rm -rf Userland/lua 179 | rm -rf Userland/luarocks 180 | $(MAKE) -C extern/limine clean 181 | 182 | -include $(CFILES:%.c=build/obj/%.c.d) 183 | -------------------------------------------------------------------------------- /src/memory/magazines.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal, pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "common.h" 21 | #include "lock.h" 22 | 23 | #define _EVAL(...) __VA_ARGS__ 24 | #define EVAL(...) _EVAL(__VA_ARGS__) 25 | 26 | #include "luck/bootloader/limine.h" 27 | #include "luck/io/log.h" 28 | #include "luck/memory/magazines.h" 29 | #include "luck/memory/manager.h" 30 | 31 | #define mag_each_size 512 32 | #define max_static_mag 2 33 | #define max_ready_mags 32 34 | 35 | static Magazine static_mags[max_static_mag]; 36 | static atomic_llong num_static_mag = 0; 37 | static MagazinePerCPU mag_percpu[max_static_mag * 256]; 38 | 39 | static qword static_mag_alloc[mag_each_size * 32]; 40 | static qword static_mag_alloc_idx = 0; 41 | 42 | static atomic_llong contended, total_attempts, mag_size_max = 128; 43 | 44 | static volatile dword *lapic_id; 45 | 46 | [[gnu::naked]] 47 | static qword get_lapic_addr_dyn(void) { 48 | $asm ("movl $0x1b, %ecx"); 49 | $asm ("rdmsr"); 50 | $asm ("shrq $32, %rdx"); 51 | $asm ("orq %rax, %rdx"); 52 | $asm ("retq"); 53 | } 54 | 55 | void magazine_init(void) 56 | { 57 | lapic_id = $virt(get_lapic_addr_dyn() & ~0xfff, dword); 58 | } 59 | 60 | #define max_lapic_id 2 // TODO: change this to the actual value once we do smp 61 | 62 | Magazine *mag_new(qword(*get)(void *ctx), void (*put)(void *ctx, qword item), void *ctx) { 63 | Magazine *mag = nullptr; 64 | uint64_t mag_id = atomic_fetch_add(&num_static_mag, 1); 65 | if (mag_id < max_static_mag) { 66 | mag = &static_mags[mag_id]; 67 | memset(mag, 0, sizeof(Magazine)); 68 | mag->mag_percpu = &mag_percpu[mag_id * 256]; 69 | memset(mag->mag_percpu, 0, sizeof(MagazinePerCPU) * 256); 70 | if (*lapic_id >= 256) $panic("arch_get_max_cpu_id() >= 256; luaOS supports a maximum of 256 cores!"); 71 | } else { 72 | mag = kalloc(sizeof(Magazine)); 73 | mag->mag_percpu = kalloc(sizeof(MagazinePerCPU) * max_lapic_id); 74 | } 75 | mag->get = get; 76 | mag->put = put; 77 | mag->ctx = ctx; 78 | return mag; 79 | } 80 | static qword *alloc_mag(void) { 81 | if (static_mag_alloc_idx >= 32) $panic("out of static magazine allocation space!"); 82 | return &static_mag_alloc[static_mag_alloc_idx++ * mag_each_size + 1]; 83 | } 84 | static void free_mag(const qword *mag) { 85 | (void)mag; 86 | $panic("TODO: free magazines (needs kmalloc)"); 87 | } 88 | 89 | #define SWAP(a, b) do { __auto_type _tmp = (a); (a) = (b); (b) = _tmp; } while (0) 90 | void mag_put(Magazine *mag, qword item) { 91 | MagazinePerCPU *mag_cpu = &mag->mag_percpu[*lapic_id >> 24]; 92 | acquire_lock(&mag_cpu->locked); 93 | free: 94 | if (mag_cpu->current && mag_cpu->current[-1] < mag_size_max) { 95 | // TODO: i really really really don't want this in the hot path for free 96 | if (__builtin_expect(!mag_cpu->current, 0)) mag_cpu->current = alloc_mag(); 97 | mag_cpu->current[mag_cpu->current[-1]++] = item; 98 | } else if (mag_cpu->previous && mag_cpu->previous[-1] == 0) { 99 | SWAP(mag_cpu->previous, mag_cpu->current); 100 | goto free; 101 | } else if (atomic_load((atomic_ullong*)&mag->num_ready_mags) < max_ready_mags) { 102 | bool done = false; 103 | acquire_lock(&mag->locked); 104 | if (mag->num_ready_mags < max_ready_mags) { 105 | if (mag_cpu->current) mag->ready_mags[mag->num_ready_mags++] = mag_cpu->current; 106 | if (mag->num_free_mags) { 107 | mag_cpu->current = mag->free_mags[--mag->num_free_mags]; 108 | } else { 109 | mag_cpu->current = alloc_mag(); 110 | } 111 | done = true; 112 | release_lock(&mag->locked); 113 | } else { 114 | release_lock(&mag->locked); 115 | goto release; 116 | } 117 | } else { 118 | release:; 119 | if (!mag_cpu->current) $panic("this is prooobably dead code"); 120 | uint64_t mag_cur_size = mag_cpu->current[-1]; 121 | for (uint64_t i = 0;i < mag_cur_size;i++) { 122 | mag->put(mag->ctx, mag_cpu->current[i]); 123 | mag_cpu->current[i] = 0; 124 | } 125 | mag_cpu->current[-1] = 0; 126 | } 127 | release_lock(&mag_cpu->locked); 128 | } 129 | bool mag_xget(Magazine *mag, qword *out, uint64_t flags) { 130 | MagazinePerCPU *mag_cpu = &mag->mag_percpu[*lapic_id >> 24]; 131 | bool ok = false; 132 | acquire_lock(&mag_cpu->locked); 133 | cur_mag_populated: 134 | if (mag_cpu->current && mag_cpu->current[-1]) { 135 | *out = mag_cpu->current[--mag_cpu->current[-1]]; 136 | ok = true; 137 | } else if (mag_cpu->previous && mag_cpu->previous[-1]) { 138 | SWAP(mag_cpu->previous, mag_cpu->current); 139 | goto cur_mag_populated; 140 | } else if (atomic_load((atomic_ullong*)&mag->num_ready_mags)) { 141 | acquire_lock(&mag->locked); 142 | if (mag->num_ready_mags) { 143 | if (mag->num_free_mags < 16) { 144 | mag->free_mags[mag->num_free_mags++] = mag_cpu->current; 145 | } else { 146 | // todo: is the if needed? 147 | if (mag_cpu->current) { 148 | free_mag(mag_cpu->current); 149 | } 150 | } 151 | mag_cpu->current = mag->ready_mags[--mag->num_ready_mags]; 152 | release_lock(&mag->locked); 153 | // current magazine has been populated 154 | goto cur_mag_populated; 155 | } else { 156 | release_lock(&mag->locked); 157 | // we need to get more resources 158 | goto allocate_new_obj; 159 | } 160 | } else { 161 | allocate_new_obj:; 162 | if (flags & MAG_MUSTGET) { 163 | acquire_lock(&mag->locked); 164 | *out = mag->get(mag->ctx); 165 | release_lock(&mag->locked); 166 | ok = true; 167 | } 168 | } 169 | release_lock(&mag_cpu->locked); 170 | return ok; 171 | } 172 | qword mag_get(Magazine *mag) { 173 | qword res = 0; 174 | mag_xget(mag, &res, MAG_MUSTGET); 175 | return res; 176 | } 177 | void mag_100ms_adjust(void) { 178 | qword contention = atomic_exchange(&contended, 0); 179 | qword tattempts = atomic_exchange(&total_attempts, 0); 180 | sqword delta = 0; 181 | if (contention * 30 < tattempts) delta = -1; 182 | if (contention * 10 >= tattempts) delta = 1; 183 | if (delta + mag_size_max >= mag_each_size - 1 && delta == 1) return; 184 | if (delta + mag_size_max < 16u && delta == -1) return; 185 | atomic_fetch_add(&mag_size_max, delta); 186 | } 187 | -------------------------------------------------------------------------------- /src/io/framebuffer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #define OLIVEC_IMPLEMENTATION 21 | #include "luck/io/framebuffer.h" 22 | #include "luck/bootloader/limine.h" 23 | 24 | #include "memory.h" 25 | #include "luck/memory/manager.h" 26 | #include "lj-libc/limits.h" 27 | #include 28 | 29 | #define CANVAS_T "OliveCanvas" 30 | 31 | enum { 32 | /*Largest framebuffer supported*/ 33 | Framebuffer_SAVE_SIZE = 1280 * 1280 34 | }; 35 | 36 | Olivec_Canvas framebuffer_init() 37 | { 38 | struct limine_framebuffer *nonnull fb = bootloader_framebuffer->framebuffers[0]; 39 | return olivec_canvas(fb->address, fb->width, fb->height, fb->width); 40 | } 41 | 42 | static int libframebuffer_canvas_fill(lua_State *L) 43 | { 44 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 45 | dword colour = luaL_checkinteger(L, 2); 46 | 47 | olivec_fill(*canvas, colour); 48 | 49 | return 0; 50 | } 51 | 52 | static int libframebuffer_canvas_set_pixel(lua_State *L) 53 | { 54 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 55 | dword x = luaL_checkinteger(L, 2); 56 | dword y = luaL_checkinteger(L, 3); 57 | dword colour = luaL_checkinteger(L, 4); 58 | 59 | if (x >= canvas->width || y >= canvas->height) { 60 | lua_pushnil(L); 61 | lua_pushstring(L, "pixel out of bounds"); 62 | return 2; 63 | } 64 | 65 | OLIVEC_PIXEL(*canvas, x, y) = colour; 66 | 67 | return 0; 68 | } 69 | 70 | static int libframebuffer_canvas_get_pixel(lua_State *L) 71 | { 72 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 73 | dword x = luaL_checkinteger(L, 2); 74 | dword y = luaL_checkinteger(L, 3); 75 | 76 | if (x >= canvas->width || y >= canvas->height) { 77 | lua_pushnil(L); 78 | lua_pushstring(L, "pixel out of bounds"); 79 | return 2; 80 | } 81 | 82 | lua_pushinteger(L, OLIVEC_PIXEL(*canvas, x, y)); 83 | 84 | return 1; 85 | } 86 | 87 | static int libframebuffer_canvas_draw_line(lua_State *L) 88 | { 89 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 90 | auto x1 = (sdword)luaL_checkinteger(L, 2); 91 | auto y1 = (sdword)luaL_checkinteger(L, 3); 92 | auto x2 = (sdword)luaL_checkinteger(L, 4); 93 | auto y2 = (sdword)luaL_checkinteger(L, 5); 94 | dword colour = luaL_checkinteger(L, 6); 95 | 96 | olivec_line(*canvas, x1, y1, x2, y2, colour); 97 | 98 | return 0; 99 | } 100 | 101 | static int libframebuffer_canvas_draw_rect(lua_State *L) 102 | { 103 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 104 | auto x = (sdword)luaL_checkinteger(L, 2); 105 | auto y = (sdword)luaL_checkinteger(L, 3); 106 | auto w = (sdword)luaL_checkinteger(L, 4); 107 | auto h = (sdword)luaL_checkinteger(L, 5); 108 | dword colour = luaL_checkinteger(L, 6); 109 | 110 | olivec_rect(*canvas, x, y, w, h, colour); 111 | 112 | return 0; 113 | } 114 | 115 | static int libframebuffer_canvas_draw_circle(lua_State *L) 116 | { 117 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 118 | auto x = (sdword)luaL_checkinteger(L, 2); 119 | auto y = (sdword)luaL_checkinteger(L, 3); 120 | auto r = (sdword)luaL_checkinteger(L, 4); 121 | dword colour = luaL_checkinteger(L, 5); 122 | 123 | olivec_circle(*canvas, x, y, r, colour); 124 | 125 | return 0; 126 | } 127 | 128 | static int libframebuffer_canvas_draw_triangle(lua_State *L) 129 | { 130 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 131 | auto x1 = (sdword)luaL_checkinteger(L, 2); 132 | auto y1 = (sdword)luaL_checkinteger(L, 3); 133 | auto x2 = (sdword)luaL_checkinteger(L, 4); 134 | auto y2 = (sdword)luaL_checkinteger(L, 5); 135 | auto x3 = (sdword)luaL_checkinteger(L, 6); 136 | auto y3 = (sdword)luaL_checkinteger(L, 7); 137 | dword colour = luaL_checkinteger(L, 8); 138 | 139 | olivec_triangle(*canvas, x1, y1, x2, y2, x3, y3, colour); 140 | 141 | return 0; 142 | } 143 | 144 | static int libframebuffer_canvas_draw_text(lua_State *L) 145 | { 146 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 147 | auto x = (sdword)luaL_checkinteger(L, 2); 148 | auto y = (sdword)luaL_checkinteger(L, 3); 149 | const char *text = luaL_checkstring(L, 4); 150 | dword colour = luaL_checkinteger(L, 5); 151 | qword size = luaL_checkinteger(L, 6); 152 | 153 | 154 | olivec_text(*canvas, text, x, y, olivec_default_font, size, colour); 155 | 156 | return 0; 157 | } 158 | 159 | // function framebuffer:get_dimensions() 160 | static int libframebuffer_dimensions(lua_State *L) 161 | { 162 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 163 | 164 | lua_pushinteger(L, (sqword)canvas->width); 165 | lua_pushinteger(L, (sqword)canvas->height); 166 | 167 | return 2; 168 | } 169 | 170 | static int libframebuffer_get(lua_State *L) 171 | { 172 | struct limine_framebuffer *nonnull fb = bootloader_framebuffer->framebuffers[0]; 173 | 174 | Olivec_Canvas *canvas = lua_newuserdata(L, sizeof(Olivec_Canvas)); 175 | *canvas = olivec_canvas(fb->address, fb->width, fb->height, fb->width); 176 | 177 | luaL_getmetatable(L, CANVAS_T); 178 | lua_setmetatable(L, -2); 179 | 180 | return 1; 181 | } 182 | 183 | static _Atomic dword save_buffer[Framebuffer_SAVE_SIZE]; 184 | 185 | static int libframebuffer_canvas_save(lua_State *L) 186 | { 187 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 188 | 189 | memory_copy(save_buffer, canvas->pixels, canvas->width * canvas->height * sizeof(dword)); 190 | return 0; 191 | } 192 | 193 | static int libframebuffer_canvas_load(lua_State *L) 194 | { 195 | Olivec_Canvas *canvas = luaL_checkudata(L, 1, CANVAS_T); 196 | 197 | memory_copy(canvas->pixels, save_buffer, canvas->width * canvas->height * sizeof(dword)); 198 | 199 | return 0; 200 | } 201 | 202 | static const luaL_Reg libframebuffer_canvas[] = { 203 | { "fill", libframebuffer_canvas_fill }, 204 | { "set_pixel", libframebuffer_canvas_set_pixel }, 205 | { "get_pixel", libframebuffer_canvas_get_pixel }, 206 | { "draw_line", libframebuffer_canvas_draw_line }, 207 | { "draw_rect", libframebuffer_canvas_draw_rect }, 208 | { "draw_circle", libframebuffer_canvas_draw_circle }, 209 | { "draw_triangle", libframebuffer_canvas_draw_triangle }, 210 | { "draw_text", libframebuffer_canvas_draw_text }, 211 | { "dimensions", libframebuffer_dimensions }, 212 | { "save", libframebuffer_canvas_save }, 213 | { "load", libframebuffer_canvas_load }, 214 | { nullptr, nullptr } 215 | }; 216 | 217 | static const luaL_Reg libframebuffer[] = { 218 | { "get", libframebuffer_get }, 219 | { nullptr, nullptr } 220 | }; 221 | 222 | int luaopen_framebuffer(lua_State *L) 223 | { 224 | luaL_newmetatable(L, CANVAS_T); 225 | // metatable.__index = metatable 226 | lua_pushvalue(L, -1); 227 | lua_setfield(L, -2, "__index"); 228 | luaL_setfuncs(L, libframebuffer_canvas, 0); 229 | lua_pop(L, 1); 230 | 231 | luaL_newlib(L, libframebuffer); 232 | return 1; 233 | } 234 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | { 42 | "lastFilter": { 43 | "state": "OPEN", 44 | "assignee": "Frityet" 45 | } 46 | } 47 | { 48 | "prStates": [] 49 | } 50 | {} 51 | { 52 | "selectedUrlAndAccountId": { 53 | "url": "https://github.com/TheLuaOSProject/Kernel.git", 54 | "accountId": "94363042-55ae-4f58-966c-e6222cc1b51b" 55 | } 56 | } 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 88 | 93 | 94 | 95 | 100 | { 101 | "associatedIndex": 8 102 | } 103 | 104 | 105 | 108 | { 109 | "keyToString": { 110 | "RunOnceActivity.RadMigrateCodeStyle": "true", 111 | "RunOnceActivity.ShowReadmeOnStart": "true", 112 | "RunOnceActivity.cidr.known.project.marker": "true", 113 | "RunOnceActivity.readMode.enableVisualFormatting": "true", 114 | "cf.first.check.clang-format": "false", 115 | "cidr.known.project.marker": "true", 116 | "git-widget-placeholder": "sched-rwr" 117 | } 118 | } 119 | 120 | 121 | 122 | 124 | 125 | 126 | 127 | 129 | 130 | 131 | 132 | 134 | 135 | 136 | 137 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 1710438112087 152 | 158 | 159 | 166 | 167 | 174 | 177 | 178 | 179 | 180 | 182 | -------------------------------------------------------------------------------- /src/processes/scheduler.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitulst 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include "luck/processes/scheduler.h" 21 | 22 | #include 23 | #include "string.h" 24 | 25 | #include "luck/arch/x86_64/cpu.h" 26 | #include "luck/io/log.h" 27 | #include "luck/memory/manager.h" 28 | #include "luck/bootloader/limine.h" 29 | 30 | #include "lj-libc/limits.h" 31 | #include 32 | #include 33 | #include 34 | 35 | #define RFLAGS 0x0202 36 | 37 | void *ljsup_alloc(void *ud, void *ptr, size_t osize, size_t nsize); 38 | 39 | #define _lua_openmodule(mname, module) ({ \ 40 | lua_pushcfunction(L, luaopen_##module); \ 41 | lua_pushstring(L, mname); \ 42 | lua_call(L, 1, 0); \ 43 | }) 44 | #define lua_openmodule(module) _lua_openmodule(#module, module) 45 | 46 | int luaopen_kernel(lua_State *L); 47 | 48 | [[noreturn]] 49 | static void thread_entry(Thread *nonnull t) 50 | { 51 | $debug("Starting thread {}", t->name); 52 | lua_State *L = t->lua; 53 | 54 | if (lua_pcall(L, 0, 0, 0) == LUA_OK) { 55 | lua_pop(L, lua_gettop(L)); 56 | } else { 57 | $error("lua error: {}", lua_tostring(L, lua_gettop(L))); 58 | lua_pop(L, lua_gettop(L)); 59 | } 60 | 61 | $debug("Killing thread {}", t->name); 62 | t->kill = true; 63 | while (true) $asm("HLT"); 64 | } 65 | 66 | static Lock sched_lock = false; 67 | static Thread *nullable ready = nullptr; 68 | static Thread *nullable ready_tail = nullptr; 69 | static Thread *nullable idle = nullptr; 70 | 71 | //During spawn of a thread, we need to lock the scheduler 72 | static Lock spawn_lock = false; 73 | 74 | Thread *spawn_thread(void *addr, size_t size, const char *name) 75 | { 76 | $debug("Creating a thread called {}", name); 77 | Thread *t = kalloc(sizeof(Thread)); 78 | 79 | lua_State *L = t->lua = lua_newstate(ljsup_alloc, nullptr); 80 | if (L == nullptr) 81 | return nullptr; 82 | 83 | _lua_openmodule("", base); 84 | lua_openmodule(table); 85 | lua_openmodule(string); 86 | lua_openmodule(math); 87 | lua_openmodule(debug); 88 | lua_openmodule(bit); 89 | luaopen_kernel(L); 90 | 91 | size_t name_len = string_length(name); 92 | string_copy(64, t->name, name_len, name); 93 | 94 | sdword v = luaL_loadbuffer(L, addr, size, t->name); 95 | if (v != 0) 96 | $panic("Could not spawn thread! Reason: {}", lua_tostring(L, -1)); 97 | 98 | t->stack_base = $assert_nonnull(kalloc(Thread_STACKSIZE), "failed to allocate stack"); 99 | t->cpu_context.rsp = (qword)(t->stack_base + Thread_STACKSIZE); 100 | t->cpu_context.rip = (qword)(thread_entry); 101 | t->cpu_context.rdi = (qword)(t); 102 | t->cpu_context.rflags = RFLAGS; // all the flags that we need 103 | t->cpu_context.cs = 0x28; 104 | t->cpu_context.ss = 0x30; 105 | t->ready = true; 106 | 107 | acquire_lock(&sched_lock); 108 | { 109 | t->next_task = ready; 110 | 111 | if (ready) { 112 | ready->previous_task = t; 113 | } else { 114 | // TODO: in debug (or some kind of "safe") mode only 115 | if (ready_tail) $panic("i'm an expert at linked lists"); 116 | ready_tail = t; 117 | } 118 | 119 | ready = t; 120 | } 121 | release_lock(&sched_lock); 122 | 123 | return t; 124 | } 125 | 126 | static volatile dword *lapic_id; 127 | 128 | [[gnu::naked]] 129 | static qword get_lapic_addr_dyn(void) { 130 | $asm ("movl $0x1b, %ecx"); 131 | $asm ("rdmsr"); 132 | $asm ("shrq $32, %rdx"); 133 | $asm ("orq %rax, %rdx"); 134 | $asm ("retq"); 135 | } 136 | 137 | static Thread *nullable threads[Thread_COUNT]; 138 | static CPUContext idle_tasks[Thread_COUNT]; 139 | static bool was_threadsweeping[Thread_COUNT]; 140 | void scheduler_init(void) 141 | { 142 | lapic_id = $virt(get_lapic_addr_dyn() & ~0xfff, dword); 143 | } 144 | 145 | [[noreturn]] 146 | [[gnu::used]] 147 | static void idle_task(void) 148 | { 149 | $info("welcome to the luaOS idle task for whatever core i'm on. I'm just chillin' here..."); 150 | while (true) $asm("hlt"); 151 | } 152 | static _Atomic(bool) threadsweeper_lock; 153 | static __attribute__((aligned(16))) uint8_t threadsweeper_stack[16384]; 154 | 155 | static void threadsweeper(Thread *nonnull t) 156 | { 157 | $debug("Cleaning up thread {}", t->name); 158 | acquire_lock(&t->lock); 159 | lua_close(t->lua); 160 | t->cpu_context.rip = 0xdeadbeefdeadbeef; 161 | kfree(t->stack_base, 16384); 162 | kfree(t, sizeof(Thread)); 163 | release_lock(&t->lock); 164 | $asm("MOVQ $0, (%%RDI)\n1: INT3\njmp 1b" :: "D"(&threadsweeper_lock)); 165 | } 166 | 167 | void reschedule(CPUContext *nonnull ctx) 168 | { 169 | if (atomic_load(&sched_lock)) return; 170 | acquire_lock(&sched_lock); 171 | qword lapic = *lapic_id >> 24; 172 | if (ctx->interrupt_number == 3) { 173 | if (!was_threadsweeping[lapic]) { 174 | $panic("invalid int3!"); 175 | } 176 | } 177 | 178 | if (threads[lapic]) { 179 | Thread *t_old = threads[lapic]; 180 | if (atomic_load(&t_old->lock)) return; 181 | acquire_lock(&t_old->lock); 182 | t_old->cpu_context = *ctx; 183 | if (t_old->ready) { 184 | if (ready_tail) { 185 | ready_tail->next_task = t_old; 186 | t_old->previous_task = ready_tail; 187 | } else { 188 | ready = ready_tail = t_old; 189 | } 190 | } else { 191 | if (idle) idle->previous_task = t_old; 192 | t_old->next_task = idle; 193 | idle = t_old; 194 | } 195 | release_lock(&threads[lapic]->lock); 196 | } else { 197 | if (!was_threadsweeping[lapic]) idle_tasks[lapic] = *ctx; 198 | } 199 | 200 | if (ready) { 201 | auto tnew = (Thread *nonnull)ready; 202 | 203 | if (atomic_load(&tnew->lock)) goto idle; 204 | acquire_lock(&tnew->lock); 205 | if (tnew->next_task) { 206 | tnew->next_task->previous_task = nullptr; 207 | ready = tnew->next_task; 208 | tnew->next_task = nullptr; 209 | } else { 210 | ready_tail = ready = nullptr; 211 | } 212 | threads[lapic] = tnew; 213 | *ctx = tnew->cpu_context; 214 | if (!tnew->ready) $panic("how is a non-ready task on the ready list?"); 215 | if (tnew->kill) { 216 | acquire_lock(&threadsweeper_lock); 217 | ctx->rip = (uint64_t)(threadsweeper); 218 | ctx->rsp = (uint64_t)(threadsweeper_stack + 16384); 219 | ctx->rdi = (uint64_t)(tnew); 220 | ctx->rflags = 0x2; 221 | was_threadsweeping[lapic] = true; 222 | threads[lapic] = nullptr; 223 | } else { 224 | ctx->rflags = RFLAGS; 225 | } 226 | release_lock(&tnew->lock); 227 | } else { 228 | idle: 229 | *ctx = idle_tasks[lapic]; 230 | threads[lapic] = nullptr; 231 | ctx->rflags = RFLAGS; 232 | } 233 | release_lock(&sched_lock); 234 | } 235 | 236 | void wait_for_thread(Thread *thread) 237 | { 238 | acquire_lock(&thread->lock); 239 | 240 | while (!thread->kill) { 241 | release_lock(&thread->lock); 242 | reschedule(&thread->cpu_context); // This will cause the current thread to yield 243 | release_lock(&thread->lock); 244 | } 245 | 246 | release_lock(&thread->lock); 247 | } 248 | 249 | void wake_futex(Futex *mtx) 250 | { 251 | acquire_lock(&mtx->lock); 252 | 253 | if (mtx->head) { 254 | Thread *to_wake = mtx->head; 255 | auto raw = to_wake->next_mutex; 256 | if (raw == nullptr) goto done; 257 | mtx->head = (Thread *nonnull)raw; 258 | 259 | acquire_lock(&to_wake->lock);\ 260 | to_wake->next_mutex = nullptr; 261 | to_wake->ready = true; 262 | release_lock(&to_wake->lock); 263 | } 264 | 265 | done: 266 | release_lock(&mtx->lock); 267 | } 268 | 269 | void wake_all_futexes(Futex *mtx) 270 | { 271 | acquire_lock(&mtx->lock); 272 | 273 | while (mtx->head) { 274 | Thread *to_wake = mtx->head; 275 | 276 | auto raw = to_wake->next_mutex; 277 | if (raw == nullptr) goto done; 278 | mtx->head = (Thread *nonnull)raw; 279 | 280 | acquire_lock(&to_wake->lock);\ 281 | to_wake->next_mutex = nullptr; 282 | to_wake->ready = true; 283 | release_lock(&to_wake->lock); 284 | } 285 | 286 | done: 287 | acquire_lock(&mtx->lock); 288 | } 289 | 290 | // function scheduler.spawn(modulename: string): Thread?, string? 291 | static int libscheduler_spawn(lua_State *nonnull L) 292 | { 293 | size_t n = 0; 294 | const char *modulename = luaL_checklstring(L, 1, &n); 295 | char expanded[n + 5]; //`modulename`.lua 296 | struct limine_file *nullable f = find_module(modulename); 297 | if (f == nullptr) { 298 | string_copy(sizeof(expanded), expanded, n, modulename); 299 | string_concatenate(sizeof(expanded), expanded, 5, ".lua"); 300 | f = find_module(expanded); 301 | } 302 | 303 | if (f == nullptr) { 304 | lua_pushnil(L); 305 | lua_pushfstring(L, "module '%s' not found", modulename); 306 | return 2; 307 | } 308 | 309 | Thread *thr = spawn_thread(f->address, f->size, modulename); 310 | 311 | lua_pushlightuserdata(L, thr); 312 | return 1; 313 | } 314 | 315 | static const luaL_Reg libscheduler[] = { 316 | { "spawn", libscheduler_spawn }, 317 | { nullptr, nullptr } 318 | }; 319 | 320 | int luaopen_scheduler(lua_State *nonnull L) 321 | { 322 | luaL_newlib(L, libscheduler); 323 | return 1; 324 | } 325 | -------------------------------------------------------------------------------- /inc/macro_util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #define _stringify(...) #__VA_ARGS__ 23 | #define $stringify(...) _stringify(__VA_ARGS__) 24 | 25 | #define _concat(x, y) x##y 26 | #define $concat(x, y) _concat(x, y) 27 | 28 | #define $foreach(F, a, ...) __VA_OPT__(_foreach_ladder0(F, a, __VA_ARGS__)) 29 | #define _foreach_ladder0(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder1(F, a, __VA_ARGS__)) 30 | #define _foreach_ladder1(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder2(F, a, __VA_ARGS__)) 31 | #define _foreach_ladder2(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder3(F, a, __VA_ARGS__)) 32 | #define _foreach_ladder3(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder4(F, a, __VA_ARGS__)) 33 | #define _foreach_ladder4(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder5(F, a, __VA_ARGS__)) 34 | #define _foreach_ladder5(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder6(F, a, __VA_ARGS__)) 35 | #define _foreach_ladder6(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder7(F, a, __VA_ARGS__)) 36 | #define _foreach_ladder7(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder8(F, a, __VA_ARGS__)) 37 | #define _foreach_ladder8(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder9(F, a, __VA_ARGS__)) 38 | #define _foreach_ladder9(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder10(F, a, __VA_ARGS__)) 39 | #define _foreach_ladder10(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder11(F, a, __VA_ARGS__)) 40 | #define _foreach_ladder11(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder12(F, a, __VA_ARGS__)) 41 | #define _foreach_ladder12(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder13(F, a, __VA_ARGS__)) 42 | #define _foreach_ladder13(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder14(F, a, __VA_ARGS__)) 43 | #define _foreach_ladder14(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder15(F, a, __VA_ARGS__)) 44 | #define _foreach_ladder15(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder16(F, a, __VA_ARGS__)) 45 | #define _foreach_ladder16(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder17(F, a, __VA_ARGS__)) 46 | #define _foreach_ladder17(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder18(F, a, __VA_ARGS__)) 47 | #define _foreach_ladder18(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder19(F, a, __VA_ARGS__)) 48 | #define _foreach_ladder19(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder20(F, a, __VA_ARGS__)) 49 | #define _foreach_ladder20(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder21(F, a, __VA_ARGS__)) 50 | #define _foreach_ladder21(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder22(F, a, __VA_ARGS__)) 51 | #define _foreach_ladder22(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder23(F, a, __VA_ARGS__)) 52 | #define _foreach_ladder23(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder24(F, a, __VA_ARGS__)) 53 | #define _foreach_ladder24(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder25(F, a, __VA_ARGS__)) 54 | #define _foreach_ladder25(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder26(F, a, __VA_ARGS__)) 55 | #define _foreach_ladder26(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder27(F, a, __VA_ARGS__)) 56 | #define _foreach_ladder27(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder28(F, a, __VA_ARGS__)) 57 | #define _foreach_ladder28(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder29(F, a, __VA_ARGS__)) 58 | #define _foreach_ladder29(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder30(F, a, __VA_ARGS__)) 59 | #define _foreach_ladder30(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder31(F, a, __VA_ARGS__)) 60 | #define _foreach_ladder31(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder32(F, a, __VA_ARGS__)) 61 | #define _foreach_ladder32(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder33(F, a, __VA_ARGS__)) 62 | #define _foreach_ladder33(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder34(F, a, __VA_ARGS__)) 63 | #define _foreach_ladder34(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder35(F, a, __VA_ARGS__)) 64 | #define _foreach_ladder35(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder36(F, a, __VA_ARGS__)) 65 | #define _foreach_ladder36(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder37(F, a, __VA_ARGS__)) 66 | #define _foreach_ladder37(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder38(F, a, __VA_ARGS__)) 67 | #define _foreach_ladder38(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder39(F, a, __VA_ARGS__)) 68 | #define _foreach_ladder39(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder40(F, a, __VA_ARGS__)) 69 | #define _foreach_ladder40(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder41(F, a, __VA_ARGS__)) 70 | #define _foreach_ladder41(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder42(F, a, __VA_ARGS__)) 71 | #define _foreach_ladder42(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder43(F, a, __VA_ARGS__)) 72 | #define _foreach_ladder43(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder44(F, a, __VA_ARGS__)) 73 | #define _foreach_ladder44(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder45(F, a, __VA_ARGS__)) 74 | #define _foreach_ladder45(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder46(F, a, __VA_ARGS__)) 75 | #define _foreach_ladder46(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder47(F, a, __VA_ARGS__)) 76 | #define _foreach_ladder47(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder48(F, a, __VA_ARGS__)) 77 | #define _foreach_ladder48(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder49(F, a, __VA_ARGS__)) 78 | #define _foreach_ladder49(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder50(F, a, __VA_ARGS__)) 79 | #define _foreach_ladder50(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder51(F, a, __VA_ARGS__)) 80 | #define _foreach_ladder51(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder52(F, a, __VA_ARGS__)) 81 | #define _foreach_ladder52(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder53(F, a, __VA_ARGS__)) 82 | #define _foreach_ladder53(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder54(F, a, __VA_ARGS__)) 83 | #define _foreach_ladder54(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder55(F, a, __VA_ARGS__)) 84 | #define _foreach_ladder55(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder56(F, a, __VA_ARGS__)) 85 | #define _foreach_ladder56(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder57(F, a, __VA_ARGS__)) 86 | #define _foreach_ladder57(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder58(F, a, __VA_ARGS__)) 87 | #define _foreach_ladder58(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder59(F, a, __VA_ARGS__)) 88 | #define _foreach_ladder59(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder60(F, a, __VA_ARGS__)) 89 | #define _foreach_ladder60(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder61(F, a, __VA_ARGS__)) 90 | #define _foreach_ladder61(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder62(F, a, __VA_ARGS__)) 91 | #define _foreach_ladder62(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder63(F, a, __VA_ARGS__)) 92 | #define _foreach_ladder63(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder64(F, a, __VA_ARGS__)) 93 | #define _foreach_ladder64(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder65(F, a, __VA_ARGS__)) 94 | #define _foreach_ladder65(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder66(F, a, __VA_ARGS__)) 95 | #define _foreach_ladder66(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder67(F, a, __VA_ARGS__)) 96 | #define _foreach_ladder67(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder68(F, a, __VA_ARGS__)) 97 | #define _foreach_ladder68(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder69(F, a, __VA_ARGS__)) 98 | #define _foreach_ladder69(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder70(F, a, __VA_ARGS__)) 99 | #define _foreach_ladder70(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder71(F, a, __VA_ARGS__)) 100 | #define _foreach_ladder71(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder72(F, a, __VA_ARGS__)) 101 | #define _foreach_ladder72(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder73(F, a, __VA_ARGS__)) 102 | #define _foreach_ladder73(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder74(F, a, __VA_ARGS__)) 103 | #define _foreach_ladder74(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder75(F, a, __VA_ARGS__)) 104 | #define _foreach_ladder75(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder76(F, a, __VA_ARGS__)) 105 | #define _foreach_ladder76(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder77(F, a, __VA_ARGS__)) 106 | #define _foreach_ladder77(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder78(F, a, __VA_ARGS__)) 107 | #define _foreach_ladder78(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder79(F, a, __VA_ARGS__)) 108 | #define _foreach_ladder79(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder80(F, a, __VA_ARGS__)) 109 | #define _foreach_ladder80(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder81(F, a, __VA_ARGS__)) 110 | #define _foreach_ladder81(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder82(F, a, __VA_ARGS__)) 111 | #define _foreach_ladder82(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder83(F, a, __VA_ARGS__)) 112 | #define _foreach_ladder83(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder84(F, a, __VA_ARGS__)) 113 | #define _foreach_ladder84(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder85(F, a, __VA_ARGS__)) 114 | #define _foreach_ladder85(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder86(F, a, __VA_ARGS__)) 115 | #define _foreach_ladder86(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder87(F, a, __VA_ARGS__)) 116 | #define _foreach_ladder87(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder88(F, a, __VA_ARGS__)) 117 | #define _foreach_ladder88(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder89(F, a, __VA_ARGS__)) 118 | #define _foreach_ladder89(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder90(F, a, __VA_ARGS__)) 119 | #define _foreach_ladder90(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder91(F, a, __VA_ARGS__)) 120 | #define _foreach_ladder91(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder92(F, a, __VA_ARGS__)) 121 | #define _foreach_ladder92(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder93(F, a, __VA_ARGS__)) 122 | #define _foreach_ladder93(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder94(F, a, __VA_ARGS__)) 123 | #define _foreach_ladder94(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder95(F, a, __VA_ARGS__)) 124 | #define _foreach_ladder95(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder96(F, a, __VA_ARGS__)) 125 | #define _foreach_ladder96(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder97(F, a, __VA_ARGS__)) 126 | #define _foreach_ladder97(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder98(F, a, __VA_ARGS__)) 127 | #define _foreach_ladder98(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder99(F, a, __VA_ARGS__)) 128 | #define _foreach_ladder99(F, a, n, ...) F(a, n) __VA_OPT__(_foreach_ladder100(F, a, __VA_ARGS__)) 129 | #define _foreach_ladder100(F, a, n, ...) F(a, n) 130 | -------------------------------------------------------------------------------- /.idea/editor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 91 | -------------------------------------------------------------------------------- /src/io/log.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2021-2024 Amrit Bhogal, pitust 3 | * 4 | * This file is part of LuaOS. 5 | * 6 | * LuaOS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * LuaOS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with LuaOS. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include "luck/io/log.h" 24 | #include "luck/io/console.h" 25 | #include "luck/arch/x86_64/io/port.h" 26 | #include "common.h" 27 | 28 | static atomic_bool console = true; 29 | static atomic_bool e9 = false; 30 | static atomic_bool serial = true; 31 | 32 | static void output_char_serial(char c) { 33 | if (atomic_load(&serial)) { 34 | while ((port_in_byte(0x3fd) & 0x20) == 0) $asm("pause"); 35 | port_out_byte(0x3f8, c); 36 | } 37 | } 38 | 39 | static void output_string_serial(const char *s) { 40 | //Remove all ansi escape sequences then output to serial 41 | char buf[1024]; 42 | char *bufptr = buf; 43 | char c; 44 | while ((c = *s) != '\0') { 45 | if (c == '\x1b') { 46 | while (*s != 'm') s++; 47 | s++; 48 | } else { 49 | *bufptr++ = *s++; 50 | } 51 | } 52 | *bufptr = '\0'; 53 | 54 | for (size_t i = 0; i < string_length(buf); i++) { 55 | output_char_serial(buf[i]); 56 | } 57 | } 58 | 59 | static void output_char_console(char c) { 60 | if (atomic_load(&console)) console_write_char(c); 61 | if (atomic_load(&e9)) port_out_byte(0xe9, c); 62 | } 63 | static void output_string_console(const char *s) { 64 | char c; 65 | while ((c = *s) != '\0') { 66 | output_char_console(*s++); 67 | } 68 | } 69 | 70 | static void output_char(char c) { 71 | output_char_console(c); 72 | output_char_serial(c); 73 | } 74 | 75 | static void output_string(const char *s) { 76 | output_string_console(s); 77 | output_string_serial(s); 78 | } 79 | 80 | typedef struct { 81 | char fill; 82 | char align; 83 | 84 | char sign; 85 | 86 | bool group; 87 | 88 | bool use_alt_form; 89 | 90 | char fill_char; 91 | unsigned int width; 92 | 93 | char type; 94 | } FormatSpecifier; 95 | 96 | static int parse_fmt(const char **fmtref, FormatSpecifier *spec) { 97 | #define current() (**fmtref) 98 | #define next() (*fmtref)++ 99 | 100 | while (current()) { 101 | if (current() == '{') { 102 | next(); 103 | if (current() == '{') { 104 | next(); 105 | output_char('{'); 106 | } else { 107 | goto scan; 108 | } 109 | } else if (current() == '}') { 110 | next(); 111 | if (current() == '}') { 112 | output_char('}'); 113 | next(); 114 | } else { 115 | output_string("(fmt error: expected '}}' after '}}', found '{}')"); 116 | return 1; 117 | } 118 | } else { 119 | output_char(current()); 120 | next(); 121 | } 122 | } 123 | 124 | output_string("(fmt error: expected '}}' after '}}', found EOF)"); 125 | return 2; 126 | scan:; 127 | 128 | spec->fill = ' '; 129 | spec->align = '>'; 130 | 131 | spec->sign = '-'; 132 | 133 | spec->group = false; 134 | 135 | spec->use_alt_form = false; 136 | 137 | spec->width = 0; 138 | 139 | spec->type = ' '; 140 | 141 | if (current() == ':') { 142 | next(); 143 | 144 | if ( 145 | current() != '<' && current() != '>' && current() != '^' // fill 146 | && current() != '+' && current() != '-' && current() != ' ' // sign 147 | && current() != '#' // alt mode 148 | && current() != '0' // 0 as fill character 149 | && (current() < '0' || current() > '9') // width 150 | && current() != '_' // grouping 151 | && current() != 'b' && current() != 'c' && current() != 'd' && current() != 'o' && current() != 'x' && current() != 'X' // type 152 | ) { 153 | // fill character 154 | spec->fill = current(); 155 | next(); 156 | } 157 | if (current() == '<' || current() == '>' || current() == '^') { 158 | spec->align = current(); 159 | next(); 160 | } else if (spec->fill != ' ') { 161 | output_string("(fmt error: spec.fill de facto implies spec.align)"); 162 | return 3; 163 | } 164 | if (current() == '#') { 165 | spec->use_alt_form = true; 166 | next(); 167 | } 168 | if (current() == '0') { 169 | spec->align = '0'; 170 | spec->fill = '='; 171 | next(); 172 | } 173 | if (current() >= '0' && current() <= '9') { 174 | int width = 0; 175 | while (current() >= '0' && current() <= '9') { 176 | width *= 10; 177 | width += current() - '0'; 178 | next(); 179 | } 180 | spec->width = width; 181 | } 182 | if (current() == '_') { 183 | spec->group = true; 184 | next(); 185 | } 186 | if ( 187 | current() == 'b' || current() == 'c' || current() == 'd' || current() == 'o'|| current() == 'x' || current() == 'X' 188 | ) { 189 | spec->type = current(); 190 | next(); 191 | } 192 | } 193 | if (current() != '}') { 194 | output_string("(fmt error: expected '}}', found '"); 195 | output_char(current()); 196 | output_string("')"); 197 | return 4; 198 | } 199 | next(); 200 | 201 | #undef current 202 | return 0; 203 | } 204 | 205 | #define log_level_impl(level, ansicolor, prefix) \ 206 | void _log_level_##level(void) { \ 207 | output_string("["); \ 208 | output_string_console("\x1b[0;3" #ansicolor ";1m"); \ 209 | output_string(prefix); \ 210 | output_string_console("\x1b[0m"); \ 211 | output_string("]"); \ 212 | } 213 | 214 | log_level_impl(success, 2, "+"); 215 | log_level_impl(info, 4, "*"); 216 | log_level_impl(debug, 0, "*"); 217 | log_level_impl(warning, 3, "!"); 218 | log_level_impl(error, 1, "-"); 219 | log_level_impl(panic, 1, "-"); 220 | 221 | void _log_begin(const char *nonnull file, const char *nonnull line, const char *nonnull function) { 222 | (void)file; 223 | (void)function; 224 | 225 | output_string(" "); 226 | output_string_console("\x1b[0;30;1m"); 227 | output_string(file); 228 | // output_string(function); 229 | output_string(":"); 230 | output_string(line); 231 | output_string_console("\x1b[0m"); 232 | output_string(" "); 233 | } 234 | 235 | void _log_level_common_end(const char **fmtref) 236 | { 237 | output_string(*fmtref); 238 | output_char('\n'); 239 | } 240 | void _log_level_panic_end(const char **fmtref) { 241 | output_string(*fmtref); 242 | output_char('\n'); 243 | halt(); 244 | } 245 | 246 | static void log_do_append_number(char **_buf, unsigned long long num, int base, bool upcase) { 247 | #define buf (*_buf) 248 | if (base < 2) { 249 | output_string("(fmt error: invalid type)"); 250 | return; 251 | } 252 | 253 | if (!num) *--buf = '0'; 254 | while (num) { 255 | *--buf = (upcase ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" : "0123456789abcdefghijklmnopqrstuvwxyz")[num % base]; 256 | num /= base; 257 | } 258 | #undef buf 259 | } 260 | static void log_emit(FormatSpecifier fi, const char *buf) { 261 | if (string_length(buf) < fi.width) { 262 | size_t wi_b = string_length(buf); 263 | size_t dis_b = wi_b - fi.width; 264 | size_t half_b = dis_b / 2; 265 | size_t half2_b = dis_b - half_b; 266 | if (fi.align == '>') { 267 | for (size_t i = 0;i < dis_b;i++) output_char(fi.fill); 268 | } 269 | if (fi.align == '^') { 270 | for (size_t i = 0;i < half2_b;i++) output_char(fi.fill); 271 | } 272 | output_string(buf); 273 | if (fi.align == '<') { 274 | for (size_t i = 0;i < dis_b;i++) output_char(fi.fill); 275 | } 276 | if (fi.align == '^') { 277 | for (size_t i = 0;i < half_b;i++) output_char(fi.fill); 278 | } 279 | } else { 280 | output_string(buf); 281 | } 282 | } 283 | static int log_num_base(FormatSpecifier fi) { 284 | if (fi.type == ' ' || fi.type == 'd') return 10; 285 | if (fi.type == 'b') return 2; 286 | if (fi.type == 'c') return -1; 287 | if (fi.type == 'o') return 8; 288 | if (fi.type == 'x' || fi.type == 'X') return 16; 289 | return -2; 290 | } 291 | static void log_num_u(FormatSpecifier fi, unsigned long long num) { 292 | char _buf[64]; 293 | char* buf = _buf + 64; 294 | *--buf = 0; 295 | if (fi.type == 'c') { 296 | if (fi.use_alt_form) *--buf = '\''; 297 | *--buf = num; 298 | if (fi.use_alt_form) *--buf = '\''; 299 | log_emit(fi, buf); 300 | return; 301 | } 302 | log_do_append_number(&buf, num, log_num_base(fi), fi.type == 'X'); 303 | if (fi.sign == ' ') *--buf = ' '; 304 | if (fi.sign == '+') *--buf = '+'; 305 | 306 | log_emit(fi, buf); 307 | } 308 | static void log_num_s(FormatSpecifier fi, long long num) { 309 | char _buf[64]; 310 | char* buf = _buf + 64; 311 | *--buf = 0; 312 | if (fi.type == 'c') { 313 | if (fi.use_alt_form) *--buf = '\''; 314 | *--buf = num; 315 | if (fi.use_alt_form) *--buf = '\''; 316 | log_emit(fi, buf); 317 | return; 318 | } 319 | if (num < 0) { 320 | log_do_append_number(&buf, -num, log_num_base(fi), fi.type == 'X'); 321 | *--buf = '-'; 322 | } else { 323 | log_do_append_number(&buf, num, log_num_base(fi), fi.type == 'X'); 324 | if (fi.sign == ' ') *--buf = ' '; 325 | if (fi.sign == '+') *--buf = '+'; 326 | } 327 | 328 | log_emit(fi, buf); 329 | } 330 | 331 | void _log_signed8(const char **fmtref, signed char num) { 332 | FormatSpecifier fs; 333 | parse_fmt(fmtref, &fs); 334 | log_num_s(fs, num); 335 | } 336 | void _log_signed16(const char **fmtref, short num) { 337 | FormatSpecifier fs; 338 | parse_fmt(fmtref, &fs); 339 | log_num_s(fs, num); 340 | } 341 | void _log_signed32(const char **fmtref, int num) { 342 | FormatSpecifier fs; 343 | parse_fmt(fmtref, &fs); 344 | log_num_s(fs, num); 345 | } 346 | void _log_signedptr(const char **fmtref, long num) { 347 | FormatSpecifier fs; 348 | parse_fmt(fmtref, &fs); 349 | log_num_s(fs, num); 350 | } 351 | void _log_signed64(const char **fmtref, long long num) { 352 | FormatSpecifier fs; 353 | parse_fmt(fmtref, &fs); 354 | log_num_s(fs, num); 355 | } 356 | void _log_unsigned8(const char **fmtref, unsigned char num) { 357 | FormatSpecifier fs; 358 | parse_fmt(fmtref, &fs); 359 | log_num_u(fs, num); 360 | } 361 | void _log_unsigned16(const char **fmtref, unsigned short num) { 362 | FormatSpecifier fs; 363 | parse_fmt(fmtref, &fs); 364 | log_num_u(fs, num); 365 | } 366 | void _log_unsigned32(const char **fmtref, unsigned int num) { 367 | FormatSpecifier fs; 368 | parse_fmt(fmtref, &fs); 369 | log_num_u(fs, num); 370 | } 371 | void _log_unsignedptr(const char **fmtref, unsigned long num) { 372 | FormatSpecifier fs; 373 | parse_fmt(fmtref, &fs); 374 | log_num_u(fs, num); 375 | } 376 | void _log_unsigned64(const char **fmtref, unsigned long long num) { 377 | FormatSpecifier fs; 378 | parse_fmt(fmtref, &fs); 379 | log_num_u(fs, num); 380 | } 381 | void _log_char(const char **fmtref, char c) { 382 | FormatSpecifier fi; 383 | parse_fmt(fmtref, &fi); 384 | 385 | char _buf[64]; 386 | char *buf = _buf + 64; 387 | if (fi.type != 'c' && fi.type != ' ') { 388 | //TODO: Add proper reporting 389 | 390 | *--buf = 0; 391 | output_string("expected 'c' or nothing as fi.type, found "); 392 | output_char(fi.type); 393 | 394 | return; 395 | } 396 | *--buf = 0; 397 | *--buf = c; 398 | 399 | log_emit(fi, buf); 400 | } 401 | 402 | void _log_string(const char **fmt, const char *str) 403 | { 404 | FormatSpecifier fi; 405 | parse_fmt(fmt, &fi); 406 | 407 | log_emit(fi, str ?: "(null)"); 408 | } 409 | 410 | void _log_voidptr(const char **fmtref, const void *ptr) 411 | { 412 | FormatSpecifier fs; 413 | parse_fmt(fmtref, &fs); 414 | 415 | char str[20] = {0}; 416 | const char *hex = "0123456789ABCDEF"; 417 | 418 | // Extract the individual bytes of the pointer 419 | uintptr_t ptr_val = (uintptr_t) ptr; 420 | byte bytes[16] = {0}; 421 | for (int i = 0; i < 16; i++) { 422 | bytes[i] = (byte)((ptr_val >> (i * 4)) & 0xF); 423 | } 424 | 425 | // Construct the hexadecimal string representation of the pointer 426 | int str_pos = 0; 427 | str[str_pos++] = '0'; 428 | str[str_pos++] = 'x'; 429 | for (int i = 15; i >= 0; i--) { 430 | str[str_pos++] = hex[bytes[i]]; 431 | } 432 | str[str_pos] = '\0'; 433 | 434 | log_emit(fs, str); 435 | } 436 | 437 | void _log_cpucontext(const char **, CPUContext) {} 438 | --------------------------------------------------------------------------------