Skip to content

Commit 65b6166

Browse files
authored
Merge pull request #108 from KaiNorberg/develop
Develop
2 parents f9289d2 + 2c96ed6 commit 65b6166

309 files changed

Lines changed: 1580 additions & 36514 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test.yml

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,36 @@ jobs:
1414
- name: Checkout repository
1515
uses: actions/checkout@v4
1616
with:
17-
submodules: trues
17+
submodules: true
1818

1919
- name: Install build dependencies
2020
run: |
2121
sudo apt-get update
22-
sudo apt-get install -y build-essential qemu-system-x86 mtools iasl
23-
24-
- name: Setup PatchworkOS
25-
run: make setup DEBUG=1 TESTING=1 QEMU_EXIT_ON_PANIC=1
22+
sudo apt-get install -y clang llvm build-essential qemu-system-x86 mtools iasl
2623
2724
- name: Build PatchworkOS
2825
run: make all DEBUG=1 TESTING=1 QEMU_EXIT_ON_PANIC=1
2926

27+
- name: Inspect kernel ELF
28+
run: |
29+
echo "=== Kernel ELF Program Headers ==="
30+
readelf -l bin/kernel/kernel || true
31+
echo "=== Kernel ELF Section Headers ==="
32+
readelf -S bin/kernel/kernel || true
33+
echo "=== Kernel file size ==="
34+
ls -la bin/kernel/kernel
35+
3036
- name: Verify PatchworkOS.img exists
3137
run: |
3238
if [ ! -f bin/PatchworkOS.img ]; then
3339
echo "Error: bin/PatchworkOS.img not found after build!"
3440
exit 1
3541
fi
3642
37-
- name: Run PatchworkOS with QEMU (test launch and graceful timeout)
43+
- name: Run PatchworkOS with QEMU
3844
id: qemu_test
39-
run: | # We use this cheap trick to check if qemu runs properly, the idea is that we start qemu, and let it run for one minute and it does not crash thats considered a success, if it crashes, well thats bad. If it doesent we shut it down and call it a success, a bit simple but gets the job done.
40-
setsid make run DEBUG=1 TESTING=1 QEMU_EXIT_ON_PANIC=1 &
45+
run: |
46+
setsid make run DEBUG=1 TESTING=1 QEMU_EXIT_ON_PANIC=1 QEMU_NOGRAPHIC=1 &
4147
QEMU_PID=$!
4248
echo "QEMU process started with PID=$QEMU_PID"
4349
echo "QEMU_PID=$QEMU_PID" >> $GITHUB_OUTPUT

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,6 @@ include/kernel/version.h
6969
lib/acpica
7070
lib/acpica_tests
7171
lib/argon2
72+
lib/gnu-efi
7273
include/argon2
7374
temp.md

Make.defaults

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ MKCWD = @mkdir -p $(@D)
33
CC = gcc
44
AS = gcc
55
LD = gcc
6-
AR = gcc-ar
6+
AR = ar
77
OBJCOPY = objcopy
8-
98
CFLAGS := \
109
-std=gnu11 \
1110
-ffreestanding \
1211
-fno-builtin \
12+
-march=x86-64 \
1313
-fno-pie \
14+
-fno-stack-protector \
15+
-fcf-protection=none \
1416
-mno-red-zone \
1517
-nostdinc \
1618
-Wall \
@@ -36,7 +38,8 @@ CFLAGS_DISABLE_SIMD := \
3638
-mno-mmx -mno-3dnow \
3739
-mno-80387 -mno-sse \
3840
-mno-sse2 -mno-sse3 \
39-
-mno-ssse3 -mno-sse4
41+
-mno-ssse3 -mno-sse4 \
42+
-mno-avx -mno-avx2
4043

4144
ASFLAGS := \
4245
-nostdinc \
@@ -51,7 +54,9 @@ LDFLAGS := \
5154
-nostdlib \
5255
-Lbin/libstd \
5356
-Lbin/libpatchwork \
54-
-no-pie
57+
-z noexecstack \
58+
-Wno-unused-command-line-argument \
59+
-no-pie
5560

