├── 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 |
5 |
6 |
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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
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 |
69 |
87 |
88 |
89 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | {
101 | "associatedIndex": 8
102 | }
103 |
104 |
105 |
106 |
107 |
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 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | 1710438112087
152 |
153 |
154 | 1710438112087
155 |
156 |
157 |
158 |
159 |
160 | 1710438757763
161 |
162 |
163 |
164 | 1710438757763
165 |
166 |
167 |
168 | 1710438812116
169 |
170 |
171 |
172 | 1710438812116
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
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 |
--------------------------------------------------------------------------------