mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-06-02 14:44:26 +02:00
Improve aarch64 support by building everything for both archictectures,
remove incorrect timer frequency set, fix interrupt handler not restoring stack ptr, handle both user and kernel aborts, remove aarch64 ps2 support, fix ELF code mapped as code making it unwritable, add assets.rs to handle both arches automatically, make PS2 x86_64 compatible with linux keycodes, always try printing kernel panic to serial
This commit is contained in:
+28
@@ -28,6 +28,16 @@ run-x86_64: edk2-ovmf $(IMAGE_NAME).iso
|
|||||||
-cdrom $(IMAGE_NAME).iso \
|
-cdrom $(IMAGE_NAME).iso \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
|
.PHONY: debug-x86_64
|
||||||
|
debug-x86_64: edk2-ovmf $(IMAGE_NAME).iso
|
||||||
|
qemu-system-$(KARCH) \
|
||||||
|
-M q35 \
|
||||||
|
-serial stdio \
|
||||||
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
|
-cdrom $(IMAGE_NAME).iso \
|
||||||
|
-d in_asm,int,mmu -D /tmp/qemu_trace.log 2>/dev/null \
|
||||||
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: run-hdd-x86_64
|
.PHONY: run-hdd-x86_64
|
||||||
run-hdd-x86_64: edk2-ovmf $(IMAGE_NAME).hdd
|
run-hdd-x86_64: edk2-ovmf $(IMAGE_NAME).hdd
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
@@ -53,6 +63,24 @@ run-aarch64: edk2-ovmf $(IMAGE_NAME).iso
|
|||||||
-semihosting-config enable=on,target=native \
|
-semihosting-config enable=on,target=native \
|
||||||
$(QEMUFLAGS)
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
|
.PHONY: debug-aarch64
|
||||||
|
debug-aarch64: edk2-ovmf $(IMAGE_NAME).iso
|
||||||
|
qemu-system-$(KARCH) \
|
||||||
|
-M virt,gic-version=2,secure=off \
|
||||||
|
-cpu cortex-a72 \
|
||||||
|
-device ramfb \
|
||||||
|
-device qemu-xhci \
|
||||||
|
-device usb-kbd \
|
||||||
|
-device usb-mouse \
|
||||||
|
-device virtio-keyboard-device \
|
||||||
|
-device virtio-mouse-device \
|
||||||
|
-serial stdio \
|
||||||
|
-drive if=pflash,unit=0,format=raw,file=edk2-ovmf/ovmf-code-$(KARCH).fd,readonly=on \
|
||||||
|
-cdrom $(IMAGE_NAME).iso \
|
||||||
|
-semihosting-config enable=on,target=native \
|
||||||
|
-d in_asm,int,mmu -D /tmp/qemu_trace.log 2>/dev/null
|
||||||
|
$(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: run-hdd-aarch64
|
.PHONY: run-hdd-aarch64
|
||||||
run-hdd-aarch64: edk2-ovmf $(IMAGE_NAME).hdd
|
run-hdd-aarch64: edk2-ovmf $(IMAGE_NAME).hdd
|
||||||
qemu-system-$(KARCH) \
|
qemu-system-$(KARCH) \
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
doomgeneric*
|
doomgeneric*
|
||||||
init
|
init
|
||||||
|
helloworld*
|
||||||
|
|||||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
bash build_libxunil.sh
|
bash build_libxunil.sh
|
||||||
cd user/apps/doomgeneric/doomgeneric
|
cd user/apps/doomgeneric/doomgeneric
|
||||||
rm -r ./build
|
rm -r ./build
|
||||||
make LD=/usr/bin/ld -j16 -f Makefile.xunil
|
make -j16 -f Makefile.xunil
|
||||||
cp doomgeneric ../../../../assets/doomgeneric
|
cp doomgeneric ../../../../assets/$KARCH/doomgeneric
|
||||||
cd ../../../..
|
cd ../../../..
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
bash build_libxunil.sh
|
bash build_libxunil.sh
|
||||||
cd user/init
|
cd user/init
|
||||||
cargo build --target x86_64-unknown-none --release
|
cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true
|
||||||
cp ./target/x86_64-unknown-none/release/init ../../assets/init
|
cp ./target/$KARCH-unknown-none/release/init ../../assets/$KARCH/init
|
||||||
cd ../..
|
cd ../..
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
cd user/libxunil
|
cd user/libxunil
|
||||||
cargo build --release
|
cargo build --target $KARCH-unknown-none --release --config profile.release.debug=true
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export KARCH ?= aarch64
|
export KARCH ?= aarch64
|
||||||
export OUTPUT ?= kernel
|
export OUTPUT ?= kernel
|
||||||
export MEMORY ?= 512M
|
export MEMORY ?= 1G
|
||||||
export TIMER_FREQUENCY_HZ ?= 1000
|
export TIMER_FREQUENCY_HZ ?= 1000
|
||||||
|
|||||||
+3
-2
@@ -12,7 +12,7 @@ ifeq ($(RUST_TARGET),)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(RUST_PROFILE),)
|
ifeq ($(RUST_PROFILE),)
|
||||||
override RUST_PROFILE := dev
|
override RUST_PROFILE := release
|
||||||
endif
|
endif
|
||||||
|
|
||||||
override RUST_PROFILE_SUBDIR := $(RUST_PROFILE)
|
override RUST_PROFILE_SUBDIR := $(RUST_PROFILE)
|
||||||
@@ -23,7 +23,8 @@ endif
|
|||||||
# Default target.
|
# Default target.
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all:
|
all:
|
||||||
RUSTFLAGS="-C relocation-model=static" cargo build --target $(RUST_TARGET) --profile $(RUST_PROFILE)
|
RUSTFLAGS="-C relocation-model=static" cargo build --target $(RUST_TARGET) --profile $(RUST_PROFILE) --config profile.release.debug=true
|
||||||
|
|
||||||
cp target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/$$(cd target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR) && find -maxdepth 1 -perm -111 -type f) kernel
|
cp target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/$$(cd target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR) && find -maxdepth 1 -perm -111 -type f) kernel
|
||||||
|
|
||||||
# Remove object files and the final executable.
|
# Remove object files and the final executable.
|
||||||
|
|||||||
@@ -15,6 +15,14 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let out_dir = out_dir.join("driver").join("io").join("fs");
|
||||||
|
|
||||||
|
fs::write(
|
||||||
|
out_dir.join("assets.rs"),
|
||||||
|
format!("pub static INIT_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/init\");\npub static DOOM_WAD: &[u8] = include_bytes!(\"../../../../../assets/doom1.wad\");\npub static DOOM_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/doomgeneric\");\npub static HELLOWORLD_ELF: &[u8] = include_bytes!(\"../../../../../assets/{karch}/helloworld.elf\");"),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
println!("cargo:rerun-if-env-changed=KARCH");
|
println!("cargo:rerun-if-env-changed=KARCH");
|
||||||
println!("cargo:rerun-if-env-changed=TIMER_FREQUENCY_HZ");
|
println!("cargo:rerun-if-env-changed=TIMER_FREQUENCY_HZ");
|
||||||
println!("cargo:rerun-if-env-changed=OUTPUT");
|
println!("cargo:rerun-if-env-changed=OUTPUT");
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ use crate::{
|
|||||||
interrupts::init_interrupts,
|
interrupts::init_interrupts,
|
||||||
paging::{AArchPageTable, initialize_paging_aarch64},
|
paging::{AArchPageTable, initialize_paging_aarch64},
|
||||||
},
|
},
|
||||||
config::TIMER_FREQUENCY_HZ,
|
driver::io::virtio::scan_virtio_devices,
|
||||||
driver::io::virtio::scan_devices,
|
|
||||||
};
|
};
|
||||||
use limine::response::{ExecutableAddressResponse, HhdmResponse, MemoryMapResponse};
|
use limine::response::{ExecutableAddressResponse, HhdmResponse, MemoryMapResponse};
|
||||||
|
|
||||||
@@ -15,12 +14,6 @@ pub struct Stack(pub [u8; 64 * 1024]);
|
|||||||
|
|
||||||
pub static KERNEL_STACK: Stack = Stack([0; 64 * 1024]);
|
pub static KERNEL_STACK: Stack = Stack([0; 64 * 1024]);
|
||||||
|
|
||||||
pub fn set_timer_freq(freq: usize) {
|
|
||||||
unsafe {
|
|
||||||
core::arch::asm!("mrs {}, cntp_tval_el0", "isb", in(reg) freq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(naked)]
|
#[unsafe(naked)]
|
||||||
pub unsafe fn init_aarch64_trampoline(mapper: &mut AArchPageTable) {
|
pub unsafe fn init_aarch64_trampoline(mapper: &mut AArchPageTable) {
|
||||||
// fix stack, since limine's bootloader stack is not mapped
|
// fix stack, since limine's bootloader stack is not mapped
|
||||||
@@ -38,8 +31,7 @@ pub unsafe fn init_aarch64_trampoline(mapper: &mut AArchPageTable) {
|
|||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn init_aarch64(mapper: &mut AArchPageTable) {
|
pub extern "C" fn init_aarch64(mapper: &mut AArchPageTable) {
|
||||||
init_heap(mapper);
|
init_heap(mapper);
|
||||||
set_timer_freq(TIMER_FREQUENCY_HZ);
|
scan_virtio_devices();
|
||||||
scan_devices();
|
|
||||||
init_interrupts();
|
init_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use core::{arch::global_asm, sync::atomic::Ordering};
|
use core::{arch::global_asm, sync::atomic::Ordering};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::syscall::syscall_dispatch,
|
arch::syscall::{check_and_reschedule, syscall_dispatch},
|
||||||
config::TIMER_FREQUENCY_HZ,
|
config::TIMER_FREQUENCY_HZ,
|
||||||
driver::{
|
driver::{
|
||||||
graphics::framebuffer::with_framebuffer,
|
graphics::framebuffer::with_framebuffer,
|
||||||
@@ -9,11 +9,9 @@ use crate::{
|
|||||||
serial::with_serial_console,
|
serial::with_serial_console,
|
||||||
timer::TIMER,
|
timer::TIMER,
|
||||||
},
|
},
|
||||||
task::context::UserContext,
|
task::context::{UserContext, ctx_save},
|
||||||
};
|
};
|
||||||
|
|
||||||
use aarch64_cpu::registers::{DAIF, Writeable};
|
|
||||||
|
|
||||||
global_asm!(
|
global_asm!(
|
||||||
r#"
|
r#"
|
||||||
.section .text.vectors
|
.section .text.vectors
|
||||||
@@ -43,6 +41,12 @@ global_asm!(
|
|||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn timer_ticks_per_irq() -> u64 {
|
||||||
|
let cntfrq: u64;
|
||||||
|
unsafe { core::arch::asm!("mrs {}, cntfrq_el0", out(reg) cntfrq) };
|
||||||
|
cntfrq / (TIMER_FREQUENCY_HZ as u64)
|
||||||
|
}
|
||||||
|
|
||||||
// stp allows storing in pairs, ldp loads in pairs
|
// stp allows storing in pairs, ldp loads in pairs
|
||||||
macro_rules! exception_handler {
|
macro_rules! exception_handler {
|
||||||
($name:ident, $rust_handler:ident) => {
|
($name:ident, $rust_handler:ident) => {
|
||||||
@@ -66,6 +70,8 @@ macro_rules! exception_handler {
|
|||||||
"stp x24, x25, [sp, #192]",
|
"stp x24, x25, [sp, #192]",
|
||||||
"stp x26, x27, [sp, #208]",
|
"stp x26, x27, [sp, #208]",
|
||||||
"stp x28, x29, [sp, #224]",
|
"stp x28, x29, [sp, #224]",
|
||||||
|
"mrs x2, sp_el0",
|
||||||
|
"str x2, [sp, #280]",
|
||||||
"mrs x0, elr_el1",
|
"mrs x0, elr_el1",
|
||||||
"mrs x1, spsr_el1",
|
"mrs x1, spsr_el1",
|
||||||
"stp x30, x0, [sp, #240]",
|
"stp x30, x0, [sp, #240]",
|
||||||
@@ -75,6 +81,8 @@ macro_rules! exception_handler {
|
|||||||
"stp x2, x3, [sp, #264]",
|
"stp x2, x3, [sp, #264]",
|
||||||
"mov x0, sp",
|
"mov x0, sp",
|
||||||
concat!("bl ", stringify!($rust_handler)),
|
concat!("bl ", stringify!($rust_handler)),
|
||||||
|
"ldr x2, [sp, #280]",
|
||||||
|
"msr sp_el0, x2",
|
||||||
"ldr x1, [sp, #256]",
|
"ldr x1, [sp, #256]",
|
||||||
"ldp x30, x0, [sp, #240]",
|
"ldp x30, x0, [sp, #240]",
|
||||||
"msr spsr_el1, x1",
|
"msr spsr_el1, x1",
|
||||||
@@ -155,6 +163,7 @@ unsafe fn gic_eoi(id: u32) {
|
|||||||
pub fn init_interrupts() {
|
pub fn init_interrupts() {
|
||||||
unsafe { use_exception_vectors() };
|
unsafe { use_exception_vectors() };
|
||||||
unsafe { gic_init() };
|
unsafe { gic_init() };
|
||||||
|
enable_interrupts();
|
||||||
unsafe { core::arch::asm!("isb") };
|
unsafe { core::arch::asm!("isb") };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,14 +177,14 @@ pub fn enable_interrupts() {
|
|||||||
gic_enable_interrupt(keyboard_irq as u32);
|
gic_enable_interrupt(keyboard_irq as u32);
|
||||||
gic_enable_interrupt(mouse_irq as u32);
|
gic_enable_interrupt(mouse_irq as u32);
|
||||||
|
|
||||||
|
let ticks = timer_ticks_per_irq();
|
||||||
|
core::arch::asm!("msr cntp_tval_el0, {}", in(reg) ticks);
|
||||||
core::arch::asm!("msr cntp_ctl_el0, {}", in(reg) 1u64); // enable timer
|
core::arch::asm!("msr cntp_ctl_el0, {}", in(reg) 1u64); // enable timer
|
||||||
}
|
}
|
||||||
DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Unmasked + DAIF::F::Masked);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables, dead_code)]
|
#[allow(unused_variables, dead_code)]
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
|
|
||||||
unsafe extern "C" fn no_operation(ctx: *mut UserContext) {
|
unsafe extern "C" fn no_operation(ctx: *mut UserContext) {
|
||||||
let interrupt_id = unsafe { gic_acknowledge() };
|
let interrupt_id = unsafe { gic_acknowledge() };
|
||||||
|
|
||||||
@@ -200,15 +209,14 @@ unsafe extern "C" fn irq_handler(ctx: *mut UserContext) {
|
|||||||
|
|
||||||
if t % 60 == 0 {
|
if t % 60 == 0 {
|
||||||
with_framebuffer(|fb| {
|
with_framebuffer(|fb| {
|
||||||
with_serial_console(|serial_console| {
|
with_serial_console(|serial_console| serial_console.render(fb));
|
||||||
serial_console.print(".", fb);
|
|
||||||
serial_console.render(fb)
|
|
||||||
});
|
|
||||||
fb.present();
|
fb.present();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { core::arch::asm!("msr cntp_tval_el0, {}", in(reg) TIMER_FREQUENCY_HZ) };
|
let ticks = timer_ticks_per_irq();
|
||||||
|
unsafe { core::arch::asm!("msr cntp_tval_el0, {}", in(reg) ticks) };
|
||||||
|
unsafe { core::arch::asm!("msr cntp_ctl_el0, {}", in(reg) 1u64) };
|
||||||
}
|
}
|
||||||
interrupt_id if keyboard_irq == interrupt_id as u64 => {
|
interrupt_id if keyboard_irq == interrupt_id as u64 => {
|
||||||
input_interrupt("kbd");
|
input_interrupt("kbd");
|
||||||
@@ -227,13 +235,13 @@ unsafe extern "C" fn irq_handler(ctx: *mut UserContext) {
|
|||||||
|
|
||||||
fn handle_aborts(ec: u64, ctx: &UserContext) {
|
fn handle_aborts(ec: u64, ctx: &UserContext) {
|
||||||
match ec {
|
match ec {
|
||||||
0x25 => {
|
ec if ec == 0x25 || ec == 0x24 => {
|
||||||
panic!(
|
panic!(
|
||||||
"Data abort at VA={:#x} ELR={:#x} ESR={:#x}",
|
"Data abort at VA={:#x} ELR={:#x} ESR={:#x}",
|
||||||
ctx.far_el1, ctx.elr_el1, ctx.esr_el1
|
ctx.far_el1, ctx.elr_el1, ctx.esr_el1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
0x21 => {
|
ec if ec == 0x21 || ec == 0x20 => {
|
||||||
panic!(
|
panic!(
|
||||||
"Instruction abort at VA={:#x} ELR={:#x}",
|
"Instruction abort at VA={:#x} ELR={:#x}",
|
||||||
ctx.far_el1, ctx.elr_el1
|
ctx.far_el1, ctx.elr_el1
|
||||||
@@ -241,8 +249,8 @@ fn handle_aborts(ec: u64, ctx: &UserContext) {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!(
|
panic!(
|
||||||
"Unhandled sync abort VA={:#x} ELR={:#x} ESR={:#x}",
|
"Unhandled sync abort VA={:#x} ELR={:#x} ESR={:#x}, ec={:#x}",
|
||||||
ctx.far_el1, ctx.elr_el1, ctx.esr_el1
|
ctx.far_el1, ctx.elr_el1, ctx.esr_el1, ec
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,10 +258,9 @@ fn handle_aborts(ec: u64, ctx: &UserContext) {
|
|||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
unsafe extern "C" fn sync_handler_user(ctx: *mut UserContext) {
|
unsafe extern "C" fn sync_handler_user(ctx: *mut UserContext) {
|
||||||
let mut ctx = unsafe { *ctx };
|
let ctx = unsafe { &mut *ctx };
|
||||||
let ec = (ctx.esr_el1 >> ESR_EC_SHIFT) & ESR_EC_MASK;
|
let ec = (ctx.esr_el1 >> ESR_EC_SHIFT) & ESR_EC_MASK;
|
||||||
|
|
||||||
#[allow(unused_assignments)]
|
|
||||||
match ec {
|
match ec {
|
||||||
EC_SVC_AA64 => {
|
EC_SVC_AA64 => {
|
||||||
ctx.x0 = unsafe {
|
ctx.x0 = unsafe {
|
||||||
@@ -267,9 +274,13 @@ unsafe extern "C" fn sync_handler_user(ctx: *mut UserContext) {
|
|||||||
ctx.x5 as isize,
|
ctx.x5 as isize,
|
||||||
)
|
)
|
||||||
} as u64;
|
} as u64;
|
||||||
|
|
||||||
|
ctx_save(ctx as *const UserContext);
|
||||||
|
|
||||||
|
let _ = unsafe { check_and_reschedule() };
|
||||||
}
|
}
|
||||||
_ => handle_aborts(ec, &ctx),
|
_ => handle_aborts(ec, ctx),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
@@ -279,6 +290,37 @@ unsafe extern "C" fn sync_handler_kernel(ctx: *mut UserContext) {
|
|||||||
handle_aborts(ec, &ctx)
|
handle_aborts(ec, &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unsafe(naked)]
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe fn run_next(ctx: *const UserContext, user_sp: u64) {
|
||||||
|
core::arch::naked_asm!(
|
||||||
|
"mov x30, x0",
|
||||||
|
"msr sp_el0, x1",
|
||||||
|
"ldr x2, [x30, #248]",
|
||||||
|
"msr elr_el1, x2",
|
||||||
|
"ldr x3, [x30, #256]",
|
||||||
|
"msr spsr_el1, x3",
|
||||||
|
"ldp x0, x1, [x30, #0]",
|
||||||
|
"ldp x2, x3, [x30, #16]",
|
||||||
|
"ldp x4, x5, [x30, #32]",
|
||||||
|
"ldp x6, x7, [x30, #48]",
|
||||||
|
"ldp x8, x9, [x30, #64]",
|
||||||
|
"ldp x10, x11, [x30, #80]",
|
||||||
|
"ldp x12, x13, [x30, #96]",
|
||||||
|
"ldp x14, x15, [x30, #112]",
|
||||||
|
"ldp x16, x17, [x30, #128]",
|
||||||
|
"ldp x18, x19, [x30, #144]",
|
||||||
|
"ldp x20, x21, [x30, #160]",
|
||||||
|
"ldp x22, x23, [x30, #176]",
|
||||||
|
"ldp x24, x25, [x30, #192]",
|
||||||
|
"ldp x26, x27, [x30, #208]",
|
||||||
|
"ldp x28, x29, [x30, #224]",
|
||||||
|
"ldr x30, [x30, #240]",
|
||||||
|
"isb",
|
||||||
|
"eret"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// these are UB and should not happen
|
// these are UB and should not happen
|
||||||
exception_handler!(current_el_sp0_sync, no_operation);
|
exception_handler!(current_el_sp0_sync, no_operation);
|
||||||
exception_handler!(current_el_sp0_irq, no_operation);
|
exception_handler!(current_el_sp0_irq, no_operation);
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
use crate::arch::arch::safe_lock;
|
|
||||||
|
|
||||||
const KMI0_BASE: u64 = 0xFFFF_0000_0905_0000;
|
|
||||||
const KMI1_BASE: u64 = 0xFFFF_0000_0906_0000;
|
|
||||||
const KMI_CR: u64 = 0x00;
|
|
||||||
const KMI_STAT: u64 = 0x04;
|
|
||||||
const KMI_DATA: u64 = 0x08;
|
|
||||||
|
|
||||||
pub unsafe fn kmi_write(base: u64, kmi_type: u64, val: u8) {
|
|
||||||
let data = (base + kmi_type) as *mut u32;
|
|
||||||
unsafe { data.write_volatile(val as u32) };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kmi_read(base: u64, kmi_type: u64) -> u8 {
|
|
||||||
let data = (base + kmi_type) as *const u32;
|
|
||||||
unsafe { data.read_volatile() as u8 }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn read_mouse_control() -> u8 {
|
|
||||||
kmi_read(KMI1_BASE, KMI_STAT)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn read_mouse_data() -> u8 {
|
|
||||||
kmi_read(KMI1_BASE, KMI_DATA)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn read_keyboard_control() -> u8 {
|
|
||||||
kmi_read(KMI0_BASE, KMI_STAT)
|
|
||||||
}
|
|
||||||
pub unsafe fn read_keyboard_data() -> u8 {
|
|
||||||
kmi_read(KMI0_BASE, KMI_DATA)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn setup_kmi() -> u8 {
|
|
||||||
safe_lock(|| unsafe {
|
|
||||||
let cr0 = (KMI0_BASE + KMI_CR) as *mut u32;
|
|
||||||
cr0.write_volatile(0x14); // enable keyboard
|
|
||||||
|
|
||||||
kmi_write(KMI0_BASE, KMI_DATA, 0xFF); // reset keyboard
|
|
||||||
|
|
||||||
if kmi_read(KMI0_BASE, KMI_DATA) != 0xFA {
|
|
||||||
// ACK
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if kmi_read(KMI0_BASE, KMI_DATA) != 0xAA {
|
|
||||||
// self-test passed
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
kmi_write(KMI0_BASE, KMI_DATA, 0xF4); // enable keyboard data reporting
|
|
||||||
|
|
||||||
if kmi_read(KMI0_BASE, KMI_DATA) != 0xFA {
|
|
||||||
// ACK
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cr1 = (KMI1_BASE + KMI_CR) as *mut u32;
|
|
||||||
cr1.write_volatile(0x14); // enable mouse
|
|
||||||
|
|
||||||
kmi_write(KMI1_BASE, KMI_DATA, 0xFF); // reset mouse
|
|
||||||
|
|
||||||
if kmi_read(KMI1_BASE, KMI_DATA) != 0xFA {
|
|
||||||
// ACK
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if kmi_read(KMI1_BASE, KMI_DATA) != 0xAA {
|
|
||||||
// self-test passed
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
if kmi_read(KMI1_BASE, KMI_DATA) != 0x00 {
|
|
||||||
// mouse ID
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
kmi_write(KMI1_BASE, KMI_DATA, 0xF4); // enable mouse data reporting
|
|
||||||
|
|
||||||
if kmi_read(KMI1_BASE, KMI_DATA) != 0xFA {
|
|
||||||
// ACK
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 9;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,5 @@ pub mod dtb;
|
|||||||
pub mod heap;
|
pub mod heap;
|
||||||
pub mod init;
|
pub mod init;
|
||||||
pub mod interrupts;
|
pub mod interrupts;
|
||||||
pub mod kmi;
|
|
||||||
pub mod paging;
|
pub mod paging;
|
||||||
pub mod syscall;
|
|
||||||
pub mod usermode;
|
pub mod usermode;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::Ordering;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{
|
arch::{
|
||||||
aarch64::init::KERNEL_STACK,
|
aarch64::init::KERNEL_STACK,
|
||||||
arch::{HHDM_OFFSET, XunilFrameAllocator, safe_lock, serial_print},
|
arch::{HHDM_OFFSET, XunilFrameAllocator, safe_lock, serial_print},
|
||||||
},
|
},
|
||||||
|
driver::graphics::framebuffer::USER_FB_BASE,
|
||||||
util::U64Buf,
|
util::U64Buf,
|
||||||
};
|
};
|
||||||
use limine::{
|
use limine::{
|
||||||
@@ -56,21 +57,12 @@ pub fn device_flags() -> u64 {
|
|||||||
// no SH bits for device memory
|
// no SH bits for device memory
|
||||||
}
|
}
|
||||||
|
|
||||||
static HHDM_OVERFLOW_REPORTED: AtomicBool = AtomicBool::new(false);
|
|
||||||
|
|
||||||
fn phys_to_virt(phys: u64) -> *mut u64 {
|
fn phys_to_virt(phys: u64) -> *mut u64 {
|
||||||
let hhdm_offset = HHDM_OFFSET.load(Ordering::Relaxed);
|
let hhdm_offset = HHDM_OFFSET.load(Ordering::Relaxed);
|
||||||
|
|
||||||
match phys.checked_add(hhdm_offset) {
|
match phys.checked_add(hhdm_offset) {
|
||||||
Some(virt) => virt as *mut u64,
|
Some(virt) => virt as *mut u64,
|
||||||
None => {
|
None => {
|
||||||
if !HHDM_OVERFLOW_REPORTED.swap(true, Ordering::Relaxed) {
|
|
||||||
serial_print("HHDM overflow phys=");
|
|
||||||
serial_print(U64Buf::new(phys).as_str());
|
|
||||||
serial_print(", hhdm_offset=");
|
|
||||||
serial_print(U64Buf::new(hhdm_offset).as_str());
|
|
||||||
serial_print("\n");
|
|
||||||
}
|
|
||||||
panic!("phys_to_virt overflow");
|
panic!("phys_to_virt overflow");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +176,8 @@ pub fn initialize_paging_aarch64<'a>(
|
|||||||
page_table.map_range(0xFFFF_0000_0900_0000, 0x0900_0000, 0x1000, device_flags()); // the UART
|
page_table.map_range(0xFFFF_0000_0900_0000, 0x0900_0000, 0x1000, device_flags()); // the UART
|
||||||
page_table.map_range(0xFFFF_0000_0800_0000, 0x0800_0000, 0x10000, device_flags()); // the GICD
|
page_table.map_range(0xFFFF_0000_0800_0000, 0x0800_0000, 0x10000, device_flags()); // the GICD
|
||||||
page_table.map_range(0xFFFF_0000_0801_0000, 0x0801_0000, 0x10000, device_flags()); // the GICC
|
page_table.map_range(0xFFFF_0000_0801_0000, 0x0801_0000, 0x10000, device_flags()); // the GICC
|
||||||
page_table.map_range(0xFFFF_0000_0a00_0000, 0x0a00_0000, 0x8000, device_flags()); // Virtio setup_mair();
|
page_table.map_range(0xFFFF_0000_0a00_0000, 0x0a00_0000, 0x8000, device_flags()); // Virtio
|
||||||
|
setup_mair();
|
||||||
setup_tcr();
|
setup_tcr();
|
||||||
|
|
||||||
let stack_phys = KERNEL_STACK.0.as_ptr() as u64 - k_virt_base + k_phys_base;
|
let stack_phys = KERNEL_STACK.0.as_ptr() as u64 - k_virt_base + k_phys_base;
|
||||||
@@ -259,6 +252,30 @@ impl AArchPageTable {
|
|||||||
unsafe {
|
unsafe {
|
||||||
entry_ptr.write_volatile(phys | flags);
|
entry_ptr.write_volatile(phys | flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if virt == USER_FB_BASE + 0x1000 {
|
||||||
|
serial_print("entry_ptr=");
|
||||||
|
serial_print(U64Buf::new(entry_ptr as u64).as_str());
|
||||||
|
serial_print(", virt=");
|
||||||
|
serial_print(U64Buf::new(virt as u64).as_str());
|
||||||
|
serial_print(", phys=");
|
||||||
|
serial_print(U64Buf::new(phys as u64).as_str());
|
||||||
|
serial_print(", l0=");
|
||||||
|
serial_print(U64Buf::new(l0 as u64).as_str());
|
||||||
|
serial_print(", l1=");
|
||||||
|
serial_print(U64Buf::new(l1 as u64).as_str());
|
||||||
|
serial_print(", l2=");
|
||||||
|
serial_print(U64Buf::new(l2 as u64).as_str());
|
||||||
|
serial_print(", l3=");
|
||||||
|
serial_print(U64Buf::new(l3 as u64).as_str());
|
||||||
|
serial_print(", flags=");
|
||||||
|
serial_print(U64Buf::new(flags).as_str());
|
||||||
|
|
||||||
|
let written = unsafe { entry_ptr.read_volatile() };
|
||||||
|
serial_print(", readback=");
|
||||||
|
serial_print(U64Buf::new(written).as_str());
|
||||||
|
serial_print("\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_range(&self, virt: u64, phys: u64, size: u64, flags: u64) {
|
pub fn map_range(&self, virt: u64, phys: u64, size: u64, flags: u64) {
|
||||||
@@ -302,17 +319,12 @@ pub fn create_and_map_multiple_pages(
|
|||||||
base: u64,
|
base: u64,
|
||||||
flags: u64,
|
flags: u64,
|
||||||
) {
|
) {
|
||||||
let mut frame_allocator = FRAME_ALLOCATOR_AARCH64.lock();
|
|
||||||
|
|
||||||
for i in 0..page_count {
|
for i in 0..page_count {
|
||||||
let frame = frame_allocator.allocate_frame().unwrap();
|
let frame = alloc_frame().unwrap();
|
||||||
|
|
||||||
let virt = base + i as u64 * 4096;
|
let virt = base + i as u64 * 4096;
|
||||||
|
|
||||||
mapper.map_page(virt, frame, flags);
|
mapper.map_page(virt, frame, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlb_flush();
|
tlb_flush();
|
||||||
|
|
||||||
drop(frame_allocator);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
// TODO: add syscalls
|
|
||||||
+29
-4
@@ -11,6 +11,9 @@ use x86_64::{
|
|||||||
structures::paging::{FrameAllocator, OffsetPageTable, PhysFrame, Size4KiB},
|
structures::paging::{FrameAllocator, OffsetPageTable, PhysFrame, Size4KiB},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use aarch64_cpu::registers::{DAIF, Writeable};
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
pub use crate::arch::aarch64::paging::FRAME_ALLOCATOR_AARCH64 as FRAME_ALLOCATOR;
|
pub use crate::arch::aarch64::paging::FRAME_ALLOCATOR_AARCH64 as FRAME_ALLOCATOR;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
@@ -91,8 +94,11 @@ impl XunilFrameAllocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn init<'a>(hhdm_response: &HhdmResponse, memory_map_response: &'a MemoryMapResponse) {
|
pub fn init<'a>(
|
||||||
init_x86_64(hhdm_response, memory_map_response);
|
hhdm_response: &HhdmResponse,
|
||||||
|
memory_map_response: &'a MemoryMapResponse,
|
||||||
|
) -> OffsetPageTable<'a> {
|
||||||
|
init_x86_64(hhdm_response, memory_map_response)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
@@ -110,11 +116,26 @@ pub fn enter_usermode(entry: u64, stack_ptr: u64, should_swapgs: bool) {
|
|||||||
enter_usermode_aarch64(entry, stack_ptr, should_swapgs);
|
enter_usermode_aarch64(entry, stack_ptr, should_swapgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn safe_lock<R, F: FnOnce() -> R>(f: F) -> R {
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub fn safe_lock<R, F: FnOnce() -> R>(f: F) -> R {
|
||||||
return without_interrupts(|| f());
|
return without_interrupts(|| f());
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
return f();
|
pub fn safe_lock<R, F: FnOnce() -> R>(f: F) -> R {
|
||||||
|
// #[cfg(target_arch = "aarch64")]
|
||||||
|
// {
|
||||||
|
// DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Masked + DAIF::F::Masked);
|
||||||
|
// }
|
||||||
|
|
||||||
|
let r = f();
|
||||||
|
|
||||||
|
// #[cfg(target_arch = "aarch64")]
|
||||||
|
// {
|
||||||
|
// DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Unmasked + DAIF::F::Masked);
|
||||||
|
// }
|
||||||
|
|
||||||
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@@ -157,6 +178,10 @@ pub fn idle() {
|
|||||||
pub fn sleep(ticks: u64) {
|
pub fn sleep(ticks: u64) {
|
||||||
let start = TIMER.now();
|
let start = TIMER.now();
|
||||||
while start.ticks_since() < ticks {
|
while start.ticks_since() < ticks {
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
{
|
||||||
|
DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Unmasked + DAIF::F::Masked);
|
||||||
|
}
|
||||||
idle();
|
idle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use crate::driver::io::ps2::process_scancodes;
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use crate::driver::io::virtio::input::process_keycodes;
|
use crate::driver::io::virtio::input::process_keycodes;
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::arch::{FRAME_ALLOCATOR, sleep},
|
arch::arch::{FRAME_ALLOCATOR, serial_print, sleep},
|
||||||
driver::{
|
driver::{
|
||||||
elf::loader::run_elf,
|
elf::loader::run_elf,
|
||||||
graphics::framebuffer::{FRAMEBUFFER, USER_FB_BASE, with_framebuffer},
|
graphics::framebuffer::{FRAMEBUFFER, USER_FB_BASE, with_framebuffer},
|
||||||
@@ -33,7 +33,7 @@ use crate::{
|
|||||||
process::ProcessState,
|
process::ProcessState,
|
||||||
scheduler::{SCHEDULER, current_pid},
|
scheduler::{SCHEDULER, current_pid},
|
||||||
},
|
},
|
||||||
util::{align_down, align_up},
|
util::{U64Buf, align_down, align_up},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -363,7 +363,7 @@ pub fn exec(arg0: isize) -> isize {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
run_elf(&buf, true);
|
run_elf(&buf, true, false);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,6 +384,7 @@ pub fn set_reschedule(should_reschedule: bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit() -> isize {
|
pub fn exit() -> isize {
|
||||||
|
serial_print("Process Exited.");
|
||||||
let pid = current_pid().unwrap_or(0);
|
let pid = current_pid().unwrap_or(0);
|
||||||
if pid == 0 {
|
if pid == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -414,6 +415,33 @@ pub fn exit() -> isize {
|
|||||||
crate::arch::arch::infinite_idle();
|
crate::arch::arch::infinite_idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn check_and_reschedule() -> usize {
|
||||||
|
let pid = current_pid().unwrap_or(0);
|
||||||
|
|
||||||
|
if pid == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let should = SCHEDULER
|
||||||
|
.with_process(pid, |process| process.should_reschedule)
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if !should {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let next_task = SCHEDULER.next_task();
|
||||||
|
|
||||||
|
if next_task == pid {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCHEDULER.switch_to(next_task, true);
|
||||||
|
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub unsafe extern "C" fn syscall_dispatch(
|
pub unsafe extern "C" fn syscall_dispatch(
|
||||||
@@ -427,20 +455,25 @@ pub unsafe extern "C" fn syscall_dispatch(
|
|||||||
) -> isize {
|
) -> isize {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
interrupts::enable();
|
interrupts::enable();
|
||||||
|
// if num != 1 {
|
||||||
|
// serial_print("syscall num=");
|
||||||
|
// serial_print(U64Buf::new(num as u64).as_str());
|
||||||
|
// serial_print("\n");
|
||||||
|
// }
|
||||||
|
|
||||||
set_reschedule(match num {
|
set_reschedule(match num {
|
||||||
BRK => false,
|
BRK => false,
|
||||||
READ => true,
|
READ => false,
|
||||||
WRITE => false,
|
WRITE => false,
|
||||||
OPEN => true,
|
OPEN => true,
|
||||||
CLOSE => true,
|
CLOSE => true,
|
||||||
LSEEK => true,
|
LSEEK => false,
|
||||||
EXIT => true,
|
EXIT => true,
|
||||||
SLEEP => true,
|
SLEEP => true,
|
||||||
CLOCK_GETTIME => false,
|
CLOCK_GETTIME => false,
|
||||||
MAP_FRAMEBUFFER => false,
|
MAP_FRAMEBUFFER => false,
|
||||||
KBD_READ => true,
|
KBD_READ => false,
|
||||||
FRAMEBUFFER_SWAP => true,
|
FRAMEBUFFER_SWAP => false,
|
||||||
GETPID => false,
|
GETPID => false,
|
||||||
EXECVE => true,
|
EXECVE => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use x86_64::structures::paging::{
|
|||||||
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 = 4 * 1024 * 1024; // 64 MiB
|
||||||
|
|
||||||
pub fn init_heap(mapper: &mut OffsetPageTable) -> Result<(), MapToError<Size4KiB>> {
|
pub fn init_heap(mapper: &mut OffsetPageTable) -> Result<(), MapToError<Size4KiB>> {
|
||||||
let page_count = HEAP_SIZE / 4096;
|
let page_count = HEAP_SIZE / 4096;
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ pub fn set_pit_interval() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_x86_64<'a>(hhdm_response: &HhdmResponse, memory_map_response: &'a MemoryMapResponse) {
|
pub fn init_x86_64<'a>(
|
||||||
|
hhdm_response: &HhdmResponse,
|
||||||
|
memory_map_response: &'a MemoryMapResponse,
|
||||||
|
) -> OffsetPageTable<'a> {
|
||||||
load_gdt_x86_64();
|
load_gdt_x86_64();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -87,4 +90,6 @@ pub fn init_x86_64<'a>(hhdm_response: &HhdmResponse, memory_map_response: &'a Me
|
|||||||
.expect("Failed to initalize heap");
|
.expect("Failed to initalize heap");
|
||||||
|
|
||||||
MOUSE.set_status(kmi_status);
|
MOUSE.set_status(kmi_status);
|
||||||
|
|
||||||
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use core::sync::atomic::Ordering;
|
use core::sync::atomic::Ordering;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::x86_64::gdt,
|
arch::{arch::serial_print, x86_64::gdt},
|
||||||
driver::{
|
driver::{
|
||||||
graphics::framebuffer::with_framebuffer,
|
graphics::framebuffer::with_framebuffer,
|
||||||
io::ps2::{keyboard_interrupt, mouse_interrupt, push_scancode},
|
io::ps2::{keyboard_interrupt, mouse_interrupt, push_scancode},
|
||||||
@@ -9,6 +9,7 @@ use crate::{
|
|||||||
timer::TIMER,
|
timer::TIMER,
|
||||||
},
|
},
|
||||||
println,
|
println,
|
||||||
|
util::U64Buf,
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use pic8259::ChainedPics;
|
use pic8259::ChainedPics;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use x86_64::instructions::tlb::flush_all;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::x86_64::gdt::{GDT, TSS},
|
arch::x86_64::gdt::{GDT, TSS},
|
||||||
task::scheduler::{SCHEDULER, current_pid},
|
task::context::UserContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
const IA32_EFER: u32 = 0xC0000080;
|
const IA32_EFER: u32 = 0xC0000080;
|
||||||
@@ -85,33 +85,6 @@ pub fn init_syscalls() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn check_and_reschedule() -> usize {
|
|
||||||
let pid = current_pid().unwrap_or(0);
|
|
||||||
|
|
||||||
if pid == 0 {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let should = SCHEDULER
|
|
||||||
.with_process(pid, |process| process.should_reschedule)
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
if !should {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let next_task = SCHEDULER.next_task();
|
|
||||||
|
|
||||||
if next_task == pid {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SCHEDULER.switch_to(next_task, false);
|
|
||||||
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(naked)]
|
#[unsafe(naked)]
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
unsafe extern "C" fn syscall_entry() {
|
unsafe extern "C" fn syscall_entry() {
|
||||||
@@ -206,3 +179,30 @@ unsafe extern "C" fn syscall_entry() {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unsafe(naked)]
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe fn run_next(ctx: *const UserContext, user_rsp: u64) {
|
||||||
|
core::arch::naked_asm!(
|
||||||
|
"mov gs:[0], rsi", // store new user rsp
|
||||||
|
"mov rsp, rdi",
|
||||||
|
"mov r15, qword ptr [rsp + 0]",
|
||||||
|
"mov r14, qword ptr [rsp + 8]",
|
||||||
|
"mov r13, qword ptr [rsp + 16]",
|
||||||
|
"mov r12, qword ptr [rsp + 24]",
|
||||||
|
"mov r11, qword ptr [rsp + 32]", // rflags
|
||||||
|
"mov r10, qword ptr [rsp + 40]",
|
||||||
|
"mov r9, qword ptr [rsp + 48]",
|
||||||
|
"mov r8, qword ptr [rsp + 56]",
|
||||||
|
"mov rsi, qword ptr [rsp + 64]",
|
||||||
|
"mov rdi, qword ptr [rsp + 72]",
|
||||||
|
"mov rbp, qword ptr [rsp + 80]",
|
||||||
|
"mov rdx, qword ptr [rsp + 88]",
|
||||||
|
"mov rcx, qword ptr [rsp + 96]", // rip
|
||||||
|
"mov rbx, qword ptr [rsp + 104]",
|
||||||
|
"mov rax, qword ptr [rsp + 112]",
|
||||||
|
"mov rsp, qword ptr [rsp + 120]", // user rsp
|
||||||
|
"swapgs",
|
||||||
|
"sysretq",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
pub const TIMER_FREQUENCY_HZ: usize = 1000;
|
pub const TIMER_FREQUENCY_HZ: usize = 1000;
|
||||||
pub const KARCH: &str = "aarch64";
|
pub const KARCH: &str = "x86_64";
|
||||||
@@ -144,6 +144,7 @@ pub const DT_VERNEED: i64 = 0x6ffffffe;
|
|||||||
pub const DT_VERNEEDNUM: i64 = 0x6fffffff;
|
pub const DT_VERNEEDNUM: i64 = 0x6fffffff;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Elf64Ehdr {
|
pub struct Elf64Ehdr {
|
||||||
pub e_ident: [u8; 16],
|
pub e_ident: [u8; 16],
|
||||||
pub e_type: u16,
|
pub e_type: u16,
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub fn load_file(mapper: &mut PageTable, elf_bytes: &[u8]) -> (*const u8, u64) {
|
|||||||
unsafe { core::ptr::read_unaligned(elf_bytes.as_ptr() as *const Elf64Ehdr) };
|
unsafe { core::ptr::read_unaligned(elf_bytes.as_ptr() as *const Elf64Ehdr) };
|
||||||
|
|
||||||
if !validate_elf(&elf_header, elf_bytes.len()) {
|
if !validate_elf(&elf_header, elf_bytes.len()) {
|
||||||
return (null(), 0);
|
panic!("Invalid ELF");
|
||||||
}
|
}
|
||||||
|
|
||||||
let elf_header_ptr = elf_bytes.as_ptr() as *const Elf64Ehdr;
|
let elf_header_ptr = elf_bytes.as_ptr() as *const Elf64Ehdr;
|
||||||
@@ -72,7 +72,7 @@ pub fn load_file(mapper: &mut PageTable, elf_bytes: &[u8]) -> (*const u8, u64) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_elf(file_bytes: &[u8], should_swapgs: bool) {
|
pub fn run_elf(file_bytes: &[u8], should_swapgs: bool, switch_to: bool) {
|
||||||
let stack_base: u64 = 0x0000_7fff_0000_0000;
|
let stack_base: u64 = 0x0000_7fff_0000_0000;
|
||||||
let page_count = 4096; // 16 mib
|
let page_count = 4096; // 16 mib
|
||||||
let page_size = 0x1000u64;
|
let page_size = 0x1000u64;
|
||||||
@@ -109,7 +109,9 @@ pub fn run_elf(file_bytes: &[u8], should_swapgs: bool) {
|
|||||||
process.address_space = Some(address_space)
|
process.address_space = Some(address_space)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if switch_to {
|
||||||
SCHEDULER.switch_to(process_pid, should_swapgs);
|
SCHEDULER.switch_to(process_pid, should_swapgs);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ use x86_64::{
|
|||||||
use crate::arch::x86_64::paging::create_and_map_multiple_pages;
|
use crate::arch::x86_64::paging::create_and_map_multiple_pages;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::arch::FRAME_ALLOCATOR,
|
|
||||||
driver::elf::header::{
|
driver::elf::header::{
|
||||||
DT_JMPREL, DT_NEEDED, DT_NULL, DT_PLTREL, DT_PLTRELSZ, DT_RELA, DT_RELASZ, DT_STRSZ,
|
DT_JMPREL, DT_NEEDED, DT_NULL, DT_PLTREL, DT_PLTRELSZ, DT_RELA, DT_RELASZ, DT_STRSZ,
|
||||||
DT_STRTAB, DT_SYMTAB, Elf64Dyn, Elf64Ehdr, Elf64Phdr, Elf64Rela, Elf64Sym, PF_X,
|
DT_STRTAB, DT_SYMTAB, Elf64Dyn, Elf64Ehdr, Elf64Phdr, Elf64Rela, Elf64Sym, PF_X,
|
||||||
@@ -319,9 +318,13 @@ pub fn load_segment_to_memory(
|
|||||||
}
|
}
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
{
|
{
|
||||||
let mut flags = user_code_flags();
|
use crate::arch::aarch64::paging::user_data_flags;
|
||||||
|
|
||||||
if unsafe { ((*phdr).p_flags & PF_X) == 0 } {
|
let mut flags = user_data_flags();
|
||||||
|
|
||||||
|
if unsafe { ((*phdr).p_flags & PF_X) != 0 } {
|
||||||
|
flags &= !UXN;
|
||||||
|
} else {
|
||||||
flags |= UXN;
|
flags |= UXN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +339,6 @@ pub fn load_segment_to_memory(
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::copy_nonoverlapping(src, dst, file_size as usize);
|
core::ptr::copy_nonoverlapping(src, dst, file_size as usize);
|
||||||
|
|
||||||
if mem_size > file_size {
|
if mem_size > file_size {
|
||||||
core::ptr::write_bytes(
|
core::ptr::write_bytes(
|
||||||
dst.add(file_size as usize),
|
dst.add(file_size as usize),
|
||||||
|
|||||||
@@ -1,5 +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 x86_64::structures::paging::OffsetPageTable;
|
||||||
|
|
||||||
use crate::arch::arch::safe_lock;
|
use crate::arch::arch::safe_lock;
|
||||||
|
|
||||||
@@ -53,9 +55,19 @@ impl Framebuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn setup_x86_64(&mut self) {
|
pub fn setup_x86_64(&mut self, mapper: &mut OffsetPageTable) {
|
||||||
use crate::arch::arch::{FRAME_ALLOCATOR, HHDM_OFFSET};
|
use crate::{
|
||||||
use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB};
|
arch::arch::{FRAME_ALLOCATOR, HHDM_OFFSET, serial_print},
|
||||||
|
arch::x86_64::paging::initialize_paging_x86_64,
|
||||||
|
util::U64Buf,
|
||||||
|
};
|
||||||
|
use x86_64::{
|
||||||
|
PhysAddr, VirtAddr,
|
||||||
|
structures::paging::{
|
||||||
|
FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const KERNEL_FB_BASE: u64 = 0xffffffffa0000000;
|
||||||
let buf_len = self.pitch * self.height;
|
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;
|
||||||
@@ -65,8 +77,6 @@ impl Framebuffer {
|
|||||||
let struct_frame: PhysFrame<Size4KiB> =
|
let struct_frame: PhysFrame<Size4KiB> =
|
||||||
fa.allocate_frame().expect("framebuffer struct frame");
|
fa.allocate_frame().expect("framebuffer struct frame");
|
||||||
let struct_phys = struct_frame.start_address().as_u64();
|
let struct_phys = struct_frame.start_address().as_u64();
|
||||||
let hhdm_offset = HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed);
|
|
||||||
let struct_virt = (struct_phys + hhdm_offset) as *mut UserFrameBuffer;
|
|
||||||
|
|
||||||
let first_pixel_frame: PhysFrame<Size4KiB> =
|
let first_pixel_frame: PhysFrame<Size4KiB> =
|
||||||
fa.allocate_frame().expect("framebuffer pixel frame 0");
|
fa.allocate_frame().expect("framebuffer pixel frame 0");
|
||||||
@@ -74,7 +84,33 @@ impl Framebuffer {
|
|||||||
for _ in 1..pixel_frames {
|
for _ in 1..pixel_frames {
|
||||||
fa.allocate_frame().expect("framebuffer pixel frame");
|
fa.allocate_frame().expect("framebuffer pixel frame");
|
||||||
}
|
}
|
||||||
let buf_virt_kernel = (buf_phys + hhdm_offset) as *mut u32;
|
|
||||||
|
let hhdm_offset = HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
|
let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::NO_EXECUTE;
|
||||||
|
|
||||||
|
let struct_page = Page::<Size4KiB>::containing_address(VirtAddr::new(KERNEL_FB_BASE));
|
||||||
|
unsafe {
|
||||||
|
mapper
|
||||||
|
.map_to(struct_page, struct_frame, flags, &mut *fa)
|
||||||
|
.unwrap()
|
||||||
|
.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..pixel_frames {
|
||||||
|
let frame = PhysFrame::<Size4KiB>::containing_address(PhysAddr::new(
|
||||||
|
buf_phys + i as u64 * 4096,
|
||||||
|
));
|
||||||
|
let page = Page::<Size4KiB>::containing_address(VirtAddr::new(
|
||||||
|
KERNEL_FB_BASE + 0x1000 + i as u64 * 4096,
|
||||||
|
));
|
||||||
|
unsafe {
|
||||||
|
mapper.map_to(page, frame, flags, &mut *fa).unwrap().flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let struct_virt = KERNEL_FB_BASE as *mut UserFrameBuffer;
|
||||||
|
let buf_virt_kernel = (KERNEL_FB_BASE + 0x1000) as *mut u32;
|
||||||
drop(fa);
|
drop(fa);
|
||||||
|
|
||||||
unsafe { core::ptr::write_bytes(buf_virt_kernel, 0, buf_len) };
|
unsafe { core::ptr::write_bytes(buf_virt_kernel, 0, buf_len) };
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
pub static INIT_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/init");
|
||||||
|
pub static DOOM_WAD: &[u8] = include_bytes!("../../../../../assets/doom1.wad");
|
||||||
|
pub static DOOM_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/doomgeneric");
|
||||||
|
pub static HELLOWORLD_ELF: &[u8] = include_bytes!("../../../../../assets/aarch64/helloworld.elf");
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
pub mod assets;
|
||||||
pub mod vfs;
|
pub mod vfs;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::driver::io::fs::assets::*;
|
||||||
use core::ptr::{null, null_mut};
|
use core::ptr::{null, null_mut};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -38,10 +39,6 @@ fn fd_ok(fd: Fd) -> bool {
|
|||||||
fd >= 0 && (fd as usize) < MAX_FD
|
fd >= 0 && (fd as usize) < MAX_FD
|
||||||
}
|
}
|
||||||
|
|
||||||
static DOOM_WAD: &[u8] = include_bytes!("../../../../../assets/doom1.wad");
|
|
||||||
static DOOM_ELF: &[u8] = include_bytes!("../../../../../assets/doomgeneric");
|
|
||||||
static HELLOWORLD_ELF: &[u8] = include_bytes!("../../../../../assets/helloworld.elf");
|
|
||||||
|
|
||||||
static FILES: &[FakeFileEntry] = &[
|
static FILES: &[FakeFileEntry] = &[
|
||||||
FakeFileEntry {
|
FakeFileEntry {
|
||||||
name: "testfile",
|
name: "testfile",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use crate::arch::x86_64::kmi::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::io::{keyboard::*, mouse::MOUSE},
|
driver::io::{keyboard::*, mouse::MOUSE},
|
||||||
|
println,
|
||||||
task::scheduler::SCHEDULER,
|
task::scheduler::SCHEDULER,
|
||||||
util::get_bit,
|
util::get_bit,
|
||||||
};
|
};
|
||||||
@@ -183,13 +184,14 @@ pub fn process_scancode(scancode: u8) -> Option<KeyboardEvent> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(linux_keycode) = keycode_to_linux(keycode) {
|
if let Some(linux_keycode) = keycode_to_linux(keycode) {
|
||||||
|
let effective_shift = kbd.get_modifiers().is_shifted() & kbd.get_modifiers().capslock;
|
||||||
return Some(KeyboardEvent {
|
return Some(KeyboardEvent {
|
||||||
state: if state == KeyState::Down { 1 } else { 0 },
|
state: if state == KeyState::Down { 1 } else { 0 },
|
||||||
_pad1: 0,
|
_pad1: 0,
|
||||||
key: linux_keycode as u16,
|
key: linux_keycode as u16,
|
||||||
mods: 0,
|
mods: 0,
|
||||||
_pad2: 0,
|
_pad2: 0,
|
||||||
unicode,
|
unicode: keycode_to_char(linux_keycode, effective_shift).unwrap_or('\0') as u32,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
|
|||||||
@@ -196,18 +196,15 @@ pub fn input_interrupt(device_type: &str) {
|
|||||||
|
|
||||||
let event = unsafe { core::ptr::read_volatile(&queue.buffers[desc_idx as usize]) };
|
let event = unsafe { core::ptr::read_volatile(&queue.buffers[desc_idx as usize]) };
|
||||||
|
|
||||||
|
handle_event(&event);
|
||||||
|
|
||||||
let avail_idx = unsafe { core::ptr::read_volatile(&queue.avail.idx) };
|
let avail_idx = unsafe { core::ptr::read_volatile(&queue.avail.idx) };
|
||||||
queue.avail.ring[(avail_idx as usize) % QUEUE_SIZE] = desc_idx as u16;
|
queue.avail.ring[(avail_idx as usize) % QUEUE_SIZE] = desc_idx as u16;
|
||||||
|
|
||||||
core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
|
core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::write_volatile(&mut queue.avail.idx, avail_idx.wrapping_add(1));
|
core::ptr::write_volatile(&mut queue.avail.idx, avail_idx.wrapping_add(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
device.write(VirtioMmioReg::QueueNotify, 0);
|
|
||||||
|
|
||||||
handle_event(&event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ pub fn get_device(slot: u64) -> Option<VirtioMmio> {
|
|||||||
Some(device)
|
Some(device)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scan_devices() {
|
pub fn scan_virtio_devices() {
|
||||||
for i in 0..VIRTIO_MMIO_COUNT {
|
for i in 0..VIRTIO_MMIO_COUNT {
|
||||||
let base = VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_STRIDE;
|
let base = VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_STRIDE;
|
||||||
let device = VirtioMmio::new(base);
|
let device = VirtioMmio::new(base);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::alloc::string::ToString;
|
use crate::alloc::string::ToString;
|
||||||
|
use crate::arch::arch::serial_print;
|
||||||
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::{arch::arch::safe_lock, driver::graphics::base::rgb};
|
use crate::{arch::arch::safe_lock, driver::graphics::base::rgb};
|
||||||
@@ -14,6 +15,7 @@ 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(())
|
||||||
}
|
}
|
||||||
|
|||||||
+38
-38
@@ -2,40 +2,42 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
#![cfg_attr(target_arch = "x86_64", 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 core::sync::atomic::{AtomicU64, Ordering};
|
use core::sync::atomic::{AtomicU64, Ordering};
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
use limine::{
|
||||||
use crate::arch::aarch64::interrupts::enable_interrupts;
|
BaseRevision,
|
||||||
|
request::{
|
||||||
|
DateAtBootRequest, ExecutableAddressRequest, FramebufferRequest, HhdmRequest,
|
||||||
|
MemoryMapRequest, RequestsEndMarker, RequestsStartMarker,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use crate::arch::aarch64::paging::AArchPageTable;
|
use crate::arch::aarch64::paging::AArchPageTable;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use crate::driver::graphics::primitives::rectangle_filled;
|
use crate::driver::{graphics::primitives::rectangle_filled, io::virtio::input::init_keyboard};
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use aarch64_cpu::registers::{DAIF, Writeable};
|
use aarch64_cpu::registers::{DAIF, Writeable};
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
use crate::driver::io::virtio::input::init_keyboard;
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use crate::driver::elf::loader::run_elf;
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::driver::io::ps2::init_keyboard;
|
use crate::driver::io::ps2::init_keyboard;
|
||||||
|
|
||||||
use crate::arch::arch::{HHDM_OFFSET, infinite_idle, init, kernel_crash, serial_print};
|
use crate::arch::arch::{HHDM_OFFSET, infinite_idle, init, kernel_crash, serial_print};
|
||||||
|
use crate::driver::{
|
||||||
use crate::driver::graphics::base::rgb;
|
elf::loader::run_elf,
|
||||||
use crate::driver::graphics::framebuffer::{init_framebuffer, with_framebuffer};
|
graphics::{
|
||||||
|
base::rgb,
|
||||||
use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console};
|
framebuffer::{init_framebuffer, with_framebuffer},
|
||||||
use crate::driver::timer::TIMER;
|
},
|
||||||
|
io::fs::assets::INIT_ELF,
|
||||||
use limine::BaseRevision;
|
serial::{ConsoleWriter, init_serial_console, with_serial_console},
|
||||||
use limine::request::{
|
timer::TIMER,
|
||||||
DateAtBootRequest, ExecutableAddressRequest, FramebufferRequest, HhdmRequest, MemoryMapRequest,
|
|
||||||
RequestsEndMarker, RequestsStartMarker,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
@@ -43,14 +45,6 @@ pub mod mm;
|
|||||||
pub mod task;
|
pub mod task;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
#[repr(C, align(16))]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
struct AlignedElf([u8; include_bytes!("../../assets/init").len()]);
|
|
||||||
#[allow(dead_code)]
|
|
||||||
static INIT_ELF: AlignedElf = AlignedElf(*include_bytes!("../../assets/init"));
|
|
||||||
#[allow(dead_code)]
|
|
||||||
static INIT_ELF_BYTES: &[u8] = &INIT_ELF.0;
|
|
||||||
|
|
||||||
/// Sets the base revision to the latest revision supported by the crate.
|
/// Sets the base revision to the latest revision supported by the crate.
|
||||||
/// See specification for further info.
|
/// See specification for further info.
|
||||||
/// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
|
/// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
|
||||||
@@ -200,13 +194,9 @@ pub unsafe extern "C" fn kernel_main_aarch64(mapper: &mut AArchPageTable) -> ! {
|
|||||||
println!("Could not get date at boot. Will default to 0.")
|
println!("Could not get date at boot. Will default to 0.")
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Hello from Aarch64!");
|
DAIF.write(DAIF::D::Masked + DAIF::A::Masked + DAIF::I::Unmasked + DAIF::F::Masked);
|
||||||
with_framebuffer(|fb| {
|
|
||||||
with_serial_console(|sc| sc.render(fb));
|
|
||||||
rectangle_filled(fb, 100, 100, 20, 20, rgb(255, 255, 255));
|
|
||||||
});
|
|
||||||
|
|
||||||
enable_interrupts();
|
run_elf(INIT_ELF, false, true);
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
@@ -217,20 +207,24 @@ pub unsafe fn kernel_main_x86_64() -> ! {
|
|||||||
// removed by the linker.
|
// removed by the linker.
|
||||||
assert!(BASE_REVISION.is_supported());
|
assert!(BASE_REVISION.is_supported());
|
||||||
|
|
||||||
if let Some(hhdm_response) = HHDM_REQUEST.get_response() {
|
let (hhdm_response, memory_map_response) = {
|
||||||
if let Some(memory_map_response) = MEMORY_MAP_REQUEST.get_response() {
|
if let Some(a) = HHDM_REQUEST.get_response() {
|
||||||
init(hhdm_response, memory_map_response);
|
if let Some(b) = MEMORY_MAP_REQUEST.get_response() {
|
||||||
|
(a, b)
|
||||||
} else {
|
} else {
|
||||||
kernel_crash(); // Could not get required info from Limine's memory map.
|
kernel_crash(); // Could not get required info from Limine's memory map.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
kernel_crash(); // Could not get required info from Limine's higher-half direct mapping.
|
kernel_crash(); // Could not get required info from Limine's higher-half direct mapping.
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut mapper = init(hhdm_response, memory_map_response);
|
||||||
|
|
||||||
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);
|
||||||
with_framebuffer(|fb| fb.setup_x86_64());
|
with_framebuffer(|fb| fb.setup_x86_64(&mut mapper));
|
||||||
} else {
|
} else {
|
||||||
serial_print("no framebuffers found");
|
serial_print("no framebuffers found");
|
||||||
}
|
}
|
||||||
@@ -246,7 +240,7 @@ pub unsafe fn kernel_main_x86_64() -> ! {
|
|||||||
println!("Could not get date at boot. Will default to 0.")
|
println!("Could not get date at boot. Will default to 0.")
|
||||||
}
|
}
|
||||||
|
|
||||||
run_elf(INIT_ELF_BYTES, false);
|
run_elf(INIT_ELF, false, true);
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
@@ -276,6 +270,12 @@ impl core::fmt::Write for BufWriter<'_> {
|
|||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
fn rust_panic(_info: &core::panic::PanicInfo) -> ! {
|
||||||
serial_print("\nKERNEL PANIC:\n");
|
serial_print("\nKERNEL PANIC:\n");
|
||||||
|
serial_print(
|
||||||
|
_info
|
||||||
|
.message()
|
||||||
|
.as_str()
|
||||||
|
.unwrap_or("Could not get message str"),
|
||||||
|
);
|
||||||
let mut buf = [0u8; 512];
|
let mut buf = [0u8; 512];
|
||||||
let msg = {
|
let msg = {
|
||||||
let mut w = BufWriter::new(&mut buf);
|
let mut w = BufWriter::new(&mut buf);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ pub struct UserContext {
|
|||||||
pub spsr_el1: u64,
|
pub spsr_el1: u64,
|
||||||
pub esr_el1: u64, // exception type
|
pub esr_el1: u64, // exception type
|
||||||
pub far_el1: u64, // fault type
|
pub far_el1: u64, // fault type
|
||||||
_pad: u64,
|
pub sp_el0: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
|
|||||||
@@ -4,13 +4,16 @@ use alloc::{collections::btree_map::BTreeMap, vec::Vec};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::arch::{enter_usermode, safe_lock},
|
arch::arch::{enter_usermode, safe_lock},
|
||||||
task::{
|
task::context::UserContext,
|
||||||
context::UserContext,
|
task::process::{Process, ProcessState},
|
||||||
process::{Process, ProcessState},
|
|
||||||
},
|
|
||||||
util::Locked,
|
util::Locked,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use crate::arch::aarch64::interrupts::run_next;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use crate::arch::x86_64::syscall::run_next;
|
||||||
|
|
||||||
pub static CURRENT_PID: AtomicU64 = AtomicU64::new(0);
|
pub static CURRENT_PID: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -119,9 +122,20 @@ impl Locked<Scheduler> {
|
|||||||
#[allow(unused_variables, unused_unsafe)]
|
#[allow(unused_variables, unused_unsafe)]
|
||||||
Some(saved_ctx) => unsafe {
|
Some(saved_ctx) => unsafe {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
run_next((&saved_ctx) as *const UserContext, saved_ctx.rsp)
|
run_next((&saved_ctx) as *const UserContext, saved_ctx.rsp);
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
run_next((&saved_ctx) as *const UserContext, saved_ctx.sp_el0);
|
||||||
},
|
},
|
||||||
None => enter_usermode(entry as u64, (stack_top & !0xF) - 8, should_swapgs),
|
None => enter_usermode(
|
||||||
|
entry as u64,
|
||||||
|
(stack_top & !0xF)
|
||||||
|
- cfg_select! {
|
||||||
|
target_arch = "x86_64" => 8,
|
||||||
|
target_arch = "aarch64" => 16,
|
||||||
|
_ => 8
|
||||||
|
},
|
||||||
|
should_swapgs,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,39 +150,3 @@ 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(no_mangle)]
|
|
||||||
unsafe fn run_next(ctx: *const UserContext, user_rsp: u64) {
|
|
||||||
core::arch::naked_asm!(
|
|
||||||
"mov gs:[0], rsi", // store new user rsp
|
|
||||||
"mov rsp, rdi",
|
|
||||||
"mov r15, qword ptr [rsp + 0]",
|
|
||||||
"mov r14, qword ptr [rsp + 8]",
|
|
||||||
"mov r13, qword ptr [rsp + 16]",
|
|
||||||
"mov r12, qword ptr [rsp + 24]",
|
|
||||||
"mov r11, qword ptr [rsp + 32]", // rflags
|
|
||||||
"mov r10, qword ptr [rsp + 40]",
|
|
||||||
"mov r9, qword ptr [rsp + 48]",
|
|
||||||
"mov r8, qword ptr [rsp + 56]",
|
|
||||||
"mov rsi, qword ptr [rsp + 64]",
|
|
||||||
"mov rdi, qword ptr [rsp + 72]",
|
|
||||||
"mov rbp, qword ptr [rsp + 80]",
|
|
||||||
"mov rdx, qword ptr [rsp + 88]",
|
|
||||||
"mov rcx, qword ptr [rsp + 96]", // rip
|
|
||||||
"mov rbx, qword ptr [rsp + 104]",
|
|
||||||
"mov rax, qword ptr [rsp + 112]",
|
|
||||||
"mov rsp, qword ptr [rsp + 120]", // user rsp
|
|
||||||
"swapgs",
|
|
||||||
"sysretq",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
#[unsafe(naked)]
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe fn run_next(ctx: *const UserContext, user_rsp: u64) {
|
|
||||||
// TODO: add switching logic
|
|
||||||
core::arch::naked_asm!("udf #0");
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-1
Submodule user/apps/doomgeneric updated: 2c34740743...6ce96f770e
@@ -1,3 +1,15 @@
|
|||||||
GCC_INCLUDES=$(gcc -print-file-name=include)
|
GCC_INCLUDES=$(gcc -print-file-name=include)
|
||||||
SYS_INCLUDES=/usr/include
|
SYS_INCLUDES=/usr/include
|
||||||
gcc -w -static -D__NO_INLINE__ -O0 -mno-mmx -mno-avx -fno-stack-protector -fno-inline -fno-inline-small-functions -fno-indirect-inlining -fno-builtin -fcompare-debug-second -nostdlib -nostdinc helloworld.c -Wl,--gc-sections -L../../libxunil/target/release -l:libxunil.a -I../../libxunil/include -I"$GCC_INCLUDES" -I"$SYS_INCLUDES" -o ../../../assets/helloworld.elf
|
|
||||||
|
if [ "$KARCH" = "aarch64" ]; then
|
||||||
|
CC="aarch64-linux-gnu-gcc"
|
||||||
|
ARCH_FLAGS="-march=armv8-a+nosimd -mabi=lp64"
|
||||||
|
elif [ "$KARCH" = "x86_64" ]; then
|
||||||
|
CC="x86_64-linux-gnu-gcc"
|
||||||
|
ARCH_FLAGS="-m64 -mno-mmx -mno-avx"
|
||||||
|
else
|
||||||
|
echo "Error: Unsupported KARCH: $KARCH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
$CC -w -static -D__NO_INLINE__ -O3 $ARCH_FLAGS -fno-stack-protector -fno-inline -fno-inline-small-functions -fno-indirect-inlining -fno-builtin -fcompare-debug-second -nostdlib -nostdinc helloworld.c -Wl,--gc-sections -L../../libxunil/target/$KARCH-unknown-none/release -l:libxunil.a -I../../libxunil/include -I"$GCC_INCLUDES" -I"$SYS_INCLUDES" -o ../../../assets/$KARCH/helloworld.elf
|
||||||
|
|||||||
+1
-1
Submodule user/init updated: 601d2cab7f...417af31481
+1
-1
Submodule user/libxunil updated: 7ddebd6df5...6025f75ab3
Reference in New Issue
Block a user