5661
ifeq ($(TESTING),1)
5762
CFLAGS += -D_TESTING_
@@ -61,10 +66,8 @@ endif
6166
ifeq ($(DEBUG),1)
6267
CFLAGS += -O0 -g3 -ggdb -fno-omit-frame-pointer -fno-inline
6368
LDFLAGS += -g
64-
DEBUG_LDFLAGS = -g
6569
else
6670
CFLAGS += -O2 -DNDEBUG
67-
DEBUG_LDFLAGS =
6871
endif
6972

7073
ifeq ($(NOSTDLIB),1)

Make.rules

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,4 @@ $(BINDIR)/%.a: $(OBJ)
1616
$(BINDIR)/%: $(OBJ)
1717
$(MKCWD)
1818
@echo " LD $@"
19-
@$(LD) -o $@ $^ $(LDFLAGS) $(LDSTDLIB)
20-
21-
$(BINDIR)/%.efi: $(OBJ)
22-
$(MKCWD)
23-
@echo " LD $@ (EFI)"
24-
@gcc -shared -nostdlib -nostartfiles -fPIC -fno-stack-protector \
25-
$(DEBUG_LDFLAGS) \
26-
-Wl,-shared,-Bsymbolic \
27-
-Wl,-T,lib/gnu-efi/gnuefi/elf_x86_64_efi.lds \
28-
-Llib/gnu-efi/x86_64/lib \
29-
-Llib/gnu-efi/x86_64/gnuefi \
30-
lib/gnu-efi/x86_64/gnuefi/crt0-efi-x86_64.o $^ \
31-
-o $(BINDIR)/temp.so \
32-
-lgnuefi -lefi
33-
34-
ifeq ($(DEBUG),1)
35-
@echo " OBJCOPY $@ (with debug symbols)"
36-
@$(OBJCOPY) --only-keep-debug $(BINDIR)/temp.so $(BINDIR)/$*.debug
37-
@$(OBJCOPY) \
38-
-j .text -j .sdata -j .data -j .dynamic -j .dynsym \
39-
-j .rel -j .rela -j .rel.* -j .rela.* -j .reloc -j .eh_frame \
40-
--target efi-app-x86_64 \
41-
--subsystem=10 \
42-
--add-gnu-debuglink=$(BINDIR)/$*.debug \
43-
$(BINDIR)/temp.so $@
44-
@$(OBJCOPY) --strip-debug $@
45-
else
46-
@echo " OBJCOPY $@"
47-
@$(OBJCOPY) \
48-
-j .text -j .sdata -j .data -j .dynamic -j .dynsym \
49-
-j .rel -j .rela -j .rel.* -j .rela.* -j .reloc -j .eh_frame \
50-
--target efi-app-x86_64 \
51-
--subsystem=10 \
52-
$(BINDIR)/temp.so $@
53-
endif
54-
55-
@rm -f $(BINDIR)/temp.so
19+
@$(LD) -o $@ $^ $(LDFLAGS) $(LDSTDLIB)

Makefile

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ $(VERSION_HEADER): .FORCE | include/kernel
9090
include/kernel:
9191
@mkdir -p $@
9292

93-
lib/gnu-efi/.built: | lib/gnu-efi
93+
lib/gnu-efi/.built:
94+
@if [ ! -d "lib/gnu-efi" ]; then \
95+
echo "CLONE gnu-efi"; \
96+
git clone https://github.com/ncroxon/gnu-efi.git lib/gnu-efi >/dev/null 2>&1; \
97+
fi
9498
@echo "BUILD gnu-efi"
9599
@$(MAKE) -C lib/gnu-efi >/dev/null 2>&1
96100
@touch $@
@@ -248,9 +252,7 @@ clean_programs:
248252

