From 24e64cac7e51ee7aecfced66dd65d93ff1239546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Holz?= Date: Fri, 27 Oct 2023 12:24:23 +0200 Subject: [PATCH] Kernel/riscv64: Add register state related headers --- Kernel/Arch/FPUState.h | 2 + Kernel/Arch/RegisterState.h | 2 + Kernel/Arch/ThreadRegisters.h | 2 + Kernel/Arch/TrapFrame.h | 2 + Kernel/Arch/riscv64/FPUState.h | 21 +++++ Kernel/Arch/riscv64/RegisterState.h | 85 +++++++++++++++++++ Kernel/Arch/riscv64/ThreadRegisters.h | 66 ++++++++++++++ Kernel/Arch/riscv64/TrapFrame.h | 32 +++++++ Userland/Libraries/LibC/sys/arch/regs.h | 2 + .../Libraries/LibC/sys/arch/riscv64/regs.h | 46 ++++++++++ 10 files changed, 260 insertions(+) create mode 100644 Kernel/Arch/riscv64/FPUState.h create mode 100644 Kernel/Arch/riscv64/RegisterState.h create mode 100644 Kernel/Arch/riscv64/ThreadRegisters.h create mode 100644 Kernel/Arch/riscv64/TrapFrame.h create mode 100644 Userland/Libraries/LibC/sys/arch/riscv64/regs.h diff --git a/Kernel/Arch/FPUState.h b/Kernel/Arch/FPUState.h index b795688c3c..8ec757e80c 100644 --- a/Kernel/Arch/FPUState.h +++ b/Kernel/Arch/FPUState.h @@ -16,6 +16,8 @@ struct FPUState; # include #elif ARCH(AARCH64) # include +#elif ARCH(RISCV64) +# include #else # error "Unknown architecture" #endif diff --git a/Kernel/Arch/RegisterState.h b/Kernel/Arch/RegisterState.h index bb2d117c98..3d7021cf8a 100644 --- a/Kernel/Arch/RegisterState.h +++ b/Kernel/Arch/RegisterState.h @@ -12,6 +12,8 @@ # include #elif ARCH(AARCH64) # include +#elif ARCH(RISCV64) +# include #else # error "Unknown architecture" #endif diff --git a/Kernel/Arch/ThreadRegisters.h b/Kernel/Arch/ThreadRegisters.h index b21b73197a..b18c431920 100644 --- a/Kernel/Arch/ThreadRegisters.h +++ b/Kernel/Arch/ThreadRegisters.h @@ -12,6 +12,8 @@ # include #elif ARCH(AARCH64) # include +#elif ARCH(RISCV64) +# include #else # error "Unknown architecture" #endif diff --git a/Kernel/Arch/TrapFrame.h b/Kernel/Arch/TrapFrame.h index 58916f46a4..f60b66715c 100644 --- a/Kernel/Arch/TrapFrame.h +++ b/Kernel/Arch/TrapFrame.h @@ -19,6 +19,8 @@ # include #elif ARCH(AARCH64) # include +#elif ARCH(RISCV64) +# include #else # error "Unknown architecture" #endif diff --git a/Kernel/Arch/riscv64/FPUState.h b/Kernel/Arch/riscv64/FPUState.h new file mode 100644 index 0000000000..bae39b1733 --- /dev/null +++ b/Kernel/Arch/riscv64/FPUState.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023, Sönke Holz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#include +VALIDATE_IS_RISCV64() + +namespace Kernel { + +struct FPUState { + u64 f[32]; + u64 fcsr; +}; + +} diff --git a/Kernel/Arch/riscv64/RegisterState.h b/Kernel/Arch/riscv64/RegisterState.h new file mode 100644 index 0000000000..e9b23b6c08 --- /dev/null +++ b/Kernel/Arch/riscv64/RegisterState.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023, Sönke Holz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#include +#include + +#include +VALIDATE_IS_RISCV64() + +namespace Kernel { + +struct RegisterState { + u64 x[31]; + + RISCV64::CSR::SSTATUS sstatus; + u64 sepc; + u64 scause; + u64 stval; + + u64 user_sp; + + FlatPtr userspace_sp() const { return user_sp; } + void set_userspace_sp(FlatPtr value) { user_sp = value; } + + FlatPtr ip() const { return sepc; } + void set_ip(FlatPtr value) { sepc = value; } + + FlatPtr bp() const { return x[7]; } + void set_bp(FlatPtr value) { x[7] = value; } + + ExecutionMode previous_mode() const + { + switch (sstatus.SPP) { + case RISCV64::CSR::SSTATUS::PrivilegeMode::User: + return ExecutionMode::User; + case RISCV64::CSR::SSTATUS::PrivilegeMode::Supervisor: + return ExecutionMode::Kernel; + default: + VERIFY_NOT_REACHED(); + } + } + + void set_return_reg(FlatPtr value) { x[9] = value; } + void capture_syscall_params(FlatPtr& function, FlatPtr& arg1, FlatPtr& arg2, FlatPtr& arg3, FlatPtr& arg4) const + { + function = x[16]; + arg1 = x[9]; + arg2 = x[10]; + arg3 = x[11]; + arg4 = x[12]; + } +}; + +#define REGISTER_STATE_SIZE (36 * 8) +static_assert(AssertSize()); + +inline void copy_kernel_registers_into_ptrace_registers(PtraceRegisters& ptrace_regs, RegisterState const& kernel_regs) +{ + for (auto i = 0; i < 31; i++) + ptrace_regs.x[i] = kernel_regs.x[i]; + + ptrace_regs.sp = kernel_regs.userspace_sp(); + ptrace_regs.pc = kernel_regs.ip(); +} + +inline void copy_ptrace_registers_into_kernel_registers(RegisterState& kernel_regs, PtraceRegisters const& ptrace_regs) +{ + for (auto i = 0; i < 31; i++) + kernel_regs.x[i] = ptrace_regs.x[i]; + + kernel_regs.set_userspace_sp(ptrace_regs.sp); + kernel_regs.set_ip(ptrace_regs.pc); +} + +struct DebugRegisterState { +}; + +} diff --git a/Kernel/Arch/riscv64/ThreadRegisters.h b/Kernel/Arch/riscv64/ThreadRegisters.h new file mode 100644 index 0000000000..73fefc9a84 --- /dev/null +++ b/Kernel/Arch/riscv64/ThreadRegisters.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023, Sönke Holz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +#include +VALIDATE_IS_RISCV64() + +namespace Kernel { + +struct ThreadRegisters { + u64 x[31]; + RISCV64::CSR::SSTATUS sstatus; + RISCV64::CSR::SATP satp; + u64 pc; + + u64 kernel_sp; + + FlatPtr ip() const { return pc; } + void set_ip(FlatPtr value) { pc = value; } + + FlatPtr sp() const { return x[1]; } + void set_sp(FlatPtr value) { x[1] = value; } + + void set_initial_state(bool is_kernel_process, Memory::AddressSpace& space, FlatPtr kernel_stack_top) + { + set_sp(kernel_stack_top); + satp = space.page_directory().satp(); + set_sstatus(is_kernel_process); + } + + void set_entry_function(FlatPtr entry_ip, FlatPtr entry_data) + { + set_ip(entry_ip); + x[9] = entry_data; // a0 + } + + void set_exec_state(FlatPtr entry_ip, FlatPtr userspace_sp, Memory::AddressSpace& space) + { + set_ip(entry_ip); + set_sp(userspace_sp); + satp = space.page_directory().satp(); + set_sstatus(false); + } + + void set_sstatus(bool is_kernel_process) + { + // Enable interrupts + sstatus.SPIE = 1; + + sstatus.FS = RISCV64::CSR::SSTATUS::FloatingPointStatus::Initial; + + sstatus.SPP = is_kernel_process ? RISCV64::CSR::SSTATUS::PrivilegeMode::Supervisor : RISCV64::CSR::SSTATUS::PrivilegeMode::User; + sstatus.UXL = RISCV64::CSR::SSTATUS::XLEN::Bits64; + } +}; + +} diff --git a/Kernel/Arch/riscv64/TrapFrame.h b/Kernel/Arch/riscv64/TrapFrame.h new file mode 100644 index 0000000000..69de942984 --- /dev/null +++ b/Kernel/Arch/riscv64/TrapFrame.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023, Sönke Holz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#include +VALIDATE_IS_RISCV64() + +namespace Kernel { + +struct TrapFrame { + TrapFrame* next_trap; + RegisterState* regs; + + TrapFrame() = delete; + TrapFrame(TrapFrame const&) = delete; + TrapFrame(TrapFrame&&) = delete; + TrapFrame& operator=(TrapFrame const&) = delete; + TrapFrame& operator=(TrapFrame&&) = delete; +}; + +#define TRAP_FRAME_SIZE (2 * 8) +static_assert(AssertSize()); + +extern "C" void exit_trap(TrapFrame*) __attribute__((used)); + +} diff --git a/Userland/Libraries/LibC/sys/arch/regs.h b/Userland/Libraries/LibC/sys/arch/regs.h index 87e1ca1302..9fc8146ad8 100644 --- a/Userland/Libraries/LibC/sys/arch/regs.h +++ b/Userland/Libraries/LibC/sys/arch/regs.h @@ -12,4 +12,6 @@ # include "x86_64/regs.h" #elif ARCH(AARCH64) # include "aarch64/regs.h" +#elif ARCH(RISCV64) +# include "riscv64/regs.h" #endif diff --git a/Userland/Libraries/LibC/sys/arch/riscv64/regs.h b/Userland/Libraries/LibC/sys/arch/riscv64/regs.h new file mode 100644 index 0000000000..84e852b6af --- /dev/null +++ b/Userland/Libraries/LibC/sys/arch/riscv64/regs.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023, Sönke Holz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#if defined(__cplusplus) && defined(__cpp_concepts) +# include +#else +# include +#endif + +#include + +#ifdef __cplusplus +struct [[gnu::packed]] PtraceRegisters : public __mcontext { +# if defined(__cplusplus) && defined(__cpp_concepts) + FlatPtr ip() const + { + return pc; + } + + void set_ip(FlatPtr ip) + { + pc = ip; + } + + FlatPtr bp() const + { + return x[7]; + } + + void set_bp(FlatPtr bp) + { + x[7] = bp; + } +# endif +}; + +#else +typedef struct __mcontext PthreadRegisters; +#endif