mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-06-02 12:44:24 +02:00
Update template to newest version which fixes edk2, make aarch64 compile
(nothing yet) by stubbing lots of functions and modules, make the frame allocator and heap multiarch, make kernel panic print inside of serial on x86_64
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/limine
|
/limine
|
||||||
/ovmf
|
/edk2-ovmf
|
||||||
*.iso
|
*.iso
|
||||||
*.hdd
|
*.hdd
|
||||||
|
|||||||
+21
-43
@@ -26,25 +26,24 @@ run: run-$(KARCH)
|
|||||||
run-hdd: run-hdd-$(KARCH)
|
run-hdd: run-hdd-$(KARCH)
|
||||||
|
|
||||||
.PHONY: run-x86_64
|
.PHONY: run-x86_64
|
||||||
run-x86_64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).iso
|
run-x86_64: edk2-ovmf $(IMAGE_NAME).iso
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
-M q35 \
|
-M q35 \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
-serial stdio \
|
||||||
-drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
-cdrom $(IMAGE_NAME).iso \
|
-cdrom $(IMAGE_NAME).iso \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: run-hdd-x86_64
|
.PHONY: run-hdd-x86_64
|
||||||
run-hdd-x86_64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).hdd
|
run-hdd-x86_64: edk2-ovmf $(IMAGE_NAME).hdd
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
-M q35 \
|
-M q35 \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
-drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \
|
|
||||||
-hda $(IMAGE_NAME).hdd \
|
-hda $(IMAGE_NAME).hdd \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: run-aarch64
|
.PHONY: run-aarch64
|
||||||
run-aarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).iso
|
run-aarch64: edk2-ovmf $(IMAGE_NAME).iso
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu cortex-a72 \
|
-cpu cortex-a72 \
|
||||||
@@ -52,13 +51,13 @@ run-aarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME)
|
|||||||
-device qemu-xhci \
|
-device qemu-xhci \
|
||||||
-device usb-kbd \
|
-device usb-kbd \
|
||||||
-device usb-mouse \
|
-device usb-mouse \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
-serial stdio \
|
||||||
-drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
-cdrom $(IMAGE_NAME).iso \
|
-cdrom $(IMAGE_NAME).iso \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: run-hdd-aarch64
|
.PHONY: run-hdd-aarch64
|
||||||
run-hdd-aarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).hdd
|
run-hdd-aarch64: edk2-ovmf $(IMAGE_NAME).hdd
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu cortex-a72 \
|
-cpu cortex-a72 \
|
||||||
@@ -66,13 +65,12 @@ run-hdd-aarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_N
|
|||||||
-device qemu-xhci \
|
-device qemu-xhci \
|
||||||
-device usb-kbd \
|
-device usb-kbd \
|
||||||
-device usb-mouse \
|
-device usb-mouse \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
-drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \
|
|
||||||
-hda $(IMAGE_NAME).hdd \
|
-hda $(IMAGE_NAME).hdd \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: run-riscv64
|
.PHONY: run-riscv64
|
||||||
run-riscv64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).iso
|
run-riscv64: edk2-ovmf $(IMAGE_NAME).iso
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu rv64 \
|
-cpu rv64 \
|
||||||
@@ -80,13 +78,12 @@ run-riscv64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME)
|
|||||||
-device qemu-xhci \
|
-device qemu-xhci \
|
||||||
-device usb-kbd \
|
-device usb-kbd \
|
||||||
-device usb-mouse \
|
-device usb-mouse \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
-drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \
|
|
||||||
-cdrom $(IMAGE_NAME).iso \
|
-cdrom $(IMAGE_NAME).iso \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: run-hdd-riscv64
|
.PHONY: run-hdd-riscv64
|
||||||
run-hdd-riscv64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).hdd
|
run-hdd-riscv64: edk2-ovmf $(IMAGE_NAME).hdd
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu rv64 \
|
-cpu rv64 \
|
||||||
@@ -94,13 +91,12 @@ run-hdd-riscv64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_N
|
|||||||
-device qemu-xhci \
|
-device qemu-xhci \
|
||||||
-device usb-kbd \
|
-device usb-kbd \
|
||||||
-device usb-mouse \
|
-device usb-mouse \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
-drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \
|
|
||||||
-hda $(IMAGE_NAME).hdd \
|
-hda $(IMAGE_NAME).hdd \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: run-loongarch64
|
.PHONY: run-loongarch64
|
||||||
run-loongarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).iso
|
run-loongarch64: edk2-ovmf $(IMAGE_NAME).iso
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu la464 \
|
-cpu la464 \
|
||||||
@@ -108,13 +104,12 @@ run-loongarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_N
|
|||||||
-device qemu-xhci \
|
-device qemu-xhci \
|
||||||
-device usb-kbd \
|
-device usb-kbd \
|
||||||
-device usb-mouse \
|
-device usb-mouse \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
-drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \
|
|
||||||
-cdrom $(IMAGE_NAME).iso \
|
-cdrom $(IMAGE_NAME).iso \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: run-hdd-loongarch64
|
.PHONY: run-hdd-loongarch64
|
||||||
run-hdd-loongarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME).hdd
|
run-hdd-loongarch64: edk2-ovmf $(IMAGE_NAME).hdd
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
-M virt \
|
-M virt \
|
||||||
-cpu la464 \
|
-cpu la464 \
|
||||||
@@ -122,8 +117,7 @@ run-hdd-loongarch64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMA
|
|||||||
-device qemu-xhci \
|
-device qemu-xhci \
|
||||||
-device usb-kbd \
|
-device usb-kbd \
|
||||||
-device usb-mouse \
|
-device usb-mouse \
|
||||||
-drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
-drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(KARCH).fd \
|
|
||||||
-hda $(IMAGE_NAME).hdd \
|
-hda $(IMAGE_NAME).hdd \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
@@ -143,27 +137,12 @@ run-hdd-bios: $(IMAGE_NAME).hdd
|
|||||||
-hda $(IMAGE_NAME).hdd \
|
-hda $(IMAGE_NAME).hdd \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
ovmf/ovmf-code-$(KARCH).fd:
|
edk2-ovmf:
|
||||||
mkdir -p ovmf
|
curl -L https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/edk2-ovmf.tar.gz | gunzip | tar -xf -
|
||||||
curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-code-$(KARCH).fd
|
|
||||||
case "$(KARCH)" in \
|
|
||||||
aarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=67108864 2>/dev/null;; \
|
|
||||||
loongarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=5242880 2>/dev/null;; \
|
|
||||||
riscv64) dd if=/dev/zero of=$@ bs=1 count=0 seek=33554432 2>/dev/null;; \
|
|
||||||
esac
|
|
||||||
|
|
||||||
ovmf/ovmf-vars-$(KARCH).fd:
|
|
||||||
mkdir -p ovmf
|
|
||||||
curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-vars-$(KARCH).fd
|
|
||||||
case "$(KARCH)" in \
|
|
||||||
aarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=67108864 2>/dev/null;; \
|
|
||||||
loongarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=5242880 2>/dev/null;; \
|
|
||||||
riscv64) dd if=/dev/zero of=$@ bs=1 count=0 seek=33554432 2>/dev/null;; \
|
|
||||||
esac
|
|
||||||
|
|
||||||
limine/limine:
|
limine/limine:
|
||||||
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=v10.x-binary --depth=1
|
||||||
$(MAKE) -C limine
|
$(MAKE) -C limine
|
||||||
|
|
||||||
.PHONY: kernel
|
.PHONY: kernel
|
||||||
@@ -213,7 +192,6 @@ ifeq ($(KARCH),loongarch64)
|
|||||||
iso_root -o $(IMAGE_NAME).iso
|
iso_root -o $(IMAGE_NAME).iso
|
||||||
endif
|
endif
|
||||||
rm -rf iso_root
|
rm -rf iso_root
|
||||||
qemu-system-$(KARCH) -cdrom $(IMAGE_NAME).iso -m 1G -serial stdio
|
|
||||||
|
|
||||||
$(IMAGE_NAME).hdd: limine/limine kernel
|
$(IMAGE_NAME).hdd: limine/limine kernel
|
||||||
rm -f $(IMAGE_NAME).hdd
|
rm -f $(IMAGE_NAME).hdd
|
||||||
|
|||||||
Generated
+16
@@ -6,6 +6,7 @@ version = 4
|
|||||||
name = "XunilOS"
|
name = "XunilOS"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aarch64-cpu",
|
||||||
"font8x8",
|
"font8x8",
|
||||||
"heapless",
|
"heapless",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@@ -17,6 +18,15 @@ dependencies = [
|
|||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aarch64-cpu"
|
||||||
|
version = "11.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44171e22925ec72b63d86747bc3655c7849a5b8d865c980222128839f45ac034"
|
||||||
|
dependencies = [
|
||||||
|
"tock-registers",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
@@ -156,6 +166,12 @@ dependencies = [
|
|||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tock-registers"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d2d250f87fb3fb6f225c907cf54381509f47b40b74b1d1f12d2dccbc915bdfe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "volatile"
|
name = "volatile"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
|||||||
+4
-1
@@ -14,13 +14,16 @@ heapless = "0.9.2"
|
|||||||
lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
|
lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
|
||||||
limine = "0.5"
|
limine = "0.5"
|
||||||
pc-keyboard = "0.8.0"
|
pc-keyboard = "0.8.0"
|
||||||
pic8259 = "0.11.0"
|
|
||||||
spin = "0.10.0"
|
spin = "0.10.0"
|
||||||
static_cell = "2.1.1"
|
static_cell = "2.1.1"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||||
|
pic8259 = "0.11.0"
|
||||||
x86_64 = "0.15.4"
|
x86_64 = "0.15.4"
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
||||||
|
aarch64-cpu = "11.2.0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly"
|
channel = "nightly"
|
||||||
targets = [
|
targets = [
|
||||||
"x86_64-unknown-none",
|
# "x86_64-unknown-none",
|
||||||
# "aarch64-unknown-none",
|
"aarch64-unknown-none",
|
||||||
# "riscv64gc-unknown-none-elf",
|
# "riscv64gc-unknown-none-elf",
|
||||||
# "loongarch64-unknown-none",
|
# "loongarch64-unknown-none",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
use crate::{mm::heap::LinkedListAllocator, util::Locked};
|
||||||
|
#[global_allocator]
|
||||||
|
pub static ALLOCATOR: Locked<LinkedListAllocator> = Locked::new(LinkedListAllocator::new());
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
use limine::response::{HhdmResponse, MemoryMapResponse};
|
||||||
|
pub fn init_aarch64<'a>(hhdm_response: &HhdmResponse, memory_map_response: &'a MemoryMapResponse) {}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod heap;
|
||||||
|
pub mod init;
|
||||||
|
pub mod paging;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
use crate::arch::arch::XunilFrameAllocator;
|
||||||
|
use spin::Mutex;
|
||||||
|
|
||||||
|
pub static FRAME_ALLOCATOR_AARCH64: Mutex<XunilFrameAllocator> =
|
||||||
|
Mutex::new(XunilFrameAllocator::new());
|
||||||
+94
-7
@@ -1,16 +1,85 @@
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub use crate::arch::x86_64::paging::FRAME_ALLOCATOR_X86_64 as FRAME_ALLOCATOR;
|
pub use crate::arch::x86_64::paging::FRAME_ALLOCATOR_X86_64 as FRAME_ALLOCATOR;
|
||||||
|
|
||||||
use crate::driver::timer::TIMER;
|
#[cfg(target_arch = "aarch64")]
|
||||||
use core::{alloc::GlobalAlloc, arch::asm};
|
pub use crate::arch::aarch64::paging::FRAME_ALLOCATOR_AARCH64 as FRAME_ALLOCATOR;
|
||||||
use limine::response::{HhdmResponse, MemoryMapResponse};
|
|
||||||
|
use crate::{driver::timer::TIMER, util::align_up};
|
||||||
|
use core::arch::asm;
|
||||||
|
use limine::{
|
||||||
|
memory_map::{Entry, EntryType},
|
||||||
|
response::{HhdmResponse, MemoryMapResponse},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct UsableRegion {
|
||||||
|
pub base: u64,
|
||||||
|
pub length: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
const EMPTY_REGION: UsableRegion = UsableRegion { base: 0, length: 0 };
|
||||||
|
|
||||||
|
// NOTE: dont change name to frameallocator as that is the name of the trait of x86_64
|
||||||
|
pub struct XunilFrameAllocator {
|
||||||
|
pub hhdm_offset: u64,
|
||||||
|
pub usable_regions: [UsableRegion; 1024],
|
||||||
|
pub usable_region_count: usize,
|
||||||
|
pub region_index: usize,
|
||||||
|
pub region_offset: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XunilFrameAllocator {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
hhdm_offset: 0,
|
||||||
|
usable_regions: [EMPTY_REGION; 1024],
|
||||||
|
usable_region_count: 0,
|
||||||
|
region_index: 0,
|
||||||
|
region_offset: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initialize(&mut self, hhdm_offset: u64, memory_map: &[&Entry]) {
|
||||||
|
let mut regions = [EMPTY_REGION; 1024];
|
||||||
|
let mut count = 0usize;
|
||||||
|
|
||||||
|
for region in memory_map.iter().copied() {
|
||||||
|
if region.entry_type != EntryType::USABLE {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if count < regions.len() && region.length >= 4096 {
|
||||||
|
let aligned_base = align_up(region.base, 4096);
|
||||||
|
let base_offset = aligned_base - region.base;
|
||||||
|
let aligned_length = region.length.saturating_sub(base_offset);
|
||||||
|
if aligned_length >= 4096 {
|
||||||
|
regions[count] = UsableRegion {
|
||||||
|
base: aligned_base,
|
||||||
|
length: aligned_length,
|
||||||
|
};
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.hhdm_offset = hhdm_offset;
|
||||||
|
self.usable_regions = regions;
|
||||||
|
self.usable_region_count = count;
|
||||||
|
self.region_index = 0;
|
||||||
|
self.region_offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::arch::x86_64::{
|
use crate::arch::x86_64::{
|
||||||
elf::run_elf_x86_64, heap::ALLOCATOR, init::init_x86_64, usermode::enter_usermode_x86_64,
|
elf::run_elf_x86_64, init::init_x86_64, usermode::enter_usermode_x86_64,
|
||||||
};
|
};
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use x86_64::structures::paging::OffsetPageTable;
|
use x86_64::{instructions::interrupts::without_interrupts, structures::paging::OffsetPageTable};
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use crate::arch::aarch64::init::init_aarch64;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn init<'a>(
|
pub fn init<'a>(
|
||||||
@@ -20,18 +89,36 @@ pub fn init<'a>(
|
|||||||
return init_x86_64(hhdm_response, memory_map_response);
|
return init_x86_64(hhdm_response, memory_map_response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub fn init<'a>(hhdm_response: &HhdmResponse, memory_map_response: &'a MemoryMapResponse) {
|
||||||
|
return init_aarch64(hhdm_response, memory_map_response);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn enter_usermode(user_rip: u64, user_rsp: u64, should_swapgs: bool) {
|
pub fn enter_usermode(user_rip: u64, user_rsp: u64, should_swapgs: bool) {
|
||||||
enter_usermode_x86_64(user_rip, user_rsp, should_swapgs);
|
enter_usermode_x86_64(user_rip, user_rsp, should_swapgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub fn enter_usermode(user_rip: u64, user_rsp: u64, should_swapgs: bool) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn run_elf(file_bytes: &[u8], should_swapgs: bool) {
|
pub fn run_elf(file_bytes: &[u8], should_swapgs: bool) {
|
||||||
run_elf_x86_64(file_bytes, should_swapgs);
|
run_elf_x86_64(file_bytes, should_swapgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_allocator<'a>() -> &'static impl GlobalAlloc {
|
#[cfg(target_arch = "aarch64")]
|
||||||
return &ALLOCATOR;
|
pub fn run_elf(file_bytes: &[u8], should_swapgs: bool) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn safe_lock<R, F: FnOnce() -> R>(f: F) -> R {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
return without_interrupts(|| f());
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
return f();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn idle() {
|
pub fn idle() {
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
pub mod arch;
|
#[cfg(target_arch = "aarch64")]
|
||||||
pub mod syscall;
|
pub mod aarch64;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub mod x86_64;
|
pub mod x86_64;
|
||||||
|
|
||||||
|
pub mod arch;
|
||||||
|
pub mod syscall;
|
||||||
|
|||||||
+86
-34
@@ -1,6 +1,7 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
PhysAddr, VirtAddr,
|
PhysAddr, VirtAddr,
|
||||||
instructions::interrupts,
|
instructions::interrupts,
|
||||||
@@ -15,7 +16,6 @@ use crate::{
|
|||||||
keyboard::{KeyboardEvent, process_scancodes},
|
keyboard::{KeyboardEvent, process_scancodes},
|
||||||
timer::TIMER,
|
timer::TIMER,
|
||||||
},
|
},
|
||||||
mm::usercopy::{copy_cstr_from_user, copy_to_user},
|
|
||||||
print,
|
print,
|
||||||
task::{
|
task::{
|
||||||
process::ProcessState,
|
process::ProcessState,
|
||||||
@@ -24,6 +24,12 @@ use crate::{
|
|||||||
util::{align_down, align_up},
|
util::{align_down, align_up},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use crate::{
|
||||||
|
arch::arch::safe_lock,
|
||||||
|
mm::usercopy::{copy_cstr_from_user, copy_to_user},
|
||||||
|
};
|
||||||
|
|
||||||
const READ: usize = 0;
|
const READ: usize = 0;
|
||||||
const WRITE: usize = 1;
|
const WRITE: usize = 1;
|
||||||
const OPEN: usize = 2;
|
const OPEN: usize = 2;
|
||||||
@@ -50,6 +56,7 @@ const SLEEP: usize = 909090; // zzz haha
|
|||||||
pub const MAP_FRAMEBUFFER: usize = 5555;
|
pub const MAP_FRAMEBUFFER: usize = 5555;
|
||||||
pub const FRAMEBUFFER_SWAP: usize = 6666;
|
pub const FRAMEBUFFER_SWAP: usize = 6666;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn map_framebuffer() -> isize {
|
fn map_framebuffer() -> isize {
|
||||||
let pid = current_pid().unwrap_or(0);
|
let pid = current_pid().unwrap_or(0);
|
||||||
if pid == 0 {
|
if pid == 0 {
|
||||||
@@ -107,6 +114,12 @@ fn map_framebuffer() -> isize {
|
|||||||
.unwrap_or(-1)
|
.unwrap_or(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
fn map_framebuffer() -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn read(ptr: isize, size: isize, nmemb: isize, fd: isize) -> isize {
|
fn read(ptr: isize, size: isize, nmemb: isize, fd: isize) -> isize {
|
||||||
let pid = current_pid().unwrap_or(0);
|
let pid = current_pid().unwrap_or(0);
|
||||||
if pid == 0 {
|
if pid == 0 {
|
||||||
@@ -142,6 +155,12 @@ fn read(ptr: isize, size: isize, nmemb: isize, fd: isize) -> isize {
|
|||||||
.unwrap_or(-1)
|
.unwrap_or(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
fn read(ptr: isize, size: isize, nmemb: isize, fd: isize) -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn open(path: isize, mode: isize) -> isize {
|
fn open(path: isize, mode: isize) -> isize {
|
||||||
let pid = current_pid().unwrap_or(0);
|
let pid = current_pid().unwrap_or(0);
|
||||||
if pid == 0 {
|
if pid == 0 {
|
||||||
@@ -160,10 +179,16 @@ fn open(path: isize, mode: isize) -> isize {
|
|||||||
.unwrap_or(-1)
|
.unwrap_or(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
fn open(path: isize, mode: isize) -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
fn close(fd: isize) -> isize {
|
fn close(fd: isize) -> isize {
|
||||||
vfs_close(fd as i64) as isize
|
vfs_close(fd as i64) as isize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize {
|
fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize {
|
||||||
process_scancodes();
|
process_scancodes();
|
||||||
if max_events <= 0 || user_ptr.is_null() {
|
if max_events <= 0 || user_ptr.is_null() {
|
||||||
@@ -198,6 +223,12 @@ fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize {
|
|||||||
.unwrap_or(-1);
|
.unwrap_or(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub unsafe fn sbrk(increment: isize) -> isize {
|
pub unsafe fn sbrk(increment: isize) -> isize {
|
||||||
let pid = current_pid().unwrap_or(0);
|
let pid = current_pid().unwrap_or(0);
|
||||||
|
|
||||||
@@ -205,9 +236,10 @@ pub unsafe fn sbrk(increment: isize) -> isize {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
|
||||||
return SCHEDULER
|
return SCHEDULER
|
||||||
.with_process(pid as u64, |process| {
|
.with_process(pid as u64, |process| {
|
||||||
|
let mut frame_allocator = safe_lock(|| FRAME_ALLOCATOR.lock());
|
||||||
|
|
||||||
let (heap_end, heap_base, stack_top) =
|
let (heap_end, heap_base, stack_top) =
|
||||||
(process.heap_end, process.heap_base, process.stack_top);
|
(process.heap_end, process.heap_base, process.stack_top);
|
||||||
|
|
||||||
@@ -223,8 +255,8 @@ pub unsafe fn sbrk(increment: isize) -> isize {
|
|||||||
if new < heap_base {
|
if new < heap_base {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if new > stack_top - 16384 * 4096 {
|
if new > stack_top - 65535 * 4096 {
|
||||||
// 67 mib max
|
// 262 mib max
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,6 +304,12 @@ pub unsafe fn sbrk(increment: isize) -> isize {
|
|||||||
.unwrap_or(-1);
|
.unwrap_or(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub unsafe fn sbrk(increment: isize) -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn exec(arg0: isize) -> isize {
|
pub fn exec(arg0: isize) -> isize {
|
||||||
let pid = current_pid().unwrap_or(0);
|
let pid = current_pid().unwrap_or(0);
|
||||||
if pid == 0 {
|
if pid == 0 {
|
||||||
@@ -336,6 +374,11 @@ pub fn exec(arg0: isize) -> isize {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub fn exec(arg0: isize) -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_reschedule(should_reschedule: bool) {
|
pub fn set_reschedule(should_reschedule: bool) {
|
||||||
let pid = current_pid().unwrap_or(0);
|
let pid = current_pid().unwrap_or(0);
|
||||||
|
|
||||||
@@ -352,6 +395,43 @@ pub fn set_reschedule(should_reschedule: bool) {
|
|||||||
drop(scheduler);
|
drop(scheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub fn exit() -> isize {
|
||||||
|
let pid = current_pid().unwrap_or(0);
|
||||||
|
if pid == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let next_pid = {
|
||||||
|
let mut sched = SCHEDULER.lock();
|
||||||
|
|
||||||
|
sched.processes.remove(&pid);
|
||||||
|
|
||||||
|
sched
|
||||||
|
.processes
|
||||||
|
.iter()
|
||||||
|
.find_map(|(other, proc)| {
|
||||||
|
if *other != pid && matches!(proc.state, ProcessState::Ready) {
|
||||||
|
Some(*other)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or(0)
|
||||||
|
};
|
||||||
|
|
||||||
|
if next_pid != 0 {
|
||||||
|
SCHEDULER.switch_to(next_pid, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::arch::arch::infinite_idle();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub fn exit() -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub unsafe extern "C" fn syscall_dispatch(
|
pub unsafe extern "C" fn syscall_dispatch(
|
||||||
num: usize,
|
num: usize,
|
||||||
@@ -362,6 +442,7 @@ pub unsafe extern "C" fn syscall_dispatch(
|
|||||||
arg4: isize,
|
arg4: isize,
|
||||||
arg5: isize,
|
arg5: isize,
|
||||||
) -> isize {
|
) -> isize {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
interrupts::enable();
|
interrupts::enable();
|
||||||
|
|
||||||
set_reschedule(match num {
|
set_reschedule(match num {
|
||||||
@@ -405,36 +486,7 @@ pub unsafe extern "C" fn syscall_dispatch(
|
|||||||
OPEN => open(arg0, arg1),
|
OPEN => open(arg0, arg1),
|
||||||
CLOSE => close(arg0),
|
CLOSE => close(arg0),
|
||||||
LSEEK => vfs_lseek(arg0 as i64, arg1 as i64, arg2 as i32) as isize,
|
LSEEK => vfs_lseek(arg0 as i64, arg1 as i64, arg2 as i32) as isize,
|
||||||
EXIT => {
|
EXIT => exit(),
|
||||||
let pid = current_pid().unwrap_or(0);
|
|
||||||
if pid == 0 {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let next_pid = {
|
|
||||||
let mut sched = SCHEDULER.lock();
|
|
||||||
|
|
||||||
sched.processes.remove(&pid);
|
|
||||||
|
|
||||||
sched
|
|
||||||
.processes
|
|
||||||
.iter()
|
|
||||||
.find_map(|(other, proc)| {
|
|
||||||
if *other != pid && matches!(proc.state, ProcessState::Ready) {
|
|
||||||
Some(*other)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap_or(0)
|
|
||||||
};
|
|
||||||
|
|
||||||
if next_pid != 0 {
|
|
||||||
SCHEDULER.switch_to(next_pid, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
crate::arch::arch::infinite_idle();
|
|
||||||
}
|
|
||||||
SLEEP => {
|
SLEEP => {
|
||||||
sleep(arg0 as u64);
|
sleep(arg0 as u64);
|
||||||
0
|
0
|
||||||
|
|||||||
@@ -26,12 +26,10 @@ pub fn run_elf_x86_64(file_bytes: &[u8], should_swapgs: bool) {
|
|||||||
.spawn_process(entry_point as u64, stack_top, heap_base)
|
.spawn_process(entry_point as u64, stack_top, heap_base)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut frames: Vec<PhysFrame<Size4KiB>> = Vec::new();
|
|
||||||
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
||||||
|
|
||||||
for i in 0..page_count {
|
for i in 0..page_count {
|
||||||
let frame = frame_allocator.allocate_frame().unwrap();
|
let frame = frame_allocator.allocate_frame().unwrap();
|
||||||
frames.push(frame);
|
|
||||||
|
|
||||||
let virt_addr = VirtAddr::new(stack_base + i as u64 * page_size);
|
let virt_addr = VirtAddr::new(stack_base + i as u64 * page_size);
|
||||||
let page = Page::<Size4KiB>::containing_address(virt_addr);
|
let page = Page::<Size4KiB>::containing_address(virt_addr);
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
use crate::arch::x86_64::paging::FRAME_ALLOCATOR_X86_64;
|
|
||||||
use crate::util::Locked;
|
use crate::util::Locked;
|
||||||
use core::{
|
use crate::{arch::x86_64::paging::FRAME_ALLOCATOR_X86_64, mm::heap::LinkedListAllocator};
|
||||||
alloc::{GlobalAlloc, Layout},
|
|
||||||
ptr::null_mut,
|
|
||||||
};
|
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
structures::paging::{
|
structures::paging::{
|
||||||
@@ -12,150 +8,12 @@ use x86_64::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn align_up(addr: usize, align: usize) -> usize {
|
|
||||||
(addr + align - 1) & !(align - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
pub static ALLOCATOR: Locked<LinkedListAllocator> = Locked::new(LinkedListAllocator::new());
|
pub static ALLOCATOR: Locked<LinkedListAllocator> = Locked::new(LinkedListAllocator::new());
|
||||||
|
|
||||||
pub const HEAP_START: usize = 0xffffffff90000000;
|
pub const HEAP_START: usize = 0xffffffff90000000;
|
||||||
pub const HEAP_SIZE: usize = 64 * 1024 * 1024; // 64 MiB
|
pub const HEAP_SIZE: usize = 64 * 1024 * 1024; // 64 MiB
|
||||||
|
|
||||||
pub struct LinkedNode {
|
|
||||||
pub size: usize,
|
|
||||||
pub next: Option<&'static mut LinkedNode>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LinkedNode {
|
|
||||||
pub const fn new(size: usize) -> LinkedNode {
|
|
||||||
LinkedNode { size, next: None }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_addr(&self) -> usize {
|
|
||||||
self as *const Self as usize
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn end_addr(&self) -> usize {
|
|
||||||
self.start_addr() + self.size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LinkedListAllocator {
|
|
||||||
head: LinkedNode,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LinkedListAllocator {
|
|
||||||
pub const fn new() -> LinkedListAllocator {
|
|
||||||
Self {
|
|
||||||
head: LinkedNode::new(0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_align(layout: Layout) -> (usize, usize) {
|
|
||||||
let layout = layout
|
|
||||||
.align_to(16)
|
|
||||||
.expect("Align to LinkedNode failed")
|
|
||||||
.pad_to_align();
|
|
||||||
|
|
||||||
let size = layout.size().max(core::mem::size_of::<LinkedNode>()); // either take layout's size or atleast the size of a single linked node.
|
|
||||||
|
|
||||||
(size, layout.align())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) {
|
|
||||||
unsafe {
|
|
||||||
self.add_free_memory_region(heap_start, heap_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn add_free_memory_region(&mut self, start: usize, size: usize) {
|
|
||||||
assert_eq!(align_up(start, 16), start); // Check if we are up at least 1 LinkedNode size
|
|
||||||
assert!(size >= core::mem::size_of::<LinkedNode>()); // check if we have enough space for a LinkedNode
|
|
||||||
|
|
||||||
let mut linked_node = LinkedNode::new(size);
|
|
||||||
linked_node.next = self.head.next.take();
|
|
||||||
|
|
||||||
let linked_node_ptr = start as *mut LinkedNode; // Treat the start memory region as a LinkedNode type
|
|
||||||
unsafe {
|
|
||||||
linked_node_ptr.write(linked_node); // write the data, very risky
|
|
||||||
self.head.next = Some(&mut *linked_node_ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_region(
|
|
||||||
&mut self,
|
|
||||||
size: usize,
|
|
||||||
align: usize,
|
|
||||||
) -> Option<(&'static mut LinkedNode, usize)> {
|
|
||||||
let mut current = &mut self.head;
|
|
||||||
|
|
||||||
while let Some(ref mut region) = current.next {
|
|
||||||
if let Ok(alloc_start) = Self::alloc_from_region(®ion, size, align) {
|
|
||||||
let next = region.next.take();
|
|
||||||
let ret = Some((current.next.take().unwrap(), alloc_start));
|
|
||||||
current.next = next;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
current = current.next.as_mut().unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alloc_from_region(region: &LinkedNode, size: usize, align: usize) -> Result<usize, ()> {
|
|
||||||
let alloc_start = align_up(region.start_addr(), align);
|
|
||||||
let alloc_end = alloc_start.checked_add(size).ok_or(())?; // check for overflows
|
|
||||||
|
|
||||||
if alloc_end > region.end_addr() {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let excess_size = region.end_addr() - alloc_end;
|
|
||||||
if excess_size > 0 && excess_size < core::mem::size_of::<LinkedNode>() {
|
|
||||||
// if the remaining space is not enough for another LinkedNode, skip this region.
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(alloc_start)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl GlobalAlloc for Locked<LinkedListAllocator> {
|
|
||||||
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
|
|
||||||
let (size, align) = LinkedListAllocator::size_align(_layout);
|
|
||||||
let mut allocator = self.lock();
|
|
||||||
|
|
||||||
if let Some((region, alloc_start)) = allocator.find_region(size, align) {
|
|
||||||
let alloc_end = alloc_start.checked_add(size).expect("overflow");
|
|
||||||
|
|
||||||
let excess_size = region.end_addr() - alloc_end;
|
|
||||||
|
|
||||||
if excess_size > 0 {
|
|
||||||
unsafe {
|
|
||||||
allocator.add_free_memory_region(alloc_end, excess_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
drop(allocator);
|
|
||||||
|
|
||||||
alloc_start as *mut u8
|
|
||||||
} else {
|
|
||||||
null_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
|
||||||
let (size, _) = LinkedListAllocator::size_align(_layout);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
self.lock().add_free_memory_region(_ptr as usize, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_heap(mapper: &mut OffsetPageTable) -> Result<(), MapToError<Size4KiB>> {
|
pub fn init_heap(mapper: &mut OffsetPageTable) -> Result<(), MapToError<Size4KiB>> {
|
||||||
let page_range = {
|
let page_range = {
|
||||||
let page_start = VirtAddr::new(HEAP_START as u64);
|
let page_start = VirtAddr::new(HEAP_START as u64);
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ use x86_64::{
|
|||||||
structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB},
|
structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB},
|
||||||
};
|
};
|
||||||
|
|
||||||
use limine::memory_map::{Entry, EntryType};
|
use crate::arch::arch::XunilFrameAllocator;
|
||||||
|
|
||||||
use crate::util::align_up;
|
|
||||||
|
|
||||||
unsafe fn active_level_4_table(mem_offset: VirtAddr) -> &'static mut PageTable {
|
unsafe fn active_level_4_table(mem_offset: VirtAddr) -> &'static mut PageTable {
|
||||||
let (level_4_table, _) = Cr3::read();
|
let (level_4_table, _) = Cr3::read();
|
||||||
@@ -26,64 +24,6 @@ pub unsafe fn initialize_paging(physical_memory_offset: VirtAddr) -> OffsetPageT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
struct UsableRegion {
|
|
||||||
base: u64,
|
|
||||||
length: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
const EMPTY_REGION: UsableRegion = UsableRegion { base: 0, length: 0 };
|
|
||||||
|
|
||||||
pub struct XunilFrameAllocator {
|
|
||||||
pub hhdm_offset: u64,
|
|
||||||
usable_regions: [UsableRegion; 1024],
|
|
||||||
usable_region_count: usize,
|
|
||||||
region_index: usize,
|
|
||||||
region_offset: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl XunilFrameAllocator {
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
hhdm_offset: 0,
|
|
||||||
usable_regions: [EMPTY_REGION; 1024],
|
|
||||||
usable_region_count: 0,
|
|
||||||
region_index: 0,
|
|
||||||
region_offset: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initialize(&mut self, hhdm_offset: u64, memory_map: &[&Entry]) {
|
|
||||||
let mut regions = [EMPTY_REGION; 1024];
|
|
||||||
let mut count = 0usize;
|
|
||||||
|
|
||||||
for region in memory_map.iter().copied() {
|
|
||||||
if region.entry_type != EntryType::USABLE {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if count < regions.len() && region.length >= 4096 {
|
|
||||||
let aligned_base = align_up(region.base, 4096);
|
|
||||||
let base_offset = aligned_base - region.base;
|
|
||||||
let aligned_length = region.length.saturating_sub(base_offset);
|
|
||||||
if aligned_length >= 4096 {
|
|
||||||
regions[count] = UsableRegion {
|
|
||||||
base: aligned_base,
|
|
||||||
length: aligned_length,
|
|
||||||
};
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.hhdm_offset = hhdm_offset;
|
|
||||||
self.usable_regions = regions;
|
|
||||||
self.usable_region_count = count;
|
|
||||||
self.region_index = 0;
|
|
||||||
self.region_offset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl FrameAllocator<Size4KiB> for XunilFrameAllocator {
|
unsafe impl FrameAllocator<Size4KiB> for XunilFrameAllocator {
|
||||||
fn allocate_frame(&mut self) -> Option<PhysFrame<Size4KiB>> {
|
fn allocate_frame(&mut self) -> Option<PhysFrame<Size4KiB>> {
|
||||||
while self.region_index < self.usable_region_count {
|
while self.region_index < self.usable_region_count {
|
||||||
@@ -93,6 +33,11 @@ unsafe impl FrameAllocator<Size4KiB> for XunilFrameAllocator {
|
|||||||
if self.region_offset < frame_count as usize {
|
if self.region_offset < frame_count as usize {
|
||||||
let addr = region.base + (self.region_offset as u64 * 4096);
|
let addr = region.base + (self.region_offset as u64 * 4096);
|
||||||
self.region_offset += 1;
|
self.region_offset += 1;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
core::ptr::write_bytes((addr + self.hhdm_offset) as *mut u8, 0, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
return Some(PhysFrame::containing_address(PhysAddr::new(addr)));
|
return Some(PhysFrame::containing_address(PhysAddr::new(addr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,43 @@
|
|||||||
use core::ptr::null;
|
use core::ptr::null;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use crate::driver::elf::{
|
||||||
|
header::{
|
||||||
|
EI_CLASS, EI_DATA, EI_VERSION, ELF_MAGIC, EM_X86_64, ET_DYN, ET_EXEC, ET_REL, Elf64Ehdr,
|
||||||
|
},
|
||||||
|
program::load_program,
|
||||||
|
};
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
use x86_64::structures::paging::OffsetPageTable;
|
use x86_64::structures::paging::OffsetPageTable;
|
||||||
|
|
||||||
use crate::driver::elf::{
|
#[cfg(target_arch = "x86_64")]
|
||||||
header::{ET_DYN, ET_EXEC, ET_REL, Elf64Ehdr},
|
pub fn validate_elf(elf_header: &Elf64Ehdr, elf_len: usize) -> bool {
|
||||||
program::load_program,
|
#[cfg(target_arch = "x86_64")]
|
||||||
validation::validate_elf,
|
let required_machine = EM_X86_64;
|
||||||
};
|
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use crate::driver::elf::header::EM_AARCH64;
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
let required_machine = EM_AARCH64;
|
||||||
|
|
||||||
|
elf_header.e_ident[0..4] == ELF_MAGIC
|
||||||
|
// 64 bit
|
||||||
|
&& elf_header.e_ident[EI_CLASS] == 2
|
||||||
|
// little-endian
|
||||||
|
&& elf_header.e_ident[EI_DATA] == 1
|
||||||
|
&& elf_header.e_ident[EI_VERSION] == 1
|
||||||
|
&& elf_header.e_version == 1
|
||||||
|
// check architecture
|
||||||
|
&& elf_header.e_machine == required_machine
|
||||||
|
// disallow object files
|
||||||
|
&& [ET_DYN, ET_EXEC].contains(&elf_header.e_type)
|
||||||
|
// standard elf64
|
||||||
|
&& elf_header.e_phentsize == 56
|
||||||
|
&& elf_header.e_phnum != 0 // zero program headers
|
||||||
|
&& (elf_header.e_phoff + (elf_header.e_phnum*elf_header.e_phentsize) as u64) <= elf_len as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn load_file(mapper: &mut OffsetPageTable, elf_bytes: &[u8]) -> (*const u8, u64) {
|
pub fn load_file(mapper: &mut OffsetPageTable, elf_bytes: &[u8]) -> (*const u8, u64) {
|
||||||
// elf header size
|
// elf header size
|
||||||
if elf_bytes.len() < 64 {
|
if elf_bytes.len() < 64 {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
mod header;
|
mod header;
|
||||||
pub mod loader;
|
pub mod loader;
|
||||||
mod program;
|
mod program;
|
||||||
pub mod validation;
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
use alloc::vec::Vec;
|
||||||
use core::ptr::{null, null_mut};
|
use core::ptr::{null, null_mut};
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
#[cfg(target_arch = "x86_64")]
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
structures::paging::{
|
structures::paging::{
|
||||||
@@ -29,6 +30,7 @@ pub fn get_vaddr(phdr: *const Elf64Phdr, load_bias: u64) -> *mut u8 {
|
|||||||
unsafe { ((*phdr).p_vaddr + load_bias) as *mut u8 }
|
unsafe { ((*phdr).p_vaddr + load_bias) as *mut u8 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub unsafe fn load_program(
|
pub unsafe fn load_program(
|
||||||
mapper: &mut OffsetPageTable,
|
mapper: &mut OffsetPageTable,
|
||||||
hdr: *const Elf64Ehdr,
|
hdr: *const Elf64Ehdr,
|
||||||
@@ -53,6 +55,7 @@ pub unsafe fn load_program(
|
|||||||
|
|
||||||
if !pie {
|
if !pie {
|
||||||
for program_header in program_headers {
|
for program_header in program_headers {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
load_segment_to_memory(mapper, program_header, elf_bytes, 0);
|
load_segment_to_memory(mapper, program_header, elf_bytes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +98,7 @@ pub unsafe fn load_program(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for program_header in program_headers {
|
for program_header in program_headers {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
load_segment_to_memory(mapper, program_header, elf_bytes, load_bias);
|
load_segment_to_memory(mapper, program_header, elf_bytes, load_bias);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,6 +279,7 @@ fn parse_dyn(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn load_segment_to_memory(
|
pub fn load_segment_to_memory(
|
||||||
mapper: &mut OffsetPageTable,
|
mapper: &mut OffsetPageTable,
|
||||||
phdr: *const Elf64Phdr,
|
phdr: *const Elf64Phdr,
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
use crate::driver::elf::header::{
|
|
||||||
EI_CLASS, EI_DATA, EI_VERSION, ELF_MAGIC, EM_X86_64, ET_DYN, ET_EXEC, Elf64Ehdr,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn validate_elf(elf_header: &Elf64Ehdr, elf_len: usize) -> bool {
|
|
||||||
#[allow(unused_mut)]
|
|
||||||
let mut required_machine = EM_X86_64;
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
{
|
|
||||||
use crate::driver::elf::header::EM_AARCH64;
|
|
||||||
required_machine = EM_AARCH64;
|
|
||||||
}
|
|
||||||
|
|
||||||
elf_header.e_ident[0..4] == ELF_MAGIC
|
|
||||||
// 64 bit
|
|
||||||
&& elf_header.e_ident[EI_CLASS] == 2
|
|
||||||
// little-endian
|
|
||||||
&& elf_header.e_ident[EI_DATA] == 1
|
|
||||||
&& elf_header.e_ident[EI_VERSION] == 1
|
|
||||||
&& elf_header.e_version == 1
|
|
||||||
// check architecture
|
|
||||||
&& elf_header.e_machine == required_machine
|
|
||||||
// disallow object files
|
|
||||||
&& [ET_DYN, ET_EXEC].contains(&elf_header.e_type)
|
|
||||||
// standard elf64
|
|
||||||
&& elf_header.e_phentsize == 56
|
|
||||||
&& elf_header.e_phnum != 0 // zero program headers
|
|
||||||
&& (elf_header.e_phoff + (elf_header.e_phnum*elf_header.e_phentsize) as u64) <= elf_len as u64
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
use limine::framebuffer::Framebuffer as LimineFramebuffer;
|
use limine::framebuffer::Framebuffer as LimineFramebuffer;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
use crate::arch::arch::safe_lock;
|
||||||
use x86_64::instructions::interrupts::without_interrupts;
|
|
||||||
use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB};
|
|
||||||
|
|
||||||
use crate::arch::arch::FRAME_ALLOCATOR;
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct UserFrameBuffer {
|
pub struct UserFrameBuffer {
|
||||||
@@ -37,11 +33,35 @@ impl Framebuffer {
|
|||||||
let width = limine_fb.width() as usize;
|
let width = limine_fb.width() as usize;
|
||||||
let height = limine_fb.height() as usize;
|
let height = limine_fb.height() as usize;
|
||||||
let pitch = limine_fb.pitch() as usize / 4;
|
let pitch = limine_fb.pitch() as usize / 4;
|
||||||
let buf_len = pitch * height;
|
|
||||||
|
Framebuffer {
|
||||||
|
addr: limine_fb.addr().cast::<u32>(),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
pitch,
|
||||||
|
user_fb: UserFrameBuffer {
|
||||||
|
buf_virt: 0 as *mut u32,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
pitch,
|
||||||
|
},
|
||||||
|
meta: FramebufferMeta {
|
||||||
|
buf_phys: 0,
|
||||||
|
buf_len: 0,
|
||||||
|
struct_phys: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub fn setup_x86_64(&mut self) {
|
||||||
|
use crate::arch::arch::FRAME_ALLOCATOR;
|
||||||
|
use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB};
|
||||||
|
let buf_len = self.pitch * self.height;
|
||||||
let byte_len = buf_len * core::mem::size_of::<u32>();
|
let byte_len = buf_len * core::mem::size_of::<u32>();
|
||||||
let pixel_frames = (byte_len + 4095) / 4096;
|
let pixel_frames = (byte_len + 4095) / 4096;
|
||||||
|
|
||||||
let mut fa = FRAME_ALLOCATOR.lock();
|
let mut fa = safe_lock(|| FRAME_ALLOCATOR.lock());
|
||||||
|
|
||||||
let struct_frame: PhysFrame<Size4KiB> =
|
let struct_frame: PhysFrame<Size4KiB> =
|
||||||
fa.allocate_frame().expect("framebuffer struct frame");
|
fa.allocate_frame().expect("framebuffer struct frame");
|
||||||
@@ -62,29 +82,16 @@ impl Framebuffer {
|
|||||||
unsafe {
|
unsafe {
|
||||||
struct_virt.write(UserFrameBuffer {
|
struct_virt.write(UserFrameBuffer {
|
||||||
buf_virt: (USER_FB_BASE + 0x1000) as *mut u32,
|
buf_virt: (USER_FB_BASE + 0x1000) as *mut u32,
|
||||||
width,
|
width: self.width,
|
||||||
height,
|
height: self.height,
|
||||||
pitch,
|
pitch: self.pitch,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
Framebuffer {
|
self.user_fb.buf_virt = buf_virt_kernel;
|
||||||
addr: limine_fb.addr().cast::<u32>(),
|
self.meta.buf_phys = buf_phys;
|
||||||
width,
|
self.meta.buf_len = buf_len;
|
||||||
height,
|
self.meta.struct_phys = struct_phys;
|
||||||
pitch,
|
|
||||||
user_fb: UserFrameBuffer {
|
|
||||||
buf_virt: buf_virt_kernel,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
pitch,
|
|
||||||
},
|
|
||||||
meta: FramebufferMeta {
|
|
||||||
buf_phys,
|
|
||||||
buf_len,
|
|
||||||
struct_phys,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -136,7 +143,7 @@ pub fn init_framebuffer(raw: &LimineFramebuffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_framebuffer<F: FnOnce(&mut Framebuffer)>(f: F) {
|
pub fn with_framebuffer<F: FnOnce(&mut Framebuffer)>(f: F) {
|
||||||
without_interrupts(|| {
|
safe_lock(|| {
|
||||||
let mut guard = FRAMEBUFFER.lock();
|
let mut guard = FRAMEBUFFER.lock();
|
||||||
if let Some(fb) = guard.as_mut() {
|
if let Some(fb) = guard.as_mut() {
|
||||||
f(fb);
|
f(fb);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use heapless::spsc::{Consumer, Producer, Queue};
|
|||||||
use pc_keyboard::{DecodedKey, HandleControl, KeyState, Keyboard, ScancodeSet2, layouts};
|
use pc_keyboard::{DecodedKey, HandleControl, KeyState, Keyboard, ScancodeSet2, layouts};
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
|
|
||||||
use crate::task::scheduler::{SCHEDULER, current_pid};
|
use crate::task::scheduler::SCHEDULER;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, Copy, Default)]
|
#[derive(Clone, Debug, Copy, Default)]
|
||||||
pub struct KeyboardEvent {
|
pub struct KeyboardEvent {
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
use crate::driver::graphics::font_render::render_text;
|
use crate::driver::graphics::font_render::render_text;
|
||||||
use crate::driver::graphics::framebuffer::Framebuffer;
|
use crate::driver::graphics::framebuffer::Framebuffer;
|
||||||
use crate::{driver::graphics::base::rgb, util::serial_print};
|
use crate::{arch::arch::safe_lock, driver::graphics::base::rgb};
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use core::fmt::{self, Write};
|
use core::fmt::{self, Write};
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use x86_64::instructions::interrupts::without_interrupts;
|
|
||||||
|
|
||||||
pub struct ConsoleWriter<'a> {
|
pub struct ConsoleWriter<'a> {
|
||||||
pub fb: &'a mut Framebuffer,
|
pub fb: &'a mut Framebuffer,
|
||||||
pub console: &'a mut SerialConsole,
|
pub console: &'a mut SerialConsole,
|
||||||
@@ -16,7 +13,6 @@ pub struct ConsoleWriter<'a> {
|
|||||||
|
|
||||||
impl Write for ConsoleWriter<'_> {
|
impl Write for ConsoleWriter<'_> {
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
serial_print(s);
|
|
||||||
self.console.print(s, self.fb);
|
self.console.print(s, self.fb);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -67,10 +63,10 @@ pub fn init_serial_console() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_serial_console<F: FnOnce(&mut SerialConsole)>(f: F) {
|
pub fn with_serial_console<F: FnOnce(&mut SerialConsole)>(f: F) {
|
||||||
without_interrupts(|| {
|
safe_lock(|| {
|
||||||
let mut guard = SERIAL_CONSOLE.lock();
|
let mut guard = SERIAL_CONSOLE.lock();
|
||||||
if let Some(fb) = guard.as_mut() {
|
if let Some(sc) = guard.as_mut() {
|
||||||
f(fb);
|
f(sc);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,17 +27,6 @@ impl Timer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn interrupt(&self) {
|
pub fn interrupt(&self) {
|
||||||
let mut scheduler = without_interrupts(|| SCHEDULER.lock());
|
|
||||||
for process in scheduler.processes.values_mut() {
|
|
||||||
if let Some(wake_tick) = process.info.wake_tick {
|
|
||||||
if self.interrupt_count.load(Ordering::Relaxed) >= wake_tick {
|
|
||||||
process.info.wake_tick = None;
|
|
||||||
process.state = crate::task::process::ProcessState::Ready;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drop(scheduler);
|
|
||||||
|
|
||||||
self.interrupt_count.fetch_add(1, Ordering::Relaxed);
|
self.interrupt_count.fetch_add(1, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-7
@@ -1,14 +1,14 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(abi_x86_interrupt)]
|
#![cfg_attr(target_arch = "x86_64", feature(abi_x86_interrupt))]
|
||||||
#![feature(naked_functions_rustic_abi)]
|
#![feature(naked_functions_rustic_abi)]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
use limine::BaseRevision;
|
use limine::BaseRevision;
|
||||||
use limine::request::{
|
use limine::request::{
|
||||||
DateAtBootRequest, FramebufferRequest, HhdmRequest, MemoryMapRequest, MpRequest,
|
DateAtBootRequest, FramebufferRequest, HhdmRequest, MemoryMapRequest, RequestsEndMarker,
|
||||||
RequestsEndMarker, RequestsStartMarker,
|
RequestsStartMarker,
|
||||||
};
|
};
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
@@ -22,6 +22,7 @@ use crate::driver::graphics::framebuffer::{init_framebuffer, with_framebuffer};
|
|||||||
use crate::driver::keyboard::init_keyboard;
|
use crate::driver::keyboard::init_keyboard;
|
||||||
use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console};
|
use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console};
|
||||||
use crate::driver::timer::TIMER;
|
use crate::driver::timer::TIMER;
|
||||||
|
use crate::util::serial_print;
|
||||||
|
|
||||||
#[repr(C, align(16))]
|
#[repr(C, align(16))]
|
||||||
struct AlignedElf([u8; include_bytes!("../../assets/init").len()]);
|
struct AlignedElf([u8; include_bytes!("../../assets/init").len()]);
|
||||||
@@ -52,10 +53,6 @@ static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new();
|
|||||||
#[unsafe(link_section = ".requests")]
|
#[unsafe(link_section = ".requests")]
|
||||||
static DATE_AT_BOOT_REQUEST: DateAtBootRequest = DateAtBootRequest::new();
|
static DATE_AT_BOOT_REQUEST: DateAtBootRequest = DateAtBootRequest::new();
|
||||||
|
|
||||||
#[used]
|
|
||||||
#[unsafe(link_section = ".requests")]
|
|
||||||
static MP_REQUEST: MpRequest = MpRequest::new();
|
|
||||||
|
|
||||||
/// Define the stand and end markers for Limine requests.
|
/// Define the stand and end markers for Limine requests.
|
||||||
#[used]
|
#[used]
|
||||||
#[unsafe(link_section = ".requests_start_marker")]
|
#[unsafe(link_section = ".requests_start_marker")]
|
||||||
@@ -114,6 +111,8 @@ unsafe extern "C" fn kmain() -> ! {
|
|||||||
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() {
|
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.get_response() {
|
||||||
if let Some(limine_framebuffer) = framebuffer_response.framebuffers().next() {
|
if let Some(limine_framebuffer) = framebuffer_response.framebuffers().next() {
|
||||||
init_framebuffer(&limine_framebuffer);
|
init_framebuffer(&limine_framebuffer);
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
with_framebuffer(|fb| fb.setup_x86_64());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +126,7 @@ unsafe extern "C" fn kmain() -> ! {
|
|||||||
println!("Could not get date at boot. Will default to 0.")
|
println!("Could not get date at boot. Will default to 0.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
run_elf(INIT_ELF_BYTES, false);
|
run_elf(INIT_ELF_BYTES, false);
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
@@ -134,6 +134,12 @@ unsafe extern "C" fn kmain() -> ! {
|
|||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
{
|
||||||
|
serial_print("\nKERNEL PANIC:\n");
|
||||||
|
serial_print(_info.message().as_str().unwrap());
|
||||||
|
serial_print("\n");
|
||||||
|
}
|
||||||
with_framebuffer(|mut fb| {
|
with_framebuffer(|mut fb| {
|
||||||
fb.clear(rgb(180, 0, 0));
|
fb.clear(rgb(180, 0, 0));
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
PhysAddr, VirtAddr,
|
PhysAddr, VirtAddr,
|
||||||
registers::control::{Cr3, Cr3Flags},
|
registers::control::{Cr3, Cr3Flags},
|
||||||
@@ -6,10 +7,16 @@ use x86_64::{
|
|||||||
|
|
||||||
use crate::arch::arch::FRAME_ALLOCATOR;
|
use crate::arch::arch::FRAME_ALLOCATOR;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub struct AddressSpace {
|
pub struct AddressSpace {
|
||||||
cr3_frame: PhysFrame<Size4KiB>,
|
cr3_frame: PhysFrame<Size4KiB>,
|
||||||
pub mapper: OffsetPageTable<'static>,
|
pub mapper: OffsetPageTable<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub struct AddressSpace {}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
impl AddressSpace {
|
impl AddressSpace {
|
||||||
pub fn new() -> Option<AddressSpace> {
|
pub fn new() -> Option<AddressSpace> {
|
||||||
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
||||||
@@ -58,6 +65,7 @@ impl AddressSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub unsafe fn physical_to_virt_pointer(phys_addr: PhysAddr, hhdm_offset: u64) -> *mut u64 {
|
pub unsafe fn physical_to_virt_pointer(phys_addr: PhysAddr, hhdm_offset: u64) -> *mut u64 {
|
||||||
(hhdm_offset + phys_addr.as_u64()) as *mut u64
|
(hhdm_offset + phys_addr.as_u64()) as *mut u64
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
use core::{
|
||||||
|
alloc::{GlobalAlloc, Layout},
|
||||||
|
ptr::null_mut,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::util::{Locked, align_up};
|
||||||
|
|
||||||
|
pub struct LinkedNode {
|
||||||
|
pub size: usize,
|
||||||
|
pub next: Option<&'static mut LinkedNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LinkedNode {
|
||||||
|
pub const fn new(size: usize) -> LinkedNode {
|
||||||
|
LinkedNode { size, next: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_addr(&self) -> usize {
|
||||||
|
self as *const Self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end_addr(&self) -> usize {
|
||||||
|
self.start_addr() + self.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LinkedListAllocator {
|
||||||
|
head: LinkedNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LinkedListAllocator {
|
||||||
|
pub const fn new() -> LinkedListAllocator {
|
||||||
|
Self {
|
||||||
|
head: LinkedNode::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_align(layout: Layout) -> (usize, usize) {
|
||||||
|
let layout = layout
|
||||||
|
.align_to(16)
|
||||||
|
.expect("Align to LinkedNode failed")
|
||||||
|
.pad_to_align();
|
||||||
|
|
||||||
|
let size = layout.size().max(core::mem::size_of::<LinkedNode>()); // either take layout's size or atleast the size of a single linked node.
|
||||||
|
|
||||||
|
(size, layout.align())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) {
|
||||||
|
unsafe {
|
||||||
|
self.add_free_memory_region(heap_start, heap_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn add_free_memory_region(&mut self, start: usize, size: usize) {
|
||||||
|
assert_eq!(align_up(start as u64, 16), start as u64); // Check if we are up at least 1 LinkedNode size
|
||||||
|
assert!(size >= core::mem::size_of::<LinkedNode>()); // check if we have enough space for a LinkedNode
|
||||||
|
|
||||||
|
let mut linked_node = LinkedNode::new(size);
|
||||||
|
linked_node.next = self.head.next.take();
|
||||||
|
|
||||||
|
let linked_node_ptr = start as *mut LinkedNode; // Treat the start memory region as a LinkedNode type
|
||||||
|
unsafe {
|
||||||
|
linked_node_ptr.write(linked_node); // write the data, very risky
|
||||||
|
self.head.next = Some(&mut *linked_node_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_region(
|
||||||
|
&mut self,
|
||||||
|
size: usize,
|
||||||
|
align: usize,
|
||||||
|
) -> Option<(&'static mut LinkedNode, usize)> {
|
||||||
|
let mut current = &mut self.head;
|
||||||
|
|
||||||
|
while let Some(ref mut region) = current.next {
|
||||||
|
if let Ok(alloc_start) = Self::alloc_from_region(®ion, size, align) {
|
||||||
|
let next = region.next.take();
|
||||||
|
let ret = Some((current.next.take().unwrap(), alloc_start));
|
||||||
|
current.next = next;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
current = current.next.as_mut().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc_from_region(region: &LinkedNode, size: usize, align: usize) -> Result<usize, ()> {
|
||||||
|
let alloc_start = align_up(region.start_addr() as u64, align as u64) as usize;
|
||||||
|
let alloc_end = alloc_start.checked_add(size).ok_or(())?; // check for overflows
|
||||||
|
|
||||||
|
if alloc_end > region.end_addr() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let excess_size = region.end_addr() - alloc_end;
|
||||||
|
if excess_size > 0 && excess_size < core::mem::size_of::<LinkedNode>() {
|
||||||
|
// if the remaining space is not enough for another LinkedNode, skip this region.
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(alloc_start)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl GlobalAlloc for Locked<LinkedListAllocator> {
|
||||||
|
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
|
||||||
|
let (size, align) = LinkedListAllocator::size_align(_layout);
|
||||||
|
let mut allocator = self.lock();
|
||||||
|
|
||||||
|
if let Some((region, alloc_start)) = allocator.find_region(size, align) {
|
||||||
|
let alloc_end = alloc_start.checked_add(size).expect("overflow");
|
||||||
|
|
||||||
|
let excess_size = region.end_addr() - alloc_end;
|
||||||
|
|
||||||
|
if excess_size > 0 {
|
||||||
|
unsafe {
|
||||||
|
allocator.add_free_memory_region(alloc_end, excess_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(allocator);
|
||||||
|
|
||||||
|
alloc_start as *mut u8
|
||||||
|
} else {
|
||||||
|
null_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
||||||
|
let (size, _) = LinkedListAllocator::size_align(_layout);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.lock().add_free_memory_region(_ptr as usize, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
pub mod address_space;
|
pub mod address_space;
|
||||||
|
pub mod heap;
|
||||||
pub mod usercopy;
|
pub mod usercopy;
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ use alloc::{
|
|||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
structures::paging::{OffsetPageTable, PageTableFlags, Translate, mapper::TranslateResult},
|
structures::paging::{OffsetPageTable, PageTableFlags, Translate, mapper::TranslateResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn copy_to_user(
|
pub fn copy_to_user(
|
||||||
mapper: &mut OffsetPageTable,
|
mapper: &mut OffsetPageTable,
|
||||||
buf: *mut u8,
|
buf: *mut u8,
|
||||||
@@ -42,6 +45,7 @@ pub fn copy_to_user(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn copy_from_user(
|
pub fn copy_from_user(
|
||||||
mapper: &mut OffsetPageTable,
|
mapper: &mut OffsetPageTable,
|
||||||
buf: *mut u8,
|
buf: *mut u8,
|
||||||
@@ -85,6 +89,7 @@ pub fn copy_from_user(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn copy_cstr_from_user(
|
pub fn copy_cstr_from_user(
|
||||||
mapper: &mut OffsetPageTable,
|
mapper: &mut OffsetPageTable,
|
||||||
user_ptr: *const u8,
|
user_ptr: *const u8,
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
use core::sync::atomic::{AtomicU64, Ordering};
|
use core::sync::atomic::{AtomicU64, Ordering};
|
||||||
|
|
||||||
use alloc::{collections::btree_map::BTreeMap, vec::Vec};
|
use alloc::{collections::btree_map::BTreeMap, vec::Vec};
|
||||||
use x86_64::instructions::interrupts::without_interrupts;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::arch::enter_usermode,
|
arch::arch::{enter_usermode, safe_lock},
|
||||||
task::{
|
task::{
|
||||||
context::UserContext,
|
context::UserContext,
|
||||||
process::{Process, ProcessState},
|
process::{Process, ProcessState},
|
||||||
@@ -43,7 +42,7 @@ impl Scheduler {
|
|||||||
|
|
||||||
impl Locked<Scheduler> {
|
impl Locked<Scheduler> {
|
||||||
pub fn spawn_process(&self, entry_point: u64, stack_top: u64, heap_base: u64) -> Option<u64> {
|
pub fn spawn_process(&self, entry_point: u64, stack_top: u64, heap_base: u64) -> Option<u64> {
|
||||||
let mut guard = without_interrupts(|| self.lock());
|
let mut guard = safe_lock(|| self.lock());
|
||||||
let pid = guard.next_pid;
|
let pid = guard.next_pid;
|
||||||
guard.next_pid += 1;
|
guard.next_pid += 1;
|
||||||
let process = Process::new(pid, entry_point, stack_top, heap_base, heap_base);
|
let process = Process::new(pid, entry_point, stack_top, heap_base, heap_base);
|
||||||
@@ -54,7 +53,7 @@ impl Locked<Scheduler> {
|
|||||||
|
|
||||||
pub fn next_task(&self) -> u64 {
|
pub fn next_task(&self) -> u64 {
|
||||||
if let Some(previous_pid) = current_pid() {
|
if let Some(previous_pid) = current_pid() {
|
||||||
let mut guard = without_interrupts(|| self.lock());
|
let mut guard = safe_lock(|| self.lock());
|
||||||
|
|
||||||
if let Some(process) = guard.processes.get_mut(&previous_pid) {
|
if let Some(process) = guard.processes.get_mut(&previous_pid) {
|
||||||
if matches!(process.state, ProcessState::Running) {
|
if matches!(process.state, ProcessState::Running) {
|
||||||
@@ -87,9 +86,10 @@ impl Locked<Scheduler> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn switch_to(&self, pid: u64, should_swapgs: bool) {
|
pub fn switch_to(&self, pid: u64, should_swapgs: bool) {
|
||||||
let (ctx_opt, entry, stack_top) = {
|
let (ctx_opt, entry, stack_top) = {
|
||||||
let mut guard = without_interrupts(|| self.lock());
|
let mut guard = safe_lock(|| self.lock());
|
||||||
|
|
||||||
if let Some(previous_pid) = current_pid() {
|
if let Some(previous_pid) = current_pid() {
|
||||||
if let Some(old_process) = guard.processes.get_mut(&previous_pid) {
|
if let Some(old_process) = guard.processes.get_mut(&previous_pid) {
|
||||||
@@ -128,7 +128,7 @@ impl Locked<Scheduler> {
|
|||||||
where
|
where
|
||||||
F: FnOnce(&mut Process) -> R,
|
F: FnOnce(&mut Process) -> R,
|
||||||
{
|
{
|
||||||
let mut guard = without_interrupts(|| self.lock());
|
let mut guard = safe_lock(|| self.lock());
|
||||||
let process = guard.processes.get_mut(&index)?;
|
let process = guard.processes.get_mut(&index)?;
|
||||||
Some(f(process))
|
Some(f(process))
|
||||||
}
|
}
|
||||||
@@ -136,6 +136,7 @@ impl Locked<Scheduler> {
|
|||||||
|
|
||||||
pub static SCHEDULER: Locked<Scheduler> = Locked::new(Scheduler::new());
|
pub static SCHEDULER: Locked<Scheduler> = Locked::new(Scheduler::new());
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[unsafe(naked)]
|
#[unsafe(naked)]
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
unsafe fn run_next(ctx: *const UserContext, user_rsp: u64) {
|
unsafe fn run_next(ctx: *const UserContext, user_rsp: u64) {
|
||||||
|
|||||||
+14
-6
@@ -5,6 +5,20 @@ pub struct Locked<A> {
|
|||||||
inner: Mutex<A>,
|
inner: Mutex<A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub fn serial_print_byte(b: u8) {
|
||||||
|
unsafe {
|
||||||
|
core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub fn serial_print(s: &str) {
|
||||||
|
for &b in s.as_bytes() {
|
||||||
|
serial_print_byte(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<A> Locked<A> {
|
impl<A> Locked<A> {
|
||||||
pub const fn new(inner: A) -> Self {
|
pub const fn new(inner: A) -> Self {
|
||||||
Locked {
|
Locked {
|
||||||
@@ -49,9 +63,3 @@ pub const fn align_up(addr: u64, align: u64) -> u64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serial_print(s: &str) {
|
|
||||||
for byte in s.bytes() {
|
|
||||||
unsafe { core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") byte) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user