249253
nuke: clean
250254
@echo "NUKE all"
251-
@$(MAKE) -C lib/gnu-efi clean 2>/dev/null || true
252-
@rm -rf lib/doomgeneric-patchworkos lib/lua-5.4.7 lib/acpica lib/acpica_tests lib/argon2 include/argon2 meta/docs
253-
@rm -rf lib/gnu-efi/.built lib/argon2/.built lib/acpica_tests/.built
255+
@rm -rf lib/doomgeneric lib/lua lib/acpica lib/acpica_tests lib/argon2 include/argon2 meta/docs lib/gnu-efi
254256

255257
QEMU_MEMORY ?= 2G
256258
QEMU_CPUS ?= $(shell nproc 2>/dev/null || echo 8)
@@ -259,15 +261,19 @@ QEMU_ARGS ?=
259261

260262
QEMU_FLAGS = \
261263
-M $(QEMU_MACHINE) \
262-
-display sdl \
263-
-serial stdio \
264264
-drive format=raw,file=$(IMAGE) \
265265
-m $(QEMU_MEMORY) \
266266
-smp $(QEMU_CPUS) \
267267
-cpu qemu64 \
268268
-drive if=pflash,format=raw,unit=0,file=lib/OVMFbin/OVMF_CODE-pure-efi.fd,readonly=on \
269269
-drive if=pflash,format=raw,unit=1,file=lib/OVMFbin/OVMF_VARS-pure-efi.fd
270270

271+
ifeq ($(QEMU_NOGRAPHIC),1)
272+
QEMU_FLAGS += -nographic
273+
else
274+
QEMU_FLAGS += -display sdl -serial stdio
275+
endif
276+
271277
ifeq ($(DEBUG),1)
272278
else
273279
QEMU_FLAGS += -no-shutdown -no-reboot

README.md

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424

2525
<img src="meta/screenshots/desktop.png" alt="Desktop Screenshot" />
2626

27-
**PatchworkOS** is a modular non-POSIX operating system for the x86_64 architecture that rigorously follows an "everything is a file" philosophy, in the style of Plan9. Built from scratch in C and assembly, it's intended to be an educational and experimental operating system.
27+
**PatchworkOS** is a modular non-POSIX operating system for the x86_64 architecture that rigorously follows an "everything is a file" philosophy. Built from scratch in C and assembly.
2828

29-
While primarily a project made for fun, the goal is still to make a "real" operating system, one that runs on real hardware and has the performance one would expect from a modern operating system without jumping ahead to user space features or drivers, a floppy disk driver and a round-robin scheduler are not enough.
29+
While primarily a project made for fun, the goal is still to make a "real" operating system, one that runs on real hardware and has the performance one would expect from a modern operating system without jumping ahead to user space features or drivers, a floppy disk driver with a round-robin scheduler is not enough.
3030

3131
PatchworkOS is not a UNIX clone, it's intended to be a (hopefully) interesting experiment in operating system design by attempting to use unique algorithms and designs over tried and tested ones. Sometimes this leads to bad results, and sometimes, with a bit of luck, good ones.
3232

@@ -55,7 +55,7 @@ Will this project ever reach its goals? Probably not, but that's not the point.
5555

