Compare commits
13 commits
Author | SHA1 | Date | |
---|---|---|---|
3c09d65774 | |||
033d85bd2f | |||
edbb5d106d | |||
|
b2cf9b4710 | ||
|
dcea7360d2 | ||
|
16246cc167 | ||
|
c658f738e4 | ||
|
875dc2685b | ||
|
33f88512d4 | ||
|
9c21f343ba | ||
|
89bb8c8a4b | ||
|
a1e27c2730 | ||
|
d017412af5 |
138 changed files with 2174 additions and 13096 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -4,5 +4,4 @@
|
||||||
/.cache
|
/.cache
|
||||||
*.iso
|
*.iso
|
||||||
*.hdd
|
*.hdd
|
||||||
/compile_commands.json
|
compile_commands.json
|
||||||
/.idea
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Contribute to Soaplin!
|
|
||||||
Do you want to improve Soaplin? You can by contributing to the project!
|
|
||||||
|
|
||||||
## Contributing guidelines
|
|
||||||
* Before making a commit, please run `make format`. This will run clang-format over all the C source files in kernel/src.
|
|
||||||
* Large language model-generated code is **allowed**, with the condition that you do extensive testing over that code.
|
|
||||||
You must also know how to make the LLM-generated code by yourself.
|
|
||||||
|
|
||||||
Note: Even if LLM-generated code is allowed, please try to not use it.
|
|
100
GNUmakefile
100
GNUmakefile
|
@ -6,9 +6,9 @@ MAKEFLAGS += -rR
|
||||||
ARCH := x86_64
|
ARCH := x86_64
|
||||||
|
|
||||||
# Default user QEMU flags. These are appended to the QEMU command calls.
|
# Default user QEMU flags. These are appended to the QEMU command calls.
|
||||||
QEMUFLAGS := -m 2G -debugcon stdio -no-reboot -no-shutdown
|
QEMUFLAGS := -m 2G
|
||||||
|
|
||||||
override IMAGE_NAME := sild-live-$(ARCH)
|
override IMAGE_NAME := soaplin-$(ARCH)
|
||||||
|
|
||||||
# Toolchain for building the 'limine' executable for the host.
|
# Toolchain for building the 'limine' executable for the host.
|
||||||
HOST_CC := cc
|
HOST_CC := cc
|
||||||
|
@ -29,29 +29,8 @@ run: run-$(ARCH)
|
||||||
.PHONY: run-hdd
|
.PHONY: run-hdd
|
||||||
run-hdd: run-hdd-$(ARCH)
|
run-hdd: run-hdd-$(ARCH)
|
||||||
|
|
||||||
.PHONY: ints
|
|
||||||
ints: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).iso"
|
|
||||||
@qemu-system-$(ARCH) \
|
|
||||||
-M q35 \
|
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \
|
|
||||||
-cdrom $(IMAGE_NAME).iso \
|
|
||||||
-d int \
|
|
||||||
$(QEMUFLAGS)
|
|
||||||
|
|
||||||
.PHONY: run-x86_64
|
|
||||||
gdb-x86_64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).iso"
|
|
||||||
@qemu-system-$(ARCH) \
|
|
||||||
-M q35 \
|
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \
|
|
||||||
-cdrom $(IMAGE_NAME).iso \
|
|
||||||
$(QEMUFLAGS) \
|
|
||||||
-S -s
|
|
||||||
|
|
||||||
.PHONY: run-x86_64
|
.PHONY: run-x86_64
|
||||||
run-x86_64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
run-x86_64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).iso"
|
|
||||||
@qemu-system-$(ARCH) \
|
@qemu-system-$(ARCH) \
|
||||||
-M q35 \
|
-M q35 \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \
|
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \
|
||||||
|
@ -60,7 +39,6 @@ run-x86_64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
||||||
|
|
||||||
.PHONY: run-hdd-x86_64
|
.PHONY: run-hdd-x86_64
|
||||||
run-hdd-x86_64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
run-hdd-x86_64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).hdd"
|
|
||||||
@qemu-system-$(ARCH) \
|
@qemu-system-$(ARCH) \
|
||||||
-M q35 \
|
-M q35 \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \
|
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \
|
||||||
|
@ -69,7 +47,6 @@ run-hdd-x86_64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
||||||
|
|
||||||
.PHONY: run-aarch64
|
.PHONY: run-aarch64
|
||||||
run-aarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
run-aarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).iso"
|
|
||||||
@qemu-system-$(ARCH) \
|
@qemu-system-$(ARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu cortex-a72 \
|
-cpu cortex-a72 \
|
||||||
|
@ -96,7 +73,6 @@ run-hdd-aarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
||||||
|
|
||||||
.PHONY: run-riscv64
|
.PHONY: run-riscv64
|
||||||
run-riscv64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
run-riscv64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).iso"
|
|
||||||
@qemu-system-$(ARCH) \
|
@qemu-system-$(ARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu rv64 \
|
-cpu rv64 \
|
||||||
|
@ -110,7 +86,6 @@ run-riscv64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
||||||
|
|
||||||
.PHONY: run-hdd-riscv64
|
.PHONY: run-hdd-riscv64
|
||||||
run-hdd-riscv64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
run-hdd-riscv64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).hdd"
|
|
||||||
@qemu-system-$(ARCH) \
|
@qemu-system-$(ARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu rv64 \
|
-cpu rv64 \
|
||||||
|
@ -124,7 +99,6 @@ run-hdd-riscv64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
||||||
|
|
||||||
.PHONY: run-loongarch64
|
.PHONY: run-loongarch64
|
||||||
run-loongarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
run-loongarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).iso"
|
|
||||||
@qemu-system-$(ARCH) \
|
@qemu-system-$(ARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu la464 \
|
-cpu la464 \
|
||||||
|
@ -138,7 +112,6 @@ run-loongarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso
|
||||||
|
|
||||||
.PHONY: run-hdd-loongarch64
|
.PHONY: run-hdd-loongarch64
|
||||||
run-hdd-loongarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
run-hdd-loongarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).hdd"
|
|
||||||
@qemu-system-$(ARCH) \
|
@qemu-system-$(ARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu la464 \
|
-cpu la464 \
|
||||||
|
@ -153,7 +126,6 @@ run-hdd-loongarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd
|
||||||
|
|
||||||
.PHONY: run-bios
|
.PHONY: run-bios
|
||||||
run-bios: $(IMAGE_NAME).iso
|
run-bios: $(IMAGE_NAME).iso
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).iso"
|
|
||||||
@qemu-system-$(ARCH) \
|
@qemu-system-$(ARCH) \
|
||||||
-M q35 \
|
-M q35 \
|
||||||
-cdrom $(IMAGE_NAME).iso \
|
-cdrom $(IMAGE_NAME).iso \
|
||||||
|
@ -162,77 +134,75 @@ run-bios: $(IMAGE_NAME).iso
|
||||||
|
|
||||||
.PHONY: run-hdd-bios
|
.PHONY: run-hdd-bios
|
||||||
run-hdd-bios: $(IMAGE_NAME).hdd
|
run-hdd-bios: $(IMAGE_NAME).hdd
|
||||||
@echo " Starting QEMU with $(IMAGE_NAME).hdd"
|
|
||||||
@qemu-system-$(ARCH) \
|
@qemu-system-$(ARCH) \
|
||||||
-M q35 \
|
-M q35 \
|
||||||
-hda $(IMAGE_NAME).hdd \
|
-hda $(IMAGE_NAME).hdd \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
ovmf/ovmf-code-$(ARCH).fd:
|
ovmf/ovmf-code-$(ARCH).fd:
|
||||||
|
@echo " DEPS Downloading OVMF for $(ARCH)..."
|
||||||
@mkdir -p ovmf
|
@mkdir -p ovmf
|
||||||
@curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-code-$(ARCH).fd
|
@curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-code-$(ARCH).fd > /dev/null 2>&1
|
||||||
@case "$(ARCH)" in \
|
@case "$(ARCH)" in \
|
||||||
aarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=67108864 2>/dev/null;; \
|
aarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=67108864 2>/dev/null;; \
|
||||||
riscv64) dd if=/dev/zero of=$@ bs=1 count=0 seek=33554432 2>/dev/null;; \
|
riscv64) dd if=/dev/zero of=$@ bs=1 count=0 seek=33554432 2>/dev/null;; \
|
||||||
@esac
|
esac
|
||||||
|
|
||||||
limine/limine:
|
limine/limine:
|
||||||
|
@echo " DEPS Downloading Limine binaries..."
|
||||||
@rm -rf limine
|
@rm -rf limine
|
||||||
@git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1
|
@git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1 > /dev/null 2>&1
|
||||||
@$(MAKE) -C limine \
|
@$(MAKE) -C limine \
|
||||||
CC="$(HOST_CC)" \
|
CC="$(HOST_CC)" \
|
||||||
CFLAGS="$(HOST_CFLAGS)" \
|
CFLAGS="$(HOST_CFLAGS)" \
|
||||||
CPPFLAGS="$(HOST_CPPFLAGS)" \
|
CPPFLAGS="$(HOST_CPPFLAGS)" \
|
||||||
LDFLAGS="$(HOST_LDFLAGS)" \
|
LDFLAGS="$(HOST_LDFLAGS)" \
|
||||||
LIBS="$(HOST_LIBS)"
|
LIBS="$(HOST_LIBS)" > /dev/null 2>&1
|
||||||
@echo " Limine installer has been built"
|
|
||||||
|
|
||||||
kernel-deps:
|
kernel-deps:
|
||||||
@./kernel/get-deps
|
@./kernel/get-deps
|
||||||
@touch kernel-deps
|
@touch kernel-deps
|
||||||
@echo " Kernel dependencies have been downloaded"
|
|
||||||
|
|
||||||
.PHONY: kernel
|
.PHONY: kernel
|
||||||
kernel: kernel-deps
|
kernel: kernel-deps
|
||||||
$(MAKE) -C kernel
|
@$(MAKE) -C kernel
|
||||||
|
@echo "Soaplin $(ARCH) has been compiled successfully."
|
||||||
|
|
||||||
$(IMAGE_NAME).iso: limine/limine kernel
|
$(IMAGE_NAME).iso: limine/limine kernel
|
||||||
@rm -rf iso_root
|
@rm -rf iso_root
|
||||||
@mkdir -p iso_root/boot
|
@mkdir -p iso_root/boot
|
||||||
@cp -v kernel/bin-$(ARCH)/soaplin iso_root/boot/
|
@cp kernel/bin-$(ARCH)/kernel iso_root/boot/
|
||||||
@mkdir -p iso_root/boot/limine
|
@mkdir -p iso_root/boot/limine
|
||||||
@cp -v limine.conf iso_root/boot/limine/
|
@cp limine.conf iso_root/boot/limine/
|
||||||
@mkdir -p iso_root/EFI/BOOT
|
@mkdir -p iso_root/EFI/BOOT
|
||||||
@cp -v testing/sk-hello.elf iso_root/
|
|
||||||
# @cp -v initramfs.tar iso_root/
|
|
||||||
ifeq ($(ARCH),x86_64)
|
ifeq ($(ARCH),x86_64)
|
||||||
@cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/
|
@cp limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/
|
||||||
@cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/
|
@cp limine/BOOTX64.EFI iso_root/EFI/BOOT/
|
||||||
@cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT/
|
@cp limine/BOOTIA32.EFI iso_root/EFI/BOOT/
|
||||||
@xorriso -as mkisofs -R -r -J -b boot/limine/limine-bios-cd.bin \
|
@xorriso -as mkisofs -R -r -J -b boot/limine/limine-bios-cd.bin \
|
||||||
-no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
|
-no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
|
||||||
-apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin \
|
-apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin \
|
||||||
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||||
iso_root -o $(IMAGE_NAME).iso
|
iso_root -o $(IMAGE_NAME).iso > /dev/null 2>&1
|
||||||
@./limine/limine bios-install $(IMAGE_NAME).iso
|
@./limine/limine bios-install $(IMAGE_NAME).iso > /dev/null 2>&1
|
||||||
endif
|
endif
|
||||||
ifeq ($(ARCH),aarch64)
|
ifeq ($(ARCH),aarch64)
|
||||||
@cp -v limine/limine-uefi-cd.bin iso_root/boot/limine/
|
@cp limine/limine-uefi-cd.bin iso_root/boot/limine/
|
||||||
@cp -v limine/BOOTAA64.EFI iso_root/EFI/BOOT/
|
@cp limine/BOOTAA64.EFI iso_root/EFI/BOOT/
|
||||||
@xorriso -as mkisofs -R -r -J \
|
@xorriso -as mkisofs -R -r -J \
|
||||||
-hfsplus -apm-block-size 2048 \
|
-hfsplus -apm-block-size 2048 \
|
||||||
--efi-boot boot/limine/limine-uefi-cd.bin \
|
--efi-boot boot/limine/limine-uefi-cd.bin \
|
||||||
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||||
iso_root -o $(IMAGE_NAME).iso
|
iso_root -o $(IMAGE_NAME).iso > /dev/null 2>&1
|
||||||
endif
|
endif
|
||||||
ifeq ($(ARCH),riscv64)
|
ifeq ($(ARCH),riscv64)
|
||||||
@cp -v limine/limine-uefi-cd.bin iso_root/boot/limine/
|
@cp limine/limine-uefi-cd.bin iso_root/boot/limine/
|
||||||
@cp -v limine/BOOTRISCV64.EFI iso_root/EFI/BOOT/
|
@cp limine/BOOTRISCV64.EFI iso_root/EFI/BOOT/
|
||||||
@xorriso -as mkisofs -R -r -J \
|
@xorriso -as mkisofs -R -r -J \
|
||||||
-hfsplus -apm-block-size 2048 \
|
-hfsplus -apm-block-size 2048 \
|
||||||
--efi-boot boot/limine/limine-uefi-cd.bin \
|
--efi-boot boot/limine/limine-uefi-cd.bin \
|
||||||
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||||
iso_root -o $(IMAGE_NAME).iso
|
iso_root -o $(IMAGE_NAME).iso > /dev/null 2>&1
|
||||||
endif
|
endif
|
||||||
ifeq ($(ARCH),loongarch64)
|
ifeq ($(ARCH),loongarch64)
|
||||||
@cp -v limine/limine-uefi-cd.bin iso_root/boot/limine/
|
@cp -v limine/limine-uefi-cd.bin iso_root/boot/limine/
|
||||||
|
@ -241,19 +211,19 @@ ifeq ($(ARCH),loongarch64)
|
||||||
-hfsplus -apm-block-size 2048 \
|
-hfsplus -apm-block-size 2048 \
|
||||||
--efi-boot boot/limine/limine-uefi-cd.bin \
|
--efi-boot boot/limine/limine-uefi-cd.bin \
|
||||||
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||||
iso_root -o $(IMAGE_NAME).iso
|
iso_root -o $(IMAGE_NAME).iso > /dev/null 2>&1
|
||||||
endif
|
endif
|
||||||
@rm -rf iso_root
|
@rm -rf iso_root
|
||||||
@echo " The final ISO image has been created: $(IMAGE_NAME).iso"
|
@echo "Soaplin $(ARCH) test disc has been built successfully."
|
||||||
|
|
||||||
$(IMAGE_NAME).hdd: limine/limine kernel
|
$(IMAGE_NAME).hdd: limine/limine kernel
|
||||||
@rm -f $(IMAGE_NAME).hdd
|
@rm -f $(IMAGE_NAME).hdd
|
||||||
@dd if=/dev/zero bs=1M count=0 seek=64 of=$(IMAGE_NAME).hdd
|
@dd if=/dev/zero bs=1M count=0 seek=64 of=$(IMAGE_NAME).hdd
|
||||||
@echo " Creating $(IMAGE_NAME).hdd"
|
|
||||||
@PATH=$$PATH:/usr/sbin:/sbin sgdisk $(IMAGE_NAME).hdd -n 1:2048 -t 1:ef00
|
|
||||||
@echo " Creating partition table"
|
|
||||||
ifeq ($(ARCH),x86_64)
|
ifeq ($(ARCH),x86_64)
|
||||||
@./limine/limine bios-install $(IMAGE_NAME).hdd
|
@PATH=$$PATH:/usr/sbin:/sbin sgdisk $(IMAGE_NAME).hdd -n 1:2048 -t 1:ef00 -m 1
|
||||||
|
@./limine/limine bios-install $(IMAGE_NAME).hdd > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
@PATH=$$PATH:/usr/sbin:/sbin sgdisk $(IMAGE_NAME).hdd -n 1:2048 -t 1:ef00
|
||||||
endif
|
endif
|
||||||
@mformat -i $(IMAGE_NAME).hdd@@1M
|
@mformat -i $(IMAGE_NAME).hdd@@1M
|
||||||
@mmd -i $(IMAGE_NAME).hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine
|
@mmd -i $(IMAGE_NAME).hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine
|
||||||
|
@ -273,22 +243,16 @@ endif
|
||||||
ifeq ($(ARCH),loongarch64)
|
ifeq ($(ARCH),loongarch64)
|
||||||
@mcopy -i $(IMAGE_NAME).hdd@@1M limine/BOOTLOONGARCH64.EFI ::/EFI/BOOT
|
@mcopy -i $(IMAGE_NAME).hdd@@1M limine/BOOTLOONGARCH64.EFI ::/EFI/BOOT
|
||||||
endif
|
endif
|
||||||
@echo " Installed Limine bootloader"
|
@echo "Soaplin $(ARCH) test drive has been built successfully."
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@$(MAKE) -C kernel clean
|
@$(MAKE) -C kernel clean
|
||||||
@rm -rf iso_root $(IMAGE_NAME).iso $(IMAGE_NAME).hdd
|
@rm -rf iso_root $(IMAGE_NAME).iso $(IMAGE_NAME).hdd
|
||||||
@echo " The output files have been removed."
|
@echo "Soaplin output files has been deleted."
|
||||||
|
|
||||||
.PHONY: distclean
|
.PHONY: distclean
|
||||||
distclean:
|
distclean:
|
||||||
@$(MAKE) -C kernel distclean
|
@$(MAKE) -C kernel distclean
|
||||||
@rm -rf iso_root *.iso *.hdd kernel-deps limine ovmf
|
@rm -rf iso_root *.iso *.hdd kernel-deps limine ovmf
|
||||||
@echo " The output & downloaded files have been removed."
|
@echo "Soaplin output files & downloaded dependencies has been deleted."
|
||||||
|
|
||||||
# Make some function to run clang-format all over the kernel
|
|
||||||
.PHONY: format
|
|
||||||
format:
|
|
||||||
@clang-format -i -style=file $(shell find kernel/src -name '*.c' -or -name '*.h')
|
|
||||||
@echo " Kernel source code formatted"
|
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright (C) 2025 Raphaël M.
|
Copyright (C) 2025 The SILD Project
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|
17
README.md
17
README.md
|
@ -1 +1,16 @@
|
||||||
This is a legacy version of the kernel.
|
# Soaplin (rewrite)
|
||||||
|
This is a carefully rewritten version of Soaplin, that should be held with super glue instead of
|
||||||
|
0.99$ duct tape bought on TEMU.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
* Support for compiling the kernel on armv8, RISC-V, and LoongArch64 (even though the kernel doesn't do anything on these architectures)
|
||||||
|
* Free list PMM with lazy loading
|
||||||
|
* x86_64 paging
|
||||||
|
* ACPI & MADT
|
||||||
|
* IOAPIC / LAPIC
|
||||||
|
|
||||||
|
## To do
|
||||||
|
* SMP
|
||||||
|
* Multithreaded scheduler
|
||||||
|
* VFS
|
||||||
|
* Tar file system
|
BIN
initramfs.tar
BIN
initramfs.tar
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
Hello World from a subdirectory!
|
|
|
@ -1 +0,0 @@
|
||||||
Hello World!
|
|
6
kernel/.gitignore
vendored
6
kernel/.gitignore
vendored
|
@ -1,5 +1,5 @@
|
||||||
/freestnd-c-hdrs
|
/compile_commands.json
|
||||||
/cc-runtime*
|
/.cache
|
||||||
/src/limine.h
|
/src/deps
|
||||||
/bin-*
|
/bin-*
|
||||||
/obj-*
|
/obj-*
|
||||||
|
|
|
@ -4,7 +4,7 @@ MAKEFLAGS += -rR
|
||||||
|
|
||||||
# This is the name that our final executable will have.
|
# This is the name that our final executable will have.
|
||||||
# Change as needed.
|
# Change as needed.
|
||||||
override OUTPUT := soaplin
|
override OUTPUT := kernel
|
||||||
|
|
||||||
# Target architecture to build for. Default to x86_64.
|
# Target architecture to build for. Default to x86_64.
|
||||||
ARCH := x86_64
|
ARCH := x86_64
|
||||||
|
@ -20,9 +20,6 @@ endif
|
||||||
# User controllable C compiler command.
|
# User controllable C compiler command.
|
||||||
CC := cc
|
CC := cc
|
||||||
|
|
||||||
# User controllable archiver command.
|
|
||||||
AR := ar
|
|
||||||
|
|
||||||
# User controllable C flags.
|
# User controllable C flags.
|
||||||
CFLAGS := -g -O2 -pipe
|
CFLAGS := -g -O2 -pipe
|
||||||
|
|
||||||
|
@ -39,7 +36,7 @@ LDFLAGS :=
|
||||||
|
|
||||||
# Ensure the dependencies have been obtained.
|
# Ensure the dependencies have been obtained.
|
||||||
ifneq ($(shell ( test '$(MAKECMDGOALS)' = clean || test '$(MAKECMDGOALS)' = distclean ); echo $$?),0)
|
ifneq ($(shell ( test '$(MAKECMDGOALS)' = clean || test '$(MAKECMDGOALS)' = distclean ); echo $$?),0)
|
||||||
ifeq ($(shell ( ! test -d freestnd-c-hdrs || ! test -d cc-runtime || ! test -f src/limine.h ); echo $$?),0)
|
ifeq ($(shell ( ! test -d src/deps/freestnd-c-hdrs || ! test -f src/deps/cc-runtime.c || ! test -f src/deps/limine.h || ! test -d src/deps/flanterm ); echo $$?),0)
|
||||||
$(error Please run the ./get-deps script first)
|
$(error Please run the ./get-deps script first)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -58,25 +55,24 @@ override CFLAGS += \
|
||||||
-fno-stack-check \
|
-fno-stack-check \
|
||||||
-fno-PIC \
|
-fno-PIC \
|
||||||
-ffunction-sections \
|
-ffunction-sections \
|
||||||
-fdata-sections \
|
-fdata-sections
|
||||||
-fno-omit-frame-pointer \
|
|
||||||
-fno-optimize-sibling-calls
|
ifeq ($(CC_IS_CLANG), 1)
|
||||||
|
# Force Clang to use it's own linker instead of the host's one, since it
|
||||||
|
# might be used for cross-compilation.
|
||||||
|
override LDFLAGS += \
|
||||||
|
-fuse-ld=lld
|
||||||
|
endif
|
||||||
|
|
||||||
# Internal C preprocessor flags that should not be changed by the user.
|
# Internal C preprocessor flags that should not be changed by the user.
|
||||||
override CPPFLAGS := \
|
override CPPFLAGS := \
|
||||||
-I src \
|
-I src \
|
||||||
-isystem freestnd-c-hdrs \
|
-isystem src/deps/freestnd-c-hdrs \
|
||||||
$(CPPFLAGS) \
|
$(CPPFLAGS) \
|
||||||
-DLIMINE_API_REVISION=3 \
|
-DLIMINE_API_REVISION=3 \
|
||||||
-MMD \
|
-MMD \
|
||||||
-MP
|
-MP
|
||||||
|
|
||||||
ifeq ($(ARCH),x86_64)
|
|
||||||
# Internal nasm flags that should not be changed by the user.
|
|
||||||
override NASMFLAGS += \
|
|
||||||
-Wall
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Architecture specific internal flags.
|
# Architecture specific internal flags.
|
||||||
ifeq ($(ARCH),x86_64)
|
ifeq ($(ARCH),x86_64)
|
||||||
ifeq ($(CC_IS_CLANG),1)
|
ifeq ($(CC_IS_CLANG),1)
|
||||||
|
@ -167,62 +163,52 @@ all: bin-$(ARCH)/$(OUTPUT)
|
||||||
# Include header dependencies.
|
# Include header dependencies.
|
||||||
-include $(HEADER_DEPS)
|
-include $(HEADER_DEPS)
|
||||||
|
|
||||||
# Link rules for building the C compiler runtime.
|
|
||||||
cc-runtime-$(ARCH)/cc-runtime.a: GNUmakefile cc-runtime/*
|
|
||||||
@rm -rf cc-runtime-$(ARCH)
|
|
||||||
@cp -r cc-runtime cc-runtime-$(ARCH)
|
|
||||||
@$(MAKE) -C cc-runtime-$(ARCH) -f cc-runtime.mk \
|
|
||||||
CC="$(CC)" \
|
|
||||||
AR="$(AR)" \
|
|
||||||
CFLAGS="$(CFLAGS)" \
|
|
||||||
CPPFLAGS='-isystem ../freestnd-c-hdrs -DCC_RUNTIME_NO_FLOAT'
|
|
||||||
@echo " C runtime built"
|
|
||||||
|
|
||||||
# Link rules for the final executable.
|
# Link rules for the final executable.
|
||||||
bin-$(ARCH)/$(OUTPUT): GNUmakefile linker-$(ARCH).ld $(OBJ) cc-runtime-$(ARCH)/cc-runtime.a
|
bin-$(ARCH)/$(OUTPUT): GNUmakefile linker-$(ARCH).ld $(OBJ)
|
||||||
@mkdir -p "$$(dirname $@)"
|
|
||||||
@echo " LD $@"
|
@echo " LD $@"
|
||||||
@$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) cc-runtime-$(ARCH)/cc-runtime.a -o $@
|
@mkdir -p "$$(dirname $@)"
|
||||||
|
@$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) -o $@
|
||||||
|
|
||||||
# Compilation rules for *.c files.
|
# Compilation rules for *.c files.
|
||||||
obj-$(ARCH)/%.c.o: src/%.c GNUmakefile
|
obj-$(ARCH)/%.c.o: src/%.c GNUmakefile
|
||||||
@mkdir -p "$$(dirname $@)"
|
|
||||||
@echo " CC $@"
|
@echo " CC $@"
|
||||||
|
@mkdir -p "$$(dirname $@)"
|
||||||
@$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
@$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
# Compilation rules for *.S files.
|
# Compilation rules for *.S files.
|
||||||
obj-$(ARCH)/%.S.o: src/%.S GNUmakefile
|
obj-$(ARCH)/%.S.o: src/%.S GNUmakefile
|
||||||
|
@echo " CC $@"
|
||||||
@mkdir -p "$$(dirname $@)"
|
@mkdir -p "$$(dirname $@)"
|
||||||
@echo " AS $@"
|
|
||||||
@$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
@$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
ifeq ($(ARCH),x86_64)
|
ifeq ($(ARCH),x86_64)
|
||||||
# Compilation rules for *.asm (nasm) files.
|
# Compilation rules for *.asm (nasm) files.
|
||||||
obj-$(ARCH)/%.asm.o: src/%.asm GNUmakefile
|
obj-$(ARCH)/%.asm.o: src/%.asm GNUmakefile
|
||||||
|
@echo " NASM $@"
|
||||||
@mkdir -p "$$(dirname $@)"
|
@mkdir -p "$$(dirname $@)"
|
||||||
@echo " NASM $@"
|
|
||||||
@nasm $(NASMFLAGS) $< -o $@
|
@nasm $(NASMFLAGS) $< -o $@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Remove object files and the final executable.
|
# Remove object files and the final executable.
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@rm -rf bin-$(ARCH) obj-$(ARCH) cc-runtime-$(ARCH)
|
@rm -rf bin-$(ARCH) obj-$(ARCH)
|
||||||
@echo " The kernel output files have been removed."
|
|
||||||
# Remove everything built and generated including downloaded dependencies.
|
# Remove everything built and generated including downloaded dependencies.
|
||||||
.PHONY: distclean
|
.PHONY: distclean
|
||||||
distclean:
|
distclean:
|
||||||
@rm -rf bin-* obj-* freestnd-c-hdrs cc-runtime* src/limine.h
|
@rm -rf bin-* obj-* src/deps
|
||||||
@echo " The kernel output & downloaded files have been removed."
|
|
||||||
|
|
||||||
# Install the final built executable to its final on-root location.
|
# Install the final built executable to its final on-root location.
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
install: all
|
install: all
|
||||||
@install -d "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)"
|
@install -d "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)"
|
||||||
@install -m 644 bin-$(ARCH)/$(OUTPUT) "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)/$(OUTPUT)-$(ARCH)"
|
@install -m 644 bin-$(ARCH)/$(OUTPUT) "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)/$(OUTPUT)-$(ARCH)"
|
||||||
|
@echo "A new copy of Soaplin has been installed to $(DESTDIR)$(PREFIX)/share/$(OUTPUT)."
|
||||||
|
|
||||||
# Try to undo whatever the "install" target did.
|
# Try to undo whatever the "install" target did.
|
||||||
.PHONY: uninstall
|
.PHONY: uninstall
|
||||||
uninstall:
|
uninstall:
|
||||||
@rm -f "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)/$(OUTPUT)-$(ARCH)"
|
@rm -f "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)/$(OUTPUT)-$(ARCH)"
|
||||||
@-rmdir "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)"
|
@-rmdir "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)"
|
||||||
|
@echo "The copy of Soaplin at $(DESTDIR)$(PREFIX)/share/$(OUTPUT) has been deleted."
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
srcdir="$(dirname "$0")"
|
srcdir="$(dirname "$0")"
|
||||||
test -z "$srcdir" && srcdir=.
|
test -z "$srcdir" && srcdir=.
|
||||||
|
|
||||||
cd "$srcdir"
|
cd "$srcdir"
|
||||||
|
|
||||||
clone_repo_commit() {
|
clone_repo_commit() {
|
||||||
|
echo " DEPS Cloning $1 to $2 (commit: $3)"
|
||||||
if test -d "$2/.git"; then
|
if test -d "$2/.git"; then
|
||||||
git -C "$2" reset --hard
|
git -C "$2" reset --hard > /dev/null 2>&1
|
||||||
git -C "$2" clean -fd
|
git -C "$2" clean -fd > /dev/null 2>&1
|
||||||
if ! git -C "$2" checkout $3; then
|
if ! git -C "$2" checkout $3; then
|
||||||
rm -rf "$2"
|
rm -rf "$2"
|
||||||
fi
|
fi
|
||||||
|
@ -22,8 +21,8 @@ clone_repo_commit() {
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if ! test -d "$2"; then
|
if ! test -d "$2"; then
|
||||||
git clone $1 "$2"
|
git clone $1 "$2" > /dev/null 2>&1
|
||||||
if ! git -C "$2" checkout $3; then
|
if ! git -C "$2" checkout $3 > /dev/null 2>&1; then
|
||||||
rm -rf "$2"
|
rm -rf "$2"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
@ -32,27 +31,28 @@ clone_repo_commit() {
|
||||||
|
|
||||||
download_by_hash() {
|
download_by_hash() {
|
||||||
DOWNLOAD_COMMAND="curl -Lo"
|
DOWNLOAD_COMMAND="curl -Lo"
|
||||||
if ! command -v $DOWNLOAD_COMMAND >/dev/null 2>&1; then
|
if ! command -v "${DOWNLOAD_COMMAND%% *}" >/dev/null 2>&1; then
|
||||||
DOWNLOAD_COMMAND="wget -O"
|
DOWNLOAD_COMMAND="wget -O"
|
||||||
if ! command -v $DOWNLOAD_COMMAND >/dev/null 2>&1; then
|
if ! command -v "${DOWNLOAD_COMMAND%% *}" >/dev/null 2>&1; then
|
||||||
set +x
|
set +x
|
||||||
echo "error: Neither curl nor wget found"
|
echo "error: Neither curl nor wget found"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
SHA256_COMMAND="sha256sum"
|
SHA256_COMMAND="sha256sum"
|
||||||
if ! command -v $SHA256_COMMAND >/dev/null 2>&1; then
|
if ! command -v "${SHA256_COMMAND%% *}" >/dev/null 2>&1; then
|
||||||
SHA256_COMMAND="sha256"
|
SHA256_COMMAND="sha256"
|
||||||
if ! command -v $SHA256_COMMAND >/dev/null 2>&1; then
|
if ! command -v "${SHA256_COMMAND%% *}" >/dev/null 2>&1; then
|
||||||
set +x
|
set +x
|
||||||
echo "error: Cannot find sha256(sum) command"
|
echo "error: Cannot find sha256(sum) command"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
echo " DEPS Downloading $1 to $2"
|
||||||
if ! test -f "$2" || ! $SHA256_COMMAND "$2" | grep $3 >/dev/null 2>&1; then
|
if ! test -f "$2" || ! $SHA256_COMMAND "$2" | grep $3 >/dev/null 2>&1; then
|
||||||
rm -f "$2"
|
rm -f "$2"
|
||||||
mkdir -p "$2" && rm -rf "$2"
|
mkdir -p "$2" && rm -rf "$2"
|
||||||
$DOWNLOAD_COMMAND "$2" $1
|
$DOWNLOAD_COMMAND "$2" $1 > /dev/null 2>&1
|
||||||
if ! $SHA256_COMMAND "$2" | grep $3 >/dev/null 2>&1; then
|
if ! $SHA256_COMMAND "$2" | grep $3 >/dev/null 2>&1; then
|
||||||
set +x
|
set +x
|
||||||
echo "error: Cannot download file '$2' by hash"
|
echo "error: Cannot download file '$2' by hash"
|
||||||
|
@ -64,17 +64,29 @@ download_by_hash() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
clone_repo_commit \
|
mkdir src/deps
|
||||||
https://github.com/osdev0/freestnd-c-hdrs-0bsd.git \
|
|
||||||
freestnd-c-hdrs \
|
|
||||||
a87c192f3eb66b0806740dc67325f9ad23fc2d0b
|
|
||||||
|
|
||||||
clone_repo_commit \
|
clone_repo_commit \
|
||||||
https://github.com/osdev0/cc-runtime.git \
|
https://codeberg.org/mintsuki/flanterm \
|
||||||
cc-runtime \
|
src/deps/flanterm \
|
||||||
576a01179f3298a4795b92f42c088f9f8800b56b
|
bdecdcb1b7dad05ab5249e2c3e4d2c27a661e864
|
||||||
|
|
||||||
|
clone_repo_commit \
|
||||||
|
https://codeberg.org/osdev/freestnd-c-hdrs-0bsd.git \
|
||||||
|
src/deps/freestnd-c-hdrs \
|
||||||
|
a87c192f3eb66b0806740dc67325f9ad23fc2d0b
|
||||||
|
|
||||||
|
download_by_hash \
|
||||||
|
https://codeberg.org/osdev/cc-runtime/raw/commit/d5425655388977fa12ff9b903e554a20b20c426e/cc-runtime.c \
|
||||||
|
src/deps/cc-runtime.c \
|
||||||
|
60bb1af4f6541077b736f19bf0f5a22b5dd8a2f3bed0d9d9d89846a33ef24b74
|
||||||
|
|
||||||
download_by_hash \
|
download_by_hash \
|
||||||
https://github.com/limine-bootloader/limine/raw/4687a182be23939c2d9f15db970382dc353ed956/limine.h \
|
https://github.com/limine-bootloader/limine/raw/4687a182be23939c2d9f15db970382dc353ed956/limine.h \
|
||||||
src/limine.h \
|
src/deps/limine.h \
|
||||||
6879e626f34c1be25ac2f72bf43b083fc2b53887280bb0fcdaee790e258c6974
|
6879e626f34c1be25ac2f72bf43b083fc2b53887280bb0fcdaee790e258c6974
|
||||||
|
|
||||||
|
download_by_hash \
|
||||||
|
https://github.com/charlesnicholson/nanoprintf/raw/49628bd79977478dbd7c9a1b5277c44e5d49b118/nanoprintf.h \
|
||||||
|
src/deps/npf.h \
|
||||||
|
ef496c71868b3942695f63e0215da9d25ebdfa21569c854950e8f91adb9e0bea
|
|
@ -23,39 +23,31 @@ SECTIONS
|
||||||
/* that is the beginning of the region. */
|
/* that is the beginning of the region. */
|
||||||
. = 0xffffffff80000000;
|
. = 0xffffffff80000000;
|
||||||
|
|
||||||
|
|
||||||
.text : {
|
|
||||||
text_start_ld = .;
|
|
||||||
*(.text .text.*)
|
|
||||||
text_end_ld = .;
|
|
||||||
} :text
|
|
||||||
|
|
||||||
/* Move to the next memory page for .limine_requests */
|
|
||||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
|
||||||
|
|
||||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
||||||
.limine_requests : {
|
.limine_requests : {
|
||||||
reqs_start_ld = .;
|
|
||||||
KEEP(*(.limine_requests_start))
|
KEEP(*(.limine_requests_start))
|
||||||
KEEP(*(.limine_requests))
|
KEEP(*(.limine_requests))
|
||||||
KEEP(*(.limine_requests_end))
|
KEEP(*(.limine_requests_end))
|
||||||
reqs_end_ld = .;
|
|
||||||
} :limine_requests
|
} :limine_requests
|
||||||
|
|
||||||
|
/* Move to the next memory page for .text */
|
||||||
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
*(.text .text.*)
|
||||||
|
} :text
|
||||||
|
|
||||||
/* Move to the next memory page for .rodata */
|
/* Move to the next memory page for .rodata */
|
||||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
.rodata : {
|
.rodata : {
|
||||||
rodata_start_ld = .;
|
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
rodata_end_ld = .;
|
|
||||||
} :rodata
|
} :rodata
|
||||||
|
|
||||||
/* Move to the next memory page for .data */
|
/* Move to the next memory page for .data */
|
||||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
.data : {
|
.data : {
|
||||||
data_start_ld = .;
|
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
} :data
|
} :data
|
||||||
|
|
||||||
|
@ -66,7 +58,6 @@ SECTIONS
|
||||||
.bss : {
|
.bss : {
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
data_end_ld = .;
|
|
||||||
} :data
|
} :data
|
||||||
|
|
||||||
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
|
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
|
||||||
|
|
74
kernel/src/acpi/acpi.c
Executable file
74
kernel/src/acpi/acpi.c
Executable file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* acpi.c - ACPI table lookup
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <acpi/acpi.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
#include <boot/limine.h>
|
||||||
|
#include <lib/log.h>
|
||||||
|
#include <mm/memop.h>
|
||||||
|
#include <mm/pmm.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static bool __acpi_use_xsdt;
|
||||||
|
static uint64_t __acpi_rsdt_addr;
|
||||||
|
|
||||||
|
void *acpi_find_table(char *sign) {
|
||||||
|
if (__acpi_use_xsdt) {
|
||||||
|
acpi_xsdt_t *xsdt = (acpi_xsdt_t*)__acpi_rsdt_addr;
|
||||||
|
uint32_t entries = (xsdt->hdr.len - sizeof(xsdt->hdr)) / 8;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < entries; i++)
|
||||||
|
{
|
||||||
|
acpi_sdt_hdr_t *h = (acpi_sdt_hdr_t *)higher_half(*((uint64_t*)xsdt->entries + i));
|
||||||
|
if (!memcmp(h->sign, sign, 4))
|
||||||
|
return (void *) h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
acpi_rsdt_t *rsdt = (acpi_rsdt_t*)__acpi_rsdt_addr;
|
||||||
|
int entries = (rsdt->hdr.len - sizeof(rsdt->hdr)) / 4;
|
||||||
|
uint32_t *entries_hhalf = (uint32_t *)higher_half((uint64_t)rsdt->entries);
|
||||||
|
|
||||||
|
for (int i = 0; i < entries; i++)
|
||||||
|
{
|
||||||
|
acpi_sdt_hdr_t *h = (acpi_sdt_hdr_t *)(entries_hhalf[i] + (i * sizeof(uint32_t)));
|
||||||
|
if (!memcmp(h->sign, sign, 4))
|
||||||
|
return (void *) h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void acpi_init() {
|
||||||
|
acpi_rsdp_t *rsdp = (acpi_rsdp_t*)limine_get_rsdp();
|
||||||
|
if (memcmp(rsdp->sign, "RSD PTR ", 8))
|
||||||
|
{
|
||||||
|
fatal("acpi: ACPI RSDP is corrupt\n");
|
||||||
|
hcf();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsdp->rev >= 2)
|
||||||
|
{
|
||||||
|
trace("acpi: ACPI v2.0 or later detected: Using XSDT.\n");
|
||||||
|
|
||||||
|
acpi_xsdp_t *xsdp = (acpi_xsdp_t *)rsdp;
|
||||||
|
__acpi_use_xsdt = 1;
|
||||||
|
__acpi_rsdt_addr = higher_half(xsdp->xsdt_addr);
|
||||||
|
|
||||||
|
goto initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
__acpi_use_xsdt = 0;
|
||||||
|
__acpi_rsdt_addr = higher_half(rsdp->rsdt_addr); // Do not use a pointer, to shut up the compiler.
|
||||||
|
|
||||||
|
initialized:
|
||||||
|
trace("acpi: Initialized!\n");
|
||||||
|
}
|
50
kernel/src/acpi/acpi.h
Executable file
50
kernel/src/acpi/acpi.h
Executable file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* acpi.h - ACPI definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char sign[8];
|
||||||
|
char chksum;
|
||||||
|
char oemid[6];
|
||||||
|
char rev;
|
||||||
|
uint32_t rsdt_addr;
|
||||||
|
} __attribute__((packed)) acpi_rsdp_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
acpi_rsdp_t base;
|
||||||
|
uint32_t len;
|
||||||
|
uint64_t xsdt_addr;
|
||||||
|
char chksumex;
|
||||||
|
} __attribute__((packed)) acpi_xsdp_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char sign[4];
|
||||||
|
uint32_t len;
|
||||||
|
uint8_t rev;
|
||||||
|
uint8_t chksum;
|
||||||
|
char oemid[6];
|
||||||
|
char oemtabid[8];
|
||||||
|
uint32_t oemrev;
|
||||||
|
uint32_t creaid;
|
||||||
|
uint32_t crearev;
|
||||||
|
} __attribute__((packed)) acpi_sdt_hdr_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
acpi_sdt_hdr_t hdr;
|
||||||
|
char entries[];
|
||||||
|
} acpi_rsdt_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
acpi_sdt_hdr_t hdr;
|
||||||
|
char entries[];
|
||||||
|
} acpi_xsdt_t;
|
||||||
|
|
||||||
|
void *acpi_find_table(char *sign);
|
||||||
|
void acpi_init();
|
42
kernel/src/acpi/madt.c
Executable file
42
kernel/src/acpi/madt.c
Executable file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* madt.c - MADT lookup
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "acpi/acpi.h"
|
||||||
|
#include "lib/log.h"
|
||||||
|
#include <acpi/madt.h>
|
||||||
|
|
||||||
|
acpi_madt_ioapic_t* madt_ioapic_list[128];
|
||||||
|
acpi_madt_iso_t* madt_iso_list[128];
|
||||||
|
|
||||||
|
uint32_t madt_ioapic_len = 0;
|
||||||
|
uint32_t madt_iso_len = 0;
|
||||||
|
|
||||||
|
uint64_t *madt_lapic_addr = (uint64_t *)0;
|
||||||
|
|
||||||
|
void madt_init() {
|
||||||
|
void *addr = acpi_find_table("APIC");
|
||||||
|
acpi_madt_t *madt = (acpi_madt_t *)addr;
|
||||||
|
uint64_t offset = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (offset > madt->hdr.len - sizeof(acpi_madt_t))
|
||||||
|
break;
|
||||||
|
|
||||||
|
madt_entry *entry = (madt_entry *)(madt->table + offset);
|
||||||
|
|
||||||
|
if (entry->type == 1)
|
||||||
|
madt_ioapic_list[madt_ioapic_len++] = (acpi_madt_ioapic_t *)entry;
|
||||||
|
else if (entry->type == 2)
|
||||||
|
madt_iso_list[madt_iso_len++] = (acpi_madt_iso_t *)entry;
|
||||||
|
else if (entry->type == 5)
|
||||||
|
madt_lapic_addr = (uint64_t *)((acpi_madt_lapic_addr_override_t *)entry)->plapic;
|
||||||
|
|
||||||
|
offset += entry->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("madt: Initialized\n");
|
||||||
|
}
|
61
kernel/src/acpi/madt.h
Executable file
61
kernel/src/acpi/madt.h
Executable file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* madt.h - MADT lookup
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <acpi/acpi.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
acpi_sdt_hdr_t hdr;
|
||||||
|
uint32_t lapic_addr;
|
||||||
|
uint32_t flags;
|
||||||
|
char table[];
|
||||||
|
} acpi_madt_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t len;
|
||||||
|
} madt_entry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
madt_entry entry;
|
||||||
|
uint8_t cpu_id;
|
||||||
|
uint8_t lapic_id;
|
||||||
|
uint32_t flags;
|
||||||
|
} acpi_madt_lapic_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
madt_entry entry;
|
||||||
|
uint8_t ioapic_id;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint32_t ioapic_addr;
|
||||||
|
uint32_t gsi_base;
|
||||||
|
} acpi_madt_ioapic_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
madt_entry entry;
|
||||||
|
uint8_t bus;
|
||||||
|
uint8_t source;
|
||||||
|
uint32_t gsi;
|
||||||
|
uint16_t flags;
|
||||||
|
} acpi_madt_iso_t; // iso = interrupt source override
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
madt_entry entry;
|
||||||
|
uint16_t reserved;
|
||||||
|
uint64_t plapic;
|
||||||
|
} acpi_madt_lapic_addr_override_t;
|
||||||
|
|
||||||
|
extern acpi_madt_ioapic_t* madt_ioapic_list[128];
|
||||||
|
extern acpi_madt_iso_t* madt_iso_list[128];
|
||||||
|
|
||||||
|
extern uint32_t madt_ioapic_len;
|
||||||
|
extern uint32_t madt_iso_len;
|
||||||
|
|
||||||
|
extern uint64_t *lapic_addr;
|
||||||
|
|
||||||
|
void madt_init();
|
29
kernel/src/arch/aarch64/cpu.c
Executable file
29
kernel/src/arch/aarch64/cpu.c
Executable file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* cpu.c - AArch64 CPU control implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined (__aarch64__)
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
|
void arch_init_stage1() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_load_pm(pagemap_t pm) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_invalidate_page(uint64_t vaddr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void hcf() {
|
||||||
|
for (;;) {
|
||||||
|
asm ("wfi");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define ENSURE_X86_64 #ifdef __x86_64__
|
|
||||||
|
|
||||||
#define ENDENSURE
|
|
35
kernel/src/arch/cpu.h
Executable file
35
kernel/src/arch/cpu.h
Executable file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* cpu.h - CPU control and management functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mm/paging.h"
|
||||||
|
|
||||||
|
// Stage 1 initialization: Core components (such as the GDT & IDT on x86_64...)
|
||||||
|
void arch_init_stage1();
|
||||||
|
|
||||||
|
// Load a pagemap
|
||||||
|
void cpu_load_pm(pagemap_t pm);
|
||||||
|
|
||||||
|
// Invalidate a page table entry
|
||||||
|
void cpu_invalidate_page(uint64_t vaddr);
|
||||||
|
|
||||||
|
// Initialize SMP. The implementations are in arch since the Limine
|
||||||
|
// structure changes depending on the architecture.
|
||||||
|
void cpu_init_smp();
|
||||||
|
|
||||||
|
// Initialize the CPU's timer
|
||||||
|
void cpu_init_timer();
|
||||||
|
|
||||||
|
// Initialize the APIC.
|
||||||
|
void cpu_init_apic();
|
||||||
|
|
||||||
|
// Enable/disable interrupts.
|
||||||
|
void cpu_enable_ints(int enabled);
|
||||||
|
|
||||||
|
// Disable interrupts and halt the system.
|
||||||
|
void hcf();
|
29
kernel/src/arch/la64/cpu.c
Executable file
29
kernel/src/arch/la64/cpu.c
Executable file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* cpu.c - LoongArch64 CPU control implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined (__loongarch64)
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
|
void arch_init_stage1() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_load_pm(pagemap_t pm) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_invalidate_page(uint64_t vaddr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void hcf() {
|
||||||
|
for (;;) {
|
||||||
|
asm ("idle 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
29
kernel/src/arch/riscv/cpu.c
Executable file
29
kernel/src/arch/riscv/cpu.c
Executable file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* cpu.c - RISC-V CPU control implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined (__riscv)
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
|
void arch_init_stage1() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_load_pm(pagemap_t pm) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_invalidate_page(uint64_t vaddr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void hcf() {
|
||||||
|
for (;;) {
|
||||||
|
asm ("wfi");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
50
kernel/src/arch/x86_64/cpu.c
Executable file
50
kernel/src/arch/x86_64/cpu.c
Executable file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* cpu.c - x86_64 CPU control implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined (__x86_64__)
|
||||||
|
|
||||||
|
#include "arch/x86_64/lapic.h"
|
||||||
|
#include "arch/x86_64/ioapic.h"
|
||||||
|
#include <arch/x86_64/gdt.h>
|
||||||
|
#include <arch/x86_64/idt.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
#include <mm/pmm.h>
|
||||||
|
#include "mm/paging.h"
|
||||||
|
|
||||||
|
void arch_init_stage1() {
|
||||||
|
gdt_init();
|
||||||
|
idt_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_load_pm(pagemap_t pm) {
|
||||||
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
__asm__ volatile("mov %0, %%cr3" : : "r"(physical((uint64_t)pm)) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_invalidate_page(uint64_t vaddr) {
|
||||||
|
asm volatile ( "invlpg (%0)" : : "b"(vaddr) : "memory" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_enable_ints(int enabled) {
|
||||||
|
if (enabled) asm("sti"); else asm("cli");
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_init_apic() {
|
||||||
|
lapic_init();
|
||||||
|
ioapic_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hcf() {
|
||||||
|
asm ("cli");
|
||||||
|
for (;;) {
|
||||||
|
asm ("hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
0
kernel/src/arch/x86_64/cpu.h
Executable file
0
kernel/src/arch/x86_64/cpu.h
Executable file
|
@ -1,647 +0,0 @@
|
||||||
#ifndef __CPUID_H__
|
|
||||||
#define __CPUID_H__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
//=================CPUID_VENDOR=================
|
|
||||||
#define CPUID_VENDOR_INTEL "GenuineIntel"
|
|
||||||
#define CPUID_VENDOR_AMD "AuthenticAMD"
|
|
||||||
|
|
||||||
//================CPUID_CPU_INFO================
|
|
||||||
#define CPUID_CPU_INFO_EAX_STEPPING_MASK 0xF
|
|
||||||
#define CPUID_CPU_INFO_EAX_MODEL_MASK 0xF << 4
|
|
||||||
#define CPUID_CPU_INFO_EAX_FAMILY_MASK 0xF << 8
|
|
||||||
#define CPUID_CPU_INFO_EAX_TYPE_MASK 0x3 << 12
|
|
||||||
#define CPUID_CPU_INFO_EAX_EXT_MODEL_MASK 0xF << 16
|
|
||||||
#define CPUID_CPU_INFO_EAX_EXT_FAMILY_MASK 0xFF << 20
|
|
||||||
|
|
||||||
#define CPUID_CPU_INFO_EBX_BRAND_INDEX 0xFF
|
|
||||||
#define CPUID_CPU_INFO_EBX_CFLUSH_SIZE 0xFF << 8
|
|
||||||
#define CPUID_CPU_INFO_EBX_MAX_LOGPROC 0xFF << 16
|
|
||||||
#define CPUID_CPU_INFO_EBX_INIT_APIC_ID 0xFF << 25
|
|
||||||
|
|
||||||
#define CPUID_CPU_INFO_ECX_SSE3 1 << 0
|
|
||||||
#define CPUID_CPU_INFO_ECX_PCLMULQDQ 1 << 1
|
|
||||||
#define CPUID_CPU_INFO_ECX_DTES64 1 << 2
|
|
||||||
#define CPUID_CPU_INFO_ECX_MONITOR 1 << 3
|
|
||||||
#define CPUID_CPU_INFO_ECX_DS_CPL 1 << 4
|
|
||||||
#define CPUID_CPU_INFO_ECX_VMX 1 << 5
|
|
||||||
#define CPUID_CPU_INFO_ECX_SMX 1 << 6
|
|
||||||
#define CPUID_CPU_INFO_ECX_EIST 1 << 7
|
|
||||||
#define CPUID_CPU_INFO_ECX_TM2 1 << 8
|
|
||||||
#define CPUID_CPU_INFO_ECX_SSSE3 1 << 9
|
|
||||||
#define CPUID_CPU_INFO_ECX_CNXT_ID 1 << 10
|
|
||||||
#define CPUID_CPU_INFO_ECX_SDBG 1 << 11
|
|
||||||
#define CPUID_CPU_INFO_ECX_FMA 1 << 12
|
|
||||||
#define CPUID_CPU_INFO_ECX_CMPXCHG16B 1 << 13
|
|
||||||
#define CPUID_CPU_INFO_ECX_XTPR_UC 1 << 14
|
|
||||||
#define CPUID_CPU_INFO_ECX_PDCM 1 << 15
|
|
||||||
// bit 16 is reserved
|
|
||||||
#define CPUID_CPU_INFO_ECX_PCID 1 << 17
|
|
||||||
#define CPUID_CPU_INFO_ECX_DCA 1 << 18
|
|
||||||
#define CPUID_CPU_INFO_ECX_SSE4_1 1 << 19
|
|
||||||
#define CPUID_CPU_INFO_ECX_SSE4_2 1 << 20
|
|
||||||
#define CPUID_CPU_INFO_ECX_X2APIC 1 << 21
|
|
||||||
#define CPUID_CPU_INFO_ECX_MOVBE 1 << 22
|
|
||||||
#define CPUID_CPU_INFO_ECX_POPCNT 1 << 23
|
|
||||||
#define CPUID_CPU_INFO_ECX_TSC_DEADLINE 1 << 24
|
|
||||||
#define CPUID_CPU_INFO_ECX_AESNI 1 << 25
|
|
||||||
#define CPUID_CPU_INFO_ECX_XSAVE 1 << 26
|
|
||||||
#define CPUID_CPU_INFO_ECX_OSXSAVE 1 << 27
|
|
||||||
#define CPUID_CPU_INFO_ECX_AVX 1 << 28
|
|
||||||
#define CPUID_CPU_INFO_ECX_F16C 1 << 29
|
|
||||||
#define CPUID_CPU_INFO_ECX_RDRAND 1 << 30
|
|
||||||
// bit 31 is unused
|
|
||||||
|
|
||||||
#define CPUID_CPU_INFO_EDX_FPU 1 << 0
|
|
||||||
#define CPUID_CPU_INFO_EDX_VME 1 << 1
|
|
||||||
#define CPUID_CPU_INFO_EDX_DE 1 << 2
|
|
||||||
#define CPUID_CPU_INFO_EDX_PSE 1 << 3
|
|
||||||
#define CPUID_CPU_INFO_EDX_TSC 1 << 4
|
|
||||||
#define CPUID_CPU_INFO_EDX_MSR 1 << 5
|
|
||||||
#define CPUID_CPU_INFO_EDX_PAE 1 << 6
|
|
||||||
#define CPUID_CPU_INFO_EDX_MCE 1 << 7
|
|
||||||
#define CPUID_CPU_INFO_EDX_CX8 1 << 8
|
|
||||||
#define CPUID_CPU_INFO_EDX_APIC 1 << 9
|
|
||||||
// bit 10 is reserved
|
|
||||||
#define CPUID_CPU_INFO_EDX_SEP 1 << 11
|
|
||||||
#define CPUID_CPU_INFO_EDX_MTRR 1 << 12
|
|
||||||
#define CPUID_CPU_INFO_EDX_PGE 1 << 13
|
|
||||||
#define CPUID_CPU_INFO_EDX_MCA 1 << 14
|
|
||||||
#define CPUID_CPU_INFO_EDX_CMOV 1 << 15
|
|
||||||
#define CPUID_CPU_INFO_EDX_PAT 1 << 16
|
|
||||||
#define CPUID_CPU_INFO_EDX_PSE_36 1 << 17
|
|
||||||
#define CPUID_CPU_INFO_EDX_PSN 1 << 18
|
|
||||||
#define CPUID_CPU_INFO_EDX_CLFSH 1 << 19
|
|
||||||
// bit 20 is reserved
|
|
||||||
#define CPUID_CPU_INFO_EDX_DS 1 << 21
|
|
||||||
#define CPUID_CPU_INFO_EDX_ACPI 1 << 22
|
|
||||||
#define CPUID_CPU_INFO_EDX_MMX 1 << 23
|
|
||||||
#define CPUID_CPU_INFO_EDX_FXSR 1 << 24
|
|
||||||
#define CPUID_CPU_INFO_EDX_SSE 1 << 25
|
|
||||||
#define CPUID_CPU_INFO_EDX_SSE2 1 << 26
|
|
||||||
#define CPUID_CPU_INFO_EDX_SS 1 << 27
|
|
||||||
#define CPUID_CPU_INFO_EDX_HTT 1 << 28
|
|
||||||
#define CPUID_CPU_INFO_EDX_TM 1 << 29
|
|
||||||
// bit 30 is reserved
|
|
||||||
#define CPUID_CPU_INFO_EDX_PBE 1 << 31
|
|
||||||
|
|
||||||
//===============CPUID_CACHE_TLB===============
|
|
||||||
// WARNING: I gave up and used ChatGPT for these
|
|
||||||
#define CPUID_CACHE_TLB_DESC_NULL 0x00
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_4_KBYTE_4WAY_32E 0x01
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_4_MBYTE_FULLY_2E 0x02
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_4_KBYTE_4WAY_64E 0x03
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_4_MBYTE_4WAY_8E 0x04
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB1_4_MBYTE_4WAY_32E 0x05
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_INST_8K_4WAY_32B 0x06
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_INST_16K_4WAY_32B 0x08
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_INST_32K_4WAY_64B 0x09
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_8K_2WAY_32B 0x0A
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_4_MBYTE_4WAY_4E 0x0B
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_16K_4WAY_32B 0x0C
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_16K_4WAY_64B 0x0D
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_24K_6WAY_64B 0x0E
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_128K_2WAY_64B 0x1D
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_256K_8WAY_64B 0x21
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_512K_4WAY_64B_2LPS 0x22
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_1M_8WAY_64B_2LPS 0x23
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_1M_16WAY_64B 0x24
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_2M_8WAY_64B_2LPS 0x25
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_4M_8WAY_64B_2LPS 0x29
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_32K_8WAY_64B 0x2C
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_INST_32K_8WAY_64B 0x30
|
|
||||||
#define CPUID_CACHE_TLB_DESC_NO_L2_OR_L3 0x40
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_128K_4WAY_32B 0x41
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_256K_4WAY_32B 0x42
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_512K_4WAY_32B 0x43
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_1M_4WAY_32B 0x44
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_2M_4WAY_32B 0x45
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_4M_4WAY_64B 0x46
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_8M_8WAY_64B 0x47
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_3M_12WAY_64B 0x48
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_4M_16WAY_64B 0x49
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_6M_12WAY_64B 0x4A
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_8M_16WAY_64B 0x4B
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_12M_12WAY_64B 0x4C
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L3_16M_16WAY_64B 0x4D
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_6M_24WAY_64B 0x4E
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_32E 0x4F
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_2M_4M_64E 0x50
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_2M_4M_128E 0x51
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_2M_4M_256E 0x52
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_2M_4M_FULLY_7E 0x55
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB0_4M_4WAY_16E 0x56
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB0_4K_4WAY_16E 0x57
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB0_4K_FULLY_16E 0x59
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB0_2M_4M_4WAY_32E 0x5A
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_4M_64E 0x5B
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_4M_128E 0x5C
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_4M_256E 0x5D
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_16K_8WAY_64B 0x60
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_FULLY_48E 0x61
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_2M_4M_32E_1G_4WAY_4E 0x63
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_4WAY_512E 0x64
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_8K_4WAY_64B 0x66
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_16K_4WAY_64B_DUPLICATE 0x67 //????????????
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_32K_4WAY_64B 0x68
|
|
||||||
#define CPUID_CACHE_TLB_DESC_UTLB_4K_8WAY_64E 0x6A
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_8WAY_256E 0x6B
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_2M_4M_8WAY_128E 0x6C
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_1G_FULLY_16E 0x6D
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TRACE_12K_8WAY 0x70
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TRACE_16K_8WAY 0x71
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TRACE_32K_8WAY 0x72
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_2M_4M_FULLY_8E 0x76
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_1M_4WAY_64B 0x78
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_128K_8WAY_64B_2LPS 0x79
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_256K_8WAY_64B_2LPS 0x7A
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_512K_8WAY_64B_2LPS 0x7B
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_1M_8WAY_64B_2LPS 0x7C
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_2M_8WAY_64B 0x7D
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_512K_2WAY_64B 0x7F
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_512K_8WAY_64B 0x80
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_256K_8WAY_32B 0x82
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_512K_8WAY_32B 0x83
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_1M_8WAY_32B 0x84
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_2M_8WAY_32B 0x85
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_512K_4WAY_64B 0x86
|
|
||||||
#define CPUID_CACHE_TLB_DESC_L2_1M_8WAY_64B 0x87
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_FULLY_ASSOC_32E 0xA0
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_4WAY_128E 0xB0
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_2M_4WAY_8E_4M_4WAY_4E 0xB1
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_4WAY_64E 0xB2
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_DATA_4K_4WAY_128E 0xB3
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_DATA_4K_4WAY_256E 0xB4
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_8WAY_64E 0xB5
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_8WAY_128E 0xB6
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_DATA_4K_4WAY_64E 0xBA
|
|
||||||
#define CPUID_CACHE_TLB_DESC_TLB_DATA_4K_4M_4WAY_8E 0xC0
|
|
||||||
#define CPUID_CACHE_TLB_DESC_STLB_2ND_LEVEL_4K_2M_8WAY_1024E 0xC1
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_2M_4WAY_16E 0xC2
|
|
||||||
#define CPUID_CACHE_TLB_DESC_STLB_2ND_LEVEL_4K_2M_6WAY_1536E_1GB_4WAY_16E 0xC3
|
|
||||||
#define CPUID_CACHE_TLB_DESC_DTLB_2M_4M_4WAY_32E 0xC4
|
|
||||||
#define CPUID_CACHE_TLB_DESC_STLB_2ND_LEVEL_4K_4WAY_512E 0xCA
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_512KB_4WAY_64B_LINE 0xD0
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_1MB_4WAY_64B_LINE 0xD1
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_2MB_4WAY_64B_LINE 0xD2
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_1MB_8WAY_64B_LINE 0xD6
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_2MB_8WAY_64B_LINE 0xD7
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_4MB_8WAY_64B_LINE 0xD8
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_1_5MB_12WAY_64B_LINE 0xDC
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_3MB_12WAY_64B_LINE 0xDD
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_6MB_12WAY_64B_LINE 0xDE
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_2MB_16WAY_64B_LINE 0xE2
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_4MB_16WAY_64B_LINE 0xE3
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_8MB_16WAY_64B_LINE 0xE4
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_12MB_24WAY_64B_LINE 0xEA
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_18MB_24WAY_64B_LINE 0xEB
|
|
||||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_24MB_24WAY_64B_LINE 0xEC
|
|
||||||
#define CPUID_CACHE_TLB_DESC_PREFETCH_64_BYTE 0xF0
|
|
||||||
#define CPUID_CACHE_TLB_DESC_PREFETCH_128_BYTE 0xF1
|
|
||||||
#define CPUID_CACHE_TLB_DESC_NO_TLB_INFO_CPUID_LEAF_18H 0xFE
|
|
||||||
#define CPUID_CACHE_TLB_DESC_NO_CACHE_INFO_CPUID_LEAF_4 0xFF
|
|
||||||
|
|
||||||
//=============CPUID_SERIAL_NUMBER=============
|
|
||||||
#define CPUID_SERIAL_NUMBER_STITCH(ECX, EDX) (uint64_t)((EDX << 32) | ECX)
|
|
||||||
|
|
||||||
//=============CPUID_CACHE_PARAMS==============
|
|
||||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE 0xF
|
|
||||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_LEVEL 0x7 << 4
|
|
||||||
#define CPUID_CACHE_PARAMS_EAX_IS_SELF_INIT 1 << 8
|
|
||||||
#define CPUID_CACHE_PARAMS_EAX_IS_FULLY_ASSOCIATIVE 1 << 9
|
|
||||||
// bits 10-13 are reserved
|
|
||||||
#define CPUID_CACHE_PARAMS_EAX_MAX_PROC_SHARING 0xFFF << 14
|
|
||||||
|
|
||||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE_NULL 0x0
|
|
||||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE_DATA 0x1
|
|
||||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE_INSTRUCTION 0x2
|
|
||||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE_UNIFIED 0x3
|
|
||||||
|
|
||||||
#define CPUID_CACHE_PARAMS_EBX_COHERENCY_LINE_SIZE 0xFFF
|
|
||||||
#define CPUID_CACHE_PARAMS_EBX_PHYS_LINE_PARTITIONS 0x3FF << 12
|
|
||||||
#define CPUID_CACHE_PARAMS_EBX_WAYS_OF_ASSOCIVITY 0x3FF
|
|
||||||
|
|
||||||
#define CPUID_CACHE_PARAMS_EDX_CACHE_INCLUSIVENESS 1
|
|
||||||
#define CPUID_CACHE_PARAMS_EDX_COMPLEX_CACHE_INDEXING 1 << 1
|
|
||||||
|
|
||||||
//=============CPUID_MONITOR_MWAIT=============
|
|
||||||
#define CPUID_MONITOR_MWAIT_ECX_ENUM_EXTENSIONS 1
|
|
||||||
#define CPUID_MONITOR_MWAIT_ECX_BREAK_EVENTS 1 << 1
|
|
||||||
|
|
||||||
#define CPUID_MONITOR_MWAIT_EDX_C0_SUBC_STATES 0xF
|
|
||||||
#define CPUID_MONITOR_MWAIT_EDX_C1_SUBC_STATES 0xF << 4
|
|
||||||
#define CPUID_MONITOR_MWAIT_EDX_C2_SUBC_STATES 0xF << 8
|
|
||||||
#define CPUID_MONITOR_MWAIT_EDX_C3_SUBC_STATES 0xF << 12
|
|
||||||
#define CPUID_MONITOR_MWAIT_EDX_C4_SUBC_STATES 0xF << 16
|
|
||||||
#define CPUID_MONITOR_MWAIT_EDX_C5_SUBC_STATES 0xF << 20
|
|
||||||
#define CPUID_MONITOR_MWAIT_EDX_C6_SUBC_STATES 0xF << 24
|
|
||||||
#define CPUID_MONITOR_MWAIT_EDX_C7_SUBC_STATES 0xF << 28
|
|
||||||
|
|
||||||
//===========CPUID_THERMAL_AND_POWER===========
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_TEMP_SENSOR 1
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_TURBO_BOOST 1 << 1
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_ARAT 1 << 2
|
|
||||||
// Bit 3 is reserved
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_PLN 1 << 3
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_ECMD 1 << 5
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_PTM 1 << 6
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP 1 << 7
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_NOTIFICATION 1 << 8
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_ACT_WINDOW 1 << 9
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_PERF_PREF 1 << 10
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_PKG_LVL_REQ 1 << 11
|
|
||||||
// Bit 12 is reserved
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_HDC 1 << 13
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_TURBO_BOOST_MAX 1 << 14
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_CAPABILITIES 1 << 15
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_PECI 1 << 16
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_FLEXIBLE_HWP 1 << 17
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_FAST_HWP_REQUEST 1 << 18
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_HW_FEEDBACK 1 << 19
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_IGNORE_HWP_IDLE 1 << 20
|
|
||||||
// Bits 21 and 22 are reserved
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_THREAD_DIRECTOR 1 << 23
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EAX_THERM_INTERRUPT 1 << 24
|
|
||||||
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EBX_INT_TRESHOLD 0xf
|
|
||||||
|
|
||||||
#define CPUID_THERMAL_AND_POWER_ECX_HW_COORD_FEEDBACK 1
|
|
||||||
#define CPUID_THERMAL_AND_POWER_ECX_ENERGY_PERF_BIAS 1 << 3
|
|
||||||
#define CPUID_THERMAL_AND_POWER_ECX_TD_CLASSES 0xff << 8
|
|
||||||
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EDX_PERF_REPORT 1
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EDX_EFFICIENCY_REPORT 1 << 1
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EDX_HW_FEEDBACK_SIZE 0xf << 8
|
|
||||||
#define CPUID_THERMAL_AND_POWER_EDX_THIS_PROC_HW_FB 0xffff << 16
|
|
||||||
|
|
||||||
//===========CPUID_EXTENDED_FEATURES===========
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_FSGSBASE 1
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_TSC_ADJUST 1 << 1
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_SGX 1 << 2
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_BMI1 1 << 3
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_HLE 1 << 4
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX2 1 << 5
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_FDP_EXCPTN_ONLY 1 << 6
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_SMEP 1 << 7
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_BMI2 1 << 8
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_ENHANCED_REP 1 << 9
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_INVCIP 1 << 10
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_RTM 1 << 11
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_RDT_M 1 << 12
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_NO_FPU_CS 1 << 13
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_MPX 1 << 14
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_RDT_A 1 << 15
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512F 1 << 16
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512DQ 1 << 17
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_RDSEED 1 << 18
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_ADX 1 << 19
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_SMAP 1 << 20
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512_IFMA 1 << 21
|
|
||||||
// Bit 22 is reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_CLFLUSHOPT 1 << 23
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_CLWB 1 << 24
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_TRACE 1 << 25
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512PF 1 << 26
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512ER 1 << 27
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512CD 1 << 28
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_SHA 1 << 29
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512BW 1 << 30
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512VL 1 << 31
|
|
||||||
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_PREFETCHWT1 1
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_AFX512_VBMI 1 << 1
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_UMIP 1 << 2
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_PKU 1 << 3
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_OSPKE 1 << 4
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_WAITPKG 1 << 5
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_AVX512_VBMI2 1 << 6
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_CET_SS 1 << 7
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_GFNI 1 << 8
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_VAES 1 << 9
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_VPCLMULQDQ 1 << 10
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_AVX512_VNNI 1 << 11
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_AVX512_BITLANG 1 << 12
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_TME_EN 1 << 13
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_AVX512_VPOPVNZDQ 1 << 14
|
|
||||||
// bit 15 is reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_LA57 1 << 16
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_MAWAU_VAL 0x1F << 17
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_RDPID 1 << 22
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_KL 1 << 23
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_BUS_LOCK_DETECT 1 << 24
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_CLDEMOTE 1 << 25
|
|
||||||
// bit 26 is reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_MOVDIRI 1 << 27
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_MOVDIR64B 1 << 28
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_ENQCMD 1 << 29
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_SGX_LC 1 << 30
|
|
||||||
#define CPUID_EXTENDED_FEATURES_ECX_PKS 1 << 31
|
|
||||||
|
|
||||||
// bit 0 is reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_SGX_KEYS 1 << 1
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_AVX512_4VNNIW 1 << 2
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_AVX512_4FMAPS 1 << 3
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_FAST_REP_MOV 1 << 4
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_UINTR 1 << 5
|
|
||||||
// bits 6 and 7 are reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_AVX512_VPINTERSECT \
|
|
||||||
1 << 8 // intel you son of a bitch
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_SRBDS_CTRL 1 << 9
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_MD_CLEAR 1 << 10
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_RTM_ALWAYS_ABORT 1 << 11
|
|
||||||
// bit 12 is reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_RTM_FORCE_ABORT 1 << 13
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_SERIALIZE 1 << 14
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_HYBRID 1 << 15
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_TSXLDTRK 1 << 16
|
|
||||||
// bit 17 is reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_PCONFIG 1 << 18
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_ARCHITECTURAL_LBR 1 << 19
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_CET_IBT 1 << 20
|
|
||||||
// bit 21 is reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_AMX_BF16 1 << 22
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_AVX512_FP16 1 << 23
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_AMX_TILE 1 << 24
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_AMX_INT8 1 << 25
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_IBRS 1 << 26
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_STIBP 1 << 27
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_L1D_FLUSH 1 << 28
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_ARCH_CAPABS_MSR 1 << 29
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_CORE_CAPABS_MSR 1 << 30
|
|
||||||
#define CPUID_EXTENDED_FEATURES_EDX_SSBD 1 << 31
|
|
||||||
|
|
||||||
//=========CPUID_EXTENDED_FEATURES_SL1=========
|
|
||||||
// bits 0-3 are reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_AVX_VNNI 1 << 4
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_AVX512_BF16 1 << 5
|
|
||||||
// bits 6-9 are reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_0_REP_MOVSB 1 << 10
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_FAST_STOSB 1 << 11
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_FAST_CMPSB 1 << 12
|
|
||||||
// bits 13-21 are reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_HRESET 1 << 22
|
|
||||||
// bits 23-19 are reserved
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_INVD_POSTPOST 1 << 30
|
|
||||||
// bit 31 is reserved
|
|
||||||
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL1_EBX_PPIN 1
|
|
||||||
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL1_EDX_CET_SSS 1 << 18
|
|
||||||
|
|
||||||
//=========CPUID_EXTENDED_FEATURES_SL2=========
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_PSFD 1
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_IPRED_CTRL 1 << 1
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_RRSBA_CTRL 1 << 2
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_DDPD_U 1 << 3
|
|
||||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_BHI_CTRL 1 << 4
|
|
||||||
// The rest of the bits are reserved
|
|
||||||
|
|
||||||
enum leaves {
|
|
||||||
/* @ Basic CPU info
|
|
||||||
* @ Returned EAX: Highest basic CPUID leaf present
|
|
||||||
* @ Returned EBX: First 4 letters of the vendor identifier string
|
|
||||||
* @ Returned ECX: Third 4 letters of the vendor identifier string
|
|
||||||
* @ Retruned EDX: Second 4 letters of the vendor identifier string
|
|
||||||
*/
|
|
||||||
CPUID_VENDOR = 0x00000000,
|
|
||||||
/* @ CPU Version information
|
|
||||||
* @ Returned EAX: Family,Model,Stepping
|
|
||||||
* @ Returned EBX: Brand Index,CLFLUSH line size, Max number of logical
|
|
||||||
* processors
|
|
||||||
* @ Returned ECX: Featrue information
|
|
||||||
* @ Retruned EDX: More feature information
|
|
||||||
*/
|
|
||||||
CPUID_CPU_INFO = 0x00000001,
|
|
||||||
/* @ CPU Cache and TLB information
|
|
||||||
* @ Returned EAX: 4 Cache, prefetch or TLB descriptors
|
|
||||||
* @ Returned EBX: 4 Cache, prefetch or TLB descriptors
|
|
||||||
* @ Returned ECX: 4 Cache, prefetch or TLB descriptors
|
|
||||||
* @ Retruned EDX: 4 Cache, prefetch or TLB descriptors
|
|
||||||
*/
|
|
||||||
CPUID_CACHE_TLB = 0x00000002,
|
|
||||||
/* @ CPU Serial Number !!! PENTIUM 3 ONLY !!!
|
|
||||||
* @ Returned EAX: Reserved
|
|
||||||
* @ Returned EBX: Reserved
|
|
||||||
* @ Returned ECX: bits 0-31 of the serial number
|
|
||||||
* @ Retruned EDX: bits 32-63 of the serial number
|
|
||||||
*/
|
|
||||||
CPUID_SERIAL_NUMBER = 0x00000003,
|
|
||||||
/* @ CPU Deterministic cache parameters !!! Initial ECX = Cache level !!!
|
|
||||||
* @ Returned EAX: Cache level,Is self init,Is fully associative,Maximum
|
|
||||||
* number of addressable IDs for logical processors sharing this cache
|
|
||||||
* @ Returned EBX: L, P and W
|
|
||||||
* @ Returned ECX: S
|
|
||||||
* @ Retruned EDX: Cache inclusiveness and Complex Cache indexing
|
|
||||||
*/
|
|
||||||
CPUID_CACHE_PARAMS = 0x00000004,
|
|
||||||
/* @ MONITOR/MWAIT params
|
|
||||||
* @ Returned EAX: Smallest monitor-line size
|
|
||||||
* @ Returned EBX: Largest monitor-line size
|
|
||||||
* @ Returned ECX: Enumeration of Monitor-Mwait extensions,Supports treating
|
|
||||||
* interrupts as break-event for MWAIT
|
|
||||||
* @ Retruned EDX: Number of sub C-states supported using MWAIT for each C
|
|
||||||
* number thingy IDK
|
|
||||||
*/
|
|
||||||
CPUID_MONITOR_MWAIT = 0x00000005,
|
|
||||||
/* @ Thermal and power managment
|
|
||||||
* @ Returned EAX: Thermal and power info
|
|
||||||
* @ Returned EBX: Thermal and power info
|
|
||||||
* @ Returned ECX: Thermal and power info
|
|
||||||
* @ Retruned EDX: Thermal and power info
|
|
||||||
*/
|
|
||||||
CPUID_THERMAL_AND_POWER = 0x00000006,
|
|
||||||
/* @ Extended features
|
|
||||||
* @ Returned EAX: Number of subleaves supported
|
|
||||||
* @ Returned EBX: Features
|
|
||||||
* @ Returned ECX: Features
|
|
||||||
* @ Retruned EDX: Features
|
|
||||||
*/
|
|
||||||
CPUID_EXTENDED_FEATURES = 0x00000007,
|
|
||||||
/* @ Direct Cache Access Information
|
|
||||||
* @ Returned EAX: Value of the MSR "IA32_PLATFORM_DCA_CAP"
|
|
||||||
* @ Returned EBX: Reserved
|
|
||||||
* @ Returned ECX: Reserved
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_CACHE_ACCESS_INFO = 0x00000009,
|
|
||||||
CPUID_PERFORMANCE_MONITORING = 0x0000000A,
|
|
||||||
CPUID_EXTENDENDED_TOPOLOGY = 0x0000000B,
|
|
||||||
CPUID_EXTENDENDED_TOPOLOGY2 = 0x0000000D,
|
|
||||||
CPUID_INTEL_RDT = 0x0000000F,
|
|
||||||
CPUID_INTEL_RDT2 = 0x00000010,
|
|
||||||
CPUID_INTEL_SGX = 0x00000012,
|
|
||||||
CPUID_CPU_TRACE_ENUM = 0x00000014,
|
|
||||||
CPUID_TSC = 0x00000015,
|
|
||||||
CPUID_CPU_FREQ_INFO = 0x00000016,
|
|
||||||
CPUID_SOC_VENDOR = 0x00000017,
|
|
||||||
CPUID_DETERMINISTIC_ADRESS_TRANSLATION_PARAMS = 0x00000018,
|
|
||||||
CPUID_KEY_LOCKER = 0x000000019,
|
|
||||||
CPUID_NATIVE_MODEL_ID = 0x0000001A,
|
|
||||||
CPUID_PCONFIG_INFO = 0x0000001B,
|
|
||||||
CPUID_LAST_BRACH = 0x00000001C,
|
|
||||||
CPUID_TILE_INFO = 0x00000001D,
|
|
||||||
CPUID_TMUL_INFO = 0x00000001E,
|
|
||||||
CPUID_V2_EXTENDED_TOPOLOGY = 0x00000001F,
|
|
||||||
CPUID_V2_EXTENDED_TOPOLOGY2 = 0x000000020,
|
|
||||||
// TODO: add the bitmasks for these Microsoft ones
|
|
||||||
/* @ Hypervisor CPUID Leaf Range
|
|
||||||
* @ Returned EAX: Highest hypervisor CPUID leaf present
|
|
||||||
* @ Returned EBX: Largest monitor-line size
|
|
||||||
* @ Returned ECX: Enumeration of Monitor-Mwait extensions,Supports treating
|
|
||||||
* interrupts as break-event for MWAIT
|
|
||||||
* @ Retruned EDX: Number of sub C-states supported using MWAIT for each C
|
|
||||||
* number thingy IDK
|
|
||||||
*/
|
|
||||||
CPUID_HYPERV_IDENT = 0x40000000,
|
|
||||||
/* @ Hypervisor Vendor-Neutral Interface Identification
|
|
||||||
* @ Returned EAX: Hypervisor interface signature
|
|
||||||
* @ Returned EBX: Reserved
|
|
||||||
* @ Returned ECX: Reserved
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_MS_HYPERV_INTERFCE_IDENT = 0x40000001,
|
|
||||||
/* @ Hypervisor System Identity
|
|
||||||
* @ Returned EAX: Build number
|
|
||||||
* @ Returned EBX: Major and minor version
|
|
||||||
* @ Returned ECX: Reserved
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_MS_HYPERV_SYSTEM_IDENT = 0x40000002,
|
|
||||||
/* @ Hypervisor Feature Identification
|
|
||||||
* @ Returned EAX: bits 0-31 of HV_PARTITION_PRIVILEGE_MASK
|
|
||||||
* @ Returned EBX: bits 31-63 of HV_PARTITION_PRIVILEGE_MASK
|
|
||||||
* @ Returned ECX: Hyper-V features
|
|
||||||
* @ Retruned EDX: Hyper-V features
|
|
||||||
*/
|
|
||||||
CPUID_MS_HYPERV_FEATURE_IDENT = 0x40000003,
|
|
||||||
/* @ Implementation Recommendations
|
|
||||||
* @ Returned EAX: Hyper-V feature recommendations
|
|
||||||
* @ Returned EBX: Hyper-V feature recommendations
|
|
||||||
* @ Returned ECX: Hyper-V feature recommendations
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_MS_HYPERV_RECOMMENDATIONS = 0x40000004,
|
|
||||||
/* @ Hypervisor Implementation Limits
|
|
||||||
* @ Returned EAX: The maximum number of virtual processors supported
|
|
||||||
* @ Returned EBX: The maximum number of logical processors supported
|
|
||||||
* @ Returned ECX: The maximum number of physical interrupt vectors available
|
|
||||||
* for interrupt remapping.
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_MS_HYPERV_IMPL_LIMITS = 0x40000005,
|
|
||||||
/* @ Implementation Hardware Features
|
|
||||||
* @ Returned EAX: Hardware features
|
|
||||||
* @ Returned EBX: Reserved
|
|
||||||
* @ Returned ECX: Reserved
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_MS_HYPERV_HARDWARE_FEATURES = 0x40000006,
|
|
||||||
/* @ Nested Hypervisor Feature Identification
|
|
||||||
* @ Returned EAX: Nested Hypervisor features
|
|
||||||
* @ Returned EBX: Reserved
|
|
||||||
* @ Returned ECX: Reserved
|
|
||||||
* @ Retruned EDX: Nested Hypervisor features
|
|
||||||
*/
|
|
||||||
CPUID_MS_HYPERV_NESTED_FEATURES = 0x40000009,
|
|
||||||
/* @ Nested Hypervisor Nested Virtualization Features
|
|
||||||
* @ Returned EAX: Nested Hypervisor features
|
|
||||||
* @ Returned EBX: Nested Hypervisor features
|
|
||||||
* @ Returned ECX: Reserved
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_MS_HYPERV_NESTED_OPTIMISATIONS = 0x4000000A,
|
|
||||||
/* @ Extended processor signature
|
|
||||||
* @ Returned EAX: Reserved
|
|
||||||
* @ Returned EBX: Reserved
|
|
||||||
* @ Returned ECX: Extended feature bits
|
|
||||||
* @ Retruned EDX: Extended feature bits
|
|
||||||
*/
|
|
||||||
CPUID_EXTENDED_SIGNATURE = 0x800000001,
|
|
||||||
/* @ Full CPU name
|
|
||||||
* @ Returned EAX: First 4 characters of the full CPU name
|
|
||||||
* @ Returned EBX: Second 4 characters of the full CPU name
|
|
||||||
* @ Returned ECX: Third 4 characters of the full CPU name
|
|
||||||
* @ Retruned EDX: Fourth 4 characters of the full CPU name
|
|
||||||
*/
|
|
||||||
CPUID_BRAND_STRING1 = 0x800000002,
|
|
||||||
/* @ Full CPU name 2
|
|
||||||
* @ Returned EAX: Fifth 4 characters of the full CPU name
|
|
||||||
* @ Returned EBX: Sexth 4 characters of the full CPU name
|
|
||||||
* @ Returned ECX: Seventh 4 characters of the full CPU name
|
|
||||||
* @ Retruned EDX: Eightth 4 characters of the full CPU name
|
|
||||||
*/
|
|
||||||
CPUID_BRAND_STRING2 = 0x800000003,
|
|
||||||
/* @ Full CPU name 3
|
|
||||||
* @ Returned EAX: Nineth 4 characters of the full CPU name
|
|
||||||
* @ Returned EBX: Tenth 4 characters of the full CPU name
|
|
||||||
* @ Returned ECX: Eleventh 4 characters of the full CPU name
|
|
||||||
* @ Retruned EDX: Twelveth 4 characters of the full CPU name
|
|
||||||
*/
|
|
||||||
CPUID_BRAND_STRING3 = 0x800000004,
|
|
||||||
/* @ Cache line size and associativity
|
|
||||||
* @ Returned EAX: Reserved
|
|
||||||
* @ Returned EBX: Reserved
|
|
||||||
* @ Returned ECX: Bits 0-7 = Cache line size in bytes, Bits 12-15 = L2
|
|
||||||
* Associativity, Bits 16-31 = Cache size in 1K blocks
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_MORE_CACHE = 0x800000006,
|
|
||||||
/* @ Invariant TSC available
|
|
||||||
* @ Returned EAX: Reserved
|
|
||||||
* @ Returned EBX: Reserved
|
|
||||||
* @ Returned ECX: Bit 8 = Invariant TSC available
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_INVARIANT_TSC_AVAILABLE = 0x800000007,
|
|
||||||
/* @ Physical adress size
|
|
||||||
* @ Returned EAX: Bits 0-7 = Physical Adress bits, Bits 8-15 = Linear
|
|
||||||
* Address bits
|
|
||||||
* @ Returned EBX: Bit 9 = WBNOINVD available
|
|
||||||
* @ Returned ECX: Reserved
|
|
||||||
* @ Retruned EDX: Reserved
|
|
||||||
*/
|
|
||||||
CPUID_PHYS_ADDR_SIZE = 0x800000008,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum sub_leaves {
|
|
||||||
/* @ Extended features available subleaf 1 !!! All fields return 0 is info not
|
|
||||||
* available !!!
|
|
||||||
* @ Returned EAX: Features
|
|
||||||
* @ Returned EBX: PPIN
|
|
||||||
* @ Returned ECX: Reserved
|
|
||||||
* @ Retruned EDX: CET_SSS
|
|
||||||
*/
|
|
||||||
CPUID_EXTENDED_FEATURES_SL1 = 0x00000001,
|
|
||||||
/* @ Extended features available subleaf 2 !!! All fields return 0 is info not
|
|
||||||
* available !!!
|
|
||||||
* @ Returned EAX: Reserved
|
|
||||||
* @ Returned EBX: Reserved
|
|
||||||
* @ Returned ECX: Reserved
|
|
||||||
* @ Retruned EDX: Features
|
|
||||||
*/
|
|
||||||
CPUID_EXTENDED_FEATURES_SL2 = 0x00000002,
|
|
||||||
CPUID_INTEL_RDT_CAPABILITY = 0x00000001,
|
|
||||||
CPUID_INTEL_RDT2_ALLOCATION = 0x00000000,
|
|
||||||
CPUID_INTEL_RDT2_RESID1 = 0x00000001,
|
|
||||||
CPUID_INTEL_RDT2_RESID2 = 0x00000002,
|
|
||||||
CPUID_INTEL_RDT2_RESID3 = 0x00000003,
|
|
||||||
CPUID_INTEL_SGX_SL1 = 0x00000001,
|
|
||||||
CPUID_INTEL_SGX_SL2 = 0x00000002,
|
|
||||||
CPUID_CPU_TRACE_ENUM_SL = 0x00000001,
|
|
||||||
CPUID_SOC_VENDOR_SL1 = 0x00000001,
|
|
||||||
CPUID_SOC_VENDOR_SL2 = 0x00000002,
|
|
||||||
CPUID_SOC_VENDOR_SL3 = 0x00000003,
|
|
||||||
// NOTE: goes higher than 1
|
|
||||||
CPUID_DETERMINISTIC_ADRESS_TRANSLATION_PARAMS_SL = 0x00000001,
|
|
||||||
CPUID_TILE_INFO_PALETTE1 = 0x000000001,
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void cpuid(int leaf, int subleaf, int *a, int *b, int *c,
|
|
||||||
int *d) {
|
|
||||||
__asm__ __volatile__("cpuid"
|
|
||||||
: "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d)
|
|
||||||
: "a"(leaf), "c"(subleaf));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __CPUID_H__
|
|
|
@ -1,12 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
void fpu_set_cw(const uint16_t cw) { asm volatile("fldcw %0" ::"m"(cw)); }
|
|
||||||
|
|
||||||
void fpu_activate() {
|
|
||||||
size_t cr4;
|
|
||||||
asm volatile("mov %%cr4, %0" : "=r"(cr4));
|
|
||||||
cr4 |= 0x200;
|
|
||||||
asm volatile("mov %0, %%cr4" ::"r"(cr4));
|
|
||||||
fpu_set_cw(0x37F);
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
void fpu_set_cw(const uint16_t cw);
|
|
||||||
void fpu_activate();
|
|
26
kernel/src/arch/x86_64/gdt.asm
Executable file
26
kernel/src/arch/x86_64/gdt.asm
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
;
|
||||||
|
; The Soaplin Kernel
|
||||||
|
; Copyright (C) 2025 The SILD Project
|
||||||
|
;
|
||||||
|
; gdt.asm - Utility for reloading the segments.
|
||||||
|
|
||||||
|
bits 64
|
||||||
|
|
||||||
|
section .text
|
||||||
|
global gdt_reload_segments
|
||||||
|
|
||||||
|
gdt_reload_segments:
|
||||||
|
; Reload CS register:
|
||||||
|
PUSH 0x08 ; Push code segment to stack, 0x08 is a stand-in for your code segment
|
||||||
|
LEA RAX, [rel .reload_CS] ; Load address of .reload_CS into RAX
|
||||||
|
PUSH RAX ; Push this value to the stack
|
||||||
|
RETFQ ; Perform a far return, RETFQ or LRETQ depending on syntax
|
||||||
|
.reload_CS:
|
||||||
|
; Reload data segment registers
|
||||||
|
MOV AX, 0x10 ; 0x10 is a stand-in for your data segment
|
||||||
|
MOV DS, AX
|
||||||
|
MOV ES, AX
|
||||||
|
MOV FS, AX
|
||||||
|
MOV GS, AX
|
||||||
|
MOV SS, AX
|
||||||
|
RET
|
83
kernel/src/arch/x86_64/gdt.c
Normal file → Executable file
83
kernel/src/arch/x86_64/gdt.c
Normal file → Executable file
|
@ -1,51 +1,58 @@
|
||||||
// #include "sys/log.h"
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* gdt.c - x86_64 Global Descriptor Table implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib/log.h"
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <arch/x86_64/gdt.h>
|
#include <arch/x86_64/gdt.h>
|
||||||
#include <mm/memop.h>
|
#include <mm/memop.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
|
|
||||||
gdt_table def_table = {{
|
gdt_table gdt = {{
|
||||||
0x0000000000000000, // 0x00
|
0x0000000000000000, // 0x0, null
|
||||||
|
|
||||||
0x00009a000000ffff, // 0x08 16 bit code
|
0x00af9b000000ffff, // 0x8, 64-bit code
|
||||||
0x000093000000ffff, // 0x10 16 bit data
|
0x00af93000000ffff, // 0x10, 64-bit data
|
||||||
|
|
||||||
0x00cf9a000000ffff, // 0x18 32 bit code
|
0x00affb000000ffff, // 0x18, usermode 64-bit code
|
||||||
0x00cf93000000ffff, // 0x20 32 bit data
|
0x00aff3000000ffff // 0x20, usermode 64-bit data
|
||||||
|
}, {}};
|
||||||
|
|
||||||
0x00af9b000000ffff, // 0x28 64 bit code cs
|
tssr tss_list[255];
|
||||||
0x00af93000000ffff, // 0x30 64 bit data ss
|
static uint64_t __gdt_kstack[4096];
|
||||||
|
|
||||||
0x00aff3000000ffff, // 0x38 user mode data ss
|
extern void gdt_reload_segments();
|
||||||
0x00affb000000ffff, // 0x40 user mode code cs
|
|
||||||
},
|
|
||||||
{}};
|
|
||||||
|
|
||||||
tssr tss_list[256]; // One tssr per CPU
|
void gdt_init() {
|
||||||
|
memset(&tss_list[0], 0, sizeof(tssr));
|
||||||
|
tss_list[0].rsp[0] = (uint64_t)__gdt_kstack;
|
||||||
|
tss_list[0].iopb = sizeof(tssr);
|
||||||
|
uintptr_t tss = (uintptr_t)&tss_list[0];
|
||||||
|
|
||||||
void gdt_init(char *kstack) {
|
gdt.tss_entry = (tss_entry){
|
||||||
|
.length = sizeof(tss_entry),
|
||||||
|
.base = (uint16_t)(tss & 0xFFFF),
|
||||||
|
.base1 = (uint8_t)((tss >> 16) & 0xFF),
|
||||||
|
.flags = 0x89,
|
||||||
|
.flags1 = 0,
|
||||||
|
.base2 = (uint8_t)((tss >> 24) & 0xFF),
|
||||||
|
.base3 = (uint32_t)(tss >> 32),
|
||||||
|
.resv = 0,
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: adapt for multiprocessor kernel
|
gdtr gdtr = {
|
||||||
memset(&tss_list[0], 0, sizeof(tssr));
|
.size = (sizeof(gdt_table)) - 1,
|
||||||
tss_list[0].rsp[0] = (uint64_t)kstack;
|
.address = (uint64_t)&gdt
|
||||||
tss_list[0].iopb = sizeof(tssr);
|
};
|
||||||
uintptr_t tss = (uintptr_t)&tss_list[0];
|
|
||||||
|
|
||||||
def_table.tss_entry.length = sizeof(tss_entry);
|
__asm__ volatile("lgdt %0\n\t" : : "m"(gdtr) : "memory");
|
||||||
def_table.tss_entry.base = (uint16_t)(tss & 0xffff);
|
__asm__ volatile("ltr %0\n\t" : : "r"((uint16_t)0x28)); // 0x20 (last GDT entry) + 0x8 (size of a GDT entry)
|
||||||
def_table.tss_entry.base1 = (uint8_t)((tss >> 16) & 0xff);
|
|
||||||
def_table.tss_entry.flags = 0x89;
|
|
||||||
def_table.tss_entry.flags1 = 0;
|
|
||||||
def_table.tss_entry.base2 = (uint8_t)((tss >> 24) & 0xff);
|
|
||||||
def_table.tss_entry.base3 = (uint32_t)(tss >> 32);
|
|
||||||
def_table.tss_entry.resv = 0;
|
|
||||||
|
|
||||||
gdtr gdt =
|
gdt_reload_segments();
|
||||||
(gdtr){.size = (sizeof(gdt_table)) - 1, .address = (uint64_t)&def_table};
|
}
|
||||||
|
|
||||||
__asm__ volatile("lgdt %0\n\t" : : "m"(gdt) : "memory");
|
#endif
|
||||||
__asm__ volatile("ltr %0\n\t" : : "r"((uint16_t)0x48));
|
|
||||||
|
|
||||||
// logln(progress, "kinit stage 1", "GDT initialized\n");
|
|
||||||
log("gdt - initialized.\n");
|
|
||||||
}
|
|
17
kernel/src/arch/x86_64/gdt.h
Normal file → Executable file
17
kernel/src/arch/x86_64/gdt.h
Normal file → Executable file
|
@ -1,8 +1,15 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* gdt.h - x86_64 Global Descriptor Table definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct tss_entry {
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
uint16_t base;
|
uint16_t base;
|
||||||
uint8_t base1;
|
uint8_t base1;
|
||||||
|
@ -14,8 +21,8 @@ typedef struct {
|
||||||
} __attribute__((packed)) tss_entry;
|
} __attribute__((packed)) tss_entry;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t gdt_entries[9];
|
uint64_t entries[5];
|
||||||
tss_entry tss_entry;
|
struct tss_entry tss_entry;
|
||||||
} __attribute__((packed)) gdt_table;
|
} __attribute__((packed)) gdt_table;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -31,6 +38,6 @@ typedef struct {
|
||||||
uint64_t resv2;
|
uint64_t resv2;
|
||||||
uint16_t resv3;
|
uint16_t resv3;
|
||||||
uint16_t iopb;
|
uint16_t iopb;
|
||||||
} __attribute__((packed)) tssr; // Per CPU
|
} __attribute__((packed)) tssr; // 1 TSSR per CPU.
|
||||||
|
|
||||||
void gdt_init(char *kstack);
|
void gdt_init();
|
|
@ -1,3 +1,10 @@
|
||||||
|
;
|
||||||
|
; The Soaplin Kernel
|
||||||
|
; Copyright (C) 2025 The SILD Project
|
||||||
|
;
|
||||||
|
; idt.asm - Defines the handler for IDT entries.
|
||||||
|
;
|
||||||
|
|
||||||
%macro pushall 0
|
%macro pushall 0
|
||||||
push rax
|
push rax
|
||||||
push rcx
|
push rcx
|
||||||
|
@ -36,13 +43,11 @@
|
||||||
|
|
||||||
%macro isr_err_stub 1
|
%macro isr_err_stub 1
|
||||||
isr_stub_%+%1:
|
isr_stub_%+%1:
|
||||||
|
|
||||||
push %1
|
push %1
|
||||||
pushall
|
pushall
|
||||||
|
mov rdi, rsp
|
||||||
mov rdi, rsp
|
|
||||||
|
call idt_interrupt_handler
|
||||||
call idt_int_handler
|
|
||||||
|
|
||||||
popall
|
popall
|
||||||
|
|
||||||
|
@ -52,13 +57,14 @@ isr_stub_%+%1:
|
||||||
|
|
||||||
%macro isr_no_err_stub 1
|
%macro isr_no_err_stub 1
|
||||||
isr_stub_%+%1:
|
isr_stub_%+%1:
|
||||||
push 0
|
push 0 ; push the error code (0) into the stack
|
||||||
push %1
|
push %1 ; push intno into the stack
|
||||||
|
|
||||||
pushall
|
pushall
|
||||||
|
|
||||||
mov rdi, rsp
|
mov rdi, rsp ; put the stack as the first arg.
|
||||||
|
|
||||||
call idt_int_handler
|
call idt_interrupt_handler
|
||||||
|
|
||||||
popall
|
popall
|
||||||
|
|
||||||
|
@ -66,7 +72,7 @@ isr_stub_%+%1:
|
||||||
iretq
|
iretq
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
extern idt_int_handler
|
extern idt_interrupt_handler
|
||||||
isr_no_err_stub 0
|
isr_no_err_stub 0
|
||||||
isr_no_err_stub 1
|
isr_no_err_stub 1
|
||||||
isr_no_err_stub 2
|
isr_no_err_stub 2
|
||||||
|
@ -100,236 +106,17 @@ isr_no_err_stub 29
|
||||||
isr_err_stub 30
|
isr_err_stub 30
|
||||||
isr_no_err_stub 31
|
isr_no_err_stub 31
|
||||||
|
|
||||||
|
%assign i 32
|
||||||
|
%rep 224
|
||||||
|
isr_no_err_stub i
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
|
||||||
isr_no_err_stub 32
|
|
||||||
isr_no_err_stub 33
|
|
||||||
isr_no_err_stub 34
|
|
||||||
isr_no_err_stub 35
|
|
||||||
isr_no_err_stub 36
|
|
||||||
isr_no_err_stub 37
|
|
||||||
isr_no_err_stub 38
|
|
||||||
isr_no_err_stub 39
|
|
||||||
isr_no_err_stub 40
|
|
||||||
isr_no_err_stub 41
|
|
||||||
isr_no_err_stub 42
|
|
||||||
isr_no_err_stub 43
|
|
||||||
isr_no_err_stub 44
|
|
||||||
isr_no_err_stub 45
|
|
||||||
isr_no_err_stub 46
|
|
||||||
isr_no_err_stub 47
|
|
||||||
isr_no_err_stub 48
|
|
||||||
isr_no_err_stub 49
|
|
||||||
isr_no_err_stub 50
|
|
||||||
isr_no_err_stub 51
|
|
||||||
isr_no_err_stub 52
|
|
||||||
isr_no_err_stub 53
|
|
||||||
isr_no_err_stub 54
|
|
||||||
isr_no_err_stub 55
|
|
||||||
isr_no_err_stub 56
|
|
||||||
isr_no_err_stub 57
|
|
||||||
isr_no_err_stub 58
|
|
||||||
isr_no_err_stub 59
|
|
||||||
isr_no_err_stub 60
|
|
||||||
isr_no_err_stub 61
|
|
||||||
isr_no_err_stub 62
|
|
||||||
isr_no_err_stub 63
|
|
||||||
isr_no_err_stub 64
|
|
||||||
isr_no_err_stub 65
|
|
||||||
isr_no_err_stub 66
|
|
||||||
isr_no_err_stub 67
|
|
||||||
isr_no_err_stub 68
|
|
||||||
isr_no_err_stub 69
|
|
||||||
isr_no_err_stub 70
|
|
||||||
isr_no_err_stub 71
|
|
||||||
isr_no_err_stub 72
|
|
||||||
isr_no_err_stub 73
|
|
||||||
isr_no_err_stub 74
|
|
||||||
isr_no_err_stub 75
|
|
||||||
isr_no_err_stub 76
|
|
||||||
isr_no_err_stub 77
|
|
||||||
isr_no_err_stub 78
|
|
||||||
isr_no_err_stub 79
|
|
||||||
isr_no_err_stub 80
|
|
||||||
isr_no_err_stub 81
|
|
||||||
isr_no_err_stub 82
|
|
||||||
isr_no_err_stub 83
|
|
||||||
isr_no_err_stub 84
|
|
||||||
isr_no_err_stub 85
|
|
||||||
isr_no_err_stub 86
|
|
||||||
isr_no_err_stub 87
|
|
||||||
isr_no_err_stub 88
|
|
||||||
isr_no_err_stub 89
|
|
||||||
isr_no_err_stub 90
|
|
||||||
isr_no_err_stub 91
|
|
||||||
isr_no_err_stub 92
|
|
||||||
isr_no_err_stub 93
|
|
||||||
isr_no_err_stub 94
|
|
||||||
isr_no_err_stub 95
|
|
||||||
isr_no_err_stub 96
|
|
||||||
isr_no_err_stub 97
|
|
||||||
isr_no_err_stub 98
|
|
||||||
isr_no_err_stub 99
|
|
||||||
isr_no_err_stub 100
|
|
||||||
isr_no_err_stub 101
|
|
||||||
isr_no_err_stub 102
|
|
||||||
isr_no_err_stub 103
|
|
||||||
isr_no_err_stub 104
|
|
||||||
isr_no_err_stub 105
|
|
||||||
isr_no_err_stub 106
|
|
||||||
isr_no_err_stub 107
|
|
||||||
isr_no_err_stub 108
|
|
||||||
isr_no_err_stub 109
|
|
||||||
isr_no_err_stub 110
|
|
||||||
isr_no_err_stub 111
|
|
||||||
isr_no_err_stub 112
|
|
||||||
isr_no_err_stub 113
|
|
||||||
isr_no_err_stub 114
|
|
||||||
isr_no_err_stub 115
|
|
||||||
isr_no_err_stub 116
|
|
||||||
isr_no_err_stub 117
|
|
||||||
isr_no_err_stub 118
|
|
||||||
isr_no_err_stub 119
|
|
||||||
isr_no_err_stub 120
|
|
||||||
isr_no_err_stub 121
|
|
||||||
isr_no_err_stub 122
|
|
||||||
isr_no_err_stub 123
|
|
||||||
isr_no_err_stub 124
|
|
||||||
isr_no_err_stub 125
|
|
||||||
isr_no_err_stub 126
|
|
||||||
isr_no_err_stub 127
|
|
||||||
isr_no_err_stub 128
|
|
||||||
isr_no_err_stub 129
|
|
||||||
isr_no_err_stub 130
|
|
||||||
isr_no_err_stub 131
|
|
||||||
isr_no_err_stub 132
|
|
||||||
isr_no_err_stub 133
|
|
||||||
isr_no_err_stub 134
|
|
||||||
isr_no_err_stub 135
|
|
||||||
isr_no_err_stub 136
|
|
||||||
isr_no_err_stub 137
|
|
||||||
isr_no_err_stub 138
|
|
||||||
isr_no_err_stub 139
|
|
||||||
isr_no_err_stub 140
|
|
||||||
isr_no_err_stub 141
|
|
||||||
isr_no_err_stub 142
|
|
||||||
isr_no_err_stub 143
|
|
||||||
isr_no_err_stub 144
|
|
||||||
isr_no_err_stub 145
|
|
||||||
isr_no_err_stub 146
|
|
||||||
isr_no_err_stub 147
|
|
||||||
isr_no_err_stub 148
|
|
||||||
isr_no_err_stub 149
|
|
||||||
isr_no_err_stub 150
|
|
||||||
isr_no_err_stub 151
|
|
||||||
isr_no_err_stub 152
|
|
||||||
isr_no_err_stub 153
|
|
||||||
isr_no_err_stub 154
|
|
||||||
isr_no_err_stub 155
|
|
||||||
isr_no_err_stub 156
|
|
||||||
isr_no_err_stub 157
|
|
||||||
isr_no_err_stub 158
|
|
||||||
isr_no_err_stub 159
|
|
||||||
isr_no_err_stub 160
|
|
||||||
isr_no_err_stub 161
|
|
||||||
isr_no_err_stub 162
|
|
||||||
isr_no_err_stub 163
|
|
||||||
isr_no_err_stub 164
|
|
||||||
isr_no_err_stub 165
|
|
||||||
isr_no_err_stub 166
|
|
||||||
isr_no_err_stub 167
|
|
||||||
isr_no_err_stub 168
|
|
||||||
isr_no_err_stub 169
|
|
||||||
isr_no_err_stub 170
|
|
||||||
isr_no_err_stub 171
|
|
||||||
isr_no_err_stub 172
|
|
||||||
isr_no_err_stub 173
|
|
||||||
isr_no_err_stub 174
|
|
||||||
isr_no_err_stub 175
|
|
||||||
isr_no_err_stub 176
|
|
||||||
isr_no_err_stub 177
|
|
||||||
isr_no_err_stub 178
|
|
||||||
isr_no_err_stub 179
|
|
||||||
isr_no_err_stub 180
|
|
||||||
isr_no_err_stub 181
|
|
||||||
isr_no_err_stub 182
|
|
||||||
isr_no_err_stub 183
|
|
||||||
isr_no_err_stub 184
|
|
||||||
isr_no_err_stub 185
|
|
||||||
isr_no_err_stub 186
|
|
||||||
isr_no_err_stub 187
|
|
||||||
isr_no_err_stub 188
|
|
||||||
isr_no_err_stub 189
|
|
||||||
isr_no_err_stub 190
|
|
||||||
isr_no_err_stub 191
|
|
||||||
isr_no_err_stub 192
|
|
||||||
isr_no_err_stub 193
|
|
||||||
isr_no_err_stub 194
|
|
||||||
isr_no_err_stub 195
|
|
||||||
isr_no_err_stub 196
|
|
||||||
isr_no_err_stub 197
|
|
||||||
isr_no_err_stub 198
|
|
||||||
isr_no_err_stub 199
|
|
||||||
isr_no_err_stub 200
|
|
||||||
isr_no_err_stub 201
|
|
||||||
isr_no_err_stub 202
|
|
||||||
isr_no_err_stub 203
|
|
||||||
isr_no_err_stub 204
|
|
||||||
isr_no_err_stub 205
|
|
||||||
isr_no_err_stub 206
|
|
||||||
isr_no_err_stub 207
|
|
||||||
isr_no_err_stub 208
|
|
||||||
isr_no_err_stub 209
|
|
||||||
isr_no_err_stub 210
|
|
||||||
isr_no_err_stub 211
|
|
||||||
isr_no_err_stub 212
|
|
||||||
isr_no_err_stub 213
|
|
||||||
isr_no_err_stub 214
|
|
||||||
isr_no_err_stub 215
|
|
||||||
isr_no_err_stub 216
|
|
||||||
isr_no_err_stub 217
|
|
||||||
isr_no_err_stub 218
|
|
||||||
isr_no_err_stub 219
|
|
||||||
isr_no_err_stub 220
|
|
||||||
isr_no_err_stub 221
|
|
||||||
isr_no_err_stub 222
|
|
||||||
isr_no_err_stub 223
|
|
||||||
isr_no_err_stub 224
|
|
||||||
isr_no_err_stub 225
|
|
||||||
isr_no_err_stub 226
|
|
||||||
isr_no_err_stub 227
|
|
||||||
isr_no_err_stub 228
|
|
||||||
isr_no_err_stub 229
|
|
||||||
isr_no_err_stub 230
|
|
||||||
isr_no_err_stub 231
|
|
||||||
isr_no_err_stub 232
|
|
||||||
isr_no_err_stub 233
|
|
||||||
isr_no_err_stub 234
|
|
||||||
isr_no_err_stub 235
|
|
||||||
isr_no_err_stub 236
|
|
||||||
isr_no_err_stub 237
|
|
||||||
isr_no_err_stub 238
|
|
||||||
isr_no_err_stub 239
|
|
||||||
isr_no_err_stub 240
|
|
||||||
isr_no_err_stub 241
|
|
||||||
isr_no_err_stub 242
|
|
||||||
isr_no_err_stub 243
|
|
||||||
isr_no_err_stub 244
|
|
||||||
isr_no_err_stub 245
|
|
||||||
isr_no_err_stub 246
|
|
||||||
isr_no_err_stub 247
|
|
||||||
isr_no_err_stub 248
|
|
||||||
isr_no_err_stub 249
|
|
||||||
isr_no_err_stub 250
|
|
||||||
isr_no_err_stub 251
|
|
||||||
isr_no_err_stub 252
|
|
||||||
isr_no_err_stub 253
|
|
||||||
isr_no_err_stub 254
|
|
||||||
isr_no_err_stub 255
|
|
||||||
|
|
||||||
global isr_stub_table
|
global isr_stub_table
|
||||||
isr_stub_table:
|
isr_stub_table:
|
||||||
%assign i 0
|
%assign i 0
|
||||||
%rep 256
|
%rep 256
|
||||||
dq isr_stub_%+i ; use DQ instead if targeting 64-bit
|
dq isr_stub_%+i
|
||||||
%assign i i+1
|
%assign i i+1
|
||||||
%endrep
|
%endrep
|
161
kernel/src/arch/x86_64/idt.c
Normal file → Executable file
161
kernel/src/arch/x86_64/idt.c
Normal file → Executable file
|
@ -1,94 +1,111 @@
|
||||||
// #include "sys/log.h"
|
/*
|
||||||
#include "arch/x86_64/smp.h"
|
* The Soaplin Kernel
|
||||||
#include "dev/ioapic.h"
|
* Copyright (C) 2025 The SILD Project
|
||||||
#include "dev/lapic.h"
|
*
|
||||||
#include "mm/vmm.h"
|
* idt.c - x86_64 Interrupt Descriptor Table implementation.
|
||||||
#include "sys/errhnd/panic.h"
|
*/
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
#include <arch/x86_64/idt.h>
|
#include <arch/x86_64/idt.h>
|
||||||
#include <stdbool.h>
|
#include <arch/x86_64/smp.h>
|
||||||
#include <sys/log.h>
|
#include <arch/x86_64/ioapic.h>
|
||||||
#include <sched/sched.h>
|
#include "arch/x86_64/lapic.h"
|
||||||
|
#include <lib/log.h>
|
||||||
__attribute__((aligned(0x10))) static idt_entry_t idt[256];
|
|
||||||
|
|
||||||
|
__attribute__((aligned(0x10)))
|
||||||
|
static idt_entry_t idt[256];
|
||||||
static idtr_t idtr;
|
static idtr_t idtr;
|
||||||
static int vectors[256];
|
|
||||||
extern void *isr_stub_table[];
|
|
||||||
idt_irq_handler_t irq_handler_table[256 - 32];
|
|
||||||
|
|
||||||
void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags) {
|
static uint8_t __idt_vectors[256];
|
||||||
idt_entry_t *descriptor = &idt[vector];
|
static interrupt_handler __idt_external_handlers[256];
|
||||||
|
|
||||||
descriptor->isr_low = (uint64_t)isr & 0xFFFF;
|
void idt_register_handler(uint8_t vector, void *isr) {
|
||||||
descriptor->kernel_cs = 0x28;
|
if (vector <= 16)
|
||||||
descriptor->ist = 0;
|
ioapic_redir_irq(bootstrap_lapic_id, vector + 32, vector, false);
|
||||||
descriptor->attributes = flags;
|
|
||||||
descriptor->isr_mid = ((uint64_t)isr >> 16) & 0xFFFF;
|
__idt_external_handlers[vector] = isr;
|
||||||
descriptor->isr_high = ((uint64_t)isr >> 32) & 0xFFFFFFFF;
|
__idt_vectors[vector <= 16 ? vector + 32 : vector] = vector <= 16 ? VT_HWI : VT_SWI;
|
||||||
descriptor->reserved = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_register_irq(uint8_t vector, void *isr) {
|
void idt_interrupt_handler(registers_t *regs) {
|
||||||
if (vector <= 14)
|
if (__idt_vectors[regs->int_no] == VT_SPURIOUS || __idt_vectors[regs->int_no] == VT_NONE)
|
||||||
ioapic_redirect_irq(bootstrap_lapic_id, vector + 32, vector, false);
|
return;
|
||||||
|
|
||||||
irq_handler_table[vector] = isr;
|
if (regs->int_no < 32) {
|
||||||
vectors[vector <= 14 ? vector + 32 : vector] = IDT_VT_IRQ;
|
fatal("Kernel panic: CPU exception %d\n", regs->int_no);
|
||||||
|
fatal("rax: %p, rbx: %p, rbp: %p, rdx\n", regs->rax, regs->rbx, regs->rbp, regs->rdx);
|
||||||
|
fatal("rdi: %p, rsi: %p, rcx: %p\n", regs->rdi, regs->rsi, regs->rcx);
|
||||||
|
fatal("r8: %p, r9: %p, r10: %p\n", regs->r8, regs->r8, regs->r10);
|
||||||
|
fatal("r11: %p, r12: %p, r13: %p\n", regs->r11, regs->r12, regs->r13);
|
||||||
|
fatal("r14: %p, r15: %p\n", regs->r14, regs->r15);
|
||||||
|
fatal("rip: %p, cs: %p, ss: %p\n", regs->rip, regs->cs, regs->ss);
|
||||||
|
fatal("rflags: %p, err: %d, rsp: %p\n", regs->rflags, regs->err_code, regs->rsp);
|
||||||
|
hcf();
|
||||||
|
}
|
||||||
|
|
||||||
|
int vec = regs->int_no;
|
||||||
|
if (vec >= 32 && vec < 48)
|
||||||
|
vec -= 32;
|
||||||
|
|
||||||
|
if (__idt_vectors[regs->int_no] == VT_HWI) {
|
||||||
|
interrupt_handler i = __idt_external_handlers[vec];
|
||||||
|
i(regs);
|
||||||
|
} else if (__idt_vectors[regs->int_no] == VT_SWI) {
|
||||||
|
interrupt_handler i = __idt_external_handlers[regs->int_no];
|
||||||
|
i(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
lapic_eoi();
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags) {
|
||||||
|
idt_entry_t* descriptor = &idt[vector];
|
||||||
|
|
||||||
|
descriptor->isr_low = (uint64_t)isr & 0xFFFF;
|
||||||
|
descriptor->kernel_cs = 0x08;
|
||||||
|
descriptor->ist = 0;
|
||||||
|
descriptor->attributes = flags;
|
||||||
|
descriptor->isr_mid = ((uint64_t)isr >> 16) & 0xFFFF;
|
||||||
|
descriptor->isr_high = ((uint64_t)isr >> 32) & 0xFFFFFFFF;
|
||||||
|
descriptor->reserved = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern void* isr_stub_table[];
|
||||||
|
|
||||||
|
void idt_load() {
|
||||||
|
__asm__ volatile ("lidt %0" : : "m"(idtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_init() {
|
void idt_init() {
|
||||||
idtr.base = (uintptr_t)&idt[0];
|
idtr.base = (uintptr_t)&idt[0];
|
||||||
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1;
|
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1;
|
||||||
|
|
||||||
for (uint16_t vector = 0; vector < 32; vector++) {
|
for (uint8_t vector = 0; vector < 32; vector++) {
|
||||||
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||||
vectors[vector] = IDT_VT_EXCEPTION;
|
__idt_vectors[vector] = VT_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
trace("idt: Exception vectors has been set!\n");
|
||||||
|
|
||||||
for (uint16_t vector = 32; vector < 256; vector++) {
|
for (uint8_t vector = 32; vector < 48; vector++) {
|
||||||
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||||
vectors[vector] = IDT_VT_UNDEFINED;
|
__idt_vectors[vector] = VT_HWI;
|
||||||
}
|
}
|
||||||
|
trace("idt: Hardware interrupt vectors has been set!\n");
|
||||||
|
for (uint16_t vector = 48; vector < 256; vector++) {
|
||||||
|
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||||
|
__idt_vectors[vector] = VT_NONE;
|
||||||
|
}
|
||||||
|
__idt_vectors[IDT_SPURIOUS_INT] = VT_SPURIOUS;
|
||||||
|
trace("idt: Spurious interrupt vector has been set!\n");
|
||||||
|
|
||||||
// Do not use the legacy PIC.
|
//__asm__ volatile ("sti");
|
||||||
// pic_init();
|
idt_load();
|
||||||
// pic_unmask_irq(1);
|
trace("arch: IDT loaded successfully\n");
|
||||||
// pic_unmask_irq(8);
|
|
||||||
|
|
||||||
__asm__ volatile("lidt %0" : : "m"(idtr)); // load the new IDT
|
|
||||||
__asm__ volatile("sti"); // set the interrupt flag
|
|
||||||
|
|
||||||
log("idt - initialized\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_int_handler(registers_t *regs) {
|
#endif
|
||||||
vmm_load_pagemap(vmm_kernel_pm);
|
|
||||||
// log("kernel - Interrupt %d\n", regs->int_no);
|
|
||||||
|
|
||||||
if (regs->int_no < 32) {
|
|
||||||
if (regs->cs == 0x43) {
|
|
||||||
log("ints - Process \"%s\" (pid: %d) caused a CPU fault: %d (err: %d, IP: %p)\n",
|
|
||||||
curr_proc->name, curr_proc->pid, regs->int_no, regs->err_code, regs->rip);
|
|
||||||
|
|
||||||
sched_exit(-144);
|
|
||||||
return;
|
|
||||||
//asm("cli");
|
|
||||||
//while (1)
|
|
||||||
// asm("hlt");
|
|
||||||
}
|
|
||||||
|
|
||||||
panic_ctx("A CPU exception occured.", regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int vec = regs->int_no;
|
|
||||||
if (vec >= 32 && vec < 47)
|
|
||||||
vec -= 32;
|
|
||||||
|
|
||||||
if (vectors[regs->int_no] == IDT_VT_IRQ) {
|
|
||||||
idt_irq_handler_t i = irq_handler_table[vec];
|
|
||||||
i(regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
lapic_eoi();
|
|
||||||
// pic_ack(regs->int_no - 32);
|
|
||||||
}
|
|
51
kernel/src/arch/x86_64/idt.h
Normal file → Executable file
51
kernel/src/arch/x86_64/idt.h
Normal file → Executable file
|
@ -1,11 +1,20 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* idt.h - x86_64 Interrupt Descriptor Table declarations.
|
||||||
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// VT = Vector type
|
#define VT_NONE 0
|
||||||
#define IDT_VT_UNDEFINED 0
|
#define VT_EXCEPTION 1
|
||||||
#define IDT_VT_EXCEPTION 1
|
#define VT_HWI 2
|
||||||
#define IDT_VT_IRQ 2
|
#define VT_SWI 3
|
||||||
|
#define VT_SPURIOUS 4
|
||||||
|
|
||||||
|
#define IDT_SPURIOUS_INT 0xFF
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t r15;
|
uint64_t r15;
|
||||||
|
@ -32,31 +41,23 @@ typedef struct {
|
||||||
uint64_t ss;
|
uint64_t ss;
|
||||||
} __attribute__((packed)) registers_t;
|
} __attribute__((packed)) registers_t;
|
||||||
|
|
||||||
typedef struct stackframe {
|
typedef void(*interrupt_handler)(registers_t*);
|
||||||
struct stackframe *rbp;
|
|
||||||
uint64_t rip;
|
|
||||||
} stackframe_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
uint16_t isr_low;
|
||||||
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS
|
uint16_t kernel_cs;
|
||||||
// before calling the ISR
|
uint8_t ist;
|
||||||
uint8_t ist; // The IST in the TSS that the CPU will load into RSP; set to
|
uint8_t attributes;
|
||||||
// zero for now
|
uint16_t isr_mid;
|
||||||
uint8_t attributes; // Type and attributes; see the IDT page
|
uint32_t isr_high;
|
||||||
uint16_t
|
uint32_t reserved;
|
||||||
isr_mid; // The higher 16 bits of the lower 32 bits of the ISR's address
|
|
||||||
uint32_t isr_high; // The higher 32 bits of the ISR's address
|
|
||||||
uint32_t reserved; // Set to zero
|
|
||||||
} __attribute__((packed)) idt_entry_t;
|
} __attribute__((packed)) idt_entry_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t limit;
|
uint16_t limit;
|
||||||
uint64_t base;
|
uint64_t base;
|
||||||
} __attribute__((packed)) idtr_t;
|
} __attribute__((packed)) idtr_t;
|
||||||
|
|
||||||
typedef void (*idt_irq_handler_t)(registers_t *regs);
|
void idt_register_handler(uint8_t vector, void *isr);
|
||||||
|
void idt_init(void);
|
||||||
void idt_register_irq(uint8_t vector, void *isr);
|
void idt_load();
|
||||||
void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags);
|
|
||||||
void idt_init(void);
|
|
|
@ -1,17 +0,0 @@
|
||||||
// Copyright (C) 2024 Sipaa Projects
|
|
||||||
// This code is part of the Soaplin kernel and is licensed under the terms of
|
|
||||||
// the MIT License.
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
uint8_t inb(uint16_t port) {
|
|
||||||
uint8_t ret;
|
|
||||||
__asm__ volatile("inb %w1, %b0" : "=a"(ret) : "Nd"(port) : "memory");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void outb(uint16_t port, uint8_t val) {
|
|
||||||
__asm__ volatile("outb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
void io_wait(void) { outb(0x80, 0); }
|
|
|
@ -1,19 +1,23 @@
|
||||||
// Copyright (C) 2024 Sipaa Projects
|
/*
|
||||||
// This code is part of the Soaplin kernel and is licensed under the terms of
|
* The Soaplin Kernel
|
||||||
// the MIT License.
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* io.h - x86_64 I/O functions
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
inline void outb(uint16_t port, uint8_t val) {
|
||||||
extern "C" {
|
__asm__ volatile ( "outb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t inb(uint16_t port);
|
|
||||||
void outb(uint16_t port, uint8_t val);
|
|
||||||
void io_wait(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
inline uint8_t inb(uint16_t port) {
|
||||||
|
uint8_t ret;
|
||||||
|
__asm__ volatile ( "inb %w1, %b0"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "Nd"(port)
|
||||||
|
: "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
87
kernel/src/arch/x86_64/ioapic.c
Executable file
87
kernel/src/arch/x86_64/ioapic.c
Executable file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* ioapic.c - I/O APIC implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <acpi/madt.h>
|
||||||
|
#include <dev/ioapic.h>
|
||||||
|
#include <lib/log.h>
|
||||||
|
#include <mm/pmm.h>
|
||||||
|
|
||||||
|
static void __ioapic_write(acpi_madt_ioapic_t *ioapic, uint32_t reg, uint32_t val) {
|
||||||
|
*(volatile uint32_t *)(higher_half(ioapic->ioapic_addr)) = reg;
|
||||||
|
*(volatile uint32_t *)(higher_half(ioapic->ioapic_addr+0x10)) = val;
|
||||||
|
}
|
||||||
|
static uint32_t __ioapic_read(acpi_madt_ioapic_t *ioapic, uint32_t reg) {
|
||||||
|
*(volatile uint32_t *)(higher_half(ioapic->ioapic_addr)) = reg;
|
||||||
|
return *(volatile uint32_t *)(higher_half(ioapic->ioapic_addr+0x10));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ioapic_init() {
|
||||||
|
acpi_madt_ioapic_t *ioapic = madt_ioapic_list[0];
|
||||||
|
|
||||||
|
uint32_t value = __ioapic_read(ioapic, IOAPIC_VERSION);
|
||||||
|
uint32_t count = (value >> 16) & 0xFF;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i <= count; ++i) {
|
||||||
|
__ioapic_write(ioapic,
|
||||||
|
IOAPIC_REDTBL+2 * i,
|
||||||
|
0x00010000 | (32 + i));
|
||||||
|
__ioapic_write(ioapic,
|
||||||
|
IOAPIC_REDTBL + 2 * i + 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("ioapic: Initialized\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ioapic_gsi_count(acpi_madt_ioapic_t* ioapic) {
|
||||||
|
return (__ioapic_read(ioapic, 1) & 0xff0000) >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
acpi_madt_ioapic_t *ioapic_get_gsi(uint32_t gsi) {
|
||||||
|
for (uint32_t i = 0; i < madt_ioapic_len; i++) {
|
||||||
|
acpi_madt_ioapic_t* ioapic = madt_ioapic_list[i];
|
||||||
|
if (ioapic->gsi_base <= gsi && ioapic->gsi_base + ioapic_gsi_count(ioapic) > gsi)
|
||||||
|
return ioapic;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ioapic_redirect_gsi(uint32_t lapic_id, uint8_t vec, uint32_t gsi, uint16_t flags, bool mask) {
|
||||||
|
acpi_madt_ioapic_t* ioapic = ioapic_get_gsi(gsi);
|
||||||
|
|
||||||
|
uint64_t redirect = vec;
|
||||||
|
|
||||||
|
if ((flags & (1 << 1)) != 0) {
|
||||||
|
redirect |= (1 << 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & (1 << 3)) != 0) {
|
||||||
|
redirect |= (1 << 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask) redirect |= (1 << 16);
|
||||||
|
else redirect &= ~(1 << 16);
|
||||||
|
|
||||||
|
redirect |= (uint64_t)lapic_id << 56;
|
||||||
|
|
||||||
|
uint32_t redtbl = (gsi - ioapic->gsi_base) * 2 + 16;
|
||||||
|
__ioapic_write(ioapic, redtbl, (uint32_t)redirect);
|
||||||
|
__ioapic_write(ioapic, redtbl + 1, (uint32_t)(redirect >> 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ioapic_redir_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq, bool mask) {
|
||||||
|
uint8_t idx = 0;
|
||||||
|
acpi_madt_iso_t* iso = NULL;
|
||||||
|
|
||||||
|
for (idx = 0; idx < madt_iso_len; ++idx) {
|
||||||
|
iso = madt_iso_list[idx];
|
||||||
|
if (iso->source == irq) { ioapic_redirect_gsi(lapic_id, vec, iso->gsi, iso->flags, mask); return; }
|
||||||
|
}
|
||||||
|
ioapic_redirect_gsi(lapic_id, vec, irq, 0, mask);
|
||||||
|
}
|
17
kernel/src/arch/x86_64/ioapic.h
Executable file
17
kernel/src/arch/x86_64/ioapic.h
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* ioapic.c - I/O APIC definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define IOAPIC_VERSION 0x1
|
||||||
|
#define IOAPIC_REDTBL 0x10
|
||||||
|
|
||||||
|
void ioapic_init();
|
||||||
|
void ioapic_redir_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq, bool mask);
|
39
kernel/src/arch/x86_64/lapic.c
Executable file
39
kernel/src/arch/x86_64/lapic.c
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* lapic.c - Local APIC implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/x86_64/lapic.h"
|
||||||
|
#include "arch/x86_64/idt.h"
|
||||||
|
#include "lib/log.h"
|
||||||
|
#include "mm/pmm.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static uint64_t __lapic_pbase = 0xfee00000;
|
||||||
|
static uint64_t __lapic_vbase;
|
||||||
|
|
||||||
|
static void __lapic_write(uint32_t reg, uint32_t val) { *(volatile uint32_t *)(__lapic_vbase + reg) = val; }
|
||||||
|
static uint32_t __lapic_read(uint32_t reg) { return *(volatile uint32_t *)(__lapic_vbase + reg); }
|
||||||
|
static void __lapic_write_svr(uint32_t reg, lapic_svr_entry e) { *(volatile uint32_t *)(__lapic_vbase + reg) = *(uint32_t*)&e; }
|
||||||
|
|
||||||
|
void lapic_init() {
|
||||||
|
__lapic_vbase = higher_half(__lapic_pbase);
|
||||||
|
__lapic_write_svr(LAPIC_SVR, (lapic_svr_entry){ .swenabled = true, .vec = IDT_SPURIOUS_INT });
|
||||||
|
trace("lapic: Initialized\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void lapic_eoi() {
|
||||||
|
__lapic_write(LAPIC_EOI, 0x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lapic_ipi(uint32_t id, uint8_t dat) {
|
||||||
|
__lapic_write(0x310, id << LAPIC_ICDESTSHIFT);
|
||||||
|
__lapic_write(0x300, dat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t lapic_get_id() {
|
||||||
|
return __lapic_read(LAPIC_ID) >> LAPIC_ICDESTSHIFT;
|
||||||
|
}
|
27
kernel/src/arch/x86_64/lapic.h
Executable file
27
kernel/src/arch/x86_64/lapic.h
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* lapic.h - Local APIC definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define LAPIC_ID 0x20
|
||||||
|
#define LAPIC_SVR 0xF0
|
||||||
|
#define LAPIC_EOI 0xB0
|
||||||
|
|
||||||
|
#define LAPIC_ICDESTSHIFT 24
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t vec;
|
||||||
|
bool swenabled;
|
||||||
|
} lapic_svr_entry;
|
||||||
|
|
||||||
|
void lapic_init();
|
||||||
|
void lapic_eoi();
|
||||||
|
void lapic_ipi(uint32_t id, uint8_t dat);
|
||||||
|
uint32_t lapic_get_id();
|
|
@ -1,18 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define IA32_GS_MSR 0xC0000101
|
|
||||||
#define IA32_GS_KERNEL_MSR 0xC0000102
|
|
||||||
|
|
||||||
static inline void wrmsr(uint64_t msr, uint64_t value) {
|
|
||||||
uint32_t low = value & 0xFFFFFFFF;
|
|
||||||
uint32_t high = value >> 32;
|
|
||||||
asm volatile("wrmsr" : : "c"(msr), "a"(low), "d"(high));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint64_t rdmsr(uint64_t msr) {
|
|
||||||
uint32_t low, high;
|
|
||||||
asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
|
|
||||||
return ((uint64_t)high << 32) | low;
|
|
||||||
}
|
|
49
kernel/src/arch/x86_64/pit.c
Normal file → Executable file
49
kernel/src/arch/x86_64/pit.c
Normal file → Executable file
|
@ -1,30 +1,31 @@
|
||||||
#include "arch/x86_64/idt.h"
|
/*
|
||||||
#include "sched/sched.h"
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* pit.c - x86_64 Programmable Interval Timer implementation.
|
||||||
|
*/
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
|
||||||
|
#include <arch/x86_64/io.h>
|
||||||
#include <arch/x86_64/idt.h>
|
#include <arch/x86_64/idt.h>
|
||||||
#include <arch/x86_64/pit.h>
|
#include <dev/lapic.h>
|
||||||
#include <stdint.h>
|
#include <lib/log.h>
|
||||||
#include <sys/log.h>
|
|
||||||
|
|
||||||
uint32_t tick = 0;
|
void pit_handler(registers_t *reg) {
|
||||||
|
//trace("pit: Interrupt from %d!\n", lapic_get_id());
|
||||||
void pit_handler(registers_t *regs) {
|
|
||||||
// log("PIT");
|
|
||||||
tick++;
|
|
||||||
schedule(regs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pit_init() {
|
void cpu_init_timer() {
|
||||||
outb(0x43, 0x36);
|
outb(0x43, 0x36);
|
||||||
uint16_t div = (uint16_t)(1193180 / 1000);
|
|
||||||
outb(0x40, (uint8_t)div);
|
uint16_t div = (uint16_t)(1193180 / 1000);
|
||||||
outb(0x40, (uint8_t)(div >> 8));
|
|
||||||
|
// Since the PIT uses 8-bit IO operations,
|
||||||
|
// we need to split div in 2.
|
||||||
|
outb(0x40, (uint8_t)div);
|
||||||
|
outb(0x40, (uint8_t)(div >> 8));
|
||||||
|
|
||||||
|
idt_register_handler(0, pit_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pit_enable() { idt_register_irq(0, pit_handler); }
|
#endif
|
||||||
|
|
||||||
void pit_sleep(uint32_t ms) {
|
|
||||||
uint64_t start = tick;
|
|
||||||
while (tick - start < ms) {
|
|
||||||
__asm__ volatile("nop");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#ifndef PIT_H
|
|
||||||
#define PIT_H
|
|
||||||
|
|
||||||
#include <arch/x86_64/io.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern uint32_t tick;
|
|
||||||
|
|
||||||
void pit_init();
|
|
||||||
void pit_sleep(uint32_t ms);
|
|
||||||
void pit_enable();
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,43 +0,0 @@
|
||||||
#include "rtc.h"
|
|
||||||
#include "io.h"
|
|
||||||
|
|
||||||
char bcd;
|
|
||||||
|
|
||||||
unsigned char read_register(unsigned char reg) {
|
|
||||||
__asm__ volatile("cli");
|
|
||||||
outb(RTC_COMMAND, reg);
|
|
||||||
return inb(RTC_DATA);
|
|
||||||
__asm__ volatile("sti");
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_register(unsigned char reg, unsigned char value) {
|
|
||||||
__asm__ volatile("cli");
|
|
||||||
outb(RTC_COMMAND, reg);
|
|
||||||
outb(RTC_DATA, value);
|
|
||||||
__asm__ volatile("sti");
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char bcd2bin(unsigned char in_bcd) {
|
|
||||||
return (bcd) ? ((in_bcd >> 4) * 10) + (in_bcd & 0x0F) : in_bcd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rtc_init() {
|
|
||||||
__asm__ volatile("cli");
|
|
||||||
unsigned char status;
|
|
||||||
status = read_register(RTC_STATUS);
|
|
||||||
status |= 0x02; // 24 hour clock
|
|
||||||
status |= 0x10; // update ended interrupts
|
|
||||||
status &= ~0x20; // no alarm interrupts
|
|
||||||
status &= ~0x40; // no periodic interrupt
|
|
||||||
bcd = !(status & 0x04); // check if data type is BCD
|
|
||||||
write_register(RTC_STATUS, status);
|
|
||||||
|
|
||||||
outb(0x70, 0x8B); // select register B, and disable NMI
|
|
||||||
char prev = inb(0x71); // read the current value of register B
|
|
||||||
outb(0x70,
|
|
||||||
0x8B); // set the index again (a read will reset the index to register D)
|
|
||||||
outb(0x71, prev | 0x40); // write the previous value ORed with 0x40. This
|
|
||||||
// turns on bit 6 of register B
|
|
||||||
__asm__ volatile("sti");
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
#ifndef __TIME_H
|
|
||||||
#define __TIME_H
|
|
||||||
|
|
||||||
#define RTC_COMMAND 0x70
|
|
||||||
#define RTC_DATA 0x71
|
|
||||||
#define RTC_STATUS 0x0B
|
|
||||||
|
|
||||||
#define RTC_SECONDS 0x00
|
|
||||||
#define RTC_MINUTES 0x02
|
|
||||||
#define RTC_HOURS 0x04
|
|
||||||
#define RTC_DAY_OF_WEEK 0x06
|
|
||||||
#define RTC_DAY 0x07
|
|
||||||
#define RTC_MONTH 0x08
|
|
||||||
#define RTC_YEAR 0x09
|
|
||||||
|
|
||||||
int rtc_init();
|
|
||||||
|
|
||||||
#endif // __TIME_H__
|
|
65
kernel/src/arch/x86_64/smp.c
Normal file → Executable file
65
kernel/src/arch/x86_64/smp.c
Normal file → Executable file
|
@ -1,52 +1,25 @@
|
||||||
#include "arch/x86_64/smp.h"
|
/*
|
||||||
#include "lib/spinlock.h"
|
* The Soaplin Kernel
|
||||||
#include "limine.h"
|
* Copyright (C) 2025 The SILD Project
|
||||||
#include "sys/log.h"
|
*
|
||||||
|
* smp.c - x86_64 Symetric Multiprocessing implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/cpu.h"
|
||||||
|
#include <boot/limine.h>
|
||||||
|
#include <deps/limine.h>
|
||||||
|
#include <lib/log.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
__attribute__((
|
uint32_t bootstrap_lapic_id;
|
||||||
used, section(".limine_requests"))) static volatile struct limine_mp_request
|
|
||||||
smp_request = {.id = LIMINE_MP_REQUEST, .revision = 0};
|
|
||||||
|
|
||||||
uint32_t bootstrap_lapic_id = 0;
|
// TODO: initialize the CPUs
|
||||||
uint32_t smp_cpu_count = 0; // Number of processors
|
|
||||||
spinlock_t smp_lock = {0};
|
|
||||||
|
|
||||||
uint32_t ctr = 0;
|
void cpu_init_smp() {
|
||||||
|
struct limine_mp_response *smp = limine_get_smp();
|
||||||
|
bootstrap_lapic_id = smp->bsp_lapic_id;
|
||||||
|
|
||||||
void smp_entry(struct limine_mp_info *smp_info) {
|
/*for (uint64_t i = 0; i < smp->cpu_count; i++) {
|
||||||
// spinlock_acquire(&smp_lock);
|
trace("smp: Starting CPU %d\n", i);
|
||||||
|
}*/
|
||||||
log("smp - CPU %d started (LAPIC ID: %d)\n", smp_info->processor_id,
|
|
||||||
smp_info->lapic_id);
|
|
||||||
__atomic_fetch_add(&ctr, 1, __ATOMIC_SEQ_CST);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
;
|
|
||||||
;
|
|
||||||
// spinlock_release(&smp_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void smp_init() {
|
|
||||||
bootstrap_lapic_id = smp_request.response->bsp_lapic_id;
|
|
||||||
smp_cpu_count = smp_request.response->cpu_count;
|
|
||||||
|
|
||||||
log("smp - detected %d CPUs\n", smp_cpu_count);
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i < smp_cpu_count; i++) {
|
|
||||||
if (smp_request.response->cpus[i]->lapic_id != bootstrap_lapic_id) {
|
|
||||||
uint32_t old_ctr = __atomic_load_n(&ctr, __ATOMIC_SEQ_CST);
|
|
||||||
|
|
||||||
__atomic_store_n(&smp_request.response->cpus[i]->goto_address, smp_entry,
|
|
||||||
__ATOMIC_SEQ_CST);
|
|
||||||
|
|
||||||
while (__atomic_load_n(&ctr, __ATOMIC_SEQ_CST) == old_ctr)
|
|
||||||
;
|
|
||||||
} else {
|
|
||||||
log("smp - CPU %d is the bootstrap processor (LAPIC ID: %d)\n", i,
|
|
||||||
smp_request.response->cpus[i]->lapic_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log("smp - initialized\n");
|
|
||||||
}
|
|
13
kernel/src/arch/x86_64/smp.h
Normal file → Executable file
13
kernel/src/arch/x86_64/smp.h
Normal file → Executable file
|
@ -1,7 +1,12 @@
|
||||||
#pragma once
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* smp.c - x86_64 Symetric Multiprocessing definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
extern uint32_t bootstrap_lapic_id;
|
extern uint32_t bootstrap_lapic_id;
|
||||||
|
|
||||||
void smp_init();
|
|
|
@ -1,59 +0,0 @@
|
||||||
#include <arch/x86_64/sse.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
#include <sys/printf.h>
|
|
||||||
|
|
||||||
int cpuid_check_bit(int reg, int bit) {
|
|
||||||
int eax, ebx, ecx, edx;
|
|
||||||
|
|
||||||
// Minimal inline assembly to execute CPUID
|
|
||||||
__asm__ volatile("cpuid" // Execute CPUID instruction
|
|
||||||
: "=a"(eax), "=b"(ebx), "=c"(ecx),
|
|
||||||
"=d"(edx) // Output registers
|
|
||||||
: "a"(0x1) // Input: EAX = 0x1 (query feature flags)
|
|
||||||
: // No clobbered registers
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check bit 25 of EDX (SSE support) in plain C
|
|
||||||
if (reg == 0) {
|
|
||||||
if (edx & (1 << bit)) {
|
|
||||||
return 1; // SSE is supported
|
|
||||||
} else {
|
|
||||||
return 0; // SSE is not supported
|
|
||||||
}
|
|
||||||
} else if (reg == 1) {
|
|
||||||
if (ecx & (1 << bit)) {
|
|
||||||
return 1; // SSE is supported
|
|
||||||
} else {
|
|
||||||
return 0; // SSE is not supported
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sse_init() {
|
|
||||||
int sse = cpuid_check_bit(0, 25);
|
|
||||||
int sse2 = cpuid_check_bit(0, 26);
|
|
||||||
int sse3 = cpuid_check_bit(1, 0);
|
|
||||||
int ssse3 = cpuid_check_bit(1, 9);
|
|
||||||
|
|
||||||
if (sse)
|
|
||||||
log("sse - sse is supported!\n");
|
|
||||||
else
|
|
||||||
log("sse - sse isn't supported!\n");
|
|
||||||
|
|
||||||
if (sse2)
|
|
||||||
log("sse - sse2 is supported!\n");
|
|
||||||
else
|
|
||||||
log("sse - sse2 isn't supported!\n");
|
|
||||||
|
|
||||||
if (sse3)
|
|
||||||
log("sse - sse3 is supported!\n");
|
|
||||||
else
|
|
||||||
log("sse - sse3 isn't supported!\n");
|
|
||||||
|
|
||||||
if (ssse3)
|
|
||||||
log("sse - ssse3 is supported!\n");
|
|
||||||
else
|
|
||||||
log("sse - ssse3 isn't supported!\n");
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
int sse_is_supported();
|
|
||||||
void sse_init();
|
|
|
@ -1,53 +0,0 @@
|
||||||
bits 64
|
|
||||||
|
|
||||||
section .text
|
|
||||||
global syscall_entry
|
|
||||||
extern syscall_handle
|
|
||||||
|
|
||||||
syscall_entry:
|
|
||||||
swapgs ; switch
|
|
||||||
mov [gs:0], rsp
|
|
||||||
mov rsp, [gs:8]
|
|
||||||
|
|
||||||
push 0
|
|
||||||
push 0
|
|
||||||
push rax
|
|
||||||
push rcx
|
|
||||||
push rdx
|
|
||||||
push rbx
|
|
||||||
push rbp
|
|
||||||
push rsi
|
|
||||||
push rdi
|
|
||||||
push r8
|
|
||||||
push r9
|
|
||||||
push r10
|
|
||||||
push r11
|
|
||||||
push r12
|
|
||||||
push r13
|
|
||||||
push r14
|
|
||||||
push r15
|
|
||||||
|
|
||||||
mov rdi, rsp
|
|
||||||
call syscall_handle
|
|
||||||
|
|
||||||
pop r15
|
|
||||||
pop r14
|
|
||||||
pop r13
|
|
||||||
pop r12
|
|
||||||
pop r11
|
|
||||||
pop r10
|
|
||||||
pop r9
|
|
||||||
pop r8
|
|
||||||
pop rdi
|
|
||||||
pop rsi
|
|
||||||
pop rbp
|
|
||||||
pop rbx
|
|
||||||
pop rdx
|
|
||||||
pop rcx
|
|
||||||
pop rax
|
|
||||||
add rsp, 16
|
|
||||||
|
|
||||||
mov [gs:8], rsp
|
|
||||||
mov rsp, [gs:0]
|
|
||||||
swapgs
|
|
||||||
o64 sysret
|
|
|
@ -1,18 +0,0 @@
|
||||||
#include <arch/x86_64/msr.h>
|
|
||||||
#include <arch/x86_64/syscall.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern void syscall_entry();
|
|
||||||
|
|
||||||
void __x86_64_syscall_init() {
|
|
||||||
uint64_t efer = rdmsr(IA32_EFER);
|
|
||||||
efer |= (1 << 0);
|
|
||||||
wrmsr(IA32_EFER, efer);
|
|
||||||
uint64_t star = 0;
|
|
||||||
star |= ((uint64_t)0x28 << 32); // kernel cs
|
|
||||||
star |= ((uint64_t)0x30 << 48); // user cs base (SYSCALL adds 16 for CS=0x40, 24 for SS=0x38)
|
|
||||||
wrmsr(IA32_STAR, star);
|
|
||||||
wrmsr(IA32_LSTAR, (uint64_t)syscall_entry);
|
|
||||||
wrmsr(IA32_CSTAR, 0x0);
|
|
||||||
wrmsr(IA32_CSTAR + 1, 0x200);
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define IA32_EFER 0xC0000080
|
|
||||||
#define IA32_STAR 0xC0000081
|
|
||||||
#define IA32_LSTAR 0xC0000082
|
|
||||||
#define IA32_CSTAR 0xC0000083
|
|
||||||
#define IA32_SFMASK 0xC0000084
|
|
126
kernel/src/boot/limine.c
Executable file
126
kernel/src/boot/limine.c
Executable file
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* limine.c - Limine bootloader interface implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <boot/limine.h>
|
||||||
|
#include <deps/limine.h>
|
||||||
|
#include <proc/exec/elf.h>
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile LIMINE_BASE_REVISION(3);
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||||
|
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_bootloader_info_request bl_info_request = {
|
||||||
|
.id = LIMINE_BOOTLOADER_INFO_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_firmware_type_request firmware_type_req = {
|
||||||
|
.id = LIMINE_FIRMWARE_TYPE_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_memmap_request memmap_req = {
|
||||||
|
.id = LIMINE_MEMMAP_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_hhdm_request hhdm_req = {
|
||||||
|
.id = LIMINE_HHDM_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_executable_address_request kaddr_req = {
|
||||||
|
.id = LIMINE_EXECUTABLE_ADDRESS_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_executable_file_request execfile_req = {
|
||||||
|
.id = LIMINE_EXECUTABLE_FILE_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_paging_mode_request pgmode_req = {
|
||||||
|
.id = LIMINE_PAGING_MODE_REQUEST,
|
||||||
|
.mode = LIMINE_PAGING_MODE_X86_64_4LVL,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_rsdp_request rsdp_req = {
|
||||||
|
.id = LIMINE_RSDP_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile struct limine_mp_request smp_req = {
|
||||||
|
.id = LIMINE_MP_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests_start")))
|
||||||
|
static volatile LIMINE_REQUESTS_START_MARKER;
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests_end")))
|
||||||
|
static volatile LIMINE_REQUESTS_END_MARKER;
|
||||||
|
|
||||||
|
|
||||||
|
static limine_bootinfo_t __limine_bootinfo;
|
||||||
|
|
||||||
|
|
||||||
|
bool limine_ensure_baserev() { return LIMINE_BASE_REVISION_SUPPORTED; }
|
||||||
|
|
||||||
|
limine_fb_t *limine_get_fb(int id) {
|
||||||
|
if (!framebuffer_request.response)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (id >= (int32_t)framebuffer_request.response->framebuffer_count) // Limine, WHY putting the FB count as a 64-bit integer??? I never seen someone with 0xFFFFFFFFFFFFFFFF screens
|
||||||
|
return NULL;
|
||||||
|
return framebuffer_request.response->framebuffers[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct limine_memmap_response *limine_get_memmap() {
|
||||||
|
return memmap_req.response;
|
||||||
|
}
|
||||||
|
|
||||||
|
limine_bootinfo_t *limine_get_bootinfo() {
|
||||||
|
__limine_bootinfo.bl_name = bl_info_request.response->name;
|
||||||
|
__limine_bootinfo.bl_ver = bl_info_request.response->version;
|
||||||
|
__limine_bootinfo.fw_type = firmware_type_req.response->firmware_type;
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
__limine_bootinfo.arch = "x86_64";
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
__limine_bootinfo.arch = "aarch64";
|
||||||
|
#elif defined(__riscv)
|
||||||
|
__limine_bootinfo.arch = "riscv";
|
||||||
|
#elif defined(__loongarch64)
|
||||||
|
__limine_bootinfo.arch = "loongarch64";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &__limine_bootinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t limine_get_hhdm_offset() { return hhdm_req.response->offset; }
|
||||||
|
uint64_t limine_get_kernel_vaddr() { return kaddr_req.response->virtual_base; }
|
||||||
|
uint64_t limine_get_kernel_paddr() { return kaddr_req.response->physical_base; }
|
||||||
|
uint64_t limine_get_kernel_ehdr_addr() { return (uint64_t)execfile_req.response->executable_file->address; }
|
||||||
|
uint64_t limine_get_rsdp() { return rsdp_req.response->address + limine_get_hhdm_offset(); }
|
||||||
|
struct limine_mp_response *limine_get_smp() { return smp_req.response; }
|
39
kernel/src/boot/limine.h
Executable file
39
kernel/src/boot/limine.h
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* limine.h - Limine bootloader interface declarations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <deps/limine.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct limine_framebuffer limine_fb_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *bl_name;
|
||||||
|
char *bl_ver;
|
||||||
|
char *arch;
|
||||||
|
int fw_type;
|
||||||
|
} limine_bootinfo_t;
|
||||||
|
|
||||||
|
// Ensure that the used boot loader supports the kernel's LBP revision
|
||||||
|
bool limine_ensure_baserev();
|
||||||
|
|
||||||
|
// Get a framebuffer
|
||||||
|
limine_fb_t *limine_get_fb(int id);
|
||||||
|
|
||||||
|
// Get some informations about how the kernel was booted
|
||||||
|
limine_bootinfo_t *limine_get_bootinfo();
|
||||||
|
|
||||||
|
// Get the memory map.
|
||||||
|
struct limine_memmap_response *limine_get_memmap();
|
||||||
|
|
||||||
|
uint64_t limine_get_hhdm_offset();
|
||||||
|
uint64_t limine_get_kernel_vaddr();
|
||||||
|
uint64_t limine_get_kernel_paddr();
|
||||||
|
uint64_t limine_get_kernel_ehdr_addr();
|
||||||
|
uint64_t limine_get_rsdp();
|
||||||
|
struct limine_mp_response *limine_get_smp();
|
11
kernel/src/config.h
Executable file
11
kernel/src/config.h
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* config.h - Kernel configuration definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define KERNEL_NAME "Soaplin"
|
||||||
|
#define KERNEL_VER "0.0.1"
|
|
@ -1,56 +0,0 @@
|
||||||
#include "dbg/sym.h"
|
|
||||||
#include "exec/elf.h"
|
|
||||||
#include "limine.h"
|
|
||||||
#include "sys/errhnd/panic.h"
|
|
||||||
#include "sys/log.h"
|
|
||||||
#include <lib/string.h>
|
|
||||||
#include <mm/liballoc/liballoc.h>
|
|
||||||
|
|
||||||
static Elf64_Sym *__ksym_symtab;
|
|
||||||
static char *__ksym_strtab;
|
|
||||||
static int __ksym_symcount = 0;
|
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests"))) static volatile struct
|
|
||||||
limine_executable_file_request exec_file_rq = {
|
|
||||||
.id = LIMINE_EXECUTABLE_FILE_REQUEST, .revision = 3};
|
|
||||||
|
|
||||||
void ksym_init() {
|
|
||||||
char *img = exec_file_rq.response->executable_file->address;
|
|
||||||
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)img;
|
|
||||||
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
|
|
||||||
ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3) {
|
|
||||||
panic("kernel - how did i even boot? *starts galaxy brain meme*");
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf64_Shdr *shdr = (Elf64_Shdr *)(img + ehdr->e_shoff);
|
|
||||||
const char *shstrtab = (char *)img + shdr[ehdr->e_shstrndx].sh_offset;
|
|
||||||
|
|
||||||
for (int j = 0; j < ehdr->e_shnum; j++) {
|
|
||||||
if (shdr[j].sh_type == SHT_SYMTAB) {
|
|
||||||
__ksym_symtab = (Elf64_Sym *)(img + shdr[j].sh_offset);
|
|
||||||
__ksym_symcount = shdr[j].sh_size / shdr[j].sh_entsize;
|
|
||||||
} else if (shdr[j].sh_type == SHT_STRTAB &&
|
|
||||||
strcmp(shstrtab + shdr[j].sh_name, ".strtab") == 0) {
|
|
||||||
__ksym_strtab = (char *)(img + shdr[j].sh_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log("kernel - loaded %d symbols\n", __ksym_symcount);
|
|
||||||
}
|
|
||||||
|
|
||||||
func *ksym_fromip(uint64_t ip) {
|
|
||||||
for (int i = 0; i < __ksym_symcount; i++) {
|
|
||||||
uint64_t value = __ksym_symtab[i].st_value;
|
|
||||||
uint64_t size = __ksym_symtab[i].st_size;
|
|
||||||
|
|
||||||
if (value <= ip && ip < (value + size)) {
|
|
||||||
func *f = malloc(sizeof(func));
|
|
||||||
f->base = value;
|
|
||||||
f->ip = ip;
|
|
||||||
f->name = (__ksym_strtab + __ksym_symtab[i].st_name);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "mm/vmm.h"
|
|
||||||
|
|
||||||
typedef struct func {
|
|
||||||
uint64_t base;
|
|
||||||
uint64_t ip;
|
|
||||||
char *name;
|
|
||||||
} func;
|
|
||||||
|
|
||||||
void ksym_init();
|
|
||||||
func *ksym_fromip(uint64_t ip);
|
|
|
@ -1,113 +0,0 @@
|
||||||
#include "sys/acpi/madt.h"
|
|
||||||
#include <dev/ioapic.h>
|
|
||||||
#include <mm/pmm.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
|
|
||||||
void ioapic_init() {
|
|
||||||
madt_ioapic *ioapic = acpi_madt_ioapic_list[0];
|
|
||||||
|
|
||||||
uint32_t val = ioapic_read(ioapic, IOAPIC_VER);
|
|
||||||
uint32_t count = ((val >> 16) & 0xFF);
|
|
||||||
|
|
||||||
if ((ioapic_read(ioapic, 0) >> 24) != ioapic->apic_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i <= count; ++i) {
|
|
||||||
ioapic_write(ioapic, IOAPIC_REDTBL + 2 * i, 0x00010000 | (32 + i));
|
|
||||||
ioapic_write(ioapic, IOAPIC_REDTBL + 2 * i + 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
log("ioapic - initialized\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ioapic_write(madt_ioapic *ioapic, uint8_t reg, uint32_t val) {
|
|
||||||
*((volatile uint32_t *)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_REGSEL)) =
|
|
||||||
reg;
|
|
||||||
*((volatile uint32_t *)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_IOWIN)) = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ioapic_read(madt_ioapic *ioapic, uint8_t reg) {
|
|
||||||
*((volatile uint32_t *)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_REGSEL)) =
|
|
||||||
reg;
|
|
||||||
return *(
|
|
||||||
(volatile uint32_t *)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_IOWIN));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ioapic_set_entry(madt_ioapic *ioapic, uint8_t idx, uint64_t data) {
|
|
||||||
ioapic_write(ioapic, (uint8_t)(IOAPIC_REDTBL + idx * 2), (uint32_t)data);
|
|
||||||
ioapic_write(ioapic, (uint8_t)(IOAPIC_REDTBL + idx * 2 + 1),
|
|
||||||
(uint32_t)(data >> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t ioapic_gsi_count(madt_ioapic *ioapic) {
|
|
||||||
return (ioapic_read(ioapic, 1) & 0xff0000) >> 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
madt_ioapic *ioapic_get_gsi(uint32_t gsi) {
|
|
||||||
for (uint64_t i = 0; i < acpi_madt_ioapic_length; i++) {
|
|
||||||
madt_ioapic *ioapic = acpi_madt_ioapic_list[i];
|
|
||||||
if (ioapic->gsi_base <= gsi &&
|
|
||||||
ioapic->gsi_base + ioapic_gsi_count(ioapic) > gsi)
|
|
||||||
return ioapic;
|
|
||||||
}
|
|
||||||
return (madt_ioapic *)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ioapic_redirect_gsi(uint32_t lapic_id, uint8_t vec, uint32_t gsi,
|
|
||||||
uint16_t flags, bool mask) {
|
|
||||||
madt_ioapic *ioapic = ioapic_get_gsi(gsi);
|
|
||||||
|
|
||||||
uint64_t redirect = vec;
|
|
||||||
|
|
||||||
if ((flags & (1 << 1)) != 0) {
|
|
||||||
redirect |= (1 << 13);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & (1 << 3)) != 0) {
|
|
||||||
redirect |= (1 << 15);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mask)
|
|
||||||
redirect |= (1 << 16);
|
|
||||||
else
|
|
||||||
redirect &= ~(1 << 16);
|
|
||||||
|
|
||||||
redirect |= (uint64_t)lapic_id << 56;
|
|
||||||
|
|
||||||
uint32_t redir_table = (gsi - ioapic->gsi_base) * 2 + 16;
|
|
||||||
ioapic_write(ioapic, redir_table, (uint32_t)redirect);
|
|
||||||
ioapic_write(ioapic, redir_table + 1, (uint32_t)(redirect >> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ioapic_redirect_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq,
|
|
||||||
bool mask) {
|
|
||||||
uint8_t idx = 0;
|
|
||||||
madt_iso *iso = (madt_iso *)0;
|
|
||||||
|
|
||||||
while (idx < acpi_madt_iso_length) {
|
|
||||||
iso = acpi_madt_iso_list[idx];
|
|
||||||
if (iso->irq_src == irq) {
|
|
||||||
ioapic_redirect_gsi(lapic_id, vec, iso->gsi, iso->flags, mask);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ioapic_redirect_gsi(lapic_id, vec, irq, 0, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ioapic_get_redirect_irq(uint8_t irq) {
|
|
||||||
uint8_t idx = 0;
|
|
||||||
madt_iso *iso;
|
|
||||||
|
|
||||||
while (idx < acpi_madt_iso_length) {
|
|
||||||
iso = acpi_madt_iso_list[idx];
|
|
||||||
if (iso->irq_src == irq) {
|
|
||||||
return iso->gsi;
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return irq;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <sys/acpi.h>
|
|
||||||
#include <sys/acpi/madt.h>
|
|
||||||
|
|
||||||
#define IOAPIC_REGSEL 0x0
|
|
||||||
#define IOAPIC_IOWIN 0x10
|
|
||||||
|
|
||||||
#define IOAPIC_ID 0x0
|
|
||||||
#define IOAPIC_VER 0x01
|
|
||||||
#define IOAPIC_ARB 0x02
|
|
||||||
#define IOAPIC_REDTBL 0x10
|
|
||||||
|
|
||||||
void ioapic_write(madt_ioapic *ioapic, uint8_t reg, uint32_t val);
|
|
||||||
uint32_t ioapic_read(madt_ioapic *ioapic, uint8_t reg);
|
|
||||||
|
|
||||||
void ioapic_redirect_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq,
|
|
||||||
bool mask);
|
|
||||||
uint32_t ioapic_get_redirect_irq(uint8_t irq);
|
|
||||||
|
|
||||||
void ioapic_set_entry(madt_ioapic *ioapic, uint8_t idx, uint64_t data);
|
|
||||||
|
|
||||||
void ioapic_init();
|
|
|
@ -1,60 +0,0 @@
|
||||||
#include "mm/pmm.h"
|
|
||||||
#include <dev/lapic.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
|
|
||||||
uint64_t apic_ticks = 0;
|
|
||||||
|
|
||||||
void lapic_init() {
|
|
||||||
lapic_write(0xf0, 0x1ff);
|
|
||||||
log("lapic - initialized\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void lapic_stop_timer() {
|
|
||||||
// We do this to avoid overlapping oneshots
|
|
||||||
lapic_write(LAPIC_TIMER_INITCNT, 0);
|
|
||||||
lapic_write(LAPIC_TIMER_LVT, LAPIC_TIMER_DISABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lapic_oneshot(uint8_t vec, uint64_t ms) {
|
|
||||||
lapic_stop_timer();
|
|
||||||
lapic_write(LAPIC_TIMER_DIV, 0);
|
|
||||||
lapic_write(LAPIC_TIMER_LVT, vec);
|
|
||||||
lapic_write(LAPIC_TIMER_INITCNT, apic_ticks * ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lapic_calibrate_timer() {
|
|
||||||
lapic_stop_timer();
|
|
||||||
lapic_write(LAPIC_TIMER_DIV, 0);
|
|
||||||
lapic_write(LAPIC_TIMER_LVT, (1 << 16) | 0xff);
|
|
||||||
lapic_write(LAPIC_TIMER_INITCNT, 0xFFFFFFFF);
|
|
||||||
// pit_sleep(1); // 1 ms
|
|
||||||
lapic_write(LAPIC_TIMER_LVT, LAPIC_TIMER_DISABLE);
|
|
||||||
uint32_t ticks = 0xFFFFFFFF - lapic_read(LAPIC_TIMER_CURCNT);
|
|
||||||
apic_ticks = ticks;
|
|
||||||
lapic_stop_timer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void lapic_write(uint32_t reg, uint32_t val) {
|
|
||||||
*((volatile uint32_t *)(HIGHER_HALF(0xfee00000) + reg)) = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lapic_read(uint32_t reg) {
|
|
||||||
return *((volatile uint32_t *)(HIGHER_HALF(0xfee00000) + reg));
|
|
||||||
}
|
|
||||||
|
|
||||||
void lapic_eoi() { lapic_write((uint8_t)0xb0, 0x0); }
|
|
||||||
|
|
||||||
void lapic_ipi(uint32_t id, uint8_t dat) {
|
|
||||||
lapic_write(LAPIC_ICRHI, id << LAPIC_ICDESTSHIFT);
|
|
||||||
lapic_write(LAPIC_ICRLO, dat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lapic_send_all_int(uint32_t id, uint32_t vec) {
|
|
||||||
lapic_ipi(id, vec | LAPIC_ICRAIS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lapic_send_others_int(uint32_t id, uint32_t vec) {
|
|
||||||
lapic_ipi(id, vec | LAPIC_ICRAES);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lapic_get_id() { return lapic_read(0x0020) >> LAPIC_ICDESTSHIFT; }
|
|
|
@ -1,52 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <sys/acpi.h>
|
|
||||||
#include <sys/acpi/madt.h>
|
|
||||||
|
|
||||||
#define LAPIC_PPR 0x00a0
|
|
||||||
|
|
||||||
#define LAPIC_ICRLO 0x0300
|
|
||||||
#define LAPIC_ICRHI 0x0310
|
|
||||||
|
|
||||||
#define LAPIC_ICINI 0x0500
|
|
||||||
#define LAPIC_ICSTR 0x0600
|
|
||||||
|
|
||||||
#define LAPIC_ICEDGE 0x0000
|
|
||||||
|
|
||||||
#define LAPIC_ICPEND 0x00001000
|
|
||||||
#define LAPIC_ICPHYS 0x00000000
|
|
||||||
#define LAPIC_ICASSR 0x00004000
|
|
||||||
#define LAPIC_ICSHRTHND 0x00000000
|
|
||||||
#define LAPIC_ICDESTSHIFT 24
|
|
||||||
|
|
||||||
#define LAPIC_ICRAIS 0x00080000
|
|
||||||
#define LAPIC_ICRAES 0x000c0000
|
|
||||||
|
|
||||||
// Timer
|
|
||||||
|
|
||||||
#define LAPIC_TIMER_DIV 0x3E0
|
|
||||||
#define LAPIC_TIMER_INITCNT 0x380
|
|
||||||
#define LAPIC_TIMER_LVT 0x320
|
|
||||||
#define LAPIC_TIMER_DISABLE 0x10000
|
|
||||||
#define LAPIC_TIMER_CURCNT 0x390
|
|
||||||
#define LAPIC_TIMER_PERIODIC 0x20000
|
|
||||||
|
|
||||||
void lapic_init();
|
|
||||||
|
|
||||||
void lapic_stop_timer();
|
|
||||||
void lapic_oneshot(uint8_t vec, uint64_t ms);
|
|
||||||
void lapic_calibrate_timer();
|
|
||||||
|
|
||||||
void lapic_write(uint32_t reg, uint32_t val);
|
|
||||||
uint32_t lapic_read(uint32_t reg);
|
|
||||||
|
|
||||||
void lapic_eoi();
|
|
||||||
|
|
||||||
void lapic_ipi(uint32_t id, uint8_t dat);
|
|
||||||
|
|
||||||
void lapic_send_all_int(uint32_t id, uint32_t vec);
|
|
||||||
void lapic_send_others_int(uint32_t id, uint32_t vec);
|
|
||||||
|
|
||||||
void lapic_init_cpu(uint32_t id);
|
|
||||||
void lapic_start_cpu(uint32_t id, uint32_t vec);
|
|
||||||
uint32_t lapic_get_id();
|
|
53
kernel/src/dev/tty.c
Executable file
53
kernel/src/dev/tty.c
Executable file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* tty.c - Terminal interface implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <deps/flanterm/backends/fb.h>
|
||||||
|
#include <deps/flanterm/flanterm.h>
|
||||||
|
#include <boot/limine.h>
|
||||||
|
#include <deps/npf.h>
|
||||||
|
#include <lib/string.h>
|
||||||
|
|
||||||
|
struct flanterm_context *tty0_ctx;
|
||||||
|
|
||||||
|
void tty_init() {
|
||||||
|
limine_fb_t *fb0 = limine_get_fb(0);
|
||||||
|
|
||||||
|
tty0_ctx = flanterm_fb_init(
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
fb0->address, fb0->width, fb0->height, fb0->pitch,
|
||||||
|
fb0->red_mask_size, fb0->red_mask_shift,
|
||||||
|
fb0->green_mask_size, fb0->green_mask_shift,
|
||||||
|
fb0->blue_mask_size, fb0->blue_mask_shift,
|
||||||
|
NULL,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL, 0, 0, 1,
|
||||||
|
0, 0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tty_putc(char c) {
|
||||||
|
flanterm_write(tty0_ctx, &c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tty_puts(char *str) {
|
||||||
|
flanterm_write(tty0_ctx, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tty_printf(char *fmt, ...) {
|
||||||
|
char buf[2048];
|
||||||
|
va_list l;
|
||||||
|
va_start(l, fmt);
|
||||||
|
npf_vsnprintf(buf, 2048, fmt, l);
|
||||||
|
va_end(l);
|
||||||
|
|
||||||
|
tty_puts(buf);
|
||||||
|
}
|
13
kernel/src/dev/tty.h
Executable file
13
kernel/src/dev/tty.h
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* tty.h - Terminal interface declarations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void tty_init();
|
||||||
|
void tty_putc(char c);
|
||||||
|
void tty_puts(char *str);
|
||||||
|
void tty_printf(char *fmt, ...);
|
|
@ -1,135 +0,0 @@
|
||||||
#include "exec/exec.h"
|
|
||||||
#include "mm/memop.h"
|
|
||||||
#include "mm/pmm.h"
|
|
||||||
#include "mm/vmm.h"
|
|
||||||
#include <exec/elf.h>
|
|
||||||
#include <mm/liballoc/liballoc.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
|
|
||||||
program_t *elf_load(char *data, int user) {
|
|
||||||
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)data;
|
|
||||||
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
|
|
||||||
ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3) {
|
|
||||||
log("elf - loading failed: magic is incorrect\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
log("elf - e_ident[EI_DATA]: %d\n", ehdr->e_ident[EI_DATA]);
|
|
||||||
log("elf - e_ident[EI_CLASS]: %d\n", ehdr->e_ident[EI_CLASS]);
|
|
||||||
log("elf - e_ident[EI_OSABI]: %d\n", ehdr->e_ident[EI_OSABI]);
|
|
||||||
log("elf - e_machine: %d\n", ehdr->e_machine);
|
|
||||||
log("elf - e_entry: %p\n", ehdr->e_entry);
|
|
||||||
log("elf - e_type: %p\n", ehdr->e_type);
|
|
||||||
log("elf - e_phnum: %p\n", ehdr->e_phnum);
|
|
||||||
|
|
||||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64 || ehdr->e_machine != EM_X86_64) {
|
|
||||||
log("elf - loading failed: is the file built for amd64?\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ehdr->e_type != ET_EXEC) {
|
|
||||||
log("elf - loading failed: ELF type isn't ET_EXEC\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There's the interesing part
|
|
||||||
elf_program_t *ret =
|
|
||||||
malloc(sizeof(elf_program_t)); // Allocate memory for the program.
|
|
||||||
|
|
||||||
pagemap_t *pm = vmm_alloc_pm(); // Allocate a pagemap, so that we can map the
|
|
||||||
// program inside.
|
|
||||||
ret->program.pm = pm;
|
|
||||||
ret->program.entry = ehdr->e_entry;
|
|
||||||
ret->ehdr = ehdr;
|
|
||||||
|
|
||||||
Elf64_Phdr *phdr = (Elf64_Phdr *)((uint8_t *)data + ehdr->e_phoff);
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < ehdr->e_phnum; i++) {
|
|
||||||
log("elf - ELF segment type: %d\n", phdr[i].p_type);
|
|
||||||
|
|
||||||
if (phdr[i].p_type == PT_INTERP) {
|
|
||||||
log("elf - A PT_INTERP program header was found. This was meant to be a dynamically-linked program, which Soaplin doesn't supports.\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phdr[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint64_t vaddr_start = ALIGN_DOWN(phdr[i].p_vaddr, PMM_PAGE_SIZE);
|
|
||||||
uint64_t vaddr_end =
|
|
||||||
ALIGN_UP(phdr[i].p_vaddr + phdr[i].p_memsz, PMM_PAGE_SIZE);
|
|
||||||
uint64_t offset = phdr[i].p_offset;
|
|
||||||
|
|
||||||
uint64_t flags = VMM_PRESENT;
|
|
||||||
if (phdr[i].p_flags & PF_W)
|
|
||||||
flags |= VMM_WRITABLE;
|
|
||||||
if (phdr[i].p_flags & PF_X)
|
|
||||||
flags &= ~VMM_NX;
|
|
||||||
else
|
|
||||||
flags |= VMM_NX;
|
|
||||||
|
|
||||||
if (user)
|
|
||||||
flags |= VMM_USER;
|
|
||||||
|
|
||||||
log("elf - loading ELF program header %u: vaddr 0x%llx - 0x%llx, offset "
|
|
||||||
"0x%llx, filesz 0x%llx, size 0x%llx, flags 0x%llx\n",
|
|
||||||
i, vaddr_start, vaddr_end, offset, phdr[i].p_filesz, phdr[i].p_memsz,
|
|
||||||
flags);
|
|
||||||
|
|
||||||
uint64_t page_offset = phdr[i].p_vaddr & (PMM_PAGE_SIZE - 1);
|
|
||||||
|
|
||||||
for (uint64_t vaddr = vaddr_start; vaddr < vaddr_end;
|
|
||||||
vaddr += PMM_PAGE_SIZE) {
|
|
||||||
uint64_t phys = (uint64_t)pmm_request_page();
|
|
||||||
if (!phys) {
|
|
||||||
log("elf - pmm page alloc failed. out of memory?\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user) {
|
|
||||||
log("elf - vmm_map_user(%p, %p, %p, %d)\n", pm, vaddr, phys, flags);
|
|
||||||
vmm_map_user(pm, vaddr, phys, flags);
|
|
||||||
} else {
|
|
||||||
log("elf - vmm_map(%p, %p, %p, %d)\n", pm, vaddr, phys, flags);
|
|
||||||
vmm_map(pm, vaddr, phys, flags);
|
|
||||||
}
|
|
||||||
log("elf - memset(%p, 0, 0x1000)\n", HIGHER_HALF(phys));
|
|
||||||
memset((void *)HIGHER_HALF(phys), 0, PMM_PAGE_SIZE);
|
|
||||||
|
|
||||||
uint64_t file_page_offset = offset + (vaddr - vaddr_start);
|
|
||||||
uint64_t file_data_end = offset + phdr[i].p_filesz;
|
|
||||||
|
|
||||||
if (file_page_offset < file_data_end) {
|
|
||||||
uint64_t bytes_from_start = vaddr - vaddr_start;
|
|
||||||
uint64_t page_data_offset = 0;
|
|
||||||
|
|
||||||
if (bytes_from_start == 0 && page_offset > 0) {
|
|
||||||
page_data_offset = page_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t copy_offset = file_page_offset;
|
|
||||||
uint64_t copy_size = PMM_PAGE_SIZE - page_data_offset;
|
|
||||||
|
|
||||||
if (copy_offset + copy_size > file_data_end) {
|
|
||||||
copy_size = file_data_end - copy_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_size > 0) {
|
|
||||||
void *dest = (void *)(HIGHER_HALF(phys) + page_data_offset);
|
|
||||||
void *src = (uint8_t *)data + copy_offset;
|
|
||||||
log("elf - memcpy(%p, %p, %d)\n", dest, src, copy_size);
|
|
||||||
memcpy(dest, src, copy_size);
|
|
||||||
|
|
||||||
// log("elf - copied 0x%llx bytes from ELF file offset 0x%llx to vaddr
|
|
||||||
// 0x%llx (phys 0x%llx)\n",
|
|
||||||
// copy_size, copy_offset, vaddr + page_data_offset, phys +
|
|
||||||
// page_data_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log("elf - loaded ELF program in memory.\n");
|
|
||||||
return (program_t *)ret;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A program (or a script, if a shebang is found inside), literally.
|
|
||||||
*/
|
|
||||||
#include "mm/vmm.h"
|
|
||||||
|
|
||||||
#define EXEC_TYPE_ELF 0
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
// The path to the program/script that will be executed.
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
// The pagemap where the program's code is loaded.
|
|
||||||
pagemap_t *pm;
|
|
||||||
|
|
||||||
// The path to the first instruction. This will be passed to the new process's
|
|
||||||
// rip register.
|
|
||||||
uint64_t entry;
|
|
||||||
|
|
||||||
// The program type. Used to get additional, unneeded information out of a
|
|
||||||
// program
|
|
||||||
int type;
|
|
||||||
|
|
||||||
// That is what Soaplin needs to know. Executable file loaders are encouraged
|
|
||||||
// to extend this structure to include info such as the EHDR for the ELF
|
|
||||||
// loader...
|
|
||||||
} program_t;
|
|
|
@ -1,343 +0,0 @@
|
||||||
unsigned char VGA8[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
|
|
||||||
0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
|
|
||||||
0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
|
|
||||||
0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
|
|
||||||
0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
|
|
||||||
0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
|
|
||||||
0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e,
|
|
||||||
0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
|
|
||||||
0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
|
|
||||||
0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
|
|
||||||
0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e,
|
|
||||||
0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
|
||||||
0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
|
|
||||||
0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6,
|
|
||||||
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
|
|
||||||
0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
|
|
||||||
0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
|
|
||||||
0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
|
|
||||||
0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c,
|
|
||||||
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
|
|
||||||
0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
|
|
||||||
0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
|
|
||||||
0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
|
|
||||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
|
|
||||||
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
|
|
||||||
0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
|
|
||||||
0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
|
|
||||||
0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
|
|
||||||
0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
|
|
||||||
0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
|
|
||||||
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
|
|
||||||
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
|
|
||||||
0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde,
|
|
||||||
0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
|
|
||||||
0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
|
|
||||||
0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c,
|
|
||||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
|
|
||||||
0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
|
|
||||||
0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
|
|
||||||
0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
|
|
||||||
0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee,
|
|
||||||
0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
|
|
||||||
0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66,
|
|
||||||
0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c,
|
|
||||||
0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
|
|
||||||
0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
|
|
||||||
0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
|
|
||||||
0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6,
|
|
||||||
0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38,
|
|
||||||
0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66,
|
|
||||||
0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
|
|
||||||
0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
|
||||||
0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
|
|
||||||
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
|
|
||||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60,
|
|
||||||
0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
|
|
||||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
|
|
||||||
0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60,
|
|
||||||
0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
|
|
||||||
0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60,
|
|
||||||
0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6,
|
|
||||||
0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
|
|
||||||
0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
|
|
||||||
0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
|
|
||||||
0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
|
|
||||||
0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
|
|
||||||
0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
|
|
||||||
0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
|
|
||||||
0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
|
|
||||||
0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
|
|
||||||
0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
|
|
||||||
0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
|
|
||||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
|
|
||||||
0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06,
|
|
||||||
0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
|
|
||||||
0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
|
|
||||||
0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66,
|
|
||||||
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
|
|
||||||
0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
|
|
||||||
0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36,
|
|
||||||
0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c,
|
|
||||||
0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
|
|
||||||
0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
|
|
||||||
0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
|
|
||||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
|
|
||||||
0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
|
|
||||||
0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
|
|
||||||
0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c,
|
|
||||||
0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
|
|
||||||
0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc,
|
|
||||||
0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
|
|
||||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
|
|
||||||
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
|
|
||||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc,
|
|
||||||
0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
|
|
||||||
0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
|
|
||||||
0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c,
|
|
||||||
0x18, 0x3e, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
|
|
||||||
0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
|
|
||||||
0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
|
|
||||||
0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
|
|
||||||
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
|
|
||||||
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
|
|
||||||
0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
|
|
||||||
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
|
|
||||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
|
|
||||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
|
||||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
||||||
0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
|
|
||||||
0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
|
|
||||||
0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
|
|
||||||
0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
|
|
||||||
0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
|
|
||||||
0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60,
|
|
||||||
0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
|
|
||||||
0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
|
|
||||||
0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
|
||||||
0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
|
|
||||||
0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
|
|
||||||
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
|
|
||||||
0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00};
|
|
|
@ -1,3 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
extern unsigned char VGA8[];
|
|
|
@ -1,101 +0,0 @@
|
||||||
#include "fs/hellofs.h"
|
|
||||||
#include "fs/vfs.h"
|
|
||||||
#include <mm/liballoc/liballoc.h>
|
|
||||||
#include <mm/memop.h>
|
|
||||||
#include <lib/string.h>
|
|
||||||
|
|
||||||
static int hellofs_read(vnode_t *vn, void *buf, size_t off, size_t size) {
|
|
||||||
if (!vn || !buf || size <= 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *hello = "hello";
|
|
||||||
const size_t hello_len = 5; // strlen("hello")
|
|
||||||
char *cbuf = (char *)buf;
|
|
||||||
size_t bytes_written = 0;
|
|
||||||
|
|
||||||
while (bytes_written < size) {
|
|
||||||
size_t pos = off % hello_len; // Position within "hello"
|
|
||||||
size_t remaining = hello_len - pos; // Remaining bytes in current "hello"
|
|
||||||
size_t to_copy = (size - bytes_written < remaining) ?
|
|
||||||
(size - bytes_written) : remaining;
|
|
||||||
|
|
||||||
memcpy(cbuf + bytes_written, hello + pos, to_copy);
|
|
||||||
bytes_written += to_copy;
|
|
||||||
off += to_copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes_written;
|
|
||||||
}
|
|
||||||
|
|
||||||
vnode_ops_t hellofs_hello_ops = {
|
|
||||||
.read = hellofs_read,
|
|
||||||
.lookup = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int hellofs_lookup(vnode_t *vn, const char *name, vnode_t **out) {
|
|
||||||
if (!vn || !name || !out) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(name, "hello") == 0) {
|
|
||||||
*out = vfs_create_node("hello", VN_FILE);
|
|
||||||
if (*out) {
|
|
||||||
(*out)->ops = &hellofs_hello_ops;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
*out = NULL; // Not found
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vnode_ops_t hellofs_root_ops = {
|
|
||||||
.read = NULL,
|
|
||||||
.lookup = hellofs_lookup,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int hellofs_mount(fs_t *fs, vnode_t *mountpoint) {
|
|
||||||
if (!fs || !mountpoint) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// mountpoint list isn't implemented.
|
|
||||||
|
|
||||||
/*mountpoint_t *mp = (mountpoint_t *)malloc(sizeof(mountpoint_t));
|
|
||||||
if (!mp) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(mp, 0, sizeof(mountpoint_t));
|
|
||||||
strncpy(mp->name, fs->name, sizeof(mp->name) - 1);
|
|
||||||
mp->fs = fs;
|
|
||||||
mp->mountpoint = mountpoint;*/
|
|
||||||
|
|
||||||
// Mounting is essentially just putting the file system's root directory operations
|
|
||||||
// on the mountpoint vnode.
|
|
||||||
mountpoint->ops = &hellofs_root_ops;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs_t *hellofs_init() {
|
|
||||||
fs_t *fs = (fs_t *)malloc(sizeof(fs_t));
|
|
||||||
if (!fs) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(fs, 0, sizeof(fs_t));
|
|
||||||
strncpy(fs->name, "hellofs", sizeof(fs->name) - 1);
|
|
||||||
|
|
||||||
fs->mount = hellofs_mount;
|
|
||||||
fs->root = vfs_create_node("/", VN_DIR);
|
|
||||||
if (!fs->root) {
|
|
||||||
free(fs);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <fs/vfs.h>
|
|
||||||
|
|
||||||
fs_t *hellofs_init(void);
|
|
|
@ -1,112 +0,0 @@
|
||||||
#include "fs/vfs.h"
|
|
||||||
#include "lib/string.h"
|
|
||||||
#include "mm/liballoc/liballoc.h"
|
|
||||||
#include "mm/memop.h"
|
|
||||||
#include "sys/errhnd/panic.h"
|
|
||||||
|
|
||||||
vnode_t *root = NULL;
|
|
||||||
|
|
||||||
void vfs_init() {
|
|
||||||
root = vfs_create_node("/", VN_DIR);
|
|
||||||
if (!root) {
|
|
||||||
panic("vfs - failed to create root node");
|
|
||||||
}
|
|
||||||
root->parent = root; // Root's parent is itself
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not worth adding to the header, since it should only lookup
|
|
||||||
// for files/directories in dir, without going deeper.
|
|
||||||
int vfs_lookup(vnode_t *dir, const char *name, vnode_t **out) {
|
|
||||||
if (!dir || !name)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (dir->ops && dir->ops->lookup) {
|
|
||||||
return dir->ops->lookup(dir, name, out);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vfs_open(vnode_t *curdir, const char *path, vnode_t **out) {
|
|
||||||
if (strcmp(path, ".") == 0) {
|
|
||||||
*out = curdir;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (strcmp(path, "..") == 0) {
|
|
||||||
*out = curdir->parent;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *path_copy = strdup(path);
|
|
||||||
if (!path_copy) {
|
|
||||||
*out = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vnode_t *cur_node = path[0] == '/' ? root : curdir;
|
|
||||||
char *token = strtok(path_copy, "/");
|
|
||||||
|
|
||||||
while (token) {
|
|
||||||
vnode_t *next;
|
|
||||||
vfs_lookup(cur_node, token, &next);
|
|
||||||
if (!next) {
|
|
||||||
free(path_copy);
|
|
||||||
*out = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
cur_node = next;
|
|
||||||
token = strtok(NULL, "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(path_copy);
|
|
||||||
*out = cur_node;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vfs_mount(char *path, fs_t *fs) {
|
|
||||||
if (!fs || !path) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vnode_t *mp;
|
|
||||||
if (strcmp(path, "/") == 0) {
|
|
||||||
mp = root;
|
|
||||||
} else {
|
|
||||||
vfs_open(root, path, &mp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fs->mount == NULL)
|
|
||||||
return -1; // why allocating a fs without the capability to mount to a node? lmao
|
|
||||||
|
|
||||||
return fs->mount(fs, mp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int vfs_unmount(char *path) {
|
|
||||||
(void)path;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vfs_read(vnode_t *vn, void *buf, size_t off, size_t size) {
|
|
||||||
if (!vn || !buf || off < 0 || size <= 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vn->ops && vn->ops->read) {
|
|
||||||
return vn->ops->read(vn, buf, off, size);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vnode_t *vfs_create_node(char *name, vnode_type_t type) {
|
|
||||||
vnode_t *node = (vnode_t *)malloc(sizeof(vnode_t));
|
|
||||||
if (!node) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(node, 0, sizeof(vnode_t));
|
|
||||||
strncpy(node->name, name, sizeof(node->name) - 1);
|
|
||||||
node->type = type;
|
|
||||||
node->ops = NULL;
|
|
||||||
// node->parent = NULL;
|
|
||||||
// node->child = NULL;
|
|
||||||
// node->next = NULL;
|
|
||||||
return node;
|
|
||||||
}
|
|
4
kernel/src/fs/vfs.h
Normal file → Executable file
4
kernel/src/fs/vfs.h
Normal file → Executable file
|
@ -20,9 +20,7 @@ typedef struct vnode {
|
||||||
vnode_type_t type;
|
vnode_type_t type;
|
||||||
uint32_t refcount;
|
uint32_t refcount;
|
||||||
struct vnode* parent; // If this vnode exists, then it's parent too.
|
struct vnode* parent; // If this vnode exists, then it's parent too.
|
||||||
// struct vnode* child;
|
|
||||||
// struct vnode* next;
|
|
||||||
|
|
||||||
struct vnode_ops *ops;
|
struct vnode_ops *ops;
|
||||||
void *internal;
|
void *internal;
|
||||||
} vnode_t;
|
} vnode_t;
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
# Soaplin vnodes
|
|
||||||
...
|
|
29
kernel/src/lib/ansi.c
Executable file
29
kernel/src/lib/ansi.c
Executable file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* ansi.c - ANSI escape sequence generation functions implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <deps/npf.h>
|
||||||
|
#include <lib/ansi.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static char __ansi_bg_buf[32];
|
||||||
|
static char __ansi_fg_buf[32];
|
||||||
|
|
||||||
|
char *ansi_gen_bg(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
int len = npf_snprintf(__ansi_bg_buf, sizeof(__ansi_bg_buf), "\033[48;2;%d;%d;%d;m", r, g, b);
|
||||||
|
if (len < 0 || len >= (int)sizeof(__ansi_bg_buf)) {
|
||||||
|
return "\033[0m";
|
||||||
|
}
|
||||||
|
return __ansi_bg_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ansi_gen_fg(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
int len = npf_snprintf(__ansi_fg_buf, sizeof(__ansi_fg_buf), "\033[38;2;%d;%d;%d;m", r, g, b);
|
||||||
|
if (len < 0 || len >= (int)sizeof(__ansi_fg_buf)) {
|
||||||
|
return "\033[0m";
|
||||||
|
}
|
||||||
|
return __ansi_fg_buf;
|
||||||
|
}
|
15
kernel/src/lib/ansi.h
Executable file
15
kernel/src/lib/ansi.h
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* ansi.h - ANSI escape sequence generation functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define ANSI_CLEAR_SCREEN "\033[H\033[2J"
|
||||||
|
#define ANSI_RESET_COLOR "\033[39m\\033[49m"
|
||||||
|
|
||||||
|
char *ansi_gen_bg(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
char *ansi_gen_fg(uint8_t r, uint8_t g, uint8_t b);
|
|
@ -1,18 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
/*int __eqdf2(double a, double b) {
|
|
||||||
union { double f; uint64_t i; } ua = { a }, ub = { b };
|
|
||||||
return ua.i == ub.i;
|
|
||||||
}
|
|
||||||
int __ltdf2(double a, double b) {
|
|
||||||
if (a < b) return -1;
|
|
||||||
if (a > b) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
double __truncxfdf2(double x) {
|
|
||||||
return (double)x;
|
|
||||||
}
|
|
||||||
int __gtdf2(double a, double b) {
|
|
||||||
if (a > b) return 1;
|
|
||||||
if (a < b) return -1;
|
|
||||||
return 0;
|
|
||||||
}**/
|
|
57
kernel/src/lib/log.c
Executable file
57
kernel/src/lib/log.c
Executable file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* log.c - Kernel logging interface.
|
||||||
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <lib/log.h>
|
||||||
|
#include <lib/spinlock.h>
|
||||||
|
|
||||||
|
static int __logger_max_loglevel = 0;
|
||||||
|
static log_output_func __logger_outputs[16];
|
||||||
|
static int __logger_output_count = 0;
|
||||||
|
static spinlock_t __logger_lock;
|
||||||
|
|
||||||
|
static char* prelog[7] = {
|
||||||
|
"\033[38;2;169;68;66;mFAULT | \033[39m",
|
||||||
|
"\033[38;2;217;83;79;mERROR | \033[39m",
|
||||||
|
"\033[38;2;240;173;78;mWARN | \033[39m",
|
||||||
|
"\033[38;2;240;240;240;mNOTICE | \033[39m",
|
||||||
|
"\033[38;2;92;184;92;mINFO | \033[39m",
|
||||||
|
"\033[38;2;87;201;193;mDEBUG | \033[39m",
|
||||||
|
"\033[38;2;150;150;150;mTRACE | \033[39m",
|
||||||
|
};
|
||||||
|
|
||||||
|
void log_init(int max_loglevel) {
|
||||||
|
__logger_max_loglevel = max_loglevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool log_register_output(log_output_func fn) {
|
||||||
|
if (fn && __logger_output_count <= 16) {
|
||||||
|
__logger_output_count ++;
|
||||||
|
__logger_outputs[__logger_output_count - 1] = fn;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log(int loglevel, char *str, ...) {
|
||||||
|
if (__logger_max_loglevel == 0 || __logger_output_count == 0)
|
||||||
|
return; // The user forgot to initialize the logger.
|
||||||
|
|
||||||
|
if (loglevel > __logger_max_loglevel)
|
||||||
|
return; // The user does not want this type of log to show up.
|
||||||
|
|
||||||
|
sl_acquire(&__logger_lock);
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl, str);
|
||||||
|
|
||||||
|
for (int i = 0; i < __logger_output_count; i++) {
|
||||||
|
__logger_outputs[i](prelog[loglevel - 1], (void*)0);
|
||||||
|
__logger_outputs[i](str, &vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(vl);
|
||||||
|
sl_release(&__logger_lock);
|
||||||
|
}
|
35
kernel/src/lib/log.h
Executable file
35
kernel/src/lib/log.h
Executable file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* log.h - Kernel logging interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Log levels in order of increasing severity
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define LOGLEVEL_TRACE 7
|
||||||
|
#define LOGLEVEL_DEBUG 6
|
||||||
|
#define LOGLEVEL_INFO 5
|
||||||
|
#define LOGLEVEL_NOTICE 4
|
||||||
|
#define LOGLEVEL_WARNING 3
|
||||||
|
#define LOGLEVEL_ERROR 2
|
||||||
|
#define LOGLEVEL_FATAL 1
|
||||||
|
|
||||||
|
typedef void(*log_output_func)(char *str, va_list *vl);
|
||||||
|
|
||||||
|
void log_init(int max_loglevel);
|
||||||
|
bool log_register_output(log_output_func fn);
|
||||||
|
void log(int loglevel, char *str, ...);
|
||||||
|
|
||||||
|
// Shortcuts to log
|
||||||
|
#define trace(str, ...) log(LOGLEVEL_TRACE, str, ##__VA_ARGS__)
|
||||||
|
#define debug(str, ...) log(LOGLEVEL_DEBUG, str, ##__VA_ARGS__)
|
||||||
|
#define info(str, ...) log(LOGLEVEL_INFO, str, ##__VA_ARGS__)
|
||||||
|
#define notice(str, ...) log(LOGLEVEL_NOTICE, str, ##__VA_ARGS__)
|
||||||
|
#define warn(str, ...) log(LOGLEVEL_WARNING, str, ##__VA_ARGS__)
|
||||||
|
#define error(str, ...) log(LOGLEVEL_ERROR, str, ##__VA_ARGS__)
|
||||||
|
#define fatal(str, ...) log(LOGLEVEL_FATAL, str, ##__VA_ARGS__)
|
26
kernel/src/lib/logoutputs_sk.c
Executable file
26
kernel/src/lib/logoutputs_sk.c
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* logoutputs_sk.c - Output functions for the logger
|
||||||
|
*/
|
||||||
|
#include "deps/npf.h"
|
||||||
|
#include <dev/tty.h>
|
||||||
|
#include <lib/logoutputs_sk.h>
|
||||||
|
|
||||||
|
void sklogoutput_tty(char *str, va_list *vl) {
|
||||||
|
if (!vl) {
|
||||||
|
tty_puts(str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[2048];
|
||||||
|
npf_vsnprintf(buf, 2048, str, *vl);
|
||||||
|
tty_puts(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sklogoutput_e9(char *str, va_list *vl) {
|
||||||
|
// TODO: implement this
|
||||||
|
(void)str;
|
||||||
|
(void)vl;
|
||||||
|
}
|
16
kernel/src/lib/logoutputs_sk.h
Executable file
16
kernel/src/lib/logoutputs_sk.h
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* logoutputs_sk.h - Output functions for the logger
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Output to the terminal.
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void sklogoutput_tty(char *str, va_list *vl);
|
||||||
|
|
||||||
|
// Output to QEMU & Bochs's E9 port.
|
||||||
|
void sklogoutput_e9(char *str, va_list *vl);
|
18
kernel/src/lib/npf.c
Executable file
18
kernel/src/lib/npf.c
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* npf.c - nanoprintf configuration and implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1
|
||||||
|
#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1
|
||||||
|
#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1
|
||||||
|
#define NANOPRINTF_USE_SMALL_FORMAT_SPECIFIERS 1
|
||||||
|
#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0
|
||||||
|
#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1
|
||||||
|
#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 0
|
||||||
|
|
||||||
|
// Compile nanoprintf in this translation unit.
|
||||||
|
#define NANOPRINTF_IMPLEMENTATION
|
||||||
|
#include <deps/npf.h>
|
25
kernel/src/lib/spinlock.c
Executable file
25
kernel/src/lib/spinlock.c
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* spinlock.c - Spinlock implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <lib/spinlock.h>
|
||||||
|
|
||||||
|
void sl_acquire(spinlock_t volatile *plock)
|
||||||
|
{
|
||||||
|
while (!__sync_bool_compare_and_swap(plock, 0, 1))
|
||||||
|
{
|
||||||
|
while (*plock)
|
||||||
|
{
|
||||||
|
asm("pause");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sl_release(spinlock_t volatile *plock)
|
||||||
|
{
|
||||||
|
__sync_lock_release(plock);
|
||||||
|
}
|
||||||
|
|
38
kernel/src/lib/spinlock.h
Normal file → Executable file
38
kernel/src/lib/spinlock.h
Normal file → Executable file
|
@ -1,31 +1,13 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* spinlock.h - Spinlock definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
typedef unsigned int spinlock_t;
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct spinlock {
|
void sl_acquire(spinlock_t volatile *plock);
|
||||||
volatile int locked;
|
void sl_release(spinlock_t volatile *plock);
|
||||||
} spinlock_t;
|
|
||||||
|
|
||||||
static inline void spinlock_acquire(spinlock_t *lock) {
|
|
||||||
// uint64_t timeout = 1000000; // Adjust this value based on your needs
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (__atomic_exchange_n(&lock->locked, 1, __ATOMIC_ACQUIRE) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (__atomic_load_n(&lock->locked, __ATOMIC_RELAXED)) {
|
|
||||||
/**if (--timeout == 0) {
|
|
||||||
// Force unlock after too many attempts
|
|
||||||
__atomic_store_n(&lock->locked, 0, __ATOMIC_RELEASE);
|
|
||||||
continue;
|
|
||||||
}**/
|
|
||||||
__asm__ volatile("pause" ::: "memory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void spinlock_release(spinlock_t *lock) {
|
|
||||||
__atomic_store_n(&lock->locked, 0, __ATOMIC_RELEASE);
|
|
||||||
}
|
|
145
kernel/src/lib/string.c
Normal file → Executable file
145
kernel/src/lib/string.c
Normal file → Executable file
|
@ -1,134 +1,15 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* string.c - String manipulation functions implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <lib/string.h>
|
#include <lib/string.h>
|
||||||
#include <mm/liballoc/liballoc.h>
|
|
||||||
#include <mm/memop.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
static char *olds;
|
size_t strlen(char *str) {
|
||||||
|
size_t i = 0;
|
||||||
int strlen(const char *str) {
|
while (str[i] != '\0')
|
||||||
int len = 0;
|
i++;
|
||||||
while (str[len])
|
return i;
|
||||||
len++;
|
}
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int strcmp(const char *s1, const char *s2) {
|
|
||||||
while (*s1 && *s1 == *s2) {
|
|
||||||
s1++;
|
|
||||||
s2++;
|
|
||||||
}
|
|
||||||
return *s1 - *s2;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *strcpy(char *dest, const char *src) {
|
|
||||||
if (dest == NULL || src == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
char *temp = dest;
|
|
||||||
while ((*dest++ = *src++) != '\0')
|
|
||||||
;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *strchr(const char *s, int c) {
|
|
||||||
while (*s++) {
|
|
||||||
if (*s == c)
|
|
||||||
return (char *)s;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *strrchr(const char *s, int c) {
|
|
||||||
const char *p = NULL;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (*s == (char)c)
|
|
||||||
p = s;
|
|
||||||
if (*s++ == '\0')
|
|
||||||
return (char *)p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int oct2bin(unsigned char *str, int size) {
|
|
||||||
int n = 0;
|
|
||||||
unsigned char *c = str;
|
|
||||||
while (size-- > 0) {
|
|
||||||
n *= 8;
|
|
||||||
n += *c - '0';
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *strdup(const char *str) {
|
|
||||||
if (str == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
int len = strlen(str);
|
|
||||||
char *dup = (char *)malloc(len + 1);
|
|
||||||
if (dup == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
strcpy(dup, str);
|
|
||||||
return dup;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *strncpy(char *dest, const char *src, size_t n) {
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < n && src[i] != '\0'; i++)
|
|
||||||
dest[i] = src[i];
|
|
||||||
for (; i < n; i++)
|
|
||||||
dest[i] = '\0';
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DICT_LEN 256
|
|
||||||
|
|
||||||
static int *create_delim_dict(char *delim) {
|
|
||||||
int *d = (int *)malloc(sizeof(int) * DICT_LEN);
|
|
||||||
memset((void *)d, 0, sizeof(int) * DICT_LEN);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < strlen(delim); i++) {
|
|
||||||
d[delim[i]] = 1;
|
|
||||||
}
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *strtok(char *str, char *delim) {
|
|
||||||
|
|
||||||
static char *last, *to_free;
|
|
||||||
int *deli_dict = create_delim_dict(delim);
|
|
||||||
|
|
||||||
if (!deli_dict) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str) {
|
|
||||||
last = (char *)malloc(strlen(str) + 1);
|
|
||||||
if (!last) {
|
|
||||||
free(deli_dict);
|
|
||||||
}
|
|
||||||
to_free = last;
|
|
||||||
strcpy(last, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (deli_dict[*last] && *last != '\0') {
|
|
||||||
last++;
|
|
||||||
}
|
|
||||||
str = last;
|
|
||||||
if (*last == '\0') {
|
|
||||||
free(deli_dict);
|
|
||||||
free(to_free);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
while (*last != '\0' && !deli_dict[*last]) {
|
|
||||||
last++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*last = '\0';
|
|
||||||
last++;
|
|
||||||
|
|
||||||
free(deli_dict);
|
|
||||||
return str;
|
|
||||||
}
|
|
18
kernel/src/lib/string.h
Normal file → Executable file
18
kernel/src/lib/string.h
Normal file → Executable file
|
@ -1,12 +1,12 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* string.h - String manipulation functions.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
int strlen(const char *str);
|
size_t strlen(char *str);
|
||||||
int strcmp(const char *s1, const char *s2);
|
|
||||||
char *strchr(const char *s, int c);
|
|
||||||
char *strcpy(char *dest, const char *src);
|
|
||||||
char *strrchr(const char *s, int c);
|
|
||||||
int oct2bin(unsigned char *str, int size);
|
|
||||||
char *strdup(const char *str);
|
|
||||||
char *strncpy(char *dest, const char *src, size_t n);
|
|
||||||
char *strtok(char *str, char *delim);
|
|
175
kernel/src/main.c
Normal file → Executable file
175
kernel/src/main.c
Normal file → Executable file
|
@ -1,141 +1,56 @@
|
||||||
#include "arch/x86_64/pit.h"
|
/*
|
||||||
#include "arch/x86_64/smp.h"
|
* The Soaplin Kernel
|
||||||
#include "arch/x86_64/sse.h"
|
* Copyright (C) 2025 The SILD Project
|
||||||
#include "dbg/sym.h"
|
*
|
||||||
#include "dev/ioapic.h"
|
* main.c - Kernel entry point and initialization.
|
||||||
#include "dev/lapic.h"
|
*/
|
||||||
#include "exec/elf.h"
|
|
||||||
#include "exec/exec.h"
|
|
||||||
#include "fs/hellofs.h"
|
|
||||||
#include "mm/liballoc/liballoc.h"
|
|
||||||
#include "mm/pmm.h"
|
|
||||||
#include "mm/vma.h"
|
|
||||||
#include "mm/vmm.h"
|
|
||||||
#include "sched/sched.h"
|
|
||||||
#include "sys/acpi.h"
|
|
||||||
#include "sys/acpi/madt.h"
|
|
||||||
#include "sys/syscall.h"
|
|
||||||
#include <arch/x86_64/fpu.h>
|
|
||||||
#include <arch/x86_64/gdt.h>
|
|
||||||
#include <arch/x86_64/idt.h>
|
|
||||||
#include <font.h>
|
|
||||||
#include <fs/vfs.h>
|
|
||||||
#include <limine.h>
|
|
||||||
#include <mm/memop.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/errhnd/panic.h>
|
#include <stddef.h>
|
||||||
#include <sys/gfx/flanterm/backends/fb.h>
|
#include <stdbool.h>
|
||||||
#include <sys/gfx/flanterm/flanterm.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
#include <sys/printf.h>
|
|
||||||
|
|
||||||
__attribute__((
|
#include <acpi/acpi.h>
|
||||||
used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3);
|
#include <acpi/madt.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
#include <boot/limine.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <dev/tty.h>
|
||||||
|
#include <lib/ansi.h>
|
||||||
|
#include <lib/log.h>
|
||||||
|
#include <lib/logoutputs_sk.h>
|
||||||
|
#include <mm/memop.h>
|
||||||
|
#include <mm/pmm.h>
|
||||||
|
#include "arch/x86_64/smp.h"
|
||||||
|
#include "mm/paging.h"
|
||||||
|
#include "mm/vma.h"
|
||||||
|
|
||||||
__attribute__((
|
void kmain(void) {
|
||||||
used,
|
tty_init();
|
||||||
section(
|
log_init(LOGLEVEL_TRACE);
|
||||||
".limine_requests"))) static volatile struct limine_framebuffer_request
|
log_register_output(sklogoutput_tty);
|
||||||
framebuffer_request = {.id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0};
|
|
||||||
|
|
||||||
__attribute__((
|
limine_bootinfo_t *bi = limine_get_bootinfo();
|
||||||
used,
|
info("%s %s-%s (booted using %s %s, with firmware type %d)\n", KERNEL_NAME, KERNEL_VER,
|
||||||
section(".limine_requests"))) static volatile struct limine_module_request
|
bi->arch, bi->bl_name, bi->bl_ver, bi->fw_type);
|
||||||
module_request = {.id = LIMINE_MODULE_REQUEST, .revision = 0};
|
|
||||||
|
|
||||||
__attribute__((used,
|
arch_init_stage1();
|
||||||
section(".limine_requests_"
|
|
||||||
"start"))) static volatile LIMINE_REQUESTS_START_MARKER;
|
|
||||||
|
|
||||||
__attribute__((
|
pmm_init();
|
||||||
used,
|
pg_init();
|
||||||
section(
|
|
||||||
".limine_requests_end"))) static volatile LIMINE_REQUESTS_END_MARKER;
|
acpi_init();
|
||||||
|
madt_init();
|
||||||
|
|
||||||
struct limine_framebuffer *fb;
|
cpu_init_apic();
|
||||||
struct flanterm_context *ft_ctx;
|
cpu_init_smp();
|
||||||
|
cpu_init_timer();
|
||||||
|
|
||||||
char kstack[8192];
|
|
||||||
|
cpu_enable_ints(1);
|
||||||
|
//lapic_ipi(bootstrap_lapic_id, 32);
|
||||||
|
|
||||||
void __kmain(void) {
|
|
||||||
if (framebuffer_request.response != NULL) {
|
|
||||||
|
|
||||||
struct limine_framebuffer *framebuffer =
|
|
||||||
framebuffer_request.response->framebuffers[0];
|
|
||||||
fb = framebuffer;
|
|
||||||
|
|
||||||
ft_ctx = flanterm_fb_init(
|
|
||||||
NULL, NULL, framebuffer->address, framebuffer->width,
|
|
||||||
framebuffer->height, framebuffer->pitch, framebuffer->red_mask_size,
|
|
||||||
framebuffer->red_mask_shift, framebuffer->green_mask_size,
|
|
||||||
framebuffer->green_mask_shift, framebuffer->blue_mask_size,
|
|
||||||
framebuffer->blue_mask_shift, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
VGA8, 8, 16, 0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n Soaplin 0.7-sild is booting up your computer...\n\n");
|
|
||||||
|
|
||||||
gdt_init(&kstack[8192]);
|
|
||||||
idt_init();
|
|
||||||
pmm_init();
|
|
||||||
vmm_init();
|
|
||||||
|
|
||||||
kernel_vma_context = vma_create_context(vmm_kernel_pm);
|
|
||||||
if (!kernel_vma_context) {
|
|
||||||
log("kernel - vma ctx creation failed. halting\n");
|
|
||||||
asm("cli");
|
|
||||||
while (1)
|
while (1)
|
||||||
asm("hlt");
|
;;
|
||||||
}
|
// We're done, just hang... for now.
|
||||||
|
//hcf();
|
||||||
ksym_init();
|
|
||||||
func *f = ksym_fromip((uint64_t)__kmain);
|
|
||||||
if (f) {
|
|
||||||
log("ksym: found %s at %p\n", f->name, f->ip);
|
|
||||||
} else {
|
|
||||||
log("ksym: not found\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
acpi_init();
|
|
||||||
madt_init();
|
|
||||||
ioapic_init();
|
|
||||||
lapic_init();
|
|
||||||
pit_init();
|
|
||||||
smp_init();
|
|
||||||
|
|
||||||
vfs_init();
|
|
||||||
fs_t *hellofs = hellofs_init();
|
|
||||||
vfs_mount("/", hellofs);
|
|
||||||
|
|
||||||
vnode_t *vn;
|
|
||||||
vfs_open(NULL, "/hello", &vn);
|
|
||||||
if (vn) {
|
|
||||||
char buf[100];
|
|
||||||
vfs_read(vn, buf, 2, sizeof(buf));
|
|
||||||
log("Read from /hello: %s\n", buf);
|
|
||||||
} else {
|
|
||||||
log("Failed to open /hello\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
syscall_init();
|
|
||||||
sched_init();
|
|
||||||
|
|
||||||
// vfs_init();
|
|
||||||
|
|
||||||
// panic("No working initialization program found. (This is normal due to "
|
|
||||||
// "Soaplin's current state, so please do not report this as a bug)");
|
|
||||||
|
|
||||||
program_t *p = elf_load(module_request.response->modules[0]->address, 1);
|
|
||||||
|
|
||||||
|
|
||||||
sched_process *proc =
|
|
||||||
sched_from_program(p);
|
|
||||||
|
|
||||||
log("kernel - Soaplin initialized sucessfully.\n");
|
|
||||||
|
|
||||||
pit_enable();
|
|
||||||
while (1)
|
|
||||||
;;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,586 +0,0 @@
|
||||||
// Copyright: Durand Miller <clutter@djm.co.za>
|
|
||||||
#include <mm/liballoc/liballoc.h>
|
|
||||||
|
|
||||||
// very dirty way of disabling logging in liballoc
|
|
||||||
#define log(...) (void)0
|
|
||||||
|
|
||||||
#define VERSION "1.1"
|
|
||||||
#define ALIGNMENT 16ul
|
|
||||||
|
|
||||||
#define ALIGN_TYPE char
|
|
||||||
#define ALIGN_INFO sizeof(ALIGN_TYPE) * 16
|
|
||||||
|
|
||||||
#define USE_CASE1
|
|
||||||
#define USE_CASE2
|
|
||||||
#define USE_CASE3
|
|
||||||
#define USE_CASE4
|
|
||||||
#define USE_CASE5
|
|
||||||
|
|
||||||
#define ALIGN(ptr) \
|
|
||||||
if (ALIGNMENT > 1) { \
|
|
||||||
uintptr_t diff; \
|
|
||||||
ptr = (void *)((uintptr_t)ptr + ALIGN_INFO); \
|
|
||||||
diff = (uintptr_t)ptr & (ALIGNMENT - 1); \
|
|
||||||
if (diff != 0) { \
|
|
||||||
diff = ALIGNMENT - diff; \
|
|
||||||
ptr = (void *)((uintptr_t)ptr + diff); \
|
|
||||||
} \
|
|
||||||
*((ALIGN_TYPE *)((uintptr_t)ptr - ALIGN_INFO)) = diff + ALIGN_INFO; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define UNALIGN(ptr) \
|
|
||||||
if (ALIGNMENT > 1) { \
|
|
||||||
uintptr_t diff = *((ALIGN_TYPE *)((uintptr_t)ptr - ALIGN_INFO)); \
|
|
||||||
if (diff < (ALIGNMENT + ALIGN_INFO)) { \
|
|
||||||
ptr = (void *)((uintptr_t)ptr - diff); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LIBALLOC_MAGIC 0xc001c0de
|
|
||||||
#define LIBALLOC_DEAD 0xdeaddead
|
|
||||||
|
|
||||||
struct liballoc_major {
|
|
||||||
struct liballoc_major *prev;
|
|
||||||
struct liballoc_major *next;
|
|
||||||
unsigned int pages;
|
|
||||||
unsigned int size;
|
|
||||||
unsigned int usage;
|
|
||||||
struct liballoc_minor *first;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct liballoc_minor {
|
|
||||||
struct liballoc_minor *prev;
|
|
||||||
struct liballoc_minor *next;
|
|
||||||
struct liballoc_major *block;
|
|
||||||
unsigned int magic;
|
|
||||||
unsigned int size;
|
|
||||||
unsigned int req_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct liballoc_major *l_memRoot = NULL;
|
|
||||||
static struct liballoc_major *l_bestBet = NULL;
|
|
||||||
|
|
||||||
static unsigned int l_pageSize = 4096;
|
|
||||||
static unsigned int l_pageCount = 16;
|
|
||||||
static unsigned long long l_allocated = 0;
|
|
||||||
static unsigned long long l_inuse = 0;
|
|
||||||
|
|
||||||
static long long l_warningCount = 0;
|
|
||||||
static long long l_errorCount = 0;
|
|
||||||
static long long l_possibleOverruns = 0;
|
|
||||||
|
|
||||||
static void *liballoc_memset(void *s, int c, size_t n) {
|
|
||||||
unsigned int i;
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
((char *)s)[i] = c;
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
static void *liballoc_memcpy(void *s1, const void *s2, size_t n) {
|
|
||||||
char *cdest;
|
|
||||||
char *csrc;
|
|
||||||
unsigned int *ldest = (unsigned int *)s1;
|
|
||||||
unsigned int *lsrc = (unsigned int *)s2;
|
|
||||||
|
|
||||||
while (n >= sizeof(unsigned int)) {
|
|
||||||
*ldest++ = *lsrc++;
|
|
||||||
n -= sizeof(unsigned int);
|
|
||||||
}
|
|
||||||
|
|
||||||
cdest = (char *)ldest;
|
|
||||||
csrc = (char *)lsrc;
|
|
||||||
|
|
||||||
while (n > 0) {
|
|
||||||
*cdest++ = *csrc++;
|
|
||||||
n -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if _DEBUG
|
|
||||||
void liballoc_dump() {
|
|
||||||
#ifdef _DEBUG
|
|
||||||
struct liballoc_major *maj = l_memRoot;
|
|
||||||
struct liballoc_minor *min = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
info("------ Memory data ---------------");
|
|
||||||
info("System memory allocated: %i bytes", l_allocated);
|
|
||||||
info("Memory in used (malloc'ed): %i bytes", l_inuse);
|
|
||||||
info("Warning count: %i", l_warningCount);
|
|
||||||
info("Error count: %i", l_errorCount);
|
|
||||||
info("Possible overruns: %i", l_possibleOverruns);
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
while (maj != NULL) {
|
|
||||||
info("%x: total = %i, used = %i", maj, maj->size, maj->usage);
|
|
||||||
|
|
||||||
min = maj->first;
|
|
||||||
while (min != NULL) {
|
|
||||||
info(" %x: %i bytes", min, min->size);
|
|
||||||
min = min->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
maj = maj->next;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void liballoc_dump() { return; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct liballoc_major *allocate_new_page(unsigned int size) {
|
|
||||||
unsigned int st;
|
|
||||||
struct liballoc_major *maj;
|
|
||||||
|
|
||||||
st = size + sizeof(struct liballoc_major);
|
|
||||||
st += sizeof(struct liballoc_minor);
|
|
||||||
|
|
||||||
if ((st % l_pageSize) == 0)
|
|
||||||
st = st / (l_pageSize);
|
|
||||||
else
|
|
||||||
st = st / (l_pageSize) + 1;
|
|
||||||
|
|
||||||
if (st < l_pageCount)
|
|
||||||
st = l_pageCount;
|
|
||||||
|
|
||||||
maj = (struct liballoc_major *)liballoc_alloc(st);
|
|
||||||
|
|
||||||
if (maj == NULL) {
|
|
||||||
l_warningCount += 1;
|
|
||||||
log("liballoc - (warning) liballoc_alloc( %i ) return NULL", st);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
maj->prev = NULL;
|
|
||||||
maj->next = NULL;
|
|
||||||
maj->pages = st;
|
|
||||||
maj->size = st * l_pageSize;
|
|
||||||
maj->usage = sizeof(struct liballoc_major);
|
|
||||||
maj->first = NULL;
|
|
||||||
|
|
||||||
l_allocated += maj->size;
|
|
||||||
|
|
||||||
log("liballoc - Resource allocated %x of %i pages (%i bytes) for %i size.",
|
|
||||||
maj, st, maj->size, size);
|
|
||||||
log("liballoc - Total memory usage = %i KB", (int)((l_allocated / (1024))));
|
|
||||||
|
|
||||||
return maj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *PREFIX(malloc)(size_t req_size) {
|
|
||||||
int startedBet = 0;
|
|
||||||
unsigned long long bestSize = 0;
|
|
||||||
void *p = NULL;
|
|
||||||
uintptr_t diff;
|
|
||||||
struct liballoc_major *maj;
|
|
||||||
struct liballoc_minor *min;
|
|
||||||
struct liballoc_minor *new_min;
|
|
||||||
unsigned long size = req_size;
|
|
||||||
|
|
||||||
if (ALIGNMENT > 1) {
|
|
||||||
size += ALIGNMENT + ALIGN_INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
liballoc_lock();
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
l_warningCount += 1;
|
|
||||||
log("liballoc - (warning) alloc( 0 ) called from %x",
|
|
||||||
__builtin_return_address(0));
|
|
||||||
|
|
||||||
liballoc_unlock();
|
|
||||||
return PREFIX(malloc)(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l_memRoot == NULL) {
|
|
||||||
log("liballoc - initialization of liballoc " VERSION "");
|
|
||||||
l_memRoot = allocate_new_page(size);
|
|
||||||
if (l_memRoot == NULL) {
|
|
||||||
liballoc_unlock();
|
|
||||||
log("liballoc - initial l_memRoot initialization failed", p);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
log("liballoc - set up first memory major %x", l_memRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
log("liballoc - %x PREFIX(malloc)( %i ): ", __builtin_return_address(0),
|
|
||||||
size);
|
|
||||||
|
|
||||||
maj = l_memRoot;
|
|
||||||
startedBet = 0;
|
|
||||||
|
|
||||||
if (l_bestBet != NULL) {
|
|
||||||
bestSize = l_bestBet->size - l_bestBet->usage;
|
|
||||||
|
|
||||||
if (bestSize > (size + sizeof(struct liballoc_minor))) {
|
|
||||||
maj = l_bestBet;
|
|
||||||
startedBet = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (maj != NULL) {
|
|
||||||
diff = maj->size - maj->usage;
|
|
||||||
|
|
||||||
if (bestSize < diff) {
|
|
||||||
|
|
||||||
l_bestBet = maj;
|
|
||||||
bestSize = diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_CASE1
|
|
||||||
|
|
||||||
if (diff < (size + sizeof(struct liballoc_minor))) {
|
|
||||||
log("liballoc - (warning) CASE 1: Insufficient space in block %x", maj);
|
|
||||||
|
|
||||||
if (maj->next != NULL) {
|
|
||||||
maj = maj->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startedBet == 1) {
|
|
||||||
maj = l_memRoot;
|
|
||||||
startedBet = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
maj->next = allocate_new_page(size);
|
|
||||||
if (maj->next == NULL)
|
|
||||||
break;
|
|
||||||
maj->next->prev = maj;
|
|
||||||
maj = maj->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_CASE2
|
|
||||||
|
|
||||||
if (maj->first == NULL) {
|
|
||||||
maj->first = (struct liballoc_minor *)((uintptr_t)maj +
|
|
||||||
sizeof(struct liballoc_major));
|
|
||||||
|
|
||||||
maj->first->magic = LIBALLOC_MAGIC;
|
|
||||||
maj->first->prev = NULL;
|
|
||||||
maj->first->next = NULL;
|
|
||||||
maj->first->block = maj;
|
|
||||||
maj->first->size = size;
|
|
||||||
maj->first->req_size = req_size;
|
|
||||||
maj->usage += size + sizeof(struct liballoc_minor);
|
|
||||||
|
|
||||||
l_inuse += size;
|
|
||||||
|
|
||||||
p = (void *)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor));
|
|
||||||
|
|
||||||
ALIGN(p);
|
|
||||||
|
|
||||||
log("liballoc - (warning) CASE 2: returning %x", p);
|
|
||||||
liballoc_unlock();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_CASE3
|
|
||||||
|
|
||||||
diff = (uintptr_t)(maj->first);
|
|
||||||
diff -= (uintptr_t)maj;
|
|
||||||
diff -= sizeof(struct liballoc_major);
|
|
||||||
|
|
||||||
if (diff >= (size + sizeof(struct liballoc_minor))) {
|
|
||||||
|
|
||||||
maj->first->prev =
|
|
||||||
(struct liballoc_minor *)((uintptr_t)maj +
|
|
||||||
sizeof(struct liballoc_major));
|
|
||||||
maj->first->prev->next = maj->first;
|
|
||||||
maj->first = maj->first->prev;
|
|
||||||
|
|
||||||
maj->first->magic = LIBALLOC_MAGIC;
|
|
||||||
maj->first->prev = NULL;
|
|
||||||
maj->first->block = maj;
|
|
||||||
maj->first->size = size;
|
|
||||||
maj->first->req_size = req_size;
|
|
||||||
maj->usage += size + sizeof(struct liballoc_minor);
|
|
||||||
|
|
||||||
l_inuse += size;
|
|
||||||
|
|
||||||
p = (void *)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor));
|
|
||||||
ALIGN(p);
|
|
||||||
|
|
||||||
log("liballoc - (warning) CASE 3: returning %x", p);
|
|
||||||
liballoc_unlock();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_CASE4
|
|
||||||
|
|
||||||
min = maj->first;
|
|
||||||
|
|
||||||
while (min != NULL) {
|
|
||||||
|
|
||||||
if (min->next == NULL) {
|
|
||||||
|
|
||||||
diff = (uintptr_t)(maj) + maj->size;
|
|
||||||
diff -= (uintptr_t)min;
|
|
||||||
diff -= sizeof(struct liballoc_minor);
|
|
||||||
diff -= min->size;
|
|
||||||
|
|
||||||
if (diff >= (size + sizeof(struct liballoc_minor))) {
|
|
||||||
|
|
||||||
min->next = (struct liballoc_minor *)((uintptr_t)min +
|
|
||||||
sizeof(struct liballoc_minor) +
|
|
||||||
min->size);
|
|
||||||
min->next->prev = min;
|
|
||||||
min = min->next;
|
|
||||||
min->next = NULL;
|
|
||||||
min->magic = LIBALLOC_MAGIC;
|
|
||||||
min->block = maj;
|
|
||||||
min->size = size;
|
|
||||||
min->req_size = req_size;
|
|
||||||
maj->usage += size + sizeof(struct liballoc_minor);
|
|
||||||
|
|
||||||
l_inuse += size;
|
|
||||||
|
|
||||||
p = (void *)((uintptr_t)min + sizeof(struct liballoc_minor));
|
|
||||||
ALIGN(p);
|
|
||||||
|
|
||||||
log("liballoc - (warning) CASE 4.1: returning %x", p);
|
|
||||||
liballoc_unlock();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (min->next != NULL) {
|
|
||||||
|
|
||||||
diff = (uintptr_t)(min->next);
|
|
||||||
diff -= (uintptr_t)min;
|
|
||||||
diff -= sizeof(struct liballoc_minor);
|
|
||||||
diff -= min->size;
|
|
||||||
|
|
||||||
if (diff >= (size + sizeof(struct liballoc_minor))) {
|
|
||||||
|
|
||||||
new_min = (struct liballoc_minor *)((uintptr_t)min +
|
|
||||||
sizeof(struct liballoc_minor) +
|
|
||||||
min->size);
|
|
||||||
|
|
||||||
new_min->magic = LIBALLOC_MAGIC;
|
|
||||||
new_min->next = min->next;
|
|
||||||
new_min->prev = min;
|
|
||||||
new_min->size = size;
|
|
||||||
new_min->req_size = req_size;
|
|
||||||
new_min->block = maj;
|
|
||||||
min->next->prev = new_min;
|
|
||||||
min->next = new_min;
|
|
||||||
maj->usage += size + sizeof(struct liballoc_minor);
|
|
||||||
|
|
||||||
l_inuse += size;
|
|
||||||
|
|
||||||
p = (void *)((uintptr_t)new_min + sizeof(struct liballoc_minor));
|
|
||||||
ALIGN(p);
|
|
||||||
|
|
||||||
log("liballoc - (warning) CASE 4.2: returning %x", p);
|
|
||||||
liballoc_unlock();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
min = min->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_CASE5
|
|
||||||
|
|
||||||
if (maj->next == NULL) {
|
|
||||||
log("liballoc - (warning) CASE 5: block full");
|
|
||||||
|
|
||||||
if (startedBet == 1) {
|
|
||||||
maj = l_memRoot;
|
|
||||||
startedBet = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
maj->next = allocate_new_page(size);
|
|
||||||
if (maj->next == NULL)
|
|
||||||
break;
|
|
||||||
maj->next->prev = maj;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
maj = maj->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
liballoc_unlock();
|
|
||||||
|
|
||||||
log("liballoc - (warning) All cases exhausted. No memory available.");
|
|
||||||
log("liballoc - (warning) PREFIX(malloc)( %i ) returning NULL.", size);
|
|
||||||
liballoc_dump();
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PREFIX(free)(void *ptr) {
|
|
||||||
struct liballoc_minor *min;
|
|
||||||
struct liballoc_major *maj;
|
|
||||||
|
|
||||||
if (ptr == NULL) {
|
|
||||||
l_warningCount += 1;
|
|
||||||
log("liballoc - (warning) PREFIX(free)( NULL ) called from %x",
|
|
||||||
__builtin_return_address(0));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UNALIGN(ptr);
|
|
||||||
|
|
||||||
liballoc_lock();
|
|
||||||
|
|
||||||
min =
|
|
||||||
(struct liballoc_minor *)((uintptr_t)ptr - sizeof(struct liballoc_minor));
|
|
||||||
|
|
||||||
if (min->magic != LIBALLOC_MAGIC) {
|
|
||||||
l_errorCount += 1;
|
|
||||||
|
|
||||||
if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
|
|
||||||
((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
|
|
||||||
((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
|
|
||||||
l_possibleOverruns += 1;
|
|
||||||
log("liballoc - (warning) Possible 1-3 byte overrun for magic %x != %x",
|
|
||||||
min->magic, LIBALLOC_MAGIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (min->magic == LIBALLOC_DEAD) {
|
|
||||||
log("liballoc - multiple PREFIX(free)() attempt on %x from %x.", ptr,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
} else {
|
|
||||||
log("liballoc - Bad PREFIX(free)( %x ) called from %x", ptr,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
liballoc_unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log("liballoc - %x PREFIX(free)( %x ): ", __builtin_return_address(0), ptr);
|
|
||||||
|
|
||||||
maj = min->block;
|
|
||||||
|
|
||||||
l_inuse -= min->size;
|
|
||||||
|
|
||||||
maj->usage -= (min->size + sizeof(struct liballoc_minor));
|
|
||||||
min->magic = LIBALLOC_DEAD;
|
|
||||||
|
|
||||||
if (min->next != NULL)
|
|
||||||
min->next->prev = min->prev;
|
|
||||||
if (min->prev != NULL)
|
|
||||||
min->prev->next = min->next;
|
|
||||||
|
|
||||||
if (min->prev == NULL)
|
|
||||||
maj->first = min->next;
|
|
||||||
|
|
||||||
if (maj->first == NULL) {
|
|
||||||
if (l_memRoot == maj)
|
|
||||||
l_memRoot = maj->next;
|
|
||||||
if (l_bestBet == maj)
|
|
||||||
l_bestBet = NULL;
|
|
||||||
if (maj->prev != NULL)
|
|
||||||
maj->prev->next = maj->next;
|
|
||||||
if (maj->next != NULL)
|
|
||||||
maj->next->prev = maj->prev;
|
|
||||||
l_allocated -= maj->size;
|
|
||||||
|
|
||||||
liballoc_free(maj, maj->pages);
|
|
||||||
} else {
|
|
||||||
if (l_bestBet != NULL) {
|
|
||||||
int bestSize = l_bestBet->size - l_bestBet->usage;
|
|
||||||
int majSize = maj->size - maj->usage;
|
|
||||||
|
|
||||||
if (majSize > bestSize)
|
|
||||||
l_bestBet = maj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log("liballoc - (warning) OK");
|
|
||||||
|
|
||||||
liballoc_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void *PREFIX(calloc)(size_t nobj, size_t size) {
|
|
||||||
int real_size;
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
real_size = nobj * size;
|
|
||||||
|
|
||||||
p = PREFIX(malloc)(real_size);
|
|
||||||
|
|
||||||
liballoc_memset(p, 0, real_size);
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *PREFIX(realloc)(void *p, size_t size) {
|
|
||||||
void *ptr;
|
|
||||||
struct liballoc_minor *min;
|
|
||||||
unsigned int real_size;
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
PREFIX(free)
|
|
||||||
(p);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
return PREFIX(malloc)(size);
|
|
||||||
|
|
||||||
ptr = p;
|
|
||||||
UNALIGN(ptr);
|
|
||||||
|
|
||||||
liballoc_lock();
|
|
||||||
|
|
||||||
min =
|
|
||||||
(struct liballoc_minor *)((uintptr_t)ptr - sizeof(struct liballoc_minor));
|
|
||||||
|
|
||||||
if (min->magic != LIBALLOC_MAGIC) {
|
|
||||||
l_errorCount += 1;
|
|
||||||
|
|
||||||
if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
|
|
||||||
((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
|
|
||||||
((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
|
|
||||||
l_possibleOverruns += 1;
|
|
||||||
log("liballoc - Possible 1-3 byte overrun for magic %x != %x", min->magic,
|
|
||||||
LIBALLOC_MAGIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (min->magic == LIBALLOC_DEAD) {
|
|
||||||
log("liballoc - liballoc: multiple PREFIX(free)() attempt on %x from %x.",
|
|
||||||
ptr, __builtin_return_address(0));
|
|
||||||
} else {
|
|
||||||
log("liballoc - liballoc: Bad PREFIX(free)( %x ) called from %x", ptr,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
liballoc_unlock();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
real_size = min->req_size;
|
|
||||||
|
|
||||||
if (real_size >= size) {
|
|
||||||
min->req_size = size;
|
|
||||||
liballoc_unlock();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
liballoc_unlock();
|
|
||||||
|
|
||||||
ptr = PREFIX(malloc)(size);
|
|
||||||
liballoc_memcpy(ptr, p, real_size);
|
|
||||||
PREFIX(free)
|
|
||||||
(p);
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
// Copyright: Durand Miller <clutter@djm.co.za>
|
|
||||||
#ifndef LIBALLOC_H
|
|
||||||
#define LIBALLOC_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
|
|
||||||
#define PREFIX(func) func
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
void liballoc_dump();
|
|
||||||
#endif // _DEBUG
|
|
||||||
|
|
||||||
extern int liballoc_lock();
|
|
||||||
extern int liballoc_unlock();
|
|
||||||
extern void *liballoc_alloc(size_t);
|
|
||||||
extern int liballoc_free(void *, size_t);
|
|
||||||
|
|
||||||
extern void *PREFIX(malloc)(size_t);
|
|
||||||
extern void *PREFIX(realloc)(void *, size_t);
|
|
||||||
extern void *PREFIX(calloc)(size_t, size_t);
|
|
||||||
extern void PREFIX(free)(void *);
|
|
||||||
|
|
||||||
#endif // LIBALLOC_H
|
|
|
@ -1,34 +0,0 @@
|
||||||
#include "mm/liballoc/liballoc.h"
|
|
||||||
#include "mm/vmm.h"
|
|
||||||
#include <lib/spinlock.h>
|
|
||||||
#include <mm/vma.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
extern vma_context_t *kernel_vma_context;
|
|
||||||
|
|
||||||
static spinlock_t liballoc_lock_var = {0};
|
|
||||||
|
|
||||||
int liballoc_lock() {
|
|
||||||
spinlock_acquire(&liballoc_lock_var);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int liballoc_unlock() {
|
|
||||||
spinlock_release(&liballoc_lock_var);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *liballoc_alloc(size_t pages) {
|
|
||||||
return vma_alloc(kernel_vma_context, pages, VMM_PRESENT | VMM_WRITABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int liballoc_free(void *ptr, size_t pages) {
|
|
||||||
(void)pages;
|
|
||||||
vma_free(kernel_vma_context, ptr);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// void *malloc(size_t s) { return PREFIX(malloc)(s); }
|
|
||||||
// void *realloc(void *v, size_t s) { return PREFIX(realloc)(v, s); }
|
|
||||||
// void *calloc(size_t s1, size_t s) { return PREFIX(calloc)(s1, s); }
|
|
||||||
// void free(void *v) { return PREFIX(free)(v); }
|
|
72
kernel/src/mm/memop.c
Normal file → Executable file
72
kernel/src/mm/memop.c
Normal file → Executable file
|
@ -1,58 +1,60 @@
|
||||||
// Copyright (C) 2024 Sipaa Projects
|
/*
|
||||||
// This code is part of the Soaplin kernel and is licensed under the terms of
|
* The Soaplin Kernel
|
||||||
// the MIT License.
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* memop.c - Memory operations implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "mm/pmm.h"
|
#include <mm/memop.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void *memcpy(void *dest, const void *src, size_t n) {
|
void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
|
||||||
uint8_t *pdest = (uint8_t *)dest;
|
uint8_t *restrict pdest = (uint8_t *restrict)dest;
|
||||||
const uint8_t *psrc = (const uint8_t *)src;
|
const uint8_t *restrict psrc = (const uint8_t *restrict)src;
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
pdest[i] = psrc[i];
|
pdest[i] = psrc[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memset(void *s, int c, size_t n) {
|
void *memset(void *s, int c, size_t n) {
|
||||||
uint8_t *p = (uint8_t *)s;
|
uint8_t *p = (uint8_t *)s;
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
p[i] = (uint8_t)c;
|
p[i] = (uint8_t)c;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memmove(void *dest, const void *src, size_t n) {
|
void *memmove(void *dest, const void *src, size_t n) {
|
||||||
uint8_t *pdest = (uint8_t *)dest;
|
uint8_t *pdest = (uint8_t *)dest;
|
||||||
const uint8_t *psrc = (const uint8_t *)src;
|
const uint8_t *psrc = (const uint8_t *)src;
|
||||||
|
|
||||||
if (src > dest) {
|
if (src > dest) {
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
pdest[i] = psrc[i];
|
pdest[i] = psrc[i];
|
||||||
|
}
|
||||||
|
} else if (src < dest) {
|
||||||
|
for (size_t i = n; i > 0; i--) {
|
||||||
|
pdest[i-1] = psrc[i-1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (src < dest) {
|
|
||||||
for (size_t i = n; i > 0; i--) {
|
|
||||||
pdest[i - 1] = psrc[i - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||||
const uint8_t *p1 = (const uint8_t *)s1;
|
const uint8_t *p1 = (const uint8_t *)s1;
|
||||||
const uint8_t *p2 = (const uint8_t *)s2;
|
const uint8_t *p2 = (const uint8_t *)s2;
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
if (p1[i] != p2[i]) {
|
if (p1[i] != p2[i]) {
|
||||||
return p1[i] < p2[i] ? -1 : 1;
|
return p1[i] < p2[i] ? -1 : 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -1,13 +1,15 @@
|
||||||
// Copyright (C) 2024 Sipaa Projects
|
/*
|
||||||
// This code is part of the Soaplin kernel and is licensed under the terms of
|
* The Soaplin Kernel
|
||||||
// the MIT License.
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* memop.h - Memory operations declarations.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
void *memcpy(void *dest, const void *src, size_t n);
|
void *memcpy(void *restrict dest, const void *restrict src, size_t n);
|
||||||
void *memset(void *s, int c, size_t n);
|
void *memset(void *s, int c, size_t n);
|
||||||
void *memmove(void *dest, const void *src, size_t n);
|
void *memmove(void *dest, const void *src, size_t n);
|
||||||
int memcmp(const void *s1, const void *s2, size_t n);
|
int memcmp(const void *s1, const void *s2, size_t n);
|
214
kernel/src/mm/paging.c
Executable file
214
kernel/src/mm/paging.c
Executable file
|
@ -0,0 +1,214 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* vmm.c - Virtual memory manager
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
#include <boot/limine.h>
|
||||||
|
#include <lib/log.h>
|
||||||
|
#include <mm/memop.h>
|
||||||
|
#include <mm/paging.h>
|
||||||
|
#include <mm/pmm.h>
|
||||||
|
#include <proc/exec/elf.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
pagemap_t pg_kernel_pm = NULL;
|
||||||
|
pagemap_t pg_current_pm = NULL;
|
||||||
|
|
||||||
|
void pg_init() {
|
||||||
|
#if !defined(__x86_64__)
|
||||||
|
fatal("vmm: not implemented\n");
|
||||||
|
hcf();
|
||||||
|
#endif
|
||||||
|
// Our objective here is to recreate the
|
||||||
|
// kernel page map that Limine provide us
|
||||||
|
|
||||||
|
pg_kernel_pm = pg_alloc_pm();
|
||||||
|
|
||||||
|
uint64_t kvaddr = limine_get_kernel_vaddr();
|
||||||
|
uint64_t kpaddr = limine_get_kernel_paddr();
|
||||||
|
|
||||||
|
char *elf_addr = (char *)limine_get_kernel_ehdr_addr();
|
||||||
|
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)elf_addr;
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < ehdr->e_phnum; i++) {
|
||||||
|
Elf64_Phdr *cur_phdr =
|
||||||
|
(Elf64_Phdr *)(elf_addr + ehdr->e_phoff + (i * ehdr->e_phentsize));
|
||||||
|
if (cur_phdr->p_type != PT_LOAD)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uintptr_t phys = (cur_phdr->p_vaddr - kvaddr) + kpaddr;
|
||||||
|
uint64_t flags = PTE_PRESENT;
|
||||||
|
if ((cur_phdr->p_flags & PF_X) == 0) {
|
||||||
|
flags |= PTE_NX;
|
||||||
|
}
|
||||||
|
if (cur_phdr->p_flags & PF_W) {
|
||||||
|
flags |= PTE_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t length = ALIGN_UP(cur_phdr->p_memsz, PMM_PAGE_SIZE);
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < length; i += PMM_PAGE_SIZE) {
|
||||||
|
pg_map(pg_kernel_pm, cur_phdr->p_vaddr + i, phys + i, flags);
|
||||||
|
}
|
||||||
|
trace("vmm: Mapped range: %p -> %p (length: %x)\n", phys, cur_phdr->p_vaddr,
|
||||||
|
length);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < 0x100000000; i += PMM_PAGE_SIZE)
|
||||||
|
pg_map(pg_kernel_pm, higher_half(i), i, PTE_PRESENT | PTE_WRITE);
|
||||||
|
trace("vmm: Mapped range: %p -> %p (length: %x)\n", 0x0, 0xFFFF800000000000,
|
||||||
|
0x100000000);
|
||||||
|
|
||||||
|
pg_load_pm(pg_kernel_pm);
|
||||||
|
trace("vmm: Initialized.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void pg_load_pm(pagemap_t pm) {
|
||||||
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pg_current_pm = pm;
|
||||||
|
cpu_load_pm((pagemap_t)physical((uint64_t)pm));
|
||||||
|
}
|
||||||
|
|
||||||
|
pagemap_t pg_alloc_pm() {
|
||||||
|
pagemap_t pm = (pagemap_t)higher_half((uint64_t)pmm_alloc_page());
|
||||||
|
memset((void *)pm, 0, PMM_PAGE_SIZE);
|
||||||
|
|
||||||
|
if (pg_kernel_pm) {
|
||||||
|
for (int i = 256; i < 512; i++)
|
||||||
|
pm[i] = pg_kernel_pm[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return pm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pg_free_pm(pagemap_t pm) {
|
||||||
|
if (pm == pg_kernel_pm) {
|
||||||
|
warn("vmm: Who tried to free the kernel's pagemap?!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pmm_free_page((void *)pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t *__pg_get_next_lvl(uint64_t *level, uint64_t entry,
|
||||||
|
uint64_t flags, bool alloc) {
|
||||||
|
if (level[entry] & PTE_PRESENT)
|
||||||
|
return (uint64_t *)higher_half(PTE_GET_ADDR(level[entry]));
|
||||||
|
if (alloc) {
|
||||||
|
uint64_t *pml = (uint64_t *)higher_half((uint64_t)pmm_alloc_page());
|
||||||
|
memset(pml, 0, PMM_PAGE_SIZE);
|
||||||
|
level[entry] = (uint64_t)physical((uint64_t)pml) | flags;
|
||||||
|
return pml;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t pg_physical(pagemap_t pm, uint64_t vaddr) {
|
||||||
|
if (!pm)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
|
uint64_t *pml3 = __pg_get_next_lvl(pm, pml4_entry, 0, false);
|
||||||
|
if (!pml3)
|
||||||
|
return 0;
|
||||||
|
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false);
|
||||||
|
if (!pml2)
|
||||||
|
return 0;
|
||||||
|
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false);
|
||||||
|
if (!pml1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return pml1[pml1_entry] & PTE_ADDR_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pg_map(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) {
|
||||||
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
|
uint64_t *pml3 =
|
||||||
|
__pg_get_next_lvl(pm, pml4_entry, PTE_PRESENT | PTE_WRITE, true);
|
||||||
|
uint64_t *pml2 =
|
||||||
|
__pg_get_next_lvl(pml3, pml3_entry, PTE_PRESENT | PTE_WRITE, true);
|
||||||
|
uint64_t *pml1 =
|
||||||
|
__pg_get_next_lvl(pml2, pml2_entry, PTE_PRESENT | PTE_WRITE, true);
|
||||||
|
|
||||||
|
pml1[pml1_entry] = paddr | flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pg_map_user(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) {
|
||||||
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
|
uint64_t *pml3 = __pg_get_next_lvl(pm, pml4_entry, flags, true);
|
||||||
|
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, flags, true);
|
||||||
|
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, flags, true);
|
||||||
|
|
||||||
|
pml1[pml1_entry] = paddr | flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pg_unmap(pagemap_t pm, uint64_t vaddr) {
|
||||||
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
|
uint64_t *pml3 = __pg_get_next_lvl(pm, pml4_entry, 0, false);
|
||||||
|
if (!pml3)
|
||||||
|
return;
|
||||||
|
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false);
|
||||||
|
if (!pml2)
|
||||||
|
return;
|
||||||
|
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false);
|
||||||
|
if (!pml1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pml1[pml1_entry] = 0;
|
||||||
|
cpu_invalidate_page(vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pg_protect(pagemap_t pm, uint64_t vaddr, uint64_t flags) {
|
||||||
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||||
|
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||||
|
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||||
|
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||||
|
|
||||||
|
uint64_t *pml3 = __pg_get_next_lvl(pm, pml4_entry, 0, false);
|
||||||
|
if (!pml3)
|
||||||
|
return;
|
||||||
|
uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false);
|
||||||
|
if (!pml2)
|
||||||
|
return;
|
||||||
|
uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false);
|
||||||
|
if (!pml1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t paddr = pml1[pml1_entry] & PTE_ADDR_MASK;
|
||||||
|
pml1[pml1_entry] = paddr | flags;
|
||||||
|
}
|
39
kernel/src/mm/paging.h
Executable file
39
kernel/src/mm/paging.h
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* pg.c - Virtual memory manager
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Page flags
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define PTE_ADDR_MASK 0x000ffffffffff000ull
|
||||||
|
#define PTE_GET_ADDR(VALUE) ((VALUE) & PTE_ADDR_MASK)
|
||||||
|
#define PTE_GET_FLAGS(VALUE) ((VALUE) & ~PTE_ADDR_MASK)
|
||||||
|
|
||||||
|
#define PTE_PRESENT (1 << 0)
|
||||||
|
#define PTE_WRITE (1 << 1)
|
||||||
|
#define PTE_USER (1 << 2)
|
||||||
|
#define PTE_NX (1ULL << 63) // NX = No eXecute.
|
||||||
|
|
||||||
|
typedef uint64_t *pagemap_t;
|
||||||
|
|
||||||
|
extern pagemap_t pg_kernel_pm;
|
||||||
|
extern pagemap_t pg_current_pm;
|
||||||
|
|
||||||
|
|
||||||
|
void pg_init();
|
||||||
|
|
||||||
|
pagemap_t pg_alloc_pm();
|
||||||
|
void pg_free_pm(pagemap_t pm);
|
||||||
|
void pg_load_pm(pagemap_t pm);
|
||||||
|
|
||||||
|
uint64_t pg_physical(pagemap_t pm, uint64_t vaddr);
|
||||||
|
void pg_map(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags);
|
||||||
|
void pg_map_user(pagemap_t pm, uint64_t vaddr, uint64_t paddr,
|
||||||
|
uint64_t flags);
|
||||||
|
void pg_unmap(pagemap_t pm, uint64_t vaddr);
|
||||||
|
void pg_protect(pagemap_t pm, uint64_t vaddr, uint64_t flags);
|
169
kernel/src/mm/pmm.c
Normal file → Executable file
169
kernel/src/mm/pmm.c
Normal file → Executable file
|
@ -1,97 +1,102 @@
|
||||||
#include "limine.h"
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* pmm.c - Physical memory allocator
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/cpu.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <boot/limine.h>
|
||||||
|
#include <lib/log.h>
|
||||||
#include <mm/memop.h>
|
#include <mm/memop.h>
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
|
|
||||||
pmm_stack_t stack;
|
uint64_t pmm_available_pages = 0;
|
||||||
struct limine_memmap_response *_memmap;
|
uint64_t pmm_total_pages = 0;
|
||||||
|
|
||||||
uint64_t hhdm_offset = 0x0;
|
static pmm_region_t *pmm_region_list_head = NULL;
|
||||||
|
static pmm_page_t *pmm_free_list_head = NULL;
|
||||||
|
|
||||||
__attribute__((
|
void pmm_free_page(void *mem) {
|
||||||
used, section(".limine_requests"))) struct limine_memmap_request mm_req = {
|
if (!mem)
|
||||||
.id = LIMINE_MEMMAP_REQUEST, .revision = 3};
|
return;
|
||||||
|
|
||||||
__attribute__((
|
pmm_page_t *page = (pmm_page_t*)higher_half((uint64_t)mem);
|
||||||
used, section(".limine_requests"))) struct limine_hhdm_request hhdm_req = {
|
page->next = pmm_free_list_head ? (pmm_page_t*)higher_half((uint64_t)pmm_free_list_head) : 0x0;
|
||||||
.id = LIMINE_HHDM_REQUEST, .revision = 3};
|
pmm_free_list_head = page;
|
||||||
|
|
||||||
int pmm_init() {
|
pmm_available_pages++;
|
||||||
uint64_t free_pages = 0;
|
|
||||||
hhdm_offset = hhdm_req.response->offset;
|
|
||||||
|
|
||||||
struct limine_memmap_response *memmap = mm_req.response;
|
|
||||||
_memmap = memmap;
|
|
||||||
|
|
||||||
// DEBUG("mm", "----- PMM //INFO -----");
|
|
||||||
int freemem = 0;
|
|
||||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
|
||||||
if (memmap->entries[i]->type == LIMINE_MEMMAP_USABLE) {
|
|
||||||
// DEBUG("mm", " - USABLE ENTRY\t\t@ 0x%.16llx, size: 0x%.16llx",
|
|
||||||
// memmap->entries[i]->base, memmap->entries[i]->length);
|
|
||||||
free_pages += DIV_ROUND_UP(memmap->entries[i]->length, PMM_PAGE_SIZE);
|
|
||||||
freemem += memmap->entries[i]->length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t array_size = ALIGN_UP(free_pages * 8, PMM_PAGE_SIZE);
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
|
||||||
struct limine_memmap_entry *entry = memmap->entries[i];
|
|
||||||
if (entry->length >= array_size && entry->type == LIMINE_MEMMAP_USABLE) {
|
|
||||||
stack.pages = (uintptr_t *)HIGHER_HALF(entry->base);
|
|
||||||
entry->length -= array_size;
|
|
||||||
entry->base += array_size;
|
|
||||||
// DEBUG("mm", " - STACK START\t\t@ 0x%.16llx", stack.pages);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
|
||||||
struct limine_memmap_entry *entry = memmap->entries[i];
|
|
||||||
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
|
||||||
for (uint64_t j = 0; j < entry->length; j += PMM_PAGE_SIZE) {
|
|
||||||
stack.pages[stack.idx++] = entry->base + j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stack.max = stack.idx;
|
|
||||||
// DEBUG("mm", " - MAX INDEX:\t\t%d", stack.max);
|
|
||||||
// DEBUG("mm", " - CURRENT INDEX:\t%d", stack.idx);
|
|
||||||
// DEBUG("mm", "--------------------");
|
|
||||||
|
|
||||||
log("pmm - %dmb is available to us.\n", freemem / (1024 * 1024));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *pmm_request_page() {
|
static void __pmm_steal_pages_from_region_head(int pages) {
|
||||||
if (stack.idx == 0) {
|
for (int i = 0; i < pages; i++) {
|
||||||
// ERROR("mm", "No more pages available.");
|
pmm_region_list_head->length -= PMM_PAGE_SIZE;
|
||||||
log("pmm - out of memory.\n");
|
void *page = (void*)pmm_region_list_head->base +
|
||||||
asm("cli");
|
pmm_region_list_head->length;
|
||||||
while (1) {
|
pmm_free_page(page);
|
||||||
asm("hlt");
|
//trace("pmm: stealer: page is %p\n", page);
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t page_addr = stack.pages[--stack.idx];
|
if (pmm_region_list_head->length == 0)
|
||||||
memset(HIGHER_HALF(page_addr), 0, PMM_PAGE_SIZE);
|
{
|
||||||
return (void *)page_addr;
|
// If a region is totally consumed,
|
||||||
|
// we can turn it into a free page :)
|
||||||
|
// So our 4kb aren't really lost
|
||||||
|
void *mem = (void*)pmm_region_list_head;
|
||||||
|
pmm_region_list_head = pmm_region_list_head->next;
|
||||||
|
|
||||||
|
pmm_free_page(mem);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pmm_free_page(void *ptr) {
|
void *pmm_alloc_page() {
|
||||||
if (ptr == NULL)
|
if (!pmm_free_list_head)
|
||||||
return;
|
{
|
||||||
|
if (!pmm_region_list_head) {
|
||||||
|
fatal("pmm: out of memory!\n");
|
||||||
|
hcf();
|
||||||
|
}
|
||||||
|
__pmm_steal_pages_from_region_head(4);
|
||||||
|
// et voila, we now have 4 free pages to allocate
|
||||||
|
}
|
||||||
|
|
||||||
if (stack.idx >= stack.max) {
|
pmm_available_pages--;
|
||||||
// ERROR("mm", "Stack overflow attempt while freeing a page.");
|
|
||||||
log("pmm - could not free the page: stack overflow.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stack.pages[stack.idx++] = (uint64_t)ptr;
|
pmm_page_t *page = pmm_free_list_head;
|
||||||
|
pmm_free_list_head = page->next;
|
||||||
|
|
||||||
|
memset(page, 0, PMM_PAGE_SIZE);
|
||||||
|
return (void*)physical((uint64_t)page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_init() {
|
||||||
|
struct limine_memmap_response *mmap = limine_get_memmap();
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < mmap->entry_count; i++) {
|
||||||
|
struct limine_memmap_entry *entry = mmap->entries[i];
|
||||||
|
|
||||||
|
if (entry->type == LIMINE_MEMMAP_USABLE ||
|
||||||
|
entry->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE)
|
||||||
|
{
|
||||||
|
trace("pmm: Found an usable memory block: %p-%p\n", entry->base, entry->base + entry->length);
|
||||||
|
|
||||||
|
uint64_t newlen = ALIGN_DOWN(entry->length, PMM_PAGE_SIZE);
|
||||||
|
|
||||||
|
// Give a page to store the PMM region.
|
||||||
|
// When the region is fully consumed, the
|
||||||
|
// page is freed so that it can be used (i love recycling)
|
||||||
|
pmm_region_t *reg = (pmm_region_t*)higher_half(entry->base);
|
||||||
|
reg->base = entry->base + PMM_PAGE_SIZE;
|
||||||
|
reg->length = newlen - PMM_PAGE_SIZE;
|
||||||
|
reg->next = pmm_region_list_head;
|
||||||
|
pmm_region_list_head = reg;
|
||||||
|
|
||||||
|
pmm_available_pages += reg->length / PMM_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("pmm: %d pages available\n", pmm_available_pages);
|
||||||
}
|
}
|
56
kernel/src/mm/pmm.h
Normal file → Executable file
56
kernel/src/mm/pmm.h
Normal file → Executable file
|
@ -1,28 +1,48 @@
|
||||||
#ifndef PMM_H
|
/*
|
||||||
#define PMM_H
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* pmm.c - Physical memory allocator
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#define PMM_PAGE_SIZE 4096
|
#include <boot/limine.h>
|
||||||
|
|
||||||
typedef struct pmm_stack {
|
|
||||||
uintptr_t *pages;
|
|
||||||
uint64_t idx;
|
|
||||||
uint64_t max;
|
|
||||||
} pmm_stack_t;
|
|
||||||
|
|
||||||
extern uint64_t hhdm_offset;
|
|
||||||
|
|
||||||
#define DIV_ROUND_UP(x, y) \
|
#define DIV_ROUND_UP(x, y) \
|
||||||
(((uint64_t)(x) + ((uint64_t)(y) - 1)) / (uint64_t)(y))
|
(((uint64_t)(x) + ((uint64_t)(y) - 1)) / (uint64_t)(y))
|
||||||
#define ALIGN_UP(x, y) (DIV_ROUND_UP(x, y) * (uint64_t)(y))
|
#define ALIGN_UP(x, y) (DIV_ROUND_UP(x, y) * (uint64_t)(y))
|
||||||
#define ALIGN_DOWN(x, y) (((uint64_t)(x) / (uint64_t)(y)) * (uint64_t)(y))
|
#define ALIGN_DOWN(x, y) (((uint64_t)(x) / (uint64_t)(y)) * (uint64_t)(y))
|
||||||
|
|
||||||
#define HIGHER_HALF(ptr) ((void *)((uint64_t)ptr) + hhdm_offset)
|
#define PMM_PAGE_SIZE 0x1000 // We are using 4kb pages.
|
||||||
#define PHYSICAL(ptr) ((void *)((uint64_t)ptr) - hhdm_offset)
|
|
||||||
|
|
||||||
int pmm_init();
|
typedef struct __pmm_page {
|
||||||
void *pmm_request_page();
|
struct __pmm_page *next;
|
||||||
void pmm_free_page(void *ptr);
|
} pmm_page_t;
|
||||||
void pmm_dump();
|
|
||||||
|
|
||||||
#endif // PMM_H
|
typedef struct __pmm_region {
|
||||||
|
uint64_t base;
|
||||||
|
uint64_t length;
|
||||||
|
struct __pmm_region *next;
|
||||||
|
} pmm_region_t;
|
||||||
|
|
||||||
|
inline uint64_t higher_half(uint64_t addr) {
|
||||||
|
uint64_t hhdm_off = limine_get_hhdm_offset();
|
||||||
|
if (addr > hhdm_off)
|
||||||
|
return addr;
|
||||||
|
|
||||||
|
return addr + hhdm_off;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint64_t physical(uint64_t addr) {
|
||||||
|
uint64_t hhdm_off = limine_get_hhdm_offset();
|
||||||
|
if (addr < hhdm_off)
|
||||||
|
return addr;
|
||||||
|
|
||||||
|
return addr - hhdm_off;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_free_page(void *mem);
|
||||||
|
void *pmm_alloc_page();
|
||||||
|
void pmm_init();
|
0
kernel/src/mm/pmm.md
Executable file
0
kernel/src/mm/pmm.md
Executable file
266
kernel/src/mm/vma.c
Normal file → Executable file
266
kernel/src/mm/vma.c
Normal file → Executable file
|
@ -1,181 +1,115 @@
|
||||||
// credit to kevin for writing the vma
|
/*
|
||||||
// go check his projects: https://github.com/kevinalavik
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* vma.c - Virtual memory allocator
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "lib/log.h"
|
||||||
|
#include "mm/memop.h"
|
||||||
|
#include <mm/paging.h>
|
||||||
|
#include "mm/vma.h"
|
||||||
#include "mm/pmm.h"
|
#include "mm/pmm.h"
|
||||||
#include "mm/vmm.h"
|
|
||||||
#include <mm/memop.h>
|
|
||||||
#include <mm/vma.h>
|
|
||||||
#include <sys/log.h>
|
|
||||||
|
|
||||||
vma_context_t *kernel_vma_context;
|
vma_ctx_t *vma_alloc_ctx(pagemap_t pm, uint64_t start) {
|
||||||
|
if (pm == NULL)
|
||||||
vma_context_t *vma_create_context(pagemap_t *pagemap) {
|
|
||||||
log("vma - creating VMA context with pagemap: 0x%.16llx\n",
|
|
||||||
(uint64_t)pagemap);
|
|
||||||
|
|
||||||
vma_context_t *ctx = (vma_context_t *)HIGHER_HALF(pmm_request_page());
|
|
||||||
if (ctx == NULL) {
|
|
||||||
log("vma - failed to allocate VMA context\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
log("vma - allocated VMA context at 0x%.16llx\n", (uint64_t)ctx);
|
|
||||||
memset(ctx, 0, sizeof(vma_context_t));
|
|
||||||
log("vma - zeroed out VMA context at 0x%.16llx\n", (uint64_t)ctx);
|
|
||||||
|
|
||||||
ctx->root = (vma_region_t *)HIGHER_HALF(pmm_request_page());
|
|
||||||
if (ctx->root == NULL) {
|
|
||||||
log("vma - failed to allocate root region\n");
|
|
||||||
pmm_free_page((void *)PHYSICAL(ctx));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
log("vma - allocated root region at 0x%.16llx\n", (uint64_t)ctx->root);
|
|
||||||
|
|
||||||
ctx->pagemap = pagemap;
|
|
||||||
ctx->root->start = PMM_PAGE_SIZE;
|
|
||||||
ctx->root->size = 0;
|
|
||||||
|
|
||||||
log("vma - VMA context created at 0x%.16llx with root region at 0x%.16llx\n",
|
|
||||||
(uint64_t)ctx, (uint64_t)ctx->root);
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vma_destroy_context(vma_context_t *ctx) {
|
|
||||||
log("vma - destroying VMA context at 0x%.16llx\n", (uint64_t)ctx);
|
|
||||||
|
|
||||||
if (ctx->root == NULL || ctx->pagemap == NULL) {
|
|
||||||
log("vma - invalid context or root passed to vma_destroy_context\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vma_region_t *region = ctx->root;
|
|
||||||
while (region != NULL) {
|
|
||||||
log("vma - freeing region at 0x%.16llx\n", (uint64_t)region);
|
|
||||||
vma_region_t *next = region->next;
|
|
||||||
pmm_free_page((void *)PHYSICAL(region));
|
|
||||||
region = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmm_free_page((void *)PHYSICAL(ctx));
|
|
||||||
log("vma - destroyed VMA context at 0x%.16llx\n", (uint64_t)ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *vma_alloc(vma_context_t *ctx, uint64_t size, uint64_t flags) {
|
|
||||||
if (ctx == NULL || ctx->root == NULL || ctx->pagemap == NULL) {
|
|
||||||
log("vma - invalid context or root passed to vma_alloc\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
vma_region_t *region = ctx->root;
|
|
||||||
vma_region_t *new_region;
|
|
||||||
vma_region_t *last_region = ctx->root;
|
|
||||||
|
|
||||||
while (region != NULL) {
|
|
||||||
if (region->next == NULL ||
|
|
||||||
region->start + region->size < region->next->start) {
|
|
||||||
new_region = (vma_region_t *)HIGHER_HALF(pmm_request_page());
|
|
||||||
if (new_region == NULL) {
|
|
||||||
log("vma - failed to allocate new VMA region\n");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
memset(new_region, 0, sizeof(vma_region_t));
|
vma_ctx_t *ctx = (vma_ctx_t *)higher_half((uint64_t)pmm_alloc_page());
|
||||||
new_region->size = size;
|
ctx->pm = pm;
|
||||||
new_region->flags = flags;
|
|
||||||
new_region->start = region->start + region->size;
|
vma_region_t *root_reg = (vma_region_t *)higher_half((uint64_t)pmm_alloc_page());
|
||||||
new_region->next = region->next;
|
root_reg->start = start;
|
||||||
new_region->prev = region;
|
root_reg->length = 0;
|
||||||
region->next = new_region;
|
root_reg->next = NULL;
|
||||||
|
|
||||||
for (uint64_t i = 0; i < size; i++) {
|
ctx->root = root_reg;
|
||||||
uint64_t page = (uint64_t)pmm_request_page();
|
return ctx;
|
||||||
if (page == 0) {
|
}
|
||||||
log("vma - failed to allocate physical memory for VMA region\n");
|
|
||||||
return NULL;
|
void *vma_alloc(vma_ctx_t *ctx, size_t length, uint64_t flags) {
|
||||||
|
if (!ctx || !ctx->pm || !ctx->root)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
vma_region_t *current = ctx->root;
|
||||||
|
while (current) {
|
||||||
|
if (current->next == NULL || current->start + (current->length * PMM_PAGE_SIZE) < current->next->start)
|
||||||
|
{
|
||||||
|
vma_region_t *reg = (vma_region_t*)higher_half((uint64_t)pmm_alloc_page());
|
||||||
|
memset((void*)reg, 0, sizeof(vma_region_t));
|
||||||
|
reg->start = current->start + (current->length * PMM_PAGE_SIZE);
|
||||||
|
reg->length = length;
|
||||||
|
reg->pflags = flags;
|
||||||
|
reg->next = current->next;
|
||||||
|
current->next = reg;
|
||||||
|
|
||||||
|
// Now, allocate the memory
|
||||||
|
for (uint64_t i = 0; i < length; i++) {
|
||||||
|
uint64_t physical = (uint64_t)pmm_alloc_page();
|
||||||
|
pg_map(ctx->pm, reg->start + (i * PMM_PAGE_SIZE), physical, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void*)reg->start;
|
||||||
}
|
}
|
||||||
|
|
||||||
vmm_map(ctx->pagemap, new_region->start + i * PMM_PAGE_SIZE, page,
|
current = current->next;
|
||||||
new_region->flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (void *)new_region->start;
|
|
||||||
}
|
}
|
||||||
region = region->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_region = (vma_region_t *)HIGHER_HALF(pmm_request_page());
|
|
||||||
if (new_region == NULL) {
|
|
||||||
log("vma - failed to allocate new VMA region\n");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
memset(new_region, 0, sizeof(vma_region_t));
|
|
||||||
|
|
||||||
last_region->next = new_region;
|
|
||||||
new_region->prev = last_region;
|
|
||||||
new_region->start = last_region->start + last_region->size;
|
|
||||||
new_region->size = size;
|
|
||||||
new_region->flags = flags;
|
|
||||||
new_region->next = NULL;
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i < size; i++) {
|
|
||||||
uint64_t page = (uint64_t)pmm_request_page();
|
|
||||||
if (page == 0) {
|
|
||||||
log("vma - failed to allocate physical memory for VMA region\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
vmm_map(ctx->pagemap, new_region->start + i * PMM_PAGE_SIZE, page,
|
|
||||||
new_region->flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (void *)new_region->start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vma_free(vma_context_t *ctx, void *ptr) {
|
static void __vma_free_region(vma_ctx_t *ctx, vma_region_t *target) {
|
||||||
if (ctx == NULL) {
|
for (uint64_t i = 0; i < target->length; i++) {
|
||||||
log("vma - invalid context passed to vma_free\n");
|
uint64_t vaddr = target->start + (i * PMM_PAGE_SIZE);
|
||||||
return;
|
uint64_t paddr = pg_physical(ctx->pm, vaddr);
|
||||||
}
|
pg_unmap(ctx->pm, vaddr);
|
||||||
|
pmm_free_page((void*)paddr);
|
||||||
vma_region_t *region = ctx->root;
|
|
||||||
while (region != NULL) {
|
|
||||||
if (region->start == (uint64_t)ptr) {
|
|
||||||
log("vma - found region to free at 0x%.16llx\n", (uint64_t)region);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
region = region->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (region == NULL) {
|
pmm_free_page((void*)physical((uint64_t)target));
|
||||||
log("vma - unable to find region to free at address 0x%.16llx\n",
|
|
||||||
(uint64_t)ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vma_region_t *prev = region->prev;
|
|
||||||
vma_region_t *next = region->next;
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i < region->size; i++) {
|
|
||||||
uint64_t virt = region->start + i * PMM_PAGE_SIZE;
|
|
||||||
uint64_t phys = virt_to_phys(vmm_kernel_pm, virt);
|
|
||||||
|
|
||||||
if (phys != 0) {
|
|
||||||
pmm_free_page((void *)phys);
|
|
||||||
vmm_unmap(ctx->pagemap, virt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prev != NULL) {
|
|
||||||
prev->next = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next != NULL) {
|
|
||||||
next->prev = prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (region == ctx->root) {
|
|
||||||
ctx->root = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmm_free_page((void *)PHYSICAL(region));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vma_free(vma_ctx_t *ctx, void *addr) {
|
||||||
|
if (!ctx || !ctx->pm || !ctx->root || !addr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vma_region_t *last = NULL;
|
||||||
|
vma_region_t *target = ctx->root;
|
||||||
|
|
||||||
|
while (target) {
|
||||||
|
if (target->start == (uint64_t)addr)
|
||||||
|
break;
|
||||||
|
|
||||||
|
last = target;
|
||||||
|
target = target->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (last)
|
||||||
|
last->next = target->next;
|
||||||
|
else
|
||||||
|
ctx->root = target->next;
|
||||||
|
|
||||||
|
// Unallocate the memory
|
||||||
|
__vma_free_region(ctx, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vma_free_ctx(vma_ctx_t *ctx) {
|
||||||
|
if (!ctx ||
|
||||||
|
!ctx->pm ||
|
||||||
|
!ctx->root)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vma_region_t *reg = ctx->root;
|
||||||
|
while (reg) {
|
||||||
|
vma_region_t *next = reg->next;
|
||||||
|
__vma_free_region(ctx, reg);
|
||||||
|
reg = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmm_free_page((void*)physical((uint64_t)ctx));
|
||||||
|
}
|
46
kernel/src/mm/vma.h
Normal file → Executable file
46
kernel/src/mm/vma.h
Normal file → Executable file
|
@ -1,29 +1,31 @@
|
||||||
// credit to kevin for writing the vma
|
/*
|
||||||
// go check his projects: https://github.com/kevinalavik
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* vma.h - Virtual memory allocator
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mm/pmm.h>
|
#include "mm/paging.h"
|
||||||
#include <mm/vmm.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct vma_region {
|
typedef struct __vma_region {
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
uint64_t size;
|
uint64_t pflags;
|
||||||
uint64_t flags;
|
|
||||||
struct vma_region *next;
|
// Length is in pages, not in bytes.
|
||||||
struct vma_region *prev;
|
uint64_t length;
|
||||||
|
|
||||||
|
struct __vma_region *next;
|
||||||
} vma_region_t;
|
} vma_region_t;
|
||||||
|
|
||||||
typedef struct vma_context {
|
typedef struct {
|
||||||
pagemap_t *pagemap;
|
pagemap_t pm;
|
||||||
vma_region_t *root;
|
vma_region_t *root;
|
||||||
} vma_context_t;
|
} vma_ctx_t;
|
||||||
|
|
||||||
extern vma_context_t *kernel_vma_context;
|
vma_ctx_t *vma_alloc_ctx(pagemap_t pm, uint64_t start);
|
||||||
|
void *vma_alloc(vma_ctx_t *ctx, size_t length, uint64_t flags);
|
||||||
vma_context_t *vma_create_context(pagemap_t *pagemap);
|
void vma_free(vma_ctx_t *ctx, void *addr);
|
||||||
void vma_destroy_context(vma_context_t *ctx);
|
void vma_free_ctx (vma_ctx_t *ctx);
|
||||||
void *vma_alloc(vma_context_t *ctx, uint64_t size, uint64_t flags);
|
|
||||||
void vma_free(vma_context_t *ctx, void *ptr);
|
|
||||||
void vma_dump_context(vma_context_t *ctx);
|
|
|
@ -1,244 +0,0 @@
|
||||||
#include "mm/vmm.h"
|
|
||||||
#include "limine.h"
|
|
||||||
#include "mm/memop.h"
|
|
||||||
#include "mm/pmm.h"
|
|
||||||
#include "sys/log.h"
|
|
||||||
#include "vmm.h"
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
__attribute__((
|
|
||||||
used,
|
|
||||||
section(
|
|
||||||
".limine_requests"))) static volatile struct limine_paging_mode_request
|
|
||||||
pmrq = {.id = LIMINE_PAGING_MODE_REQUEST,
|
|
||||||
.revision = 3,
|
|
||||||
.mode = LIMINE_PAGING_MODE_X86_64_4LVL};
|
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests"))) volatile struct
|
|
||||||
limine_executable_address_request karq = {
|
|
||||||
.id = LIMINE_EXECUTABLE_ADDRESS_REQUEST,
|
|
||||||
.revision = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
pagemap_t *vmm_kernel_pm = NULL;
|
|
||||||
pagemap_t *vmm_current_pm = NULL;
|
|
||||||
int vmm_kernel_pm_exists = 0;
|
|
||||||
|
|
||||||
pagemap_t *vmm_alloc_pm() {
|
|
||||||
pagemap_t *pm = (pagemap_t *)HIGHER_HALF((uint64_t)pmm_request_page());
|
|
||||||
memset(pm, 0, PMM_PAGE_SIZE);
|
|
||||||
|
|
||||||
pm->toplevel = (uint64_t *)HIGHER_HALF((uint64_t)pmm_request_page());
|
|
||||||
memset(pm->toplevel, 0, PMM_PAGE_SIZE);
|
|
||||||
|
|
||||||
if (vmm_kernel_pm_exists) {
|
|
||||||
for (int i = 256; i < 512; i++) {
|
|
||||||
pm->toplevel[i] = vmm_kernel_pm->toplevel[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pm;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_release_pm(pagemap_t *pm) {
|
|
||||||
memset(pm->toplevel, 0, PMM_PAGE_SIZE);
|
|
||||||
memset(pm, 0, PMM_PAGE_SIZE);
|
|
||||||
pmm_free_page(pm->toplevel);
|
|
||||||
pmm_free_page(pm);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_sanity_check() {
|
|
||||||
uint64_t *my_memory = HIGHER_HALF(pmm_request_page());
|
|
||||||
*my_memory = 0x40;
|
|
||||||
|
|
||||||
pagemap_t *pm = vmm_alloc_pm();
|
|
||||||
vmm_map(pm, 0x1000, (uint64_t)my_memory, VMM_PRESENT | VMM_WRITABLE);
|
|
||||||
|
|
||||||
uint64_t *my_ptr = (uint64_t *)0x1000;
|
|
||||||
uint64_t ptr_val = 0;
|
|
||||||
vmm_load_pagemap(pm);
|
|
||||||
ptr_val = *my_ptr;
|
|
||||||
vmm_load_pagemap(vmm_kernel_pm);
|
|
||||||
|
|
||||||
if (ptr_val != 0x40) {
|
|
||||||
log("vmm - sanity check failed. system halted.\n");
|
|
||||||
asm("cli");
|
|
||||||
while (1)
|
|
||||||
asm("hlt");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_init() {
|
|
||||||
if (pmrq.response->mode != LIMINE_PAGING_MODE_X86_64_4LVL) {
|
|
||||||
log("vmm - Soaplin only supports 4-level paging!\n");
|
|
||||||
asm("cli; hlt;");
|
|
||||||
}
|
|
||||||
vmm_kernel_pm = vmm_alloc_pm();
|
|
||||||
vmm_kernel_pm_exists = 1;
|
|
||||||
|
|
||||||
uint64_t kphysaddr = karq.response->physical_base;
|
|
||||||
uint64_t kvirtaddr = karq.response->virtual_base;
|
|
||||||
|
|
||||||
uint64_t reqs_start = ALIGN_DOWN((uint64_t)reqs_start_ld, PMM_PAGE_SIZE);
|
|
||||||
uint64_t reqs_end = ALIGN_UP((uint64_t)reqs_end_ld, PMM_PAGE_SIZE);
|
|
||||||
uint64_t text_start = ALIGN_DOWN((uint64_t)text_start_ld, PMM_PAGE_SIZE);
|
|
||||||
uint64_t text_end = ALIGN_UP((uint64_t)text_end_ld, PMM_PAGE_SIZE);
|
|
||||||
uint64_t rodata_start = ALIGN_DOWN((uint64_t)rodata_start_ld, PMM_PAGE_SIZE);
|
|
||||||
uint64_t rodata_end = ALIGN_UP((uint64_t)rodata_end_ld, PMM_PAGE_SIZE);
|
|
||||||
uint64_t data_start = ALIGN_DOWN((uint64_t)data_start_ld, PMM_PAGE_SIZE);
|
|
||||||
uint64_t data_end = ALIGN_UP((uint64_t)data_end_ld, PMM_PAGE_SIZE);
|
|
||||||
|
|
||||||
log("vmm - mapping .requests section...\n");
|
|
||||||
for (uint64_t req = reqs_start; req < reqs_end; req += PMM_PAGE_SIZE) {
|
|
||||||
vmm_map(vmm_kernel_pm, req, req - kvirtaddr + kphysaddr,
|
|
||||||
VMM_PRESENT | VMM_WRITABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
log("vmm - mapping .text section...\n");
|
|
||||||
for (uint64_t text = text_start; text < text_end; text += PMM_PAGE_SIZE) {
|
|
||||||
vmm_map(vmm_kernel_pm, text, text - kvirtaddr + kphysaddr, VMM_PRESENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
log("vmm - mapping .rodata section...\n");
|
|
||||||
for (uint64_t roData = rodata_start; roData < rodata_end;
|
|
||||||
roData += PMM_PAGE_SIZE)
|
|
||||||
vmm_map(vmm_kernel_pm, roData, roData - kvirtaddr + kphysaddr,
|
|
||||||
VMM_PRESENT | VMM_NX);
|
|
||||||
|
|
||||||
log("vmm - mapping .data section...\n");
|
|
||||||
for (uint64_t data = data_start; data < data_end; data += PMM_PAGE_SIZE)
|
|
||||||
vmm_map(vmm_kernel_pm, data, data - kvirtaddr + kphysaddr,
|
|
||||||
VMM_PRESENT | VMM_WRITABLE | VMM_NX);
|
|
||||||
|
|
||||||
log("vmm - mapping address from 0x0 to 0x100000000...\n");
|
|
||||||
for (uint64_t gb4 = 0; gb4 < 0x100000000; gb4 += PMM_PAGE_SIZE) {
|
|
||||||
//vmm_map(vmm_kernel_pm, gb4, gb4, VMM_PRESENT | VMM_WRITABLE);
|
|
||||||
vmm_map(vmm_kernel_pm, (uint64_t)HIGHER_HALF(gb4), gb4,
|
|
||||||
VMM_PRESENT | VMM_WRITABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
vmm_load_pagemap(vmm_kernel_pm);
|
|
||||||
|
|
||||||
//vmm_sanity_check();
|
|
||||||
log("vmm - initialized!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_load_pagemap(pagemap_t *pm) {
|
|
||||||
if (!pm)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!pm->toplevel)
|
|
||||||
return;
|
|
||||||
|
|
||||||
vmm_current_pm = pm;
|
|
||||||
__asm__ volatile("mov %0, %%cr3" : : "r"(PHYSICAL(pm->toplevel)) : "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t *__vmm_get_next_lvl(uint64_t *level, uint64_t entry,
|
|
||||||
uint64_t flags, bool alloc) {
|
|
||||||
if (level[entry] & VMM_PRESENT)
|
|
||||||
return HIGHER_HALF(PTE_GET_ADDR(level[entry]));
|
|
||||||
if (alloc) {
|
|
||||||
uint64_t *pml = (uint64_t *)HIGHER_HALF(pmm_request_page());
|
|
||||||
memset(pml, 0, PMM_PAGE_SIZE);
|
|
||||||
level[entry] = (uint64_t)PHYSICAL(pml) | flags;
|
|
||||||
return pml;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t vmm_get_flags(pagemap_t *pm, uint64_t vaddr) {
|
|
||||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
|
||||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
|
||||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
|
||||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
|
||||||
|
|
||||||
uint64_t *pml3 = __vmm_get_next_lvl(pm->toplevel, pml4_entry, 0, false);
|
|
||||||
if (!pml3)
|
|
||||||
return 0;
|
|
||||||
uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_entry, 0, false);
|
|
||||||
if (!pml2)
|
|
||||||
return 0;
|
|
||||||
uint64_t *pml1 = __vmm_get_next_lvl(pml2, pml2_entry, 0, false);
|
|
||||||
if (!pml1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return pml1[pml1_entry] & 0x7000000000000FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t virt_to_phys(pagemap_t *pagemap, uint64_t virt) {
|
|
||||||
uint64_t pml4_idx = (virt >> 39) & 0x1FF;
|
|
||||||
uint64_t pml3_idx = (virt >> 30) & 0x1FF;
|
|
||||||
uint64_t pml2_idx = (virt >> 21) & 0x1FF;
|
|
||||||
uint64_t pml1_idx = (virt >> 12) & 0x1FF;
|
|
||||||
|
|
||||||
uint64_t *pml3 = __vmm_get_next_lvl(pagemap->toplevel, pml4_idx, 0, false);
|
|
||||||
if (!pml3)
|
|
||||||
return 0;
|
|
||||||
uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_idx, 0, false);
|
|
||||||
if (!pml2)
|
|
||||||
return 0;
|
|
||||||
uint64_t *pml1 = __vmm_get_next_lvl(pml2, pml2_idx, 0, false);
|
|
||||||
if (!pml1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
uint64_t phys_addr = pml1[pml1_idx] & 0x000FFFFFFFFFF000;
|
|
||||||
|
|
||||||
return phys_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_map(pagemap_t *pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) {
|
|
||||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
|
||||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
|
||||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
|
||||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
|
||||||
|
|
||||||
uint64_t *pml3 = __vmm_get_next_lvl(pm->toplevel, pml4_entry,
|
|
||||||
VMM_PRESENT | VMM_WRITABLE, true);
|
|
||||||
uint64_t *pml2 =
|
|
||||||
__vmm_get_next_lvl(pml3, pml3_entry, VMM_PRESENT | VMM_WRITABLE, true);
|
|
||||||
uint64_t *pml1 =
|
|
||||||
__vmm_get_next_lvl(pml2, pml2_entry, VMM_PRESENT | VMM_WRITABLE, true);
|
|
||||||
|
|
||||||
pml1[pml1_entry] = paddr | flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_map_user(pagemap_t *pm, uint64_t vaddr, uint64_t paddr,
|
|
||||||
uint64_t flags) {
|
|
||||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
|
||||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
|
||||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
|
||||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
|
||||||
|
|
||||||
uint64_t *pml3 =
|
|
||||||
__vmm_get_next_lvl(pm->toplevel, pml4_entry, flags | VMM_WRITABLE,
|
|
||||||
true); // PML3 / Page Directory Pointer Entry
|
|
||||||
uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_entry, flags | VMM_WRITABLE,
|
|
||||||
true); // PML2 / Page Directory Entry
|
|
||||||
uint64_t *pml1 = __vmm_get_next_lvl(pml2, pml2_entry, flags | VMM_WRITABLE,
|
|
||||||
true); // PML1 / Page Table Entry
|
|
||||||
|
|
||||||
pml1[pml1_entry] = paddr | flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_unmap(pagemap_t *pm, uint64_t vaddr) {
|
|
||||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
|
||||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
|
||||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
|
||||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
|
||||||
|
|
||||||
uint64_t *pml3 = __vmm_get_next_lvl(pm->toplevel, pml4_entry, 0, false);
|
|
||||||
if (pml3 == NULL)
|
|
||||||
return;
|
|
||||||
uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_entry, 0, false);
|
|
||||||
if (pml2 == NULL)
|
|
||||||
return;
|
|
||||||
uint64_t *pml1 = __vmm_get_next_lvl(pml2, pml2_entry, 0, false);
|
|
||||||
if (pml1 == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pml1[pml1_entry] = 0;
|
|
||||||
|
|
||||||
__asm__ volatile("invlpg (%0)" : : "b"(vaddr) : "memory");
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define PTE_ADDR_MASK 0x000ffffffffff000
|
|
||||||
#define PTE_GET_ADDR(VALUE) ((VALUE) & PTE_ADDR_MASK)
|
|
||||||
#define PTE_GET_FLAGS(VALUE) ((VALUE) & ~PTE_ADDR_MASK)
|
|
||||||
|
|
||||||
#define VMM_PRESENT (1 << 0)
|
|
||||||
#define VMM_WRITABLE (1 << 1)
|
|
||||||
#define VMM_USER (1 << 2)
|
|
||||||
#define VMM_NX (1ULL << 63)
|
|
||||||
|
|
||||||
typedef char sym[];
|
|
||||||
|
|
||||||
extern sym reqs_start_ld;
|
|
||||||
extern sym reqs_end_ld;
|
|
||||||
|
|
||||||
extern sym text_start_ld;
|
|
||||||
extern sym text_end_ld;
|
|
||||||
|
|
||||||
extern sym rodata_start_ld;
|
|
||||||
extern sym rodata_end_ld;
|
|
||||||
|
|
||||||
extern sym data_start_ld;
|
|
||||||
extern sym data_end_ld;
|
|
||||||
|
|
||||||
typedef struct pagemap {
|
|
||||||
uint64_t *toplevel;
|
|
||||||
} pagemap_t;
|
|
||||||
|
|
||||||
extern pagemap_t *vmm_kernel_pm;
|
|
||||||
extern pagemap_t *vmm_current_pm;
|
|
||||||
|
|
||||||
pagemap_t *vmm_alloc_pm();
|
|
||||||
void vmm_init();
|
|
||||||
void vmm_release_pm(pagemap_t *pm);
|
|
||||||
void vmm_load_pagemap(pagemap_t *pm);
|
|
||||||
uint64_t vmm_get_flags(pagemap_t *pm, uint64_t vaddr);
|
|
||||||
uint64_t virt_to_phys(pagemap_t *pagemap, uint64_t virt);
|
|
||||||
|
|
||||||
// NOTE: for user mode, please use vmm_map_user instead.
|
|
||||||
void vmm_map(pagemap_t *pm, uint64_t vaddr, uint64_t paddr, uint64_t flags);
|
|
||||||
void vmm_map_user(pagemap_t *pm, uint64_t vaddr, uint64_t paddr,
|
|
||||||
uint64_t flags);
|
|
||||||
void vmm_unmap(pagemap_t *pm, uint64_t vaddr);
|
|
|
@ -1,10 +0,0 @@
|
||||||
bits 64
|
|
||||||
section .text
|
|
||||||
global kmain
|
|
||||||
extern __kmain
|
|
||||||
extern kstack
|
|
||||||
|
|
||||||
kmain:
|
|
||||||
mov rsp, kstack+0x2000 ; supposons 16 KiB de stack
|
|
||||||
xor rbp, rbp ; Set %ebp to NULL
|
|
||||||
call __kmain
|
|
21
kernel/src/exec/elf.h → kernel/src/proc/exec/elf.h
Normal file → Executable file
21
kernel/src/exec/elf.h → kernel/src/proc/exec/elf.h
Normal file → Executable file
|
@ -1,6 +1,12 @@
|
||||||
|
/*
|
||||||
|
* The Soaplin Kernel
|
||||||
|
* Copyright (C) 2025 The SILD Project
|
||||||
|
*
|
||||||
|
* elf.h - ELF definitions
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "exec/exec.h"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// ELF magic.
|
// ELF magic.
|
||||||
|
@ -94,6 +100,8 @@ typedef struct {
|
||||||
uint16_t e_shstrndx;
|
uint16_t e_shstrndx;
|
||||||
} Elf64_Ehdr;
|
} Elf64_Ehdr;
|
||||||
|
|
||||||
|
#define SHN_UNDEF 0
|
||||||
|
|
||||||
#define PT_NULL 0
|
#define PT_NULL 0
|
||||||
#define PT_LOAD 1
|
#define PT_LOAD 1
|
||||||
#define PT_DYNAMIC 2
|
#define PT_DYNAMIC 2
|
||||||
|
@ -116,17 +124,6 @@ typedef struct {
|
||||||
uint64_t p_align;
|
uint64_t p_align;
|
||||||
} Elf64_Phdr;
|
} Elf64_Phdr;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
program_t program;
|
|
||||||
|
|
||||||
Elf64_Ehdr *ehdr;
|
|
||||||
} elf_program_t;
|
|
||||||
|
|
||||||
program_t *elf_load(char *data, int user);
|
|
||||||
|
|
||||||
// Those aren't used for loading, but used by
|
|
||||||
// the kernel to resolve symbols from an instruction
|
|
||||||
// pointer.
|
|
||||||
#define SHT_SYMTAB 2
|
#define SHT_SYMTAB 2
|
||||||
#define SHT_STRTAB 3
|
#define SHT_STRTAB 3
|
||||||
|
|
30
kernel/src/proc/exec/exec.h
Normal file
30
kernel/src/proc/exec/exec.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
// Structure for an executable program loaded into memory.
|
||||||
|
|
||||||
|
#include "mm/paging.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EXEC_FMT_ELF,
|
||||||
|
EXEC_FMT_PE,
|
||||||
|
EXEC_FMT_MACHO,
|
||||||
|
EXEC_FMT_SCRIPT
|
||||||
|
} exec_format_t;
|
||||||
|
|
||||||
|
typedef struct exec {
|
||||||
|
pagemap_t pm;
|
||||||
|
|
||||||
|
void *rwdata_start;
|
||||||
|
size_t rwdata_len;
|
||||||
|
|
||||||
|
uint64_t entry;
|
||||||
|
|
||||||
|
int argc; // 0 for useds
|
||||||
|
char **argv; // NULL when the executable is a used
|
||||||
|
|
||||||
|
char *path;
|
||||||
|
exec_format_t format;
|
||||||
|
|
||||||
|
size_t usecount; // -1 for users, else, the number of processes sharing the executable's read only sections
|
||||||
|
struct exec *used; // The reference executable.
|
||||||
|
} exec_t;
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue