diff --git a/SConstruct b/SConstruct index 4ed02fd..5d70a66 100644 --- a/SConstruct +++ b/SConstruct @@ -14,7 +14,7 @@ AddOption( target = GetOption('target') env = Environment(tools = ['default', 'compilation_db']) -env.Append(CCFLAGS = ['-g', '-O0']) +env.Append(CCFLAGS = ['-g', '-O0', '-fno-stack-protector']) env.Append(CPPDEFINES = ['BASTL_EXTENSIONS=1']) # env.Append(CCFLAGS = ['-O2']) diff --git a/targets/_any/include/os/syscall.hpp b/targets/_any/include/os/syscall.hpp index 540ac10..157186c 100644 --- a/targets/_any/include/os/syscall.hpp +++ b/targets/_any/include/os/syscall.hpp @@ -12,7 +12,8 @@ namespace baos enum class Syscall : std::uint64_t { FILE_READ = 0, - FILE_WRITE = 1 + FILE_WRITE = 1, + EXIT = 0x3C }; void setupSyscall() noexcept; diff --git a/targets/_any/src/app/main.cpp b/targets/_any/src/app/main.cpp index 84b6127..dcb4c73 100644 --- a/targets/_any/src/app/main.cpp +++ b/targets/_any/src/app/main.cpp @@ -108,7 +108,7 @@ void cmdDumpPageTable() noexcept } } -extern "C" void main() +extern "C" void usermode_main() { std::string cmd; while(true) @@ -132,6 +132,10 @@ extern "C" void main() cmdDumpPageTable(); continue; } + else if (cmd == "exit") + { + return; + } std::printf("Unknown command: %s.\n", cmd.c_str()); } } diff --git a/targets/_any/src/os/syscall.cpp b/targets/_any/src/os/syscall.cpp index e5f07e5..2088265 100644 --- a/targets/_any/src/os/syscall.cpp +++ b/targets/_any/src/os/syscall.cpp @@ -46,5 +46,7 @@ extern "C" void __baosSyscall(baos::Syscall cmd, std::uint64_t param0, std::uint case Syscall::FILE_WRITE: sysFileWrite(static_cast(param0), std::bit_cast(param1), param2); break; + case Syscall::EXIT: + break; } } diff --git a/targets/x86_64/src/kernel/boot.s b/targets/x86_64/src/kernel/boot.s index b2e4dab..8d80ad9 100644 --- a/targets/x86_64/src/kernel/boot.s +++ b/targets/x86_64/src/kernel/boot.s @@ -103,6 +103,12 @@ __enterUsermode: movw %si, %fs movw %si, %gs + // the ABI expects the stack pointer to be 16-byte aligned BEFORE calling the function + // i.e. after pushing the instruction pointer, and when arriving in the function, it should be offset by 8 byte + // since we're not using a regular call, manually offset the stack pointer by 8 bytes and write the "return" address + subq $8, %r8 + movq $__exitUsermode, (%r8) + movq %rsp, (%rdx) pushq %rsi // data segment pushq %r8 @@ -111,10 +117,16 @@ __enterUsermode: pushq %rcx iretq +__exitUsermode: + movq $0x3C, %rdi + syscall + jmp __exitUsermode + .global __handleSyscall .type __handleSyscall @function // void __handleSyscall() __handleSyscall: + enter $0, $0 pushq %rcx // store the original instruction pointer pushq %rsp // also store the original stack pointer movq %r8, %rcx @@ -122,6 +134,7 @@ __handleSyscall: call __baosSyscall popq %rsp popq %rcx + leave sysretq /* diff --git a/targets/x86_64/src/kernel/startup.cpp b/targets/x86_64/src/kernel/startup.cpp index 3497814..6f2e5f7 100644 --- a/targets/x86_64/src/kernel/startup.cpp +++ b/targets/x86_64/src/kernel/startup.cpp @@ -186,7 +186,7 @@ extern "C" { EfiBootInfo* gBootInfo; -void main(); +void usermode_main(); void kernel_main() { @@ -284,7 +284,7 @@ void kernel_main() initializePCIDevice(header); } - static std::array usermodeStack; - __enterUsermode(SEGIDX_USER_CODE, SEGIDX_USER_DATA, &tss.rsp0, &main, &usermodeStack.back()); + static std::array usermodeStack alignas(16); + __enterUsermode(SEGIDX_USER_CODE, SEGIDX_USER_DATA, &tss.rsp0, &usermode_main, &usermodeStack.back() + 1); } } // extern "C"