5656
- Preemptive and tickless [EEVDF scheduler](https://kainorberg.github.io/PatchworkOS/html/d7/d85/group__kernel__sched.html) based upon the [original paper](https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=805acf7726282721504c8f00575d91ebfd750564) and implemented using an [Augmented Red-Black tree](https://kainorberg.github.io/PatchworkOS/html/da/d90/group__kernel__utils__rbtree.html) to achieve `O(log n)` worst case complexity. EEVDF is the same algorithm used in the modern Linux kernel, but ours is obviously **a lot** less mature.
5757
- Multithreading and Symmetric Multi Processing with fine-grained locking.
58-
- Physical and virtual memory management is `O(1)` per page and `O(n)` where `n` is the number of pages per allocation/mapping operation, see [benchmarks](#benchmarks) for more info.
58+
- Optimized memory management, featuring object caching and `O(1)` per page physical and virtual memory managers. See [benchmarks](#benchmarks) for more info.
5959
- File based IPC including [pipes](https://kainorberg.github.io/PatchworkOS/html/d7/d64/group__modules__ipc__pipe.html), [shared memory](https://kainorberg.github.io/PatchworkOS/html/df/d3f/group__modules__ipc__shmem.html), [sockets](https://kainorberg.github.io/PatchworkOS/html/d4/db0/group__kernel__fs__netfs.html) and Plan9 inspired "signals" called [notes](https://kainorberg.github.io/PatchworkOS/html/d8/db1/group__kernel__ipc__note.html).
6060
- File based device API [abstractions](https://kainorberg.github.io/PatchworkOS/html/de/d7b/group__kernel__drivers__abstract.html), including framebuffers, input devices, etc.
6161
- [Synchronization primitives](https://kainorberg.github.io/PatchworkOS/html/dd/d6b/group__kernel__sync.html) including Read-Copy-Update, mutexes, R/W locks, sequential locks, futexes and others.
@@ -92,6 +92,24 @@ Will this project ever reach its goals? Probably not, but that's not the point.
9292
- Fully Asynchronous I/O and syscalls (io_uring?).
9393
- USB support.
9494

95+
## Setup
96+
97+
```bash
98+
# Install dependencies
99+
sudo dnf install gcc make mtools qemu-system-x86 # For Fedora
100+
sudo apt install build-essential mtools qemu-system-x86 # For Debian/Ubuntu
101+
102+
# Clone this repository, you can also use the green Code button at the top of the Github.
103+
git clone https://github.com/KaiNorberg/PatchworkOS
104+
cd PatchworkOS
105+
106+
# Build (creates PatchworkOS.img in bin/)
107+
make all
108+
109+
# Run using QEMU
110+
make run
111+
```
112+
95113
---
96114

97115
## Doxygen Documentation
@@ -635,7 +653,9 @@ The scheduler has not yet been properly benchmarked. However, testing using the
635653

636654
## Shell Utilities
637655

638-
PatchworkOS includes its own shell utilities designed around its [file flags](#file-flags) system, when file flags are used we also demonstrate the short form. Included is a brief overview with some usage examples. For convenience the shell utilities are named after their POSIX counterparts, however they are not drop-in replacements.
656+
PatchworkOS includes its own shell utilities designed around its [file flags](#file-flags) system, allowing all shell utilities to be "dumb" and rely on the virtual file system to provide more complex behavior.
657+
658+
Included is a brief overview with some usage examples. For convenience the shell utilities are named after their POSIX counterparts, however they are not drop-in replacements. When file flags are used we also demonstrate the short form.
639659

640660
### touch
641661

@@ -734,28 +754,7 @@ There are other utils available that work as expected, for example `symlink` and
734754

735755
---
736756

737-
## Setup
738-
739-
### Requirements
740-
741-
| Requirement | Details |
742-
|:------------|:--------|
743-
| **OS** | Linux (WSL might work, but I make no guarantees) |
744-
| **Tools** | GCC, make, mtools, QEMU (optional) |
745-
746-
### Build and Run
747-
748-
```bash
749-
# Clone this repository, you can also use the green Code button at the top of the Github.
750-
git clone https://github.com/KaiNorberg/PatchworkOS
751-
cd PatchworkOS
752-
753-
# Build (creates PatchworkOS.img in bin/)
754-
make all
755-
756-
# Run using QEMU
757-
make run
758-
```
757+
## Development
759758

760759
### Additional commands
761760

@@ -855,6 +854,10 @@ If you are unsure where to start, check the [Todo List](https://kainorberg.githu
855854

856855
Check out the [contribution guidelines](CONTRIBUTING.md) to get started.
857856

857+
## License
858+
859+
Distributed under the MIT License. See [LICENSE](https://github.com/KaiNorberg/PatchworkOS/blob/main/LICENSE) for more information.
860+
858861
## Nostalgia
859862

860863
[The first Reddit post and image of PatchworkOS](https://www.reddit.com/r/osdev/comments/18gbsng/a_little_over_2_years_ago_i_posted_a_screenshot/) from back when getting to user space was a massive milestone and the kernel was supposed to be a UNIX-like microkernel.

include/boot/boot_info.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
#include <kernel/mem/paging_types.h>
44

55
#include <gnu-efi/inc/efi.h>
6-
#include <gnu-efi/inc/efilib.h>
76

7+
#include <_internal/MAX_NAME.h>
88
#include <stdint.h>
9+
#include <sys/defs.h>
910
#include <sys/elf.h>
10-
#include <sys/io.h>
1111
#include <sys/list.h>
1212

1313
/**
@@ -21,7 +21,7 @@
2121
* @{
2222
*/
2323

24-
static bool boot_is_mem_ram(EFI_MEMORY_TYPE type)
24+
static UNUSED_FUNC bool boot_is_mem_ram(EFI_MEMORY_TYPE type)
2525
{
2626
switch (type)
2727
{

include/kernel/cpu/cli.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
static inline void cli_push(void)
2525
{
2626
uint64_t rflags = rflags_read();
27-
asm volatile("cli" ::: "memory");
27+
ASM("cli" :: : "memory");
2828

2929
if (SELF->cli == 0)
3030
{
@@ -46,7 +46,7 @@ static inline void cli_pop(void)
4646
SELF->cli--;
4747
if (SELF->cli == 0 && (SELF->oldRflags & RFLAGS_INTERRUPT_ENABLE))
4848
{
49-
asm volatile("sti" ::: "memory");
49+
ASM("sti" :: : "memory");
5050
}
5151
}
5252

include/kernel/cpu/cpu.h

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
#ifndef __ASSEMBLER__
44
#include <kernel/config.h>
5-
#include <kernel/cpu/cpu_id.h>
65
#include <kernel/cpu/stack_pointer.h>
76
#include <kernel/cpu/tss.h>
87

@@ -38,6 +37,33 @@ typedef struct cpu cpu_t;
3837

3938
#ifndef __ASSEMBLER__
4039

40+
/**
41+
* @brief The offset of the `id` member in the `cpu_t` structure.
42+
*
43+
* Needed to access the CPU ID from assembly code.
44+
*/
45+
#define CPU_OFFSET_ID 0x8
46+
47+
/**
48+
* @brief Maximum number of CPUs supported.
49+
*/
50+
#define CPU_MAX UINT8_MAX
51+
52+
/**
53+
* @brief ID of the bootstrap CPU.
54+
*/
55+
#define CPU_ID_BOOTSTRAP 0
56+
57+
/**
58+
* @brief Invalid CPU ID.
59+
*/
60+
#define CPU_ID_INVALID UINT16_MAX
61+
62+
/**
63+
* @brief Type used to identify a CPU.
64+
*/
65+
typedef uint16_t cpu_id_t;
66+
4167
/**
4268
* @brief CPU stack canary value.
4369
*
@@ -72,7 +98,7 @@ typedef struct cpu
7298
uint8_t doubleFaultStackBuffer[CONFIG_INTERRUPT_STACK_PAGES * PAGE_SIZE] ALIGNED(PAGE_SIZE);
7399
uint8_t nmiStackBuffer[CONFIG_INTERRUPT_STACK_PAGES * PAGE_SIZE] ALIGNED(PAGE_SIZE);
74100
uint8_t interruptStackBuffer[CONFIG_INTERRUPT_STACK_PAGES * PAGE_SIZE] ALIGNED(PAGE_SIZE);
75-
uint8_t percpu[CONFIG_PERCPU_SIZE] ALIGNED(PAGE_SIZE);
101+
uint8_t percpu[CONFIG_PERCPU_SIZE] ALIGNED(PAGE_SIZE); ///< Buffer used for per-CPU data.
76102
} cpu_t;
77103

78104
static_assert(offsetof(cpu_t, self) == CPU_OFFSET_SELF,

0 commit comments

Comments
 